From 14ac40436ead929506d5fdf16eb3721940e60956 Mon Sep 17 00:00:00 2001 From: Subv Date: Sun, 15 Apr 2018 14:14:57 -0500 Subject: [PATCH] GPU: Don't use explicit binding points when uploading the constbuffers to opengl. The bindpoints will now be dynamically calculated based on the number of buffers used by the previous shader stage. --- .../renderer_opengl/gl_rasterizer.cpp | 30 +++++++++++++++---- .../renderer_opengl/gl_rasterizer.h | 13 ++++++-- .../renderer_opengl/gl_shader_manager.h | 11 +++++++ 3 files changed, 47 insertions(+), 7 deletions(-) diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index a778dfc64..a80923285 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -193,6 +193,9 @@ void RasterizerOpenGL::SetupShaders(u8* buffer_ptr, GLintptr buffer_offset, size auto& gpu = Core::System().GetInstance().GPU().Maxwell3D(); ASSERT_MSG(!gpu.regs.shader_config[0].enable, "VertexA is unsupported!"); + // Next available bindpoint to use when uploading the const buffers to the GLSL shaders. + u32 current_constbuffer_bindpoint = 0; + for (unsigned index = 1; index < Maxwell::MaxShaderProgram; ++index) { ptr_pos += sizeof(GLShader::MaxwellUniformData); @@ -223,6 +226,10 @@ void RasterizerOpenGL::SetupShaders(u8* buffer_ptr, GLintptr buffer_offset, size Memory::ReadBlock(cpu_address, program_code.data(), program_code.size() * sizeof(u64)); GLShader::ShaderSetup setup{std::move(program_code)}; + static constexpr std::array base_names = { + "buffer_vs_c", "buffer_tessc_c", "buffer_tesse_c", "buffer_gs_c", "buffer_fs_c", + }; + GLShader::ShaderEntries shader_resources; switch (program) { @@ -244,9 +251,13 @@ void RasterizerOpenGL::SetupShaders(u8* buffer_ptr, GLintptr buffer_offset, size UNREACHABLE(); } + GLuint gl_stage_program = shader_program_manager->GetCurrentProgramStage( + static_cast(stage)); + // Configure the const buffers for this shader stage. - SetupConstBuffers(static_cast(stage), - shader_resources.const_buffer_entries); + current_constbuffer_bindpoint = SetupConstBuffers( + static_cast(stage), gl_stage_program, base_names[stage], + current_constbuffer_bindpoint, shader_resources.const_buffer_entries); } shader_program_manager->UseTrivialGeometryShader(); @@ -543,8 +554,9 @@ void RasterizerOpenGL::SamplerInfo::SyncWithConfig(const Tegra::Texture::TSCEntr } } -void RasterizerOpenGL::SetupConstBuffers(Maxwell::ShaderStage stage, - const std::vector& entries) { +u32 RasterizerOpenGL::SetupConstBuffers(Maxwell::ShaderStage stage, GLuint program, + const std::string& base_name, u32 current_bindpoint, + const std::vector& entries) { auto& gpu = Core::System::GetInstance().GPU(); auto& maxwell3d = gpu.Get3DEngine(); @@ -568,7 +580,7 @@ void RasterizerOpenGL::SetupConstBuffers(Maxwell::ShaderStage stage, ASSERT_MSG(buffer.enabled, "Attempted to upload disabled constbuffer"); buffer_draw_state.enabled = true; - buffer_draw_state.bindpoint = bindpoint; + buffer_draw_state.bindpoint = current_bindpoint + bindpoint; VAddr addr = gpu.memory_manager->PhysicalToVirtualAddress(buffer.address); std::vector data(used_buffer.GetSize() * sizeof(float)); @@ -577,9 +589,17 @@ void RasterizerOpenGL::SetupConstBuffers(Maxwell::ShaderStage stage, glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer_draw_state.ssbo); glBufferData(GL_SHADER_STORAGE_BUFFER, data.size(), data.data(), GL_DYNAMIC_DRAW); glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); + + // Now configure the bindpoint of the buffer inside the shader + std::string buffer_name = base_name + std::to_string(used_buffer.GetIndex()); + GLuint index = + glGetProgramResourceIndex(program, GL_SHADER_STORAGE_BLOCK, buffer_name.c_str()); + glShaderStorageBlockBinding(program, index, buffer_draw_state.bindpoint); } state.Apply(); + + return current_bindpoint + entries.size(); } void RasterizerOpenGL::BindFramebufferSurfaces(const Surface& color_surface, diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index 1ea0dfa71..32d9598aa 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h @@ -87,8 +87,17 @@ private: /// Binds the required textures to OpenGL before drawing a batch. void BindTextures(); - /// Configures the current constbuffers to use for the draw command. - void SetupConstBuffers(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage, + /* + * Configures the current constbuffers to use for the draw command. + * @param stage The shader stage to configure buffers for. + * @param program The OpenGL program object that contains the specified stage. + * @param base_name The name prefix of the buffer objects in the GLSL shaders. + * @param current_bindpoint The offset at which to start counting new buffer bindpoints. + * @param entries Vector describing the buffers that are actually used in the guest shader. + * @returns The next available bindpoint for use in the next shader stage. + */ + u32 SetupConstBuffers(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage, GLuint program, + const std::string& base_name, u32 current_bindpoint, const std::vector& entries); /// Syncs the viewport to match the guest state diff --git a/src/video_core/renderer_opengl/gl_shader_manager.h b/src/video_core/renderer_opengl/gl_shader_manager.h index ecc92d986..be63320e0 100644 --- a/src/video_core/renderer_opengl/gl_shader_manager.h +++ b/src/video_core/renderer_opengl/gl_shader_manager.h @@ -121,6 +121,17 @@ public: return result; } + GLuint GetCurrentProgramStage(Maxwell3D::Regs::ShaderStage stage) { + switch (stage) { + case Maxwell3D::Regs::ShaderStage::Vertex: + return current.vs; + case Maxwell3D::Regs::ShaderStage::Fragment: + return current.fs; + } + + UNREACHABLE(); + } + void UseTrivialGeometryShader() { current.gs = 0; }