Merge pull request #337 from Subv/used_buffers
GPU: Don't use explicit binding points when uploading the constbuffers to opengl
This commit is contained in:
		
						commit
						d6d7d0989c
					
				@ -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);
 | 
			
		||||
 | 
			
		||||
@ -244,9 +247,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,
 | 
			
		||||
                              current_constbuffer_bindpoint, shader_resources.const_buffer_entries);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    shader_program_manager->UseTrivialGeometryShader();
 | 
			
		||||
@ -543,8 +550,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,
 | 
			
		||||
                                        u32 current_bindpoint,
 | 
			
		||||
                                        const std::vector<GLShader::ConstBufferEntry>& entries) {
 | 
			
		||||
    auto& gpu = Core::System::GetInstance().GPU();
 | 
			
		||||
    auto& maxwell3d = gpu.Get3DEngine();
 | 
			
		||||
 | 
			
		||||
@ -568,7 +576,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 +585,18 @@ 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 = used_buffer.GetName();
 | 
			
		||||
        GLuint index =
 | 
			
		||||
            glGetProgramResourceIndex(program, GL_SHADER_STORAGE_BLOCK, buffer_name.c_str());
 | 
			
		||||
        if (index != -1)
 | 
			
		||||
            glShaderStorageBlockBinding(program, index, buffer_draw_state.bindpoint);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    state.Apply();
 | 
			
		||||
 | 
			
		||||
    return current_bindpoint + entries.size();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerOpenGL::BindFramebufferSurfaces(const Surface& color_surface,
 | 
			
		||||
 | 
			
		||||
@ -87,9 +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,
 | 
			
		||||
                           const std::vector<GLShader::ConstBufferEntry>& entries);
 | 
			
		||||
    /*
 | 
			
		||||
     * 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 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,
 | 
			
		||||
                          u32 current_bindpoint,
 | 
			
		||||
                          const std::vector<GLShader::ConstBufferEntry>& entries);
 | 
			
		||||
 | 
			
		||||
    /// Syncs the viewport to match the guest state
 | 
			
		||||
    void SyncViewport(const MathUtil::Rectangle<u32>& surfaces_rect, u16 res_scale);
 | 
			
		||||
 | 
			
		||||
@ -192,7 +192,7 @@ private:
 | 
			
		||||
 | 
			
		||||
    /// Generates code representing a uniform (C buffer) register.
 | 
			
		||||
    std::string GetUniform(const Uniform& reg) {
 | 
			
		||||
        declr_const_buffers[reg.index].MarkAsUsed(reg.index, reg.offset);
 | 
			
		||||
        declr_const_buffers[reg.index].MarkAsUsed(reg.index, reg.offset, stage);
 | 
			
		||||
        return 'c' + std::to_string(reg.index) + '[' + std::to_string(reg.offset) + ']';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -478,8 +478,7 @@ private:
 | 
			
		||||
 | 
			
		||||
        unsigned const_buffer_layout = 0;
 | 
			
		||||
        for (const auto& entry : GetConstBuffersDeclarations()) {
 | 
			
		||||
            declarations.AddLine("layout(std430, binding = " + std::to_string(const_buffer_layout) +
 | 
			
		||||
                                 ") buffer c" + std::to_string(entry.GetIndex()) + "_buffer");
 | 
			
		||||
            declarations.AddLine("layout(std430) buffer " + entry.GetName());
 | 
			
		||||
            declarations.AddLine("{");
 | 
			
		||||
            declarations.AddLine("    float c" + std::to_string(entry.GetIndex()) + "[];");
 | 
			
		||||
            declarations.AddLine("};");
 | 
			
		||||
 | 
			
		||||
@ -19,10 +19,13 @@ constexpr size_t MAX_PROGRAM_CODE_LENGTH{0x1000};
 | 
			
		||||
using ProgramCode = std::array<u64, MAX_PROGRAM_CODE_LENGTH>;
 | 
			
		||||
 | 
			
		||||
class ConstBufferEntry {
 | 
			
		||||
    using Maxwell = Tegra::Engines::Maxwell3D::Regs;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    void MarkAsUsed(unsigned index, unsigned offset) {
 | 
			
		||||
    void MarkAsUsed(unsigned index, unsigned offset, Maxwell::ShaderStage stage) {
 | 
			
		||||
        is_used = true;
 | 
			
		||||
        this->index = index;
 | 
			
		||||
        this->stage = stage;
 | 
			
		||||
        max_offset = std::max(max_offset, offset);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -38,10 +41,19 @@ public:
 | 
			
		||||
        return max_offset + 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::string GetName() const {
 | 
			
		||||
        return BufferBaseNames[static_cast<size_t>(stage)] + std::to_string(index);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    static constexpr std::array<const char*, Maxwell::MaxShaderStage> BufferBaseNames = {
 | 
			
		||||
        "buffer_vs_c", "buffer_tessc_c", "buffer_tesse_c", "buffer_gs_c", "buffer_fs_c",
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    bool is_used{};
 | 
			
		||||
    unsigned index{};
 | 
			
		||||
    unsigned max_offset{};
 | 
			
		||||
    Maxwell::ShaderStage stage;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct ShaderEntries {
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user