summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorReinUsesLisp <reinuseslisp@airmail.cc>2019-01-05 05:01:38 +0100
committerReinUsesLisp <reinuseslisp@airmail.cc>2019-01-30 04:00:15 +0100
commit9f803299de3a9c512939ede48654fab838343a8a (patch)
tree4ba30f0ad404bd4120dd5b2e4f21193bf03952fd
parentshader_decode: Implement LDG and basic cbuf tracking (diff)
downloadyuzu-9f803299de3a9c512939ede48654fab838343a8a.tar
yuzu-9f803299de3a9c512939ede48654fab838343a8a.tar.gz
yuzu-9f803299de3a9c512939ede48654fab838343a8a.tar.bz2
yuzu-9f803299de3a9c512939ede48654fab838343a8a.tar.lz
yuzu-9f803299de3a9c512939ede48654fab838343a8a.tar.xz
yuzu-9f803299de3a9c512939ede48654fab838343a8a.tar.zst
yuzu-9f803299de3a9c512939ede48654fab838343a8a.zip
-rw-r--r--src/video_core/renderer_opengl/gl_global_cache.cpp70
-rw-r--r--src/video_core/renderer_opengl/gl_global_cache.h18
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp22
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h10
-rw-r--r--src/video_core/renderer_opengl/gl_shader_cache.cpp18
-rw-r--r--src/video_core/renderer_opengl/gl_shader_cache.h6
6 files changed, 140 insertions, 4 deletions
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 <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
diff --git a/src/video_core/renderer_opengl/gl_global_cache.h b/src/video_core/renderer_opengl/gl_global_cache.h
index 406a735bc..37830bb7c 100644
--- a/src/video_core/renderer_opengl/gl_global_cache.h
+++ b/src/video_core/renderer_opengl/gl_global_cache.h
@@ -5,9 +5,13 @@
#pragma once
#include <memory>
+#include <unordered_map>
+
#include <glad/glad.h>
+#include "common/assert.h"
#include "common/common_types.h"
+#include "video_core/engines/maxwell_3d.h"
#include "video_core/rasterizer_cache.h"
#include "video_core/renderer_opengl/gl_resource_manager.h"
@@ -40,6 +44,9 @@ public:
return buffer.handle;
}
+ /// Reloads the global region from guest memory
+ void Reload(u32 size_);
+
// TODO(Rodrigo): When global memory is written (STG), implement flushing
void Flush() override {
UNIMPLEMENTED();
@@ -55,6 +62,17 @@ private:
class GlobalRegionCacheOpenGL final : public RasterizerCache<GlobalRegion> {
public:
explicit GlobalRegionCacheOpenGL(RasterizerOpenGL& rasterizer);
+
+ /// Gets the current specified shader stage program
+ GlobalRegion GetGlobalRegion(const GLShader::GlobalMemoryEntry& descriptor,
+ Tegra::Engines::Maxwell3D::Regs::ShaderStage stage);
+
+private:
+ GlobalRegion TryGetReservedGlobalRegion(VAddr addr, u32 size) const;
+ GlobalRegion GetUncachedGlobalRegion(VAddr addr, u32 size);
+ void ReserveGlobalRegion(const GlobalRegion& region);
+
+ std::unordered_map<VAddr, GlobalRegion> reserve;
};
} // namespace OpenGL
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 71829fee0..ca421ef28 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -300,6 +300,7 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) {
// Next available bindpoints to use when uploading the const buffers and textures to the GLSL
// shaders. The constbuffer bindpoint starts after the shader stage configuration bind points.
u32 current_constbuffer_bindpoint = Tegra::Engines::Maxwell3D::Regs::MaxShaderStage;
+ u32 current_gmem_bindpoint = 0;
u32 current_texture_bindpoint = 0;
std::array<bool, Maxwell::NumClipDistances> clip_distances{};
@@ -358,6 +359,10 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) {
SetupConstBuffers(static_cast<Maxwell::ShaderStage>(stage), shader, primitive_mode,
current_constbuffer_bindpoint);
+ // Configure global memory regions for this shader stage.
+ current_gmem_bindpoint = SetupGlobalRegions(static_cast<Maxwell::ShaderStage>(stage),
+ shader, primitive_mode, current_gmem_bindpoint);
+
// Configure the textures for this shader stage.
current_texture_bindpoint = SetupTextures(static_cast<Maxwell::ShaderStage>(stage), shader,
primitive_mode, current_texture_bindpoint);
@@ -993,6 +998,23 @@ u32 RasterizerOpenGL::SetupConstBuffers(Maxwell::ShaderStage stage, Shader& shad
return current_bindpoint + static_cast<u32>(entries.size());
}
+u32 RasterizerOpenGL::SetupGlobalRegions(Maxwell::ShaderStage stage, Shader& shader,
+ GLenum primitive_mode, u32 current_bindpoint) {
+ for (const auto& global_region : shader->GetShaderEntries().global_memory_entries) {
+ const auto& region =
+ global_cache.GetGlobalRegion(global_region, static_cast<Maxwell::ShaderStage>(stage));
+ const GLuint block_index{shader->GetProgramResourceIndex(global_region)};
+ ASSERT(block_index != GL_INVALID_INDEX);
+
+ glBindBufferBase(GL_SHADER_STORAGE_BUFFER, current_bindpoint, region->GetBufferHandle());
+ glShaderStorageBlockBinding(shader->GetProgramHandle(primitive_mode), block_index,
+ current_bindpoint);
+ ++current_bindpoint;
+ }
+
+ return current_bindpoint;
+}
+
u32 RasterizerOpenGL::SetupTextures(Maxwell::ShaderStage stage, Shader& shader,
GLenum primitive_mode, u32 current_unit) {
MICROPROFILE_SCOPE(OpenGL_Texture);
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index 21c51f874..57ab2f627 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -138,6 +138,16 @@ private:
GLenum primitive_mode, u32 current_bindpoint);
/**
+ * Configures the current global memory regions to use for the draw command.
+ * @param stage The shader stage to configure buffers for.
+ * @param shader The shader object that contains the specified stage.
+ * @param current_bindpoint The offset at which to start counting new buffer bindpoints.
+ * @returns The next available bindpoint for use in the next shader stage.
+ */
+ u32 SetupGlobalRegions(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage, Shader& shader,
+ GLenum primitive_mode, u32 current_bindpoint);
+
+ /**
* Configures the current textures to use for the draw command.
* @param stage The shader stage to configure textures for.
* @param shader The shader object that contains the specified stage.
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp
index b3aca39af..54ec23f3a 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp
@@ -108,11 +108,23 @@ CachedShader::CachedShader(VAddr addr, Maxwell::ShaderProgram program_type)
}
GLuint CachedShader::GetProgramResourceIndex(const GLShader::ConstBufferEntry& buffer) {
- const auto search{resource_cache.find(buffer.GetHash())};
- if (search == resource_cache.end()) {
+ const auto search{cbuf_resource_cache.find(buffer.GetHash())};
+ if (search == cbuf_resource_cache.end()) {
const GLuint index{
glGetProgramResourceIndex(program.handle, GL_UNIFORM_BLOCK, buffer.GetName().c_str())};
- resource_cache[buffer.GetHash()] = index;
+ cbuf_resource_cache[buffer.GetHash()] = index;
+ return index;
+ }
+
+ return search->second;
+}
+
+GLuint CachedShader::GetProgramResourceIndex(const GLShader::GlobalMemoryEntry& global_mem) {
+ const auto search{gmem_resource_cache.find(global_mem.GetHash())};
+ if (search == gmem_resource_cache.end()) {
+ const GLuint index{glGetProgramResourceIndex(program.handle, GL_SHADER_STORAGE_BLOCK,
+ global_mem.GetName().c_str())};
+ gmem_resource_cache[global_mem.GetHash()] = index;
return index;
}
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.h b/src/video_core/renderer_opengl/gl_shader_cache.h
index e0887dd7b..62b1733b4 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.h
+++ b/src/video_core/renderer_opengl/gl_shader_cache.h
@@ -76,6 +76,9 @@ public:
/// Gets the GL program resource location for the specified resource, caching as needed
GLuint GetProgramResourceIndex(const GLShader::ConstBufferEntry& buffer);
+ /// Gets the GL program resource location for the specified resource, caching as needed
+ GLuint GetProgramResourceIndex(const GLShader::GlobalMemoryEntry& global_mem);
+
/// Gets the GL uniform location for the specified resource, caching as needed
GLint GetUniformLocation(const GLShader::SamplerEntry& sampler);
@@ -107,7 +110,8 @@ private:
OGLProgram triangles_adjacency;
} geometry_programs;
- std::map<u32, GLuint> resource_cache;
+ std::map<u32, GLuint> cbuf_resource_cache;
+ std::map<u32, GLuint> gmem_resource_cache;
std::map<u32, GLint> uniform_cache;
};