diff options
| author | 2020-02-06 21:39:59 -0500 | |
|---|---|---|
| committer | 2020-02-06 21:39:59 -0500 | |
| commit | 09d766d3574b94dbc349ab24359e87e8d08177d9 (patch) | |
| tree | 12bbdd55bfa407e717eafbcb44a945aa76af2fd3 /src | |
| parent | Merge pull request #3366 from bunnei/swkbd-fixes (diff) | |
| parent | gl_rasterizer: Fix instanced draw arrays (diff) | |
| download | yuzu-09d766d3574b94dbc349ab24359e87e8d08177d9.tar.gz yuzu-09d766d3574b94dbc349ab24359e87e8d08177d9.tar.xz yuzu-09d766d3574b94dbc349ab24359e87e8d08177d9.zip | |
Merge pull request #3362 from ReinUsesLisp/fix-instanced
gl_rasterizer: Fix instanced draw arrays
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 127 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.h | 7 |
2 files changed, 28 insertions, 106 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 362942e09..46a7433ea 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -248,9 +248,6 @@ void RasterizerOpenGL::SetupVertexInstances(GLuint vao) { | |||
| 248 | } | 248 | } |
| 249 | 249 | ||
| 250 | GLintptr RasterizerOpenGL::SetupIndexBuffer() { | 250 | GLintptr RasterizerOpenGL::SetupIndexBuffer() { |
| 251 | if (accelerate_draw != AccelDraw::Indexed) { | ||
| 252 | return 0; | ||
| 253 | } | ||
| 254 | MICROPROFILE_SCOPE(OpenGL_Index); | 251 | MICROPROFILE_SCOPE(OpenGL_Index); |
| 255 | const auto& regs = system.GPU().Maxwell3D().regs; | 252 | const auto& regs = system.GPU().Maxwell3D().regs; |
| 256 | const std::size_t size = CalculateIndexBufferSize(); | 253 | const std::size_t size = CalculateIndexBufferSize(); |
| @@ -546,7 +543,8 @@ void RasterizerOpenGL::Clear() { | |||
| 546 | } | 543 | } |
| 547 | } | 544 | } |
| 548 | 545 | ||
| 549 | void RasterizerOpenGL::DrawPrelude() { | 546 | void RasterizerOpenGL::Draw(bool is_indexed, bool is_instanced) { |
| 547 | MICROPROFILE_SCOPE(OpenGL_Drawing); | ||
| 550 | auto& gpu = system.GPU().Maxwell3D(); | 548 | auto& gpu = system.GPU().Maxwell3D(); |
| 551 | 549 | ||
| 552 | SyncRasterizeEnable(state); | 550 | SyncRasterizeEnable(state); |
| @@ -567,9 +565,6 @@ void RasterizerOpenGL::DrawPrelude() { | |||
| 567 | 565 | ||
| 568 | buffer_cache.Acquire(); | 566 | buffer_cache.Acquire(); |
| 569 | 567 | ||
| 570 | // Draw the vertex batch | ||
| 571 | const bool is_indexed = accelerate_draw == AccelDraw::Indexed; | ||
| 572 | |||
| 573 | std::size_t buffer_size = CalculateVertexArraysSize(); | 568 | std::size_t buffer_size = CalculateVertexArraysSize(); |
| 574 | 569 | ||
| 575 | // Add space for index buffer | 570 | // Add space for index buffer |
| @@ -596,7 +591,11 @@ void RasterizerOpenGL::DrawPrelude() { | |||
| 596 | // Upload vertex and index data. | 591 | // Upload vertex and index data. |
| 597 | SetupVertexBuffer(vao); | 592 | SetupVertexBuffer(vao); |
| 598 | SetupVertexInstances(vao); | 593 | SetupVertexInstances(vao); |
| 599 | index_buffer_offset = SetupIndexBuffer(); | 594 | |
| 595 | GLintptr index_buffer_offset; | ||
| 596 | if (is_indexed) { | ||
| 597 | index_buffer_offset = SetupIndexBuffer(); | ||
| 598 | } | ||
| 600 | 599 | ||
| 601 | // Prepare packed bindings. | 600 | // Prepare packed bindings. |
| 602 | bind_ubo_pushbuffer.Setup(); | 601 | bind_ubo_pushbuffer.Setup(); |
| @@ -630,6 +629,7 @@ void RasterizerOpenGL::DrawPrelude() { | |||
| 630 | // As all cached buffers are invalidated, we need to recheck their state. | 629 | // As all cached buffers are invalidated, we need to recheck their state. |
| 631 | gpu.dirty.ResetVertexArrays(); | 630 | gpu.dirty.ResetVertexArrays(); |
| 632 | } | 631 | } |
| 632 | gpu.dirty.memory_general = false; | ||
| 633 | 633 | ||
| 634 | shader_program_manager->ApplyTo(state); | 634 | shader_program_manager->ApplyTo(state); |
| 635 | state.Apply(); | 635 | state.Apply(); |
| @@ -637,106 +637,33 @@ void RasterizerOpenGL::DrawPrelude() { | |||
| 637 | if (texture_cache.TextureBarrier()) { | 637 | if (texture_cache.TextureBarrier()) { |
| 638 | glTextureBarrier(); | 638 | glTextureBarrier(); |
| 639 | } | 639 | } |
| 640 | } | ||
| 641 | |||
| 642 | struct DrawParams { | ||
| 643 | bool is_indexed{}; | ||
| 644 | bool is_instanced{}; | ||
| 645 | GLenum primitive_mode{}; | ||
| 646 | GLint count{}; | ||
| 647 | GLint base_vertex{}; | ||
| 648 | |||
| 649 | // Indexed settings | ||
| 650 | GLenum index_format{}; | ||
| 651 | GLintptr index_buffer_offset{}; | ||
| 652 | |||
| 653 | // Instanced setting | ||
| 654 | GLint num_instances{}; | ||
| 655 | GLint base_instance{}; | ||
| 656 | |||
| 657 | void DispatchDraw() { | ||
| 658 | if (is_indexed) { | ||
| 659 | const auto index_buffer_ptr = reinterpret_cast<const void*>(index_buffer_offset); | ||
| 660 | if (is_instanced) { | ||
| 661 | glDrawElementsInstancedBaseVertexBaseInstance(primitive_mode, count, index_format, | ||
| 662 | index_buffer_ptr, num_instances, | ||
| 663 | base_vertex, base_instance); | ||
| 664 | } else { | ||
| 665 | glDrawElementsBaseVertex(primitive_mode, count, index_format, index_buffer_ptr, | ||
| 666 | base_vertex); | ||
| 667 | } | ||
| 668 | } else { | ||
| 669 | if (is_instanced) { | ||
| 670 | glDrawArraysInstancedBaseInstance(primitive_mode, base_vertex, count, num_instances, | ||
| 671 | base_instance); | ||
| 672 | } else { | ||
| 673 | glDrawArrays(primitive_mode, base_vertex, count); | ||
| 674 | } | ||
| 675 | } | ||
| 676 | } | ||
| 677 | }; | ||
| 678 | |||
| 679 | bool RasterizerOpenGL::DrawBatch(bool is_indexed) { | ||
| 680 | accelerate_draw = is_indexed ? AccelDraw::Indexed : AccelDraw::Arrays; | ||
| 681 | 640 | ||
| 682 | MICROPROFILE_SCOPE(OpenGL_Drawing); | 641 | const GLuint base_instance = static_cast<GLuint>(gpu.regs.vb_base_instance); |
| 683 | 642 | const GLsizei num_instances = | |
| 684 | DrawPrelude(); | 643 | static_cast<GLsizei>(is_instanced ? gpu.mme_draw.instance_count : 1); |
| 685 | 644 | if (is_indexed) { | |
| 686 | auto& maxwell3d = system.GPU().Maxwell3D(); | 645 | const GLenum index_format = MaxwellToGL::IndexFormat(gpu.regs.index_array.format); |
| 687 | const auto& regs = maxwell3d.regs; | 646 | const GLint base_vertex = static_cast<GLint>(gpu.regs.vb_element_base); |
| 688 | const auto current_instance = maxwell3d.state.current_instance; | 647 | const GLsizei num_vertices = static_cast<GLsizei>(gpu.regs.index_array.count); |
| 689 | DrawParams draw_call{}; | 648 | glDrawElementsInstancedBaseVertexBaseInstance( |
| 690 | draw_call.is_indexed = is_indexed; | 649 | primitive_mode, num_vertices, index_format, |
| 691 | draw_call.num_instances = static_cast<GLint>(1); | 650 | reinterpret_cast<const void*>(index_buffer_offset), num_instances, base_vertex, |
| 692 | draw_call.base_instance = static_cast<GLint>(current_instance); | 651 | base_instance); |
| 693 | draw_call.is_instanced = current_instance > 0; | ||
| 694 | draw_call.primitive_mode = MaxwellToGL::PrimitiveTopology(regs.draw.topology); | ||
| 695 | if (draw_call.is_indexed) { | ||
| 696 | draw_call.count = static_cast<GLint>(regs.index_array.count); | ||
| 697 | draw_call.base_vertex = static_cast<GLint>(regs.vb_element_base); | ||
| 698 | draw_call.index_format = MaxwellToGL::IndexFormat(regs.index_array.format); | ||
| 699 | draw_call.index_buffer_offset = index_buffer_offset; | ||
| 700 | } else { | 652 | } else { |
| 701 | draw_call.count = static_cast<GLint>(regs.vertex_buffer.count); | 653 | const GLint base_vertex = static_cast<GLint>(gpu.regs.vertex_buffer.first); |
| 702 | draw_call.base_vertex = static_cast<GLint>(regs.vertex_buffer.first); | 654 | const GLsizei num_vertices = static_cast<GLsizei>(gpu.regs.vertex_buffer.count); |
| 655 | glDrawArraysInstancedBaseInstance(primitive_mode, base_vertex, num_vertices, num_instances, | ||
| 656 | base_instance); | ||
| 703 | } | 657 | } |
| 704 | draw_call.DispatchDraw(); | 658 | } |
| 705 | 659 | ||
| 706 | maxwell3d.dirty.memory_general = false; | 660 | bool RasterizerOpenGL::DrawBatch(bool is_indexed) { |
| 707 | accelerate_draw = AccelDraw::Disabled; | 661 | Draw(is_indexed, false); |
| 708 | return true; | 662 | return true; |
| 709 | } | 663 | } |
| 710 | 664 | ||
| 711 | bool RasterizerOpenGL::DrawMultiBatch(bool is_indexed) { | 665 | bool RasterizerOpenGL::DrawMultiBatch(bool is_indexed) { |
| 712 | accelerate_draw = is_indexed ? AccelDraw::Indexed : AccelDraw::Arrays; | 666 | Draw(is_indexed, true); |
| 713 | |||
| 714 | MICROPROFILE_SCOPE(OpenGL_Drawing); | ||
| 715 | |||
| 716 | DrawPrelude(); | ||
| 717 | |||
| 718 | auto& maxwell3d = system.GPU().Maxwell3D(); | ||
| 719 | const auto& regs = maxwell3d.regs; | ||
| 720 | const auto& draw_setup = maxwell3d.mme_draw; | ||
| 721 | DrawParams draw_call{}; | ||
| 722 | draw_call.is_indexed = is_indexed; | ||
| 723 | draw_call.num_instances = static_cast<GLint>(draw_setup.instance_count); | ||
| 724 | draw_call.base_instance = static_cast<GLint>(regs.vb_base_instance); | ||
| 725 | draw_call.is_instanced = draw_setup.instance_count > 1; | ||
| 726 | draw_call.primitive_mode = MaxwellToGL::PrimitiveTopology(regs.draw.topology); | ||
| 727 | if (draw_call.is_indexed) { | ||
| 728 | draw_call.count = static_cast<GLint>(regs.index_array.count); | ||
| 729 | draw_call.base_vertex = static_cast<GLint>(regs.vb_element_base); | ||
| 730 | draw_call.index_format = MaxwellToGL::IndexFormat(regs.index_array.format); | ||
| 731 | draw_call.index_buffer_offset = index_buffer_offset; | ||
| 732 | } else { | ||
| 733 | draw_call.count = static_cast<GLint>(regs.vertex_buffer.count); | ||
| 734 | draw_call.base_vertex = static_cast<GLint>(regs.vertex_buffer.first); | ||
| 735 | } | ||
| 736 | draw_call.DispatchDraw(); | ||
| 737 | |||
| 738 | maxwell3d.dirty.memory_general = false; | ||
| 739 | accelerate_draw = AccelDraw::Disabled; | ||
| 740 | return true; | 667 | return true; |
| 741 | } | 668 | } |
| 742 | 669 | ||
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index 6a27cf497..0501f3828 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h | |||
| @@ -103,7 +103,7 @@ private: | |||
| 103 | std::size_t size); | 103 | std::size_t size); |
| 104 | 104 | ||
| 105 | /// Syncs all the state, shaders, render targets and textures setting before a draw call. | 105 | /// Syncs all the state, shaders, render targets and textures setting before a draw call. |
| 106 | void DrawPrelude(); | 106 | void Draw(bool is_indexed, bool is_instanced); |
| 107 | 107 | ||
| 108 | /// Configures the current textures to use for the draw command. | 108 | /// Configures the current textures to use for the draw command. |
| 109 | void SetupDrawTextures(std::size_t stage_index, const Shader& shader); | 109 | void SetupDrawTextures(std::size_t stage_index, const Shader& shader); |
| @@ -220,12 +220,7 @@ private: | |||
| 220 | 220 | ||
| 221 | GLintptr SetupIndexBuffer(); | 221 | GLintptr SetupIndexBuffer(); |
| 222 | 222 | ||
| 223 | GLintptr index_buffer_offset; | ||
| 224 | |||
| 225 | void SetupShaders(GLenum primitive_mode); | 223 | void SetupShaders(GLenum primitive_mode); |
| 226 | |||
| 227 | enum class AccelDraw { Disabled, Arrays, Indexed }; | ||
| 228 | AccelDraw accelerate_draw = AccelDraw::Disabled; | ||
| 229 | }; | 224 | }; |
| 230 | 225 | ||
| 231 | } // namespace OpenGL | 226 | } // namespace OpenGL |