diff options
| author | 2020-01-30 02:08:46 -0300 | |
|---|---|---|
| committer | 2020-01-30 02:22:00 -0300 | |
| commit | b69321650e440f28dfc071f5a442901cc21a1139 (patch) | |
| tree | 2f16dd4eab40cc3f8fb389ccc5738d7acdde3c9d | |
| parent | Merge pull request #3350 from ReinUsesLisp/atom (diff) | |
| download | yuzu-b69321650e440f28dfc071f5a442901cc21a1139.tar.gz yuzu-b69321650e440f28dfc071f5a442901cc21a1139.tar.xz yuzu-b69321650e440f28dfc071f5a442901cc21a1139.zip | |
gl_rasterizer: Fix instanced draw arrays
glDrawArrays was being used when the draw had a base instance specified.
This commit removes the draw parameters abstraction and fixes the
mentioned issue.
| -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 c428f06e4..52e5d2005 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -244,9 +244,6 @@ void RasterizerOpenGL::SetupVertexInstances(GLuint vao) { | |||
| 244 | } | 244 | } |
| 245 | 245 | ||
| 246 | GLintptr RasterizerOpenGL::SetupIndexBuffer() { | 246 | GLintptr RasterizerOpenGL::SetupIndexBuffer() { |
| 247 | if (accelerate_draw != AccelDraw::Indexed) { | ||
| 248 | return 0; | ||
| 249 | } | ||
| 250 | MICROPROFILE_SCOPE(OpenGL_Index); | 247 | MICROPROFILE_SCOPE(OpenGL_Index); |
| 251 | const auto& regs = system.GPU().Maxwell3D().regs; | 248 | const auto& regs = system.GPU().Maxwell3D().regs; |
| 252 | const std::size_t size = CalculateIndexBufferSize(); | 249 | const std::size_t size = CalculateIndexBufferSize(); |
| @@ -542,7 +539,8 @@ void RasterizerOpenGL::Clear() { | |||
| 542 | } | 539 | } |
| 543 | } | 540 | } |
| 544 | 541 | ||
| 545 | void RasterizerOpenGL::DrawPrelude() { | 542 | void RasterizerOpenGL::Draw(bool is_indexed, bool is_instanced) { |
| 543 | MICROPROFILE_SCOPE(OpenGL_Drawing); | ||
| 546 | auto& gpu = system.GPU().Maxwell3D(); | 544 | auto& gpu = system.GPU().Maxwell3D(); |
| 547 | 545 | ||
| 548 | SyncRasterizeEnable(state); | 546 | SyncRasterizeEnable(state); |
| @@ -563,9 +561,6 @@ void RasterizerOpenGL::DrawPrelude() { | |||
| 563 | 561 | ||
| 564 | buffer_cache.Acquire(); | 562 | buffer_cache.Acquire(); |
| 565 | 563 | ||
| 566 | // Draw the vertex batch | ||
| 567 | const bool is_indexed = accelerate_draw == AccelDraw::Indexed; | ||
| 568 | |||
| 569 | std::size_t buffer_size = CalculateVertexArraysSize(); | 564 | std::size_t buffer_size = CalculateVertexArraysSize(); |
| 570 | 565 | ||
| 571 | // Add space for index buffer | 566 | // Add space for index buffer |
| @@ -592,7 +587,11 @@ void RasterizerOpenGL::DrawPrelude() { | |||
| 592 | // Upload vertex and index data. | 587 | // Upload vertex and index data. |
| 593 | SetupVertexBuffer(vao); | 588 | SetupVertexBuffer(vao); |
| 594 | SetupVertexInstances(vao); | 589 | SetupVertexInstances(vao); |
| 595 | index_buffer_offset = SetupIndexBuffer(); | 590 | |
| 591 | GLintptr index_buffer_offset; | ||
| 592 | if (is_indexed) { | ||
| 593 | index_buffer_offset = SetupIndexBuffer(); | ||
| 594 | } | ||
| 596 | 595 | ||
| 597 | // Prepare packed bindings. | 596 | // Prepare packed bindings. |
| 598 | bind_ubo_pushbuffer.Setup(); | 597 | bind_ubo_pushbuffer.Setup(); |
| @@ -626,6 +625,7 @@ void RasterizerOpenGL::DrawPrelude() { | |||
| 626 | // As all cached buffers are invalidated, we need to recheck their state. | 625 | // As all cached buffers are invalidated, we need to recheck their state. |
| 627 | gpu.dirty.ResetVertexArrays(); | 626 | gpu.dirty.ResetVertexArrays(); |
| 628 | } | 627 | } |
| 628 | gpu.dirty.memory_general = false; | ||
| 629 | 629 | ||
| 630 | shader_program_manager->ApplyTo(state); | 630 | shader_program_manager->ApplyTo(state); |
| 631 | state.Apply(); | 631 | state.Apply(); |
| @@ -633,106 +633,33 @@ void RasterizerOpenGL::DrawPrelude() { | |||
| 633 | if (texture_cache.TextureBarrier()) { | 633 | if (texture_cache.TextureBarrier()) { |
| 634 | glTextureBarrier(); | 634 | glTextureBarrier(); |
| 635 | } | 635 | } |
| 636 | } | ||
| 637 | |||
| 638 | struct DrawParams { | ||
| 639 | bool is_indexed{}; | ||
| 640 | bool is_instanced{}; | ||
| 641 | GLenum primitive_mode{}; | ||
| 642 | GLint count{}; | ||
| 643 | GLint base_vertex{}; | ||
| 644 | |||
| 645 | // Indexed settings | ||
| 646 | GLenum index_format{}; | ||
| 647 | GLintptr index_buffer_offset{}; | ||
| 648 | |||
| 649 | // Instanced setting | ||
| 650 | GLint num_instances{}; | ||
| 651 | GLint base_instance{}; | ||
| 652 | |||
| 653 | void DispatchDraw() { | ||
| 654 | if (is_indexed) { | ||
| 655 | const auto index_buffer_ptr = reinterpret_cast<const void*>(index_buffer_offset); | ||
| 656 | if (is_instanced) { | ||
| 657 | glDrawElementsInstancedBaseVertexBaseInstance(primitive_mode, count, index_format, | ||
| 658 | index_buffer_ptr, num_instances, | ||
| 659 | base_vertex, base_instance); | ||
| 660 | } else { | ||
| 661 | glDrawElementsBaseVertex(primitive_mode, count, index_format, index_buffer_ptr, | ||
| 662 | base_vertex); | ||
| 663 | } | ||
| 664 | } else { | ||
| 665 | if (is_instanced) { | ||
| 666 | glDrawArraysInstancedBaseInstance(primitive_mode, base_vertex, count, num_instances, | ||
| 667 | base_instance); | ||
| 668 | } else { | ||
| 669 | glDrawArrays(primitive_mode, base_vertex, count); | ||
| 670 | } | ||
| 671 | } | ||
| 672 | } | ||
| 673 | }; | ||
| 674 | |||
| 675 | bool RasterizerOpenGL::DrawBatch(bool is_indexed) { | ||
| 676 | accelerate_draw = is_indexed ? AccelDraw::Indexed : AccelDraw::Arrays; | ||
| 677 | 636 | ||
| 678 | MICROPROFILE_SCOPE(OpenGL_Drawing); | 637 | const GLuint base_instance = static_cast<GLuint>(gpu.regs.vb_base_instance); |
| 679 | 638 | const GLsizei num_instances = | |
| 680 | DrawPrelude(); | 639 | static_cast<GLsizei>(is_instanced ? gpu.mme_draw.instance_count : 1); |
| 681 | 640 | if (is_indexed) { | |
| 682 | auto& maxwell3d = system.GPU().Maxwell3D(); | 641 | const GLenum index_format = MaxwellToGL::IndexFormat(gpu.regs.index_array.format); |
| 683 | const auto& regs = maxwell3d.regs; | 642 | const GLint base_vertex = static_cast<GLint>(gpu.regs.vb_element_base); |
| 684 | const auto current_instance = maxwell3d.state.current_instance; | 643 | const GLsizei num_vertices = static_cast<GLsizei>(gpu.regs.index_array.count); |
| 685 | DrawParams draw_call{}; | 644 | glDrawElementsInstancedBaseVertexBaseInstance( |
| 686 | draw_call.is_indexed = is_indexed; | 645 | primitive_mode, num_vertices, index_format, |
| 687 | draw_call.num_instances = static_cast<GLint>(1); | 646 | reinterpret_cast<const void*>(index_buffer_offset), num_instances, base_vertex, |
| 688 | draw_call.base_instance = static_cast<GLint>(current_instance); | 647 | base_instance); |
| 689 | draw_call.is_instanced = current_instance > 0; | ||
| 690 | draw_call.primitive_mode = MaxwellToGL::PrimitiveTopology(regs.draw.topology); | ||
| 691 | if (draw_call.is_indexed) { | ||
| 692 | draw_call.count = static_cast<GLint>(regs.index_array.count); | ||
| 693 | draw_call.base_vertex = static_cast<GLint>(regs.vb_element_base); | ||
| 694 | draw_call.index_format = MaxwellToGL::IndexFormat(regs.index_array.format); | ||
| 695 | draw_call.index_buffer_offset = index_buffer_offset; | ||
| 696 | } else { | 648 | } else { |
| 697 | draw_call.count = static_cast<GLint>(regs.vertex_buffer.count); | 649 | const GLint base_vertex = static_cast<GLint>(gpu.regs.vertex_buffer.first); |
| 698 | draw_call.base_vertex = static_cast<GLint>(regs.vertex_buffer.first); | 650 | const GLsizei num_vertices = static_cast<GLsizei>(gpu.regs.vertex_buffer.count); |
| 651 | glDrawArraysInstancedBaseInstance(primitive_mode, base_vertex, num_vertices, num_instances, | ||
| 652 | base_instance); | ||
| 699 | } | 653 | } |
| 700 | draw_call.DispatchDraw(); | 654 | } |
| 701 | 655 | ||
| 702 | maxwell3d.dirty.memory_general = false; | 656 | bool RasterizerOpenGL::DrawBatch(bool is_indexed) { |
| 703 | accelerate_draw = AccelDraw::Disabled; | 657 | Draw(is_indexed, false); |
| 704 | return true; | 658 | return true; |
| 705 | } | 659 | } |
| 706 | 660 | ||
| 707 | bool RasterizerOpenGL::DrawMultiBatch(bool is_indexed) { | 661 | bool RasterizerOpenGL::DrawMultiBatch(bool is_indexed) { |
| 708 | accelerate_draw = is_indexed ? AccelDraw::Indexed : AccelDraw::Arrays; | 662 | Draw(is_indexed, true); |
| 709 | |||
| 710 | MICROPROFILE_SCOPE(OpenGL_Drawing); | ||
| 711 | |||
| 712 | DrawPrelude(); | ||
| 713 | |||
| 714 | auto& maxwell3d = system.GPU().Maxwell3D(); | ||
| 715 | const auto& regs = maxwell3d.regs; | ||
| 716 | const auto& draw_setup = maxwell3d.mme_draw; | ||
| 717 | DrawParams draw_call{}; | ||
| 718 | draw_call.is_indexed = is_indexed; | ||
| 719 | draw_call.num_instances = static_cast<GLint>(draw_setup.instance_count); | ||
| 720 | draw_call.base_instance = static_cast<GLint>(regs.vb_base_instance); | ||
| 721 | draw_call.is_instanced = draw_setup.instance_count > 1; | ||
| 722 | draw_call.primitive_mode = MaxwellToGL::PrimitiveTopology(regs.draw.topology); | ||
| 723 | if (draw_call.is_indexed) { | ||
| 724 | draw_call.count = static_cast<GLint>(regs.index_array.count); | ||
| 725 | draw_call.base_vertex = static_cast<GLint>(regs.vb_element_base); | ||
| 726 | draw_call.index_format = MaxwellToGL::IndexFormat(regs.index_array.format); | ||
| 727 | draw_call.index_buffer_offset = index_buffer_offset; | ||
| 728 | } else { | ||
| 729 | draw_call.count = static_cast<GLint>(regs.vertex_buffer.count); | ||
| 730 | draw_call.base_vertex = static_cast<GLint>(regs.vertex_buffer.first); | ||
| 731 | } | ||
| 732 | draw_call.DispatchDraw(); | ||
| 733 | |||
| 734 | maxwell3d.dirty.memory_general = false; | ||
| 735 | accelerate_draw = AccelDraw::Disabled; | ||
| 736 | return true; | 663 | return true; |
| 737 | } | 664 | } |
| 738 | 665 | ||
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 |