diff options
| author | 2018-06-26 10:25:56 -0400 | |
|---|---|---|
| committer | 2018-06-26 10:25:56 -0400 | |
| commit | 36dedae842b3bc094f52e46f0e8edc028edeec25 (patch) | |
| tree | 79886fcda14b4db11b65e2c2dff338c4e9c2689c | |
| parent | Merge pull request #589 from mailwl/fix-crash (diff) | |
| parent | Rasterizer: Use UBOs instead of SSBOs for uploading const buffers. (diff) | |
| download | yuzu-36dedae842b3bc094f52e46f0e8edc028edeec25.tar.gz yuzu-36dedae842b3bc094f52e46f0e8edc028edeec25.tar.xz yuzu-36dedae842b3bc094f52e46f0e8edc028edeec25.zip | |
Merge pull request #554 from Subv/constbuffer_ubo
Rasterizer: Use UBOs instead of SSBOs for uploading const buffers.
Diffstat (limited to '')
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 28 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.h | 5 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 22 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_state.cpp | 2 |
4 files changed, 39 insertions, 18 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 3ba20f978..0f6dec60b 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -197,8 +197,8 @@ void RasterizerOpenGL::SetupShaders(u8* buffer_ptr, GLintptr buffer_offset) { | |||
| 197 | ASSERT_MSG(!gpu.regs.shader_config[0].enable, "VertexA is unsupported!"); | 197 | ASSERT_MSG(!gpu.regs.shader_config[0].enable, "VertexA is unsupported!"); |
| 198 | 198 | ||
| 199 | // Next available bindpoints to use when uploading the const buffers and textures to the GLSL | 199 | // Next available bindpoints to use when uploading the const buffers and textures to the GLSL |
| 200 | // shaders. | 200 | // shaders. The constbuffer bindpoint starts after the shader stage configuration bind points. |
| 201 | u32 current_constbuffer_bindpoint = 0; | 201 | u32 current_constbuffer_bindpoint = uniform_buffers.size(); |
| 202 | u32 current_texture_bindpoint = 0; | 202 | u32 current_texture_bindpoint = 0; |
| 203 | 203 | ||
| 204 | for (unsigned index = 1; index < Maxwell::MaxShaderProgram; ++index) { | 204 | for (unsigned index = 1; index < Maxwell::MaxShaderProgram; ++index) { |
| @@ -608,27 +608,33 @@ u32 RasterizerOpenGL::SetupConstBuffers(Maxwell::ShaderStage stage, GLuint progr | |||
| 608 | 608 | ||
| 609 | boost::optional<VAddr> addr = gpu.memory_manager->GpuToCpuAddress(buffer.address); | 609 | boost::optional<VAddr> addr = gpu.memory_manager->GpuToCpuAddress(buffer.address); |
| 610 | 610 | ||
| 611 | std::vector<u8> data; | 611 | size_t size = 0; |
| 612 | |||
| 612 | if (used_buffer.IsIndirect()) { | 613 | if (used_buffer.IsIndirect()) { |
| 613 | // Buffer is accessed indirectly, so upload the entire thing | 614 | // Buffer is accessed indirectly, so upload the entire thing |
| 614 | data.resize(buffer.size * sizeof(float)); | 615 | size = buffer.size * sizeof(float); |
| 615 | } else { | 616 | } else { |
| 616 | // Buffer is accessed directly, upload just what we use | 617 | // Buffer is accessed directly, upload just what we use |
| 617 | data.resize(used_buffer.GetSize() * sizeof(float)); | 618 | size = used_buffer.GetSize() * sizeof(float); |
| 618 | } | 619 | } |
| 619 | 620 | ||
| 621 | // Align the actual size so it ends up being a multiple of vec4 to meet the OpenGL std140 | ||
| 622 | // UBO alignment requirements. | ||
| 623 | size = Common::AlignUp(size, sizeof(GLvec4)); | ||
| 624 | ASSERT_MSG(size <= MaxConstbufferSize, "Constbuffer too big"); | ||
| 625 | |||
| 626 | std::vector<u8> data(size); | ||
| 620 | Memory::ReadBlock(*addr, data.data(), data.size()); | 627 | Memory::ReadBlock(*addr, data.data(), data.size()); |
| 621 | 628 | ||
| 622 | glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer_draw_state.ssbo); | 629 | glBindBuffer(GL_UNIFORM_BUFFER, buffer_draw_state.ssbo); |
| 623 | glBufferData(GL_SHADER_STORAGE_BUFFER, data.size(), data.data(), GL_DYNAMIC_DRAW); | 630 | glBufferData(GL_UNIFORM_BUFFER, data.size(), data.data(), GL_DYNAMIC_DRAW); |
| 624 | glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); | 631 | glBindBuffer(GL_UNIFORM_BUFFER, 0); |
| 625 | 632 | ||
| 626 | // Now configure the bindpoint of the buffer inside the shader | 633 | // Now configure the bindpoint of the buffer inside the shader |
| 627 | std::string buffer_name = used_buffer.GetName(); | 634 | std::string buffer_name = used_buffer.GetName(); |
| 628 | GLuint index = | 635 | GLuint index = glGetProgramResourceIndex(program, GL_UNIFORM_BLOCK, buffer_name.c_str()); |
| 629 | glGetProgramResourceIndex(program, GL_SHADER_STORAGE_BLOCK, buffer_name.c_str()); | ||
| 630 | if (index != -1) | 636 | if (index != -1) |
| 631 | glShaderStorageBlockBinding(program, index, buffer_draw_state.bindpoint); | 637 | glUniformBlockBinding(program, index, buffer_draw_state.bindpoint); |
| 632 | } | 638 | } |
| 633 | 639 | ||
| 634 | state.Apply(); | 640 | state.Apply(); |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index b7c8cf843..2ab066681 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h | |||
| @@ -54,6 +54,11 @@ public: | |||
| 54 | OGLShader shader; | 54 | OGLShader shader; |
| 55 | }; | 55 | }; |
| 56 | 56 | ||
| 57 | /// Maximum supported size that a constbuffer can have in bytes. | ||
| 58 | static constexpr size_t MaxConstbufferSize = 0x1000; | ||
| 59 | static_assert(MaxConstbufferSize % sizeof(GLvec4) == 0, | ||
| 60 | "The maximum size of a constbuffer must be a multiple of the size of GLvec4"); | ||
| 61 | |||
| 57 | private: | 62 | private: |
| 58 | class SamplerInfo { | 63 | class SamplerInfo { |
| 59 | public: | 64 | public: |
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index 65fed77ef..cd7569e2f 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include "common/assert.h" | 9 | #include "common/assert.h" |
| 10 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 11 | #include "video_core/engines/shader_bytecode.h" | 11 | #include "video_core/engines/shader_bytecode.h" |
| 12 | #include "video_core/renderer_opengl/gl_rasterizer.h" | ||
| 12 | #include "video_core/renderer_opengl/gl_shader_decompiler.h" | 13 | #include "video_core/renderer_opengl/gl_shader_decompiler.h" |
| 13 | 14 | ||
| 14 | namespace GLShader { | 15 | namespace GLShader { |
| @@ -397,7 +398,8 @@ public: | |||
| 397 | /// Generates code representing a uniform (C buffer) register, interpreted as the input type. | 398 | /// Generates code representing a uniform (C buffer) register, interpreted as the input type. |
| 398 | std::string GetUniform(u64 index, u64 offset, GLSLRegister::Type type) { | 399 | std::string GetUniform(u64 index, u64 offset, GLSLRegister::Type type) { |
| 399 | declr_const_buffers[index].MarkAsUsed(index, offset, stage); | 400 | declr_const_buffers[index].MarkAsUsed(index, offset, stage); |
| 400 | std::string value = 'c' + std::to_string(index) + '[' + std::to_string(offset) + ']'; | 401 | std::string value = 'c' + std::to_string(index) + '[' + std::to_string(offset / 4) + "][" + |
| 402 | std::to_string(offset % 4) + ']'; | ||
| 401 | 403 | ||
| 402 | if (type == GLSLRegister::Type::Float) { | 404 | if (type == GLSLRegister::Type::Float) { |
| 403 | return value; | 405 | return value; |
| @@ -411,8 +413,12 @@ public: | |||
| 411 | std::string GetUniformIndirect(u64 index, s64 offset, const Register& index_reg, | 413 | std::string GetUniformIndirect(u64 index, s64 offset, const Register& index_reg, |
| 412 | GLSLRegister::Type type) { | 414 | GLSLRegister::Type type) { |
| 413 | declr_const_buffers[index].MarkAsUsedIndirect(index, stage); | 415 | declr_const_buffers[index].MarkAsUsedIndirect(index, stage); |
| 414 | std::string value = 'c' + std::to_string(index) + "[(floatBitsToInt(" + | 416 | |
| 415 | GetRegister(index_reg, 0) + ") + " + std::to_string(offset) + ") / 4]"; | 417 | std::string final_offset = "((floatBitsToInt(" + GetRegister(index_reg, 0) + ") + " + |
| 418 | std::to_string(offset) + ") / 4)"; | ||
| 419 | |||
| 420 | std::string value = | ||
| 421 | 'c' + std::to_string(index) + '[' + final_offset + " / 4][" + final_offset + " % 4]"; | ||
| 416 | 422 | ||
| 417 | if (type == GLSLRegister::Type::Float) { | 423 | if (type == GLSLRegister::Type::Float) { |
| 418 | return value; | 424 | return value; |
| @@ -454,9 +460,10 @@ public: | |||
| 454 | 460 | ||
| 455 | unsigned const_buffer_layout = 0; | 461 | unsigned const_buffer_layout = 0; |
| 456 | for (const auto& entry : GetConstBuffersDeclarations()) { | 462 | for (const auto& entry : GetConstBuffersDeclarations()) { |
| 457 | declarations.AddLine("layout(std430) buffer " + entry.GetName()); | 463 | declarations.AddLine("layout(std140) uniform " + entry.GetName()); |
| 458 | declarations.AddLine('{'); | 464 | declarations.AddLine('{'); |
| 459 | declarations.AddLine(" float c" + std::to_string(entry.GetIndex()) + "[];"); | 465 | declarations.AddLine(" vec4 c" + std::to_string(entry.GetIndex()) + |
| 466 | "[MAX_CONSTBUFFER_ELEMENTS];"); | ||
| 460 | declarations.AddLine("};"); | 467 | declarations.AddLine("};"); |
| 461 | declarations.AddNewLine(); | 468 | declarations.AddNewLine(); |
| 462 | ++const_buffer_layout; | 469 | ++const_buffer_layout; |
| @@ -1713,7 +1720,10 @@ private: | |||
| 1713 | }; // namespace Decompiler | 1720 | }; // namespace Decompiler |
| 1714 | 1721 | ||
| 1715 | std::string GetCommonDeclarations() { | 1722 | std::string GetCommonDeclarations() { |
| 1716 | return "bool exec_shader();"; | 1723 | std::string declarations = "bool exec_shader();\n"; |
| 1724 | declarations += "#define MAX_CONSTBUFFER_ELEMENTS " + | ||
| 1725 | std::to_string(RasterizerOpenGL::MaxConstbufferSize / (sizeof(GLvec4))); | ||
| 1726 | return declarations; | ||
| 1717 | } | 1727 | } |
| 1718 | 1728 | ||
| 1719 | boost::optional<ProgramResult> DecompileProgram(const ProgramCode& program_code, u32 main_offset, | 1729 | boost::optional<ProgramResult> DecompileProgram(const ProgramCode& program_code, u32 main_offset, |
diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp index 1f1e48425..6e5f9a789 100644 --- a/src/video_core/renderer_opengl/gl_state.cpp +++ b/src/video_core/renderer_opengl/gl_state.cpp | |||
| @@ -223,7 +223,7 @@ void OpenGLState::Apply() const { | |||
| 223 | if (current.enabled != new_state.enabled || current.bindpoint != new_state.bindpoint || | 223 | if (current.enabled != new_state.enabled || current.bindpoint != new_state.bindpoint || |
| 224 | current.ssbo != new_state.ssbo) { | 224 | current.ssbo != new_state.ssbo) { |
| 225 | if (new_state.enabled) { | 225 | if (new_state.enabled) { |
| 226 | glBindBufferBase(GL_SHADER_STORAGE_BUFFER, new_state.bindpoint, new_state.ssbo); | 226 | glBindBufferBase(GL_UNIFORM_BUFFER, new_state.bindpoint, new_state.ssbo); |
| 227 | } | 227 | } |
| 228 | } | 228 | } |
| 229 | } | 229 | } |