diff options
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 30 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.h | 13 | ||||
| -rw-r--r-- | src/video_core/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<const char*, Maxwell::MaxShaderStage> 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<Maxwell::ShaderStage>(stage)); +          // Configure the const buffers for this shader stage. -        SetupConstBuffers(static_cast<Maxwell::ShaderStage>(stage), -                          shader_resources.const_buffer_entries); +        current_constbuffer_bindpoint = SetupConstBuffers( +            static_cast<Maxwell::ShaderStage>(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<GLShader::ConstBufferEntry>& entries) { +u32 RasterizerOpenGL::SetupConstBuffers(Maxwell::ShaderStage stage, GLuint program, +                                        const std::string& base_name, u32 current_bindpoint, +                                        const std::vector<GLShader::ConstBufferEntry>& 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<u8> 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<GLShader::ConstBufferEntry>& 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;      } | 
