From 9f803299de3a9c512939ede48654fab838343a8a Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Sat, 5 Jan 2019 01:01:38 -0300 Subject: gl_rasterizer: Implement global memory management --- src/video_core/renderer_opengl/gl_global_cache.cpp | 70 ++++++++++++++++++++++ 1 file changed, 70 insertions(+) (limited to 'src/video_core/renderer_opengl/gl_global_cache.cpp') diff --git a/src/video_core/renderer_opengl/gl_global_cache.cpp b/src/video_core/renderer_opengl/gl_global_cache.cpp index 7992b82c4..c7f32feaa 100644 --- a/src/video_core/renderer_opengl/gl_global_cache.cpp +++ b/src/video_core/renderer_opengl/gl_global_cache.cpp @@ -4,8 +4,13 @@ #include +#include "common/assert.h" +#include "common/logging/log.h" +#include "core/core.h" +#include "core/memory.h" #include "video_core/renderer_opengl/gl_global_cache.h" #include "video_core/renderer_opengl/gl_rasterizer.h" +#include "video_core/renderer_opengl/gl_shader_decompiler.h" #include "video_core/renderer_opengl/utils.h" namespace OpenGL { @@ -18,7 +23,72 @@ CachedGlobalRegion::CachedGlobalRegion(VAddr addr, u32 size) : addr{addr}, size{ LabelGLObject(GL_BUFFER, buffer.handle, addr, "GlobalMemory"); } +void CachedGlobalRegion::Reload(u32 size_) { + constexpr auto max_size = static_cast(RasterizerOpenGL::MaxGlobalMemorySize); + + size = size_; + if (size > max_size) { + size = max_size; + LOG_CRITICAL(HW_GPU, "Global region size {} exceeded the expected size {}!", size_, + max_size); + } + + // TODO(Rodrigo): Get rid of Memory::GetPointer with a staging buffer + glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer.handle); + glBufferData(GL_SHADER_STORAGE_BUFFER, size, Memory::GetPointer(addr), GL_DYNAMIC_DRAW); +} + +GlobalRegion GlobalRegionCacheOpenGL::TryGetReservedGlobalRegion(VAddr addr, u32 size) const { + const auto search{reserve.find(addr)}; + if (search == reserve.end()) { + return {}; + } + return search->second; +} + +GlobalRegion GlobalRegionCacheOpenGL::GetUncachedGlobalRegion(VAddr addr, u32 size) { + GlobalRegion region{TryGetReservedGlobalRegion(addr, size)}; + if (!region) { + // No reserved surface available, create a new one and reserve it + region = std::make_shared(addr, size); + ReserveGlobalRegion(region); + } + region->Reload(size); + return region; +} + +void GlobalRegionCacheOpenGL::ReserveGlobalRegion(const GlobalRegion& region) { + reserve[region->GetAddr()] = region; +} + GlobalRegionCacheOpenGL::GlobalRegionCacheOpenGL(RasterizerOpenGL& rasterizer) : RasterizerCache{rasterizer} {} +GlobalRegion GlobalRegionCacheOpenGL::GetGlobalRegion( + const GLShader::GlobalMemoryEntry& global_region, + Tegra::Engines::Maxwell3D::Regs::ShaderStage stage) { + + auto& gpu{Core::System::GetInstance().GPU()}; + const auto cbufs = gpu.Maxwell3D().state.shader_stages[static_cast(stage)]; + const auto cbuf_addr = gpu.MemoryManager().GpuToCpuAddress( + cbufs.const_buffers[global_region.GetCbufIndex()].address + global_region.GetCbufOffset()); + ASSERT(cbuf_addr); + + const auto actual_addr_gpu = Memory::Read64(*cbuf_addr); + const auto size = Memory::Read32(*cbuf_addr + 8); + const auto actual_addr = gpu.MemoryManager().GpuToCpuAddress(actual_addr_gpu); + ASSERT(actual_addr); + + // Look up global region in the cache based on address + GlobalRegion region = TryGet(*actual_addr); + + if (!region) { + // No global region found - create a new one + region = GetUncachedGlobalRegion(*actual_addr, size); + Register(region); + } + + return region; +} + } // namespace OpenGL -- cgit v1.2.3