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();
|
auto& gpu = Core::System().GetInstance().GPU().Maxwell3D();
|
||||||
ASSERT_MSG(!gpu.regs.shader_config[0].enable, "VertexA is unsupported!");
|
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) {
|
for (unsigned index = 1; index < Maxwell::MaxShaderProgram; ++index) {
|
||||||
ptr_pos += sizeof(GLShader::MaxwellUniformData);
|
ptr_pos += sizeof(GLShader::MaxwellUniformData);
|
||||||
|
|
||||||
|
@ -244,9 +247,13 @@ void RasterizerOpenGL::SetupShaders(u8* buffer_ptr, GLintptr buffer_offset, size
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLuint gl_stage_program = shader_program_manager->GetCurrentProgramStage(
|
||||||
|
static_cast<Maxwell::ShaderStage>(stage));
|
||||||
|
|
||||||
// Configure the const buffers for this shader stage.
|
// Configure the const buffers for this shader stage.
|
||||||
SetupConstBuffers(static_cast<Maxwell::ShaderStage>(stage),
|
current_constbuffer_bindpoint =
|
||||||
shader_resources.const_buffer_entries);
|
SetupConstBuffers(static_cast<Maxwell::ShaderStage>(stage), gl_stage_program,
|
||||||
|
current_constbuffer_bindpoint, shader_resources.const_buffer_entries);
|
||||||
}
|
}
|
||||||
|
|
||||||
shader_program_manager->UseTrivialGeometryShader();
|
shader_program_manager->UseTrivialGeometryShader();
|
||||||
|
@ -543,7 +550,8 @@ void RasterizerOpenGL::SamplerInfo::SyncWithConfig(const Tegra::Texture::TSCEntr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::SetupConstBuffers(Maxwell::ShaderStage stage,
|
u32 RasterizerOpenGL::SetupConstBuffers(Maxwell::ShaderStage stage, GLuint program,
|
||||||
|
u32 current_bindpoint,
|
||||||
const std::vector<GLShader::ConstBufferEntry>& entries) {
|
const std::vector<GLShader::ConstBufferEntry>& entries) {
|
||||||
auto& gpu = Core::System::GetInstance().GPU();
|
auto& gpu = Core::System::GetInstance().GPU();
|
||||||
auto& maxwell3d = gpu.Get3DEngine();
|
auto& maxwell3d = gpu.Get3DEngine();
|
||||||
|
@ -568,7 +576,7 @@ void RasterizerOpenGL::SetupConstBuffers(Maxwell::ShaderStage stage,
|
||||||
|
|
||||||
ASSERT_MSG(buffer.enabled, "Attempted to upload disabled constbuffer");
|
ASSERT_MSG(buffer.enabled, "Attempted to upload disabled constbuffer");
|
||||||
buffer_draw_state.enabled = true;
|
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);
|
VAddr addr = gpu.memory_manager->PhysicalToVirtualAddress(buffer.address);
|
||||||
std::vector<u8> data(used_buffer.GetSize() * sizeof(float));
|
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);
|
glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer_draw_state.ssbo);
|
||||||
glBufferData(GL_SHADER_STORAGE_BUFFER, data.size(), data.data(), GL_DYNAMIC_DRAW);
|
glBufferData(GL_SHADER_STORAGE_BUFFER, data.size(), data.data(), GL_DYNAMIC_DRAW);
|
||||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
|
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();
|
state.Apply();
|
||||||
|
|
||||||
|
return current_bindpoint + entries.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::BindFramebufferSurfaces(const Surface& color_surface,
|
void RasterizerOpenGL::BindFramebufferSurfaces(const Surface& color_surface,
|
||||||
|
|
|
@ -87,8 +87,16 @@ private:
|
||||||
/// Binds the required textures to OpenGL before drawing a batch.
|
/// Binds the required textures to OpenGL before drawing a batch.
|
||||||
void BindTextures();
|
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 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);
|
const std::vector<GLShader::ConstBufferEntry>& entries);
|
||||||
|
|
||||||
/// Syncs the viewport to match the guest state
|
/// Syncs the viewport to match the guest state
|
||||||
|
|
|
@ -192,7 +192,7 @@ private:
|
||||||
|
|
||||||
/// Generates code representing a uniform (C buffer) register.
|
/// Generates code representing a uniform (C buffer) register.
|
||||||
std::string GetUniform(const Uniform& reg) {
|
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) + ']';
|
return 'c' + std::to_string(reg.index) + '[' + std::to_string(reg.offset) + ']';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -478,8 +478,7 @@ private:
|
||||||
|
|
||||||
unsigned const_buffer_layout = 0;
|
unsigned const_buffer_layout = 0;
|
||||||
for (const auto& entry : GetConstBuffersDeclarations()) {
|
for (const auto& entry : GetConstBuffersDeclarations()) {
|
||||||
declarations.AddLine("layout(std430, binding = " + std::to_string(const_buffer_layout) +
|
declarations.AddLine("layout(std430) buffer " + entry.GetName());
|
||||||
") buffer c" + std::to_string(entry.GetIndex()) + "_buffer");
|
|
||||||
declarations.AddLine("{");
|
declarations.AddLine("{");
|
||||||
declarations.AddLine(" float c" + std::to_string(entry.GetIndex()) + "[];");
|
declarations.AddLine(" float c" + std::to_string(entry.GetIndex()) + "[];");
|
||||||
declarations.AddLine("};");
|
declarations.AddLine("};");
|
||||||
|
|
|
@ -19,10 +19,13 @@ constexpr size_t MAX_PROGRAM_CODE_LENGTH{0x1000};
|
||||||
using ProgramCode = std::array<u64, MAX_PROGRAM_CODE_LENGTH>;
|
using ProgramCode = std::array<u64, MAX_PROGRAM_CODE_LENGTH>;
|
||||||
|
|
||||||
class ConstBufferEntry {
|
class ConstBufferEntry {
|
||||||
|
using Maxwell = Tegra::Engines::Maxwell3D::Regs;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void MarkAsUsed(unsigned index, unsigned offset) {
|
void MarkAsUsed(unsigned index, unsigned offset, Maxwell::ShaderStage stage) {
|
||||||
is_used = true;
|
is_used = true;
|
||||||
this->index = index;
|
this->index = index;
|
||||||
|
this->stage = stage;
|
||||||
max_offset = std::max(max_offset, offset);
|
max_offset = std::max(max_offset, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,10 +41,19 @@ public:
|
||||||
return max_offset + 1;
|
return max_offset + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string GetName() const {
|
||||||
|
return BufferBaseNames[static_cast<size_t>(stage)] + std::to_string(index);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
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{};
|
bool is_used{};
|
||||||
unsigned index{};
|
unsigned index{};
|
||||||
unsigned max_offset{};
|
unsigned max_offset{};
|
||||||
|
Maxwell::ShaderStage stage;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ShaderEntries {
|
struct ShaderEntries {
|
||||||
|
|
|
@ -121,6 +121,17 @@ public:
|
||||||
return result;
|
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() {
|
void UseTrivialGeometryShader() {
|
||||||
current.gs = 0;
|
current.gs = 0;
|
||||||
}
|
}
|
||||||
|
|
Reference in New Issue