diff --git a/src/video_core/renderer_opengl/gl_global_cache.h b/src/video_core/renderer_opengl/gl_global_cache.h index 951505d301..c68c1948e8 100644 --- a/src/video_core/renderer_opengl/gl_global_cache.h +++ b/src/video_core/renderer_opengl/gl_global_cache.h @@ -17,7 +17,24 @@ namespace OpenGL { class RasterizerOpenGL; class CachedGlobalRegion; using GlobalRegion = std::shared_ptr; -using Maxwell = Tegra::Engines::Maxwell3D::Regs; + +/// Helper class for caching global region uniform locations +class CachedGlobalRegionUniform { +public: + CachedGlobalRegionUniform(std::size_t index) : index{index} {} + + std::string GetName() const { + return fmt::format("global_memory_region_declblock_{}", index); + } + + u32 GetHash() const { + // This needs to be unique from ConstBufferEntry::GetHash and SamplerEntry::GetHash + return (static_cast(index) << 16) | 0xFFFF; + } + +private: + std::size_t index{}; +}; class CachedGlobalRegion final : public RasterizerCacheObject { public: diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index be5b2d1655..462e504f48 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -267,7 +267,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_buffer_bindpoint = Tegra::Engines::Maxwell3D::Regs::MaxShaderStage; u32 current_texture_bindpoint = 0; for (std::size_t index = 0; index < Maxwell::MaxShaderProgram; ++index) { @@ -321,9 +321,14 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) { } // Configure the const buffers for this shader stage. - current_constbuffer_bindpoint = + current_buffer_bindpoint = SetupConstBuffers(static_cast(stage), shader, primitive_mode, - current_constbuffer_bindpoint); + current_buffer_bindpoint); + + // Configure global memory regions for this shader stage. + current_buffer_bindpoint = + SetupGlobalRegions(static_cast(stage), shader, primitive_mode, + current_buffer_bindpoint); // Configure the textures for this shader stage. current_texture_bindpoint = SetupTextures(static_cast(stage), shader, @@ -334,27 +339,6 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) { // VertexB was combined with VertexA, so we skip the VertexB iteration index++; } - - auto& maxwell3d{Core::System::GetInstance().GPU().Maxwell3D()}; - auto& regions = maxwell3d.state.global_memory_uniforms; - size_t i = 0; - for (const auto& global_region : regions) { - const auto region = global_cache.GetGlobalRegion( - global_region, static_cast(stage)); - - const auto uniform_name = fmt::format("global_memory_region_declblock_{}", i); - const auto b_index = glGetProgramResourceIndex(shader->GetProgramHandle(primitive_mode), - GL_UNIFORM_BLOCK, uniform_name.c_str()); - if (b_index != GL_INVALID_INDEX) { - glBindBufferBase(GL_UNIFORM_BUFFER, current_constbuffer_bindpoint, - region->GetBufferHandle()); - glUniformBlockBinding(shader->GetProgramHandle(primitive_mode), b_index, - current_constbuffer_bindpoint); - ++current_constbuffer_bindpoint; - } - - ++i; - } } } @@ -941,6 +925,29 @@ u32 RasterizerOpenGL::SetupConstBuffers(Maxwell::ShaderStage stage, Shader& shad return current_bindpoint + static_cast(entries.size()); } +u32 RasterizerOpenGL::SetupGlobalRegions(Maxwell::ShaderStage stage, Shader& shader, + GLenum primitive_mode, u32 current_bindpoint) { + std::size_t global_region_index{}; + const auto& maxwell3d{Core::System::GetInstance().GPU().Maxwell3D()}; + for (const auto& global_region : maxwell3d.state.global_memory_uniforms) { + const auto& region{ + global_cache.GetGlobalRegion(global_region, static_cast(stage))}; + const GLenum b_index{ + shader->GetProgramResourceIndex(CachedGlobalRegionUniform{global_region_index})}; + + if (b_index != GL_INVALID_INDEX) { + glBindBufferBase(GL_UNIFORM_BUFFER, current_bindpoint, region->GetBufferHandle()); + glUniformBlockBinding(shader->GetProgramHandle(primitive_mode), b_index, + current_bindpoint); + ++current_bindpoint; + } + + ++global_region_index; + } + + 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 6a7378086e..6ed86f4172 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h @@ -119,7 +119,7 @@ private: bool using_depth_fb = true, bool preserve_contents = true, std::optional single_color_target = {}); - /* + /** * Configures the current constbuffers 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. @@ -129,7 +129,17 @@ private: u32 SetupConstBuffers(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage, Shader& shader, 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 038b25c758..fc42ee3168 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp @@ -98,18 +98,6 @@ 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 GLuint index{ - glGetProgramResourceIndex(program.handle, GL_UNIFORM_BLOCK, buffer.GetName().c_str())}; - resource_cache[buffer.GetHash()] = index; - return index; - } - - return search->second; -} - GLint CachedShader::GetUniformLocation(const GLShader::SamplerEntry& sampler) { const auto search{uniform_cache.find(sampler.GetHash())}; if (search == uniform_cache.end()) { diff --git a/src/video_core/renderer_opengl/gl_shader_cache.h b/src/video_core/renderer_opengl/gl_shader_cache.h index 08f470de3a..83585cded8 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.h +++ b/src/video_core/renderer_opengl/gl_shader_cache.h @@ -71,7 +71,18 @@ public: } /// Gets the GL program resource location for the specified resource, caching as needed - GLuint GetProgramResourceIndex(const GLShader::ConstBufferEntry& buffer); + template + GLuint GetProgramResourceIndex(const T& buffer) { + const auto& search{resource_cache.find(buffer.GetHash())}; + if (search == resource_cache.end()) { + const GLuint index{glGetProgramResourceIndex(program.handle, GL_UNIFORM_BLOCK, + buffer.GetName().c_str())}; + resource_cache[buffer.GetHash()] = index; + return index; + } + + return search->second; + } /// Gets the GL uniform location for the specified resource, caching as needed GLint GetUniformLocation(const GLShader::SamplerEntry& sampler); diff --git a/src/video_core/renderer_opengl/gl_shader_gen.h b/src/video_core/renderer_opengl/gl_shader_gen.h index b425d98ae5..285a54ed61 100644 --- a/src/video_core/renderer_opengl/gl_shader_gen.h +++ b/src/video_core/renderer_opengl/gl_shader_gen.h @@ -57,7 +57,8 @@ public: } u32 GetHash() const { - return (static_cast(stage) << 16) | index; + // This needs to be unique from CachedGlobalRegionUniform::GetHash + return (static_cast(stage) << 12) | index; } private: @@ -138,7 +139,8 @@ public: } u32 GetHash() const { - return (static_cast(stage) << 16) | static_cast(sampler_index); + // This needs to be unique from CachedGlobalRegionUniform::GetHash + return (static_cast(stage) << 12) | static_cast(sampler_index); } static std::string GetArrayName(Maxwell::ShaderStage stage) {