diff --git a/src/video_core/rasterizer_interface.h b/src/video_core/rasterizer_interface.h index a37b84b8c..fe0d82255 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 void DrawArrays() = 0; - /// Draw the current batch of vertex arrays + /// Draw the current batch of multiple instasnces of vertex arrays virtual void DrawMultiArrays() = 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 f71a22738..9ca832863 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -49,40 +49,6 @@ MICROPROFILE_DEFINE(OpenGL_Blits, "OpenGL", "Blits", MP_RGB(128, 128, 192)); MICROPROFILE_DEFINE(OpenGL_CacheManagement, "OpenGL", "Cache Mgmt", MP_RGB(100, 255, 100)); MICROPROFILE_DEFINE(OpenGL_PrimitiveAssembly, "OpenGL", "Prim Asmbl", MP_RGB(255, 100, 100)); -struct DrawParameters { - GLenum primitive_mode; - GLsizei count; - GLint current_instance; - bool use_indexed; - - GLint vertex_first; - - GLenum index_format; - GLint base_vertex; - GLintptr index_buffer_offset; - - void DispatchDraw() const { - if (use_indexed) { - const auto index_buffer_ptr = reinterpret_cast(index_buffer_offset); - if (current_instance > 0) { - glDrawElementsInstancedBaseVertexBaseInstance(primitive_mode, count, index_format, - index_buffer_ptr, 1, base_vertex, - current_instance); - } else { - glDrawElementsBaseVertex(primitive_mode, count, index_format, index_buffer_ptr, - base_vertex); - } - } else { - if (current_instance > 0) { - glDrawArraysInstancedBaseInstance(primitive_mode, vertex_first, count, 1, - current_instance); - } else { - glDrawArrays(primitive_mode, vertex_first, count); - } - } - } -}; - static std::size_t GetConstBufferSize(const Tegra::Engines::ConstBufferInfo& buffer, const GLShader::ConstBufferEntry& entry) { if (!entry.IsIndirect()) { @@ -270,29 +236,6 @@ GLintptr RasterizerOpenGL::SetupIndexBuffer() { return offset; } -DrawParameters RasterizerOpenGL::SetupDraw(GLintptr index_buffer_offset) { - const auto& gpu = system.GPU().Maxwell3D(); - const auto& regs = gpu.regs; - const bool is_indexed = accelerate_draw == AccelDraw::Indexed; - - DrawParameters params{}; - params.current_instance = gpu.state.current_instance; - - params.use_indexed = is_indexed; - params.primitive_mode = MaxwellToGL::PrimitiveTopology(regs.draw.topology); - - if (is_indexed) { - params.index_format = MaxwellToGL::IndexFormat(regs.index_array.format); - params.count = regs.index_array.count; - params.index_buffer_offset = index_buffer_offset; - params.base_vertex = static_cast(regs.vb_element_base); - } else { - params.count = regs.vertex_buffer.count; - params.vertex_first = regs.vertex_buffer.first; - } - return params; -} - void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) { MICROPROFILE_SCOPE(OpenGL_Shader); auto& gpu = system.GPU().Maxwell3D(); @@ -784,36 +727,65 @@ void RasterizerOpenGL::DrawPrelude() { } } +struct DrawParams { + bool is_indexed; + bool is_instanced; + GLenum primitive_mode; + GLint count; + GLint base_vertex; + + // Indexed settings + GLenum index_format; + GLintptr index_buffer_offset; + + // Instanced setting + GLint num_instances; + GLint base_instance; + + void DispatchDraw() { + if (is_indexed) { + const auto index_buffer_ptr = reinterpret_cast(index_buffer_offset); + if (is_instanced) { + glDrawElementsInstancedBaseVertexBaseInstance(primitive_mode, count, index_format, + index_buffer_ptr, num_instances, + base_vertex, base_instance); + } else { + glDrawElementsBaseVertex(primitive_mode, count, index_format, index_buffer_ptr, + base_vertex); + } + } else { + if (is_instanced) { + glDrawArraysInstancedBaseInstance(primitive_mode, base_vertex, count, num_instances, + base_instance); + } else { + glDrawArrays(primitive_mode, base_vertex, count); + } + } + } +}; + void RasterizerOpenGL::DrawArrays() { DrawPrelude(); auto& maxwell3d = system.GPU().Maxwell3D(); const auto& regs = maxwell3d.regs; const auto current_instance = maxwell3d.state.current_instance; - const auto primitive_mode = MaxwellToGL::PrimitiveTopology(regs.draw.topology); - if (accelerate_draw == AccelDraw::Indexed) { - const auto index_format = MaxwellToGL::IndexFormat(regs.index_array.format); - const auto count = regs.index_array.count; - const auto base_vertex = static_cast(regs.vb_element_base); - const auto index_buffer_ptr = reinterpret_cast(index_buffer_offset); - if (current_instance > 0) { - glDrawElementsInstancedBaseVertexBaseInstance(primitive_mode, count, index_format, - index_buffer_ptr, 1, base_vertex, - current_instance); - } else { - glDrawElementsBaseVertex(primitive_mode, count, index_format, index_buffer_ptr, - base_vertex); - } + DrawParams draw_call; + draw_call.is_indexed = accelerate_draw == AccelDraw::Indexed; + draw_call.num_instances = static_cast(1); + draw_call.base_instance = static_cast(current_instance); + draw_call.is_instanced = current_instance > 0; + draw_call.primitive_mode = MaxwellToGL::PrimitiveTopology(regs.draw.topology); + if (draw_call.is_indexed) { + draw_call.count = static_cast(regs.index_array.count); + draw_call.base_vertex = static_cast(regs.vb_element_base); + draw_call.index_format = MaxwellToGL::IndexFormat(regs.index_array.format); + draw_call.index_buffer_offset = index_buffer_offset; } else { - const auto count = regs.vertex_buffer.count; - const auto vertex_first = regs.vertex_buffer.first; - if (current_instance > 0) { - glDrawArraysInstancedBaseInstance(primitive_mode, vertex_first, count, 1, - current_instance); - } else { - glDrawArrays(primitive_mode, vertex_first, count); - } + draw_call.count = static_cast(regs.vertex_buffer.count); + draw_call.base_vertex = static_cast(regs.vertex_buffer.first); } + draw_call.DispatchDraw(); accelerate_draw = AccelDraw::Disabled; maxwell3d.dirty.memory_general = false; @@ -825,32 +797,23 @@ void RasterizerOpenGL::DrawMultiArrays() { auto& maxwell3d = system.GPU().Maxwell3D(); const auto& regs = maxwell3d.regs; const auto& draw_setup = maxwell3d.mme_draw; - const auto num_instances = draw_setup.instance_count; - const auto base_instance = static_cast(regs.vb_base_instance); - const auto primitive_mode = MaxwellToGL::PrimitiveTopology(regs.draw.topology); - if (draw_setup.current_mode == Tegra::Engines::Maxwell3D::MMMEDrawMode::Indexed) { - const auto index_format = MaxwellToGL::IndexFormat(regs.index_array.format); - const auto count = regs.index_array.count; - const auto base_vertex = static_cast(regs.vb_element_base); - const auto index_buffer_ptr = reinterpret_cast(index_buffer_offset); - if (num_instances > 1) { - glDrawElementsInstancedBaseVertexBaseInstance(primitive_mode, count, index_format, - index_buffer_ptr, num_instances, - base_vertex, base_instance); - } else { - glDrawElementsBaseVertex(primitive_mode, count, index_format, index_buffer_ptr, - base_vertex); - } + DrawParams draw_call; + draw_call.is_indexed = + draw_setup.current_mode == Tegra::Engines::Maxwell3D::MMMEDrawMode::Indexed; + draw_call.num_instances = static_cast(draw_setup.instance_count); + draw_call.base_instance = static_cast(regs.vb_base_instance); + draw_call.is_instanced = draw_setup.instance_count > 1; + draw_call.primitive_mode = MaxwellToGL::PrimitiveTopology(regs.draw.topology); + if (draw_call.is_indexed) { + draw_call.count = static_cast(regs.index_array.count); + draw_call.base_vertex = static_cast(regs.vb_element_base); + draw_call.index_format = MaxwellToGL::IndexFormat(regs.index_array.format); + draw_call.index_buffer_offset = index_buffer_offset; } else { - const auto count = regs.vertex_buffer.count; - const auto vertex_first = regs.vertex_buffer.first; - if (num_instances > 1) { - glDrawArraysInstancedBaseInstance(primitive_mode, vertex_first, count, num_instances, - base_instance); - } else { - glDrawArrays(primitive_mode, vertex_first, count); - } + draw_call.count = static_cast(regs.vertex_buffer.count); + draw_call.base_vertex = static_cast(regs.vertex_buffer.first); } + draw_call.DispatchDraw(); accelerate_draw = AccelDraw::Disabled; maxwell3d.dirty.memory_general = false; diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index 63a914ff9..b4e21b9de 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h @@ -138,6 +138,7 @@ private: void SetupGlobalMemory(const GLShader::GlobalMemoryEntry& entry, GPUVAddr gpu_addr, std::size_t size); + /// Syncs all the state, shaders, render targets and textures setting before a draw call. void DrawPrelude(); /// Configures the current textures to use for the draw command. Returns shaders texture buffer @@ -254,8 +255,6 @@ private: GLintptr SetupIndexBuffer(); - DrawParameters SetupDraw(GLintptr index_buffer_offset); - GLintptr index_buffer_offset; void SetupShaders(GLenum primitive_mode);