diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index b8f071bc0a..e9c15beff9 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp @@ -260,7 +260,7 @@ void Maxwell3D::CallMacroMethod(u32 method, std::size_t num_parameters, const u3 // Execute the current macro. macro_interpreter.Execute(macro_positions[entry], num_parameters, parameters); - if (mme_draw.current_mode != MMMEDrawMode::Undefined) { + if (mme_draw.current_mode != MMEDrawMode::Undefined) { FlushMMEInlineDraw(); } } @@ -423,37 +423,40 @@ void Maxwell3D::CallMethod(const GPU::MethodCall& method_call) { } } +void Maxwell3D::StepInstance(const MMEDrawMode expected_mode, const u32 count) { + if (mme_draw.current_mode == MMEDrawMode::Undefined) { + if (mme_draw.gl_begin_consume) { + mme_draw.current_mode = expected_mode; + mme_draw.current_count = count; + mme_draw.instance_count = 1; + mme_draw.gl_begin_consume = false; + mme_draw.gl_end_count = 0; + } + return; + } else { + if (mme_draw.current_mode == expected_mode && count == mme_draw.current_count && + mme_draw.instance_mode && mme_draw.gl_begin_consume) { + mme_draw.instance_count++; + mme_draw.gl_begin_consume = false; + return; + } else { + FlushMMEInlineDraw(); + } + } + // Tail call in case it needs to retry. + StepInstance(expected_mode, count); +} + void Maxwell3D::CallMethodFromMME(const GPU::MethodCall& method_call) { const u32 method = method_call.method; if (mme_inline[method]) { regs.reg_array[method] = method_call.argument; if (method == MAXWELL3D_REG_INDEX(vertex_buffer.count) || method == MAXWELL3D_REG_INDEX(index_array.count)) { - const MMMEDrawMode expected_mode = method == MAXWELL3D_REG_INDEX(vertex_buffer.count) - ? MMMEDrawMode::Array - : MMMEDrawMode::Indexed; - const u32 count = method_call.argument; - while (true) { - if (mme_draw.current_mode == MMMEDrawMode::Undefined) { - if (mme_draw.gl_begin_consume) { - mme_draw.current_mode = expected_mode; - mme_draw.current_count = count; - mme_draw.instance_count = 1; - mme_draw.gl_begin_consume = false; - mme_draw.gl_end_count = 0; - } - break; - } else { - if (mme_draw.current_mode == expected_mode && count == mme_draw.current_count && - mme_draw.instance_mode && mme_draw.gl_begin_consume) { - mme_draw.instance_count++; - mme_draw.gl_begin_consume = false; - break; - } else { - FlushMMEInlineDraw(); - } - } - } + const MMEDrawMode expected_mode = method == MAXWELL3D_REG_INDEX(vertex_buffer.count) + ? MMEDrawMode::Array + : MMEDrawMode::Indexed; + StepInstance(expected_mode, method_call.argument); } else if (method == MAXWELL3D_REG_INDEX(draw.vertex_begin_gl)) { mme_draw.instance_mode = (regs.draw.instance_next != 0) || (regs.draw.instance_cont != 0); @@ -462,7 +465,7 @@ void Maxwell3D::CallMethodFromMME(const GPU::MethodCall& method_call) { mme_draw.gl_end_count++; } } else { - if (mme_draw.current_mode != MMMEDrawMode::Undefined) { + if (mme_draw.current_mode != MMEDrawMode::Undefined) { FlushMMEInlineDraw(); } CallMethod(method_call); @@ -485,8 +488,10 @@ void Maxwell3D::FlushMMEInlineDraw() { ASSERT_MSG(!regs.draw.instance_next || !regs.draw.instance_cont, "Illegal combination of instancing parameters"); - const bool is_indexed = mme_draw.current_mode == MMMEDrawMode::Indexed; - rasterizer.DrawMultiBatch(is_indexed); + const bool is_indexed = mme_draw.current_mode == MMEDrawMode::Indexed; + if (ShouldExecute()) { + rasterizer.DrawMultiBatch(is_indexed); + } if (debug_context) { debug_context->OnEvent(Tegra::DebugContext::Event::FinishedPrimitiveBatch, nullptr); @@ -501,7 +506,7 @@ void Maxwell3D::FlushMMEInlineDraw() { } else { regs.vertex_buffer.count = 0; } - mme_draw.current_mode = MMMEDrawMode::Undefined; + mme_draw.current_mode = MMEDrawMode::Undefined; mme_draw.current_count = 0; mme_draw.instance_count = 0; mme_draw.instance_mode = false; @@ -657,7 +662,9 @@ void Maxwell3D::DrawArrays() { } const bool is_indexed{regs.index_array.count && !regs.vertex_buffer.count}; - rasterizer.DrawBatch(is_indexed); + if (ShouldExecute()) { + rasterizer.DrawBatch(is_indexed); + } if (debug_context) { debug_context->OnEvent(Tegra::DebugContext::Event::FinishedPrimitiveBatch, nullptr); diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index 8fd3ec85c6..4c97759ed6 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h @@ -1269,14 +1269,14 @@ public: return execute_on; } - enum class MMMEDrawMode : u32 { + enum class MMEDrawMode : u32 { Undefined, Array, Indexed, }; struct MMEDrawState { - MMMEDrawMode current_mode{MMMEDrawMode::Undefined}; + MMEDrawMode current_mode{MMEDrawMode::Undefined}; u32 current_count{}; u32 instance_count{}; bool instance_mode{}; @@ -1369,6 +1369,9 @@ private: /// Handles a write to the VERTEX_END_GL register, triggering a draw. void DrawArrays(); + + // Handles a instance drawcall from MME + void StepInstance(MMEDrawMode expected_mode, u32 count); }; #define ASSERT_REG_POSITION(field_name, position) \ diff --git a/src/video_core/rasterizer_interface.h b/src/video_core/rasterizer_interface.h index deadd70ec3..5b0eca9e2b 100644 --- a/src/video_core/rasterizer_interface.h +++ b/src/video_core/rasterizer_interface.h @@ -31,7 +31,7 @@ public: /// Draw the current batch of vertex arrays virtual bool DrawBatch(bool is_indexed) = 0; - /// Draw the current batch of multiple instasnces of vertex arrays + /// Draw the current batch of multiple instances of vertex arrays virtual bool DrawMultiBatch(bool is_indexed) = 0; /// Clear the current framebuffer diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index a6fe7dd71e..246b892c5e 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -749,13 +749,9 @@ bool RasterizerOpenGL::DrawBatch(bool is_indexed) { MICROPROFILE_SCOPE(OpenGL_Drawing); - auto& maxwell3d = system.GPU().Maxwell3D(); - if (!maxwell3d.ShouldExecute()) { - return false; - } - DrawPrelude(); + auto& maxwell3d = system.GPU().Maxwell3D(); const auto& regs = maxwell3d.regs; const auto current_instance = maxwell3d.state.current_instance; DrawParams draw_call{}; @@ -785,13 +781,9 @@ bool RasterizerOpenGL::DrawMultiBatch(bool is_indexed) { MICROPROFILE_SCOPE(OpenGL_Drawing); - auto& maxwell3d = system.GPU().Maxwell3D(); - if (!maxwell3d.ShouldExecute()) { - return false; - } - DrawPrelude(); + auto& maxwell3d = system.GPU().Maxwell3D(); const auto& regs = maxwell3d.regs; const auto& draw_setup = maxwell3d.mme_draw; DrawParams draw_call{};