diff --git a/src/video_core/command_processor.cpp b/src/video_core/command_processor.cpp index f7e424a34..643b3f187 100644 --- a/src/video_core/command_processor.cpp +++ b/src/video_core/command_processor.cpp @@ -352,10 +352,6 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) { shader_engine->SetupBatch(g_state.vs, regs.vs.main_offset); const bool use_gs = regs.pipeline.use_gs == PipelineRegs::UseGS::Yes; - g_state.geometry_pipeline.Reconfigure(); - g_state.geometry_pipeline.Setup(shader_engine); - if (g_state.geometry_pipeline.NeedIndexInput()) - ASSERT(is_indexed); auto VSUnitLoop = [&](u32 thread_id, auto num_threads) { constexpr bool single_thread = std::is_same_v, decltype(num_threads)>; @@ -436,6 +432,11 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) { } } + g_state.geometry_pipeline.Reconfigure(); + g_state.geometry_pipeline.Setup(shader_engine); + if (g_state.geometry_pipeline.NeedIndexInput()) + ASSERT(is_indexed); + for (unsigned int index = 0; index < regs.pipeline.num_vertices; ++index) { unsigned int vertex = VertexIndex(index); auto& cached_vertex = vs_output[is_indexed ? vertex : index]; diff --git a/src/video_core/primitive_assembly.cpp b/src/video_core/primitive_assembly.cpp index 9c3dd4cab..9ff9d097a 100644 --- a/src/video_core/primitive_assembly.cpp +++ b/src/video_core/primitive_assembly.cpp @@ -15,7 +15,7 @@ PrimitiveAssembler::PrimitiveAssembler(PipelineRegs::TriangleTopolog template void PrimitiveAssembler::SubmitVertex(const VertexType& vtx, - TriangleHandler triangle_handler) { + const TriangleHandler& triangle_handler) { switch (topology) { case PipelineRegs::TriangleTopology::List: case PipelineRegs::TriangleTopology::Shader: diff --git a/src/video_core/primitive_assembly.h b/src/video_core/primitive_assembly.h index 12de8e3b9..2ecbe6742 100644 --- a/src/video_core/primitive_assembly.h +++ b/src/video_core/primitive_assembly.h @@ -27,7 +27,7 @@ struct PrimitiveAssembler { * NOTE: We could specify the triangle handler in the constructor, but this way we can * keep event and handler code next to each other. */ - void SubmitVertex(const VertexType& vtx, TriangleHandler triangle_handler); + void SubmitVertex(const VertexType& vtx, const TriangleHandler& triangle_handler); /** * Invert the vertex order of the next triangle. Called by geometry shader emitter. diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 7e09e4712..9bcd7c103 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -27,7 +27,7 @@ MICROPROFILE_DEFINE(OpenGL_Drawing, "OpenGL", "Drawing", MP_RGB(128, 128, 192)); MICROPROFILE_DEFINE(OpenGL_Blits, "OpenGL", "Blits", MP_RGB(100, 100, 255)); MICROPROFILE_DEFINE(OpenGL_CacheManagement, "OpenGL", "Cache Mgmt", MP_RGB(100, 255, 100)); -RasterizerOpenGL::RasterizerOpenGL() : shader_dirty(true) { +RasterizerOpenGL::RasterizerOpenGL() : shader_dirty(true), vertex_buffer_size(0) { // Clipping plane 0 is always enabled for PICA fixed clip plane z <= 0 state.clip_distance[0] = true; @@ -236,24 +236,24 @@ void RasterizerOpenGL::DrawTriangles() { state.Apply(); glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, - color_surface != nullptr ? color_surface->texture.handle : 0, 0); + color_surface != nullptr ? color_surface->texture.handle : 0, 0); if (depth_surface != nullptr) { if (regs.framebuffer.framebuffer.depth_format == Pica::FramebufferRegs::DepthFormat::D24S8) { // attach both depth and stencil glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, - depth_surface->texture.handle, 0); + depth_surface->texture.handle, 0); } else { // attach depth glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, - depth_surface->texture.handle, 0); + depth_surface->texture.handle, 0); // clear stencil attachment glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0); } } else { // clear both depth and stencil attachment glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, - 0); + 0); } // Sync the viewport @@ -263,6 +263,11 @@ void RasterizerOpenGL::DrawTriangles() { GLsizei viewport_height = (GLsizei)Pica::float24::FromRaw(regs.rasterizer.viewport_size_y).ToFloat32() * 2; + const float res_scale_width = color_surface != nullptr ? color_surface->res_scale_width : + (depth_surface == nullptr ? 1.0f : depth_surface->res_scale_width); + const float res_scale_height = color_surface != nullptr ? color_surface->res_scale_height : + (depth_surface == nullptr ? 1.0f : depth_surface->res_scale_height); + glViewport( (GLint)(rect.left + regs.rasterizer.viewport_corner.x * color_surface->res_scale_width), (GLint)(rect.bottom + regs.rasterizer.viewport_corner.y * color_surface->res_scale_height), @@ -374,16 +379,21 @@ void RasterizerOpenGL::DrawTriangles() { // Sync the uniform data if (uniform_block_data.dirty) { glBufferData(GL_UNIFORM_BUFFER, sizeof(UniformData), &uniform_block_data.data, - GL_STATIC_DRAW); + GL_STATIC_DRAW); uniform_block_data.dirty = false; } state.Apply(); // Draw the vertex batch - glBufferData(GL_ARRAY_BUFFER, vertex_batch.size() * sizeof(HardwareVertex), vertex_batch.data(), - GL_STREAM_DRAW); - glDrawArrays(GL_TRIANGLES, 0, (GLsizei)vertex_batch.size()); + GLsizeiptr target_size = vertex_batch.size() * sizeof(HardwareVertex); + if (vertex_buffer_size < target_size) { + vertex_buffer_size = target_size * 2; + glBufferData(GL_ARRAY_BUFFER, vertex_buffer_size, nullptr, GL_STREAM_DRAW); + } + glBufferSubData(GL_ARRAY_BUFFER, 0, target_size, vertex_batch.data()); + glDrawArrays(GL_TRIANGLES, 0, static_cast(vertex_batch.size())); + vertex_batch.clear(); // Mark framebuffer surfaces as dirty // TODO: Restrict invalidation area to the viewport @@ -396,8 +406,6 @@ void RasterizerOpenGL::DrawTriangles() { res_cache.FlushRegion(depth_surface->addr, depth_surface->size, depth_surface, true); } - vertex_batch.clear(); - // Unbind textures for potential future use as framebuffer attachments for (unsigned texture_index = 0; texture_index < pica_textures.size(); ++texture_index) { state.texture_units[texture_index].texture_2d = 0; diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index 46c62961c..ef94d498a 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h @@ -283,6 +283,7 @@ private: std::array texture_samplers; OGLVertexArray vertex_array; OGLBuffer vertex_buffer; + GLsizeiptr vertex_buffer_size; OGLBuffer uniform_buffer; OGLFramebuffer framebuffer;