|
|
|
@ -4,8 +4,13 @@ |
|
|
|
|
|
|
|
#include <glad/glad.h>
|
|
|
|
|
|
|
|
#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<u32>(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<CachedGlobalRegion>(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<u64>(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
|