diff options
| author | 2015-11-18 22:20:12 -0500 | |
|---|---|---|
| committer | 2015-11-18 22:20:12 -0500 | |
| commit | ac829f87e0d32c693b333a35be823878a9b7d178 (patch) | |
| tree | f14c20303507dbf6e3606761a077c699cbe26b74 /src | |
| parent | Merge pull request #1239 from wwylele/silent-vec-warning (diff) | |
| parent | FragShader: Use an UBO instead of several individual uniforms (diff) | |
| download | yuzu-ac829f87e0d32c693b333a35be823878a9b7d178.tar.gz yuzu-ac829f87e0d32c693b333a35be823878a9b7d178.tar.xz yuzu-ac829f87e0d32c693b333a35be823878a9b7d178.zip | |
Merge pull request #1237 from Subv/ubos
Shaders: Use UBOs instead of individual uniforms in the generated frag shaders
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 33 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.h | 27 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_gen.cpp | 10 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_state.cpp | 8 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_state.h | 1 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/renderer_opengl.cpp | 1 |
6 files changed, 67 insertions, 13 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index d1def2f3b..9b4bddabd 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -46,14 +46,21 @@ void RasterizerOpenGL::InitObjects() { | |||
| 46 | state.texture_units[i].sampler = texture_samplers[i].sampler.handle; | 46 | state.texture_units[i].sampler = texture_samplers[i].sampler.handle; |
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | // Generate VBO and VAO | 49 | // Generate VBO, VAO and UBO |
| 50 | vertex_buffer.Create(); | 50 | vertex_buffer.Create(); |
| 51 | vertex_array.Create(); | 51 | vertex_array.Create(); |
| 52 | uniform_buffer.Create(); | ||
| 52 | 53 | ||
| 53 | state.draw.vertex_array = vertex_array.handle; | 54 | state.draw.vertex_array = vertex_array.handle; |
| 54 | state.draw.vertex_buffer = vertex_buffer.handle; | 55 | state.draw.vertex_buffer = vertex_buffer.handle; |
| 56 | state.draw.uniform_buffer = uniform_buffer.handle; | ||
| 55 | state.Apply(); | 57 | state.Apply(); |
| 56 | 58 | ||
| 59 | // Bind the UBO to binding point 0 | ||
| 60 | glBindBufferBase(GL_UNIFORM_BUFFER, 0, uniform_buffer.handle); | ||
| 61 | |||
| 62 | uniform_block_data.dirty = true; | ||
| 63 | |||
| 57 | // Set vertex attributes | 64 | // Set vertex attributes |
| 58 | glVertexAttribPointer(GLShader::ATTRIBUTE_POSITION, 4, GL_FLOAT, GL_FALSE, sizeof(HardwareVertex), (GLvoid*)offsetof(HardwareVertex, position)); | 65 | glVertexAttribPointer(GLShader::ATTRIBUTE_POSITION, 4, GL_FLOAT, GL_FALSE, sizeof(HardwareVertex), (GLvoid*)offsetof(HardwareVertex, position)); |
| 59 | glEnableVertexAttribArray(GLShader::ATTRIBUTE_POSITION); | 66 | glEnableVertexAttribArray(GLShader::ATTRIBUTE_POSITION); |
| @@ -148,6 +155,11 @@ void RasterizerOpenGL::DrawTriangles() { | |||
| 148 | state.draw.shader_dirty = false; | 155 | state.draw.shader_dirty = false; |
| 149 | } | 156 | } |
| 150 | 157 | ||
| 158 | if (uniform_block_data.dirty) { | ||
| 159 | glBufferData(GL_UNIFORM_BUFFER, sizeof(UniformData), &uniform_block_data.data, GL_STATIC_DRAW); | ||
| 160 | uniform_block_data.dirty = false; | ||
| 161 | } | ||
| 162 | |||
| 151 | glBufferData(GL_ARRAY_BUFFER, vertex_batch.size() * sizeof(HardwareVertex), vertex_batch.data(), GL_STREAM_DRAW); | 163 | glBufferData(GL_ARRAY_BUFFER, vertex_batch.size() * sizeof(HardwareVertex), vertex_batch.data(), GL_STREAM_DRAW); |
| 152 | glDrawArrays(GL_TRIANGLES, 0, (GLsizei)vertex_batch.size()); | 164 | glDrawArrays(GL_TRIANGLES, 0, (GLsizei)vertex_batch.size()); |
| 153 | 165 | ||
| @@ -485,6 +497,9 @@ void RasterizerOpenGL::SetShader() { | |||
| 485 | glUniform1i(PicaShader::Uniform::Texture2, 2); | 497 | glUniform1i(PicaShader::Uniform::Texture2, 2); |
| 486 | 498 | ||
| 487 | current_shader = shader_cache.emplace(config, std::move(shader)).first->second.get(); | 499 | current_shader = shader_cache.emplace(config, std::move(shader)).first->second.get(); |
| 500 | |||
| 501 | unsigned int block_index = glGetUniformBlockIndex(current_shader->shader.handle, "shader_data"); | ||
| 502 | glUniformBlockBinding(current_shader->shader.handle, block_index, 0); | ||
| 488 | } | 503 | } |
| 489 | 504 | ||
| 490 | // Update uniforms | 505 | // Update uniforms |
| @@ -615,7 +630,10 @@ void RasterizerOpenGL::SyncBlendColor() { | |||
| 615 | 630 | ||
| 616 | void RasterizerOpenGL::SyncAlphaTest() { | 631 | void RasterizerOpenGL::SyncAlphaTest() { |
| 617 | const auto& regs = Pica::g_state.regs; | 632 | const auto& regs = Pica::g_state.regs; |
| 618 | glUniform1i(PicaShader::Uniform::AlphaTestRef, regs.output_merger.alpha_test.ref); | 633 | if (regs.output_merger.alpha_test.ref != uniform_block_data.data.alphatest_ref) { |
| 634 | uniform_block_data.data.alphatest_ref = regs.output_merger.alpha_test.ref; | ||
| 635 | uniform_block_data.dirty = true; | ||
| 636 | } | ||
| 619 | } | 637 | } |
| 620 | 638 | ||
| 621 | void RasterizerOpenGL::SyncLogicOp() { | 639 | void RasterizerOpenGL::SyncLogicOp() { |
| @@ -647,12 +665,18 @@ void RasterizerOpenGL::SyncDepthTest() { | |||
| 647 | 665 | ||
| 648 | void RasterizerOpenGL::SyncCombinerColor() { | 666 | void RasterizerOpenGL::SyncCombinerColor() { |
| 649 | auto combiner_color = PicaToGL::ColorRGBA8(Pica::g_state.regs.tev_combiner_buffer_color.raw); | 667 | auto combiner_color = PicaToGL::ColorRGBA8(Pica::g_state.regs.tev_combiner_buffer_color.raw); |
| 650 | glUniform4fv(PicaShader::Uniform::TevCombinerBufferColor, 1, combiner_color.data()); | 668 | if (combiner_color != uniform_block_data.data.tev_combiner_buffer_color) { |
| 669 | uniform_block_data.data.tev_combiner_buffer_color = combiner_color; | ||
| 670 | uniform_block_data.dirty = true; | ||
| 671 | } | ||
| 651 | } | 672 | } |
| 652 | 673 | ||
| 653 | void RasterizerOpenGL::SyncTevConstColor(int stage_index, const Pica::Regs::TevStageConfig& tev_stage) { | 674 | void RasterizerOpenGL::SyncTevConstColor(int stage_index, const Pica::Regs::TevStageConfig& tev_stage) { |
| 654 | auto const_color = PicaToGL::ColorRGBA8(tev_stage.const_color); | 675 | auto const_color = PicaToGL::ColorRGBA8(tev_stage.const_color); |
| 655 | glUniform4fv(PicaShader::Uniform::TevConstColors + stage_index, 1, const_color.data()); | 676 | if (const_color != uniform_block_data.data.const_color[stage_index]) { |
| 677 | uniform_block_data.data.const_color[stage_index] = const_color; | ||
| 678 | uniform_block_data.dirty = true; | ||
| 679 | } | ||
| 656 | } | 680 | } |
| 657 | 681 | ||
| 658 | void RasterizerOpenGL::SyncDrawState() { | 682 | void RasterizerOpenGL::SyncDrawState() { |
| @@ -683,6 +707,7 @@ void RasterizerOpenGL::SyncDrawState() { | |||
| 683 | } | 707 | } |
| 684 | } | 708 | } |
| 685 | 709 | ||
| 710 | state.draw.uniform_buffer = uniform_buffer.handle; | ||
| 686 | state.Apply(); | 711 | state.Apply(); |
| 687 | } | 712 | } |
| 688 | 713 | ||
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index 872cae7da..071051dbc 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h | |||
| @@ -141,12 +141,9 @@ public: | |||
| 141 | 141 | ||
| 142 | /// Fragment shader uniforms | 142 | /// Fragment shader uniforms |
| 143 | enum Uniform : GLuint { | 143 | enum Uniform : GLuint { |
| 144 | AlphaTestRef = 0, | 144 | Texture0 = 0, |
| 145 | TevConstColors = 1, | 145 | Texture1 = 1, |
| 146 | Texture0 = 7, | 146 | Texture2 = 2, |
| 147 | Texture1 = 8, | ||
| 148 | Texture2 = 9, | ||
| 149 | TevCombinerBufferColor = 10, | ||
| 150 | }; | 147 | }; |
| 151 | }; | 148 | }; |
| 152 | 149 | ||
| @@ -216,6 +213,18 @@ private: | |||
| 216 | GLfloat tex_coord2[2]; | 213 | GLfloat tex_coord2[2]; |
| 217 | }; | 214 | }; |
| 218 | 215 | ||
| 216 | /// Uniform structure for the Uniform Buffer Object, all members must be 16-byte aligned | ||
| 217 | struct UniformData { | ||
| 218 | // A vec4 color for each of the six tev stages | ||
| 219 | std::array<GLfloat, 4> const_color[6]; | ||
| 220 | std::array<GLfloat, 4> tev_combiner_buffer_color; | ||
| 221 | GLint alphatest_ref; | ||
| 222 | INSERT_PADDING_BYTES(12); | ||
| 223 | }; | ||
| 224 | |||
| 225 | static_assert(sizeof(UniformData) == 0x80, "The size of the UniformData structure has changed, update the structure in the shader"); | ||
| 226 | static_assert(sizeof(UniformData) < 16000, "UniformData structure must be less than 16kb as per the OpenGL spec"); | ||
| 227 | |||
| 219 | /// Reconfigure the OpenGL color texture to use the given format and dimensions | 228 | /// Reconfigure the OpenGL color texture to use the given format and dimensions |
| 220 | void ReconfigureColorTexture(TextureInfo& texture, Pica::Regs::ColorFormat format, u32 width, u32 height); | 229 | void ReconfigureColorTexture(TextureInfo& texture, Pica::Regs::ColorFormat format, u32 width, u32 height); |
| 221 | 230 | ||
| @@ -298,7 +307,13 @@ private: | |||
| 298 | std::unordered_map<PicaShaderConfig, std::unique_ptr<PicaShader>> shader_cache; | 307 | std::unordered_map<PicaShaderConfig, std::unique_ptr<PicaShader>> shader_cache; |
| 299 | const PicaShader* current_shader = nullptr; | 308 | const PicaShader* current_shader = nullptr; |
| 300 | 309 | ||
| 310 | struct { | ||
| 311 | UniformData data; | ||
| 312 | bool dirty; | ||
| 313 | } uniform_block_data; | ||
| 314 | |||
| 301 | OGLVertexArray vertex_array; | 315 | OGLVertexArray vertex_array; |
| 302 | OGLBuffer vertex_buffer; | 316 | OGLBuffer vertex_buffer; |
| 317 | OGLBuffer uniform_buffer; | ||
| 303 | OGLFramebuffer framebuffer; | 318 | OGLFramebuffer framebuffer; |
| 304 | }; | 319 | }; |
diff --git a/src/video_core/renderer_opengl/gl_shader_gen.cpp b/src/video_core/renderer_opengl/gl_shader_gen.cpp index d19d15e75..3f1cf7a6f 100644 --- a/src/video_core/renderer_opengl/gl_shader_gen.cpp +++ b/src/video_core/renderer_opengl/gl_shader_gen.cpp | |||
| @@ -329,13 +329,17 @@ in vec4 primary_color; | |||
| 329 | in vec2 texcoord[3]; | 329 | in vec2 texcoord[3]; |
| 330 | 330 | ||
| 331 | out vec4 color; | 331 | out vec4 color; |
| 332 | |||
| 333 | layout (std140) uniform shader_data { | ||
| 334 | vec4 const_color[NUM_TEV_STAGES]; | ||
| 335 | vec4 tev_combiner_buffer_color; | ||
| 336 | int alphatest_ref; | ||
| 337 | }; | ||
| 338 | |||
| 332 | )"; | 339 | )"; |
| 333 | 340 | ||
| 334 | using Uniform = RasterizerOpenGL::PicaShader::Uniform; | 341 | using Uniform = RasterizerOpenGL::PicaShader::Uniform; |
| 335 | out += "layout(location = " + std::to_string((int)Uniform::AlphaTestRef) + ") uniform int alphatest_ref;\n"; | ||
| 336 | out += "layout(location = " + std::to_string((int)Uniform::TevConstColors) + ") uniform vec4 const_color[NUM_TEV_STAGES];\n"; | ||
| 337 | out += "layout(location = " + std::to_string((int)Uniform::Texture0) + ") uniform sampler2D tex[3];\n"; | 342 | out += "layout(location = " + std::to_string((int)Uniform::Texture0) + ") uniform sampler2D tex[3];\n"; |
| 338 | out += "layout(location = " + std::to_string((int)Uniform::TevCombinerBufferColor) + ") uniform vec4 tev_combiner_buffer_color;\n"; | ||
| 339 | 343 | ||
| 340 | out += "void main() {\n"; | 344 | out += "void main() {\n"; |
| 341 | out += "vec4 combiner_buffer = tev_combiner_buffer_color;\n"; | 345 | out += "vec4 combiner_buffer = tev_combiner_buffer_color;\n"; |
diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp index 77b2816cb..c44497fc3 100644 --- a/src/video_core/renderer_opengl/gl_state.cpp +++ b/src/video_core/renderer_opengl/gl_state.cpp | |||
| @@ -180,6 +180,11 @@ void OpenGLState::Apply() { | |||
| 180 | glBindBuffer(GL_ARRAY_BUFFER, draw.vertex_buffer); | 180 | glBindBuffer(GL_ARRAY_BUFFER, draw.vertex_buffer); |
| 181 | } | 181 | } |
| 182 | 182 | ||
| 183 | // Uniform buffer | ||
| 184 | if (draw.uniform_buffer != cur_state.draw.uniform_buffer) { | ||
| 185 | glBindBuffer(GL_UNIFORM_BUFFER, draw.uniform_buffer); | ||
| 186 | } | ||
| 187 | |||
| 183 | // Shader program | 188 | // Shader program |
| 184 | if (draw.shader_program != cur_state.draw.shader_program) { | 189 | if (draw.shader_program != cur_state.draw.shader_program) { |
| 185 | glUseProgram(draw.shader_program); | 190 | glUseProgram(draw.shader_program); |
| @@ -214,6 +219,9 @@ void OpenGLState::ResetBuffer(GLuint id) { | |||
| 214 | if (cur_state.draw.vertex_buffer == id) { | 219 | if (cur_state.draw.vertex_buffer == id) { |
| 215 | cur_state.draw.vertex_buffer = 0; | 220 | cur_state.draw.vertex_buffer = 0; |
| 216 | } | 221 | } |
| 222 | if (cur_state.draw.uniform_buffer == id) { | ||
| 223 | cur_state.draw.uniform_buffer = 0; | ||
| 224 | } | ||
| 217 | } | 225 | } |
| 218 | 226 | ||
| 219 | void OpenGLState::ResetVertexArray(GLuint id) { | 227 | void OpenGLState::ResetVertexArray(GLuint id) { |
diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h index 668b04259..84b3d49bc 100644 --- a/src/video_core/renderer_opengl/gl_state.h +++ b/src/video_core/renderer_opengl/gl_state.h | |||
| @@ -64,6 +64,7 @@ public: | |||
| 64 | GLuint framebuffer; // GL_DRAW_FRAMEBUFFER_BINDING | 64 | GLuint framebuffer; // GL_DRAW_FRAMEBUFFER_BINDING |
| 65 | GLuint vertex_array; // GL_VERTEX_ARRAY_BINDING | 65 | GLuint vertex_array; // GL_VERTEX_ARRAY_BINDING |
| 66 | GLuint vertex_buffer; // GL_ARRAY_BUFFER_BINDING | 66 | GLuint vertex_buffer; // GL_ARRAY_BUFFER_BINDING |
| 67 | GLuint uniform_buffer; // GL_UNIFORM_BUFFER_BINDING | ||
| 67 | GLuint shader_program; // GL_CURRENT_PROGRAM | 68 | GLuint shader_program; // GL_CURRENT_PROGRAM |
| 68 | bool shader_dirty; | 69 | bool shader_dirty; |
| 69 | } draw; | 70 | } draw; |
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index ac0a058db..1420229cc 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp | |||
| @@ -256,6 +256,7 @@ void RendererOpenGL::InitOpenGLObjects() { | |||
| 256 | 256 | ||
| 257 | state.draw.vertex_array = vertex_array_handle; | 257 | state.draw.vertex_array = vertex_array_handle; |
| 258 | state.draw.vertex_buffer = vertex_buffer_handle; | 258 | state.draw.vertex_buffer = vertex_buffer_handle; |
| 259 | state.draw.uniform_buffer = 0; | ||
| 259 | state.Apply(); | 260 | state.Apply(); |
| 260 | 261 | ||
| 261 | // Attach vertex data to VAO | 262 | // Attach vertex data to VAO |