summaryrefslogtreecommitdiff
path: root/src/video_core/renderer_opengl
diff options
context:
space:
mode:
authorGravatar bunnei2019-07-21 00:59:52 -0400
committerGravatar GitHub2019-07-21 00:59:52 -0400
commit27e10e0442dfd347387c6eaf148b27f5cc38bcaf (patch)
treec078fc3f0e62e55fc92a0c8b582666deece0a968 /src/video_core/renderer_opengl
parentUpdate README.md (diff)
parentMaxwell3D: Reorganize and address feedback (diff)
downloadyuzu-27e10e0442dfd347387c6eaf148b27f5cc38bcaf.tar.gz
yuzu-27e10e0442dfd347387c6eaf148b27f5cc38bcaf.tar.xz
yuzu-27e10e0442dfd347387c6eaf148b27f5cc38bcaf.zip
Merge pull request #2735 from FernandoS27/pipeline-rework
Rework Dirty Flags in GPU Pipeline, Optimize CBData and Redo Clearing mechanism
Diffstat (limited to 'src/video_core/renderer_opengl')
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp178
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h6
-rw-r--r--src/video_core/renderer_opengl/gl_shader_cache.cpp2
-rw-r--r--src/video_core/renderer_opengl/gl_state.cpp41
-rw-r--r--src/video_core/renderer_opengl/gl_state.h33
-rw-r--r--src/video_core/renderer_opengl/gl_texture_cache.cpp6
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp7
7 files changed, 233 insertions, 40 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 0bb5c068c..0432a9e10 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -105,6 +105,7 @@ RasterizerOpenGL::RasterizerOpenGL(Core::System& system, Core::Frontend::EmuWind
105 shader_program_manager = std::make_unique<GLShader::ProgramManager>(); 105 shader_program_manager = std::make_unique<GLShader::ProgramManager>();
106 state.draw.shader_program = 0; 106 state.draw.shader_program = 0;
107 state.Apply(); 107 state.Apply();
108 clear_framebuffer.Create();
108 109
109 LOG_DEBUG(Render_OpenGL, "Sync fixed function OpenGL state here"); 110 LOG_DEBUG(Render_OpenGL, "Sync fixed function OpenGL state here");
110 CheckExtensions(); 111 CheckExtensions();
@@ -124,10 +125,10 @@ GLuint RasterizerOpenGL::SetupVertexFormat() {
124 auto& gpu = system.GPU().Maxwell3D(); 125 auto& gpu = system.GPU().Maxwell3D();
125 const auto& regs = gpu.regs; 126 const auto& regs = gpu.regs;
126 127
127 if (!gpu.dirty_flags.vertex_attrib_format) { 128 if (!gpu.dirty.vertex_attrib_format) {
128 return state.draw.vertex_array; 129 return state.draw.vertex_array;
129 } 130 }
130 gpu.dirty_flags.vertex_attrib_format = false; 131 gpu.dirty.vertex_attrib_format = false;
131 132
132 MICROPROFILE_SCOPE(OpenGL_VAO); 133 MICROPROFILE_SCOPE(OpenGL_VAO);
133 134
@@ -181,7 +182,7 @@ GLuint RasterizerOpenGL::SetupVertexFormat() {
181 } 182 }
182 183
183 // Rebinding the VAO invalidates the vertex buffer bindings. 184 // Rebinding the VAO invalidates the vertex buffer bindings.
184 gpu.dirty_flags.vertex_array.set(); 185 gpu.dirty.ResetVertexArrays();
185 186
186 state.draw.vertex_array = vao_entry.handle; 187 state.draw.vertex_array = vao_entry.handle;
187 return vao_entry.handle; 188 return vao_entry.handle;
@@ -189,17 +190,20 @@ GLuint RasterizerOpenGL::SetupVertexFormat() {
189 190
190void RasterizerOpenGL::SetupVertexBuffer(GLuint vao) { 191void RasterizerOpenGL::SetupVertexBuffer(GLuint vao) {
191 auto& gpu = system.GPU().Maxwell3D(); 192 auto& gpu = system.GPU().Maxwell3D();
192 const auto& regs = gpu.regs; 193 if (!gpu.dirty.vertex_array_buffers)
193
194 if (gpu.dirty_flags.vertex_array.none())
195 return; 194 return;
195 gpu.dirty.vertex_array_buffers = false;
196
197 const auto& regs = gpu.regs;
196 198
197 MICROPROFILE_SCOPE(OpenGL_VB); 199 MICROPROFILE_SCOPE(OpenGL_VB);
198 200
199 // Upload all guest vertex arrays sequentially to our buffer 201 // Upload all guest vertex arrays sequentially to our buffer
200 for (u32 index = 0; index < Maxwell::NumVertexArrays; ++index) { 202 for (u32 index = 0; index < Maxwell::NumVertexArrays; ++index) {
201 if (!gpu.dirty_flags.vertex_array[index]) 203 if (!gpu.dirty.vertex_array[index])
202 continue; 204 continue;
205 gpu.dirty.vertex_array[index] = false;
206 gpu.dirty.vertex_instance[index] = false;
203 207
204 const auto& vertex_array = regs.vertex_array[index]; 208 const auto& vertex_array = regs.vertex_array[index];
205 if (!vertex_array.IsEnabled()) 209 if (!vertex_array.IsEnabled())
@@ -224,8 +228,32 @@ void RasterizerOpenGL::SetupVertexBuffer(GLuint vao) {
224 glVertexArrayBindingDivisor(vao, index, 0); 228 glVertexArrayBindingDivisor(vao, index, 0);
225 } 229 }
226 } 230 }
231}
232
233void RasterizerOpenGL::SetupVertexInstances(GLuint vao) {
234 auto& gpu = system.GPU().Maxwell3D();
235
236 if (!gpu.dirty.vertex_instances)
237 return;
238 gpu.dirty.vertex_instances = false;
227 239
228 gpu.dirty_flags.vertex_array.reset(); 240 const auto& regs = gpu.regs;
241 // Upload all guest vertex arrays sequentially to our buffer
242 for (u32 index = 0; index < Maxwell::NumVertexArrays; ++index) {
243 if (!gpu.dirty.vertex_instance[index])
244 continue;
245
246 gpu.dirty.vertex_instance[index] = false;
247
248 if (regs.instanced_arrays.IsInstancingEnabled(index) &&
249 regs.vertex_array[index].divisor != 0) {
250 // Enable vertex buffer instancing with the specified divisor.
251 glVertexArrayBindingDivisor(vao, index, regs.vertex_array[index].divisor);
252 } else {
253 // Disable the vertex buffer instancing.
254 glVertexArrayBindingDivisor(vao, index, 0);
255 }
256 }
229} 257}
230 258
231GLintptr RasterizerOpenGL::SetupIndexBuffer() { 259GLintptr RasterizerOpenGL::SetupIndexBuffer() {
@@ -341,7 +369,7 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) {
341 369
342 SyncClipEnabled(clip_distances); 370 SyncClipEnabled(clip_distances);
343 371
344 gpu.dirty_flags.shaders = false; 372 gpu.dirty.shaders = false;
345} 373}
346 374
347std::size_t RasterizerOpenGL::CalculateVertexArraysSize() const { 375std::size_t RasterizerOpenGL::CalculateVertexArraysSize() const {
@@ -424,13 +452,13 @@ std::pair<bool, bool> RasterizerOpenGL::ConfigureFramebuffers(
424 452
425 const FramebufferConfigState fb_config_state{using_color_fb, using_depth_fb, preserve_contents, 453 const FramebufferConfigState fb_config_state{using_color_fb, using_depth_fb, preserve_contents,
426 single_color_target}; 454 single_color_target};
427 if (fb_config_state == current_framebuffer_config_state && 455 if (fb_config_state == current_framebuffer_config_state && !gpu.dirty.render_settings) {
428 gpu.dirty_flags.color_buffer.none() && !gpu.dirty_flags.zeta_buffer) {
429 // Only skip if the previous ConfigureFramebuffers call was from the same kind (multiple or 456 // Only skip if the previous ConfigureFramebuffers call was from the same kind (multiple or
430 // single color targets). This is done because the guest registers may not change but the 457 // single color targets). This is done because the guest registers may not change but the
431 // host framebuffer may contain different attachments 458 // host framebuffer may contain different attachments
432 return current_depth_stencil_usage; 459 return current_depth_stencil_usage;
433 } 460 }
461 gpu.dirty.render_settings = false;
434 current_framebuffer_config_state = fb_config_state; 462 current_framebuffer_config_state = fb_config_state;
435 463
436 texture_cache.GuardRenderTargets(true); 464 texture_cache.GuardRenderTargets(true);
@@ -519,13 +547,65 @@ std::pair<bool, bool> RasterizerOpenGL::ConfigureFramebuffers(
519 return current_depth_stencil_usage = {static_cast<bool>(depth_surface), fbkey.stencil_enable}; 547 return current_depth_stencil_usage = {static_cast<bool>(depth_surface), fbkey.stencil_enable};
520} 548}
521 549
550void RasterizerOpenGL::ConfigureClearFramebuffer(OpenGLState& current_state, bool using_color_fb,
551 bool using_depth_fb, bool using_stencil_fb) {
552 auto& gpu = system.GPU().Maxwell3D();
553 const auto& regs = gpu.regs;
554
555 texture_cache.GuardRenderTargets(true);
556 View color_surface{};
557 if (using_color_fb) {
558 color_surface = texture_cache.GetColorBufferSurface(regs.clear_buffers.RT, false);
559 }
560 View depth_surface{};
561 if (using_depth_fb || using_stencil_fb) {
562 depth_surface = texture_cache.GetDepthBufferSurface(false);
563 }
564 texture_cache.GuardRenderTargets(false);
565
566 current_state.draw.draw_framebuffer = clear_framebuffer.handle;
567 current_state.ApplyFramebufferState();
568
569 if (color_surface) {
570 color_surface->Attach(GL_COLOR_ATTACHMENT0, GL_DRAW_FRAMEBUFFER);
571 } else {
572 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
573 }
574
575 if (depth_surface) {
576 const auto& params = depth_surface->GetSurfaceParams();
577 switch (params.type) {
578 case VideoCore::Surface::SurfaceType::Depth: {
579 depth_surface->Attach(GL_DEPTH_ATTACHMENT, GL_DRAW_FRAMEBUFFER);
580 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
581 break;
582 }
583 case VideoCore::Surface::SurfaceType::DepthStencil: {
584 depth_surface->Attach(GL_DEPTH_ATTACHMENT, GL_DRAW_FRAMEBUFFER);
585 break;
586 }
587 default: { UNIMPLEMENTED(); }
588 }
589 } else {
590 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0,
591 0);
592 }
593}
594
522void RasterizerOpenGL::Clear() { 595void RasterizerOpenGL::Clear() {
523 const auto& regs = system.GPU().Maxwell3D().regs; 596 const auto& regs = system.GPU().Maxwell3D().regs;
524 bool use_color{}; 597 bool use_color{};
525 bool use_depth{}; 598 bool use_depth{};
526 bool use_stencil{}; 599 bool use_stencil{};
527 600
528 OpenGLState clear_state; 601 OpenGLState prev_state{OpenGLState::GetCurState()};
602 SCOPE_EXIT({
603 prev_state.AllDirty();
604 prev_state.Apply();
605 });
606
607 OpenGLState clear_state{OpenGLState::GetCurState()};
608 clear_state.SetDefaultViewports();
529 if (regs.clear_buffers.R || regs.clear_buffers.G || regs.clear_buffers.B || 609 if (regs.clear_buffers.R || regs.clear_buffers.G || regs.clear_buffers.B ||
530 regs.clear_buffers.A) { 610 regs.clear_buffers.A) {
531 use_color = true; 611 use_color = true;
@@ -545,6 +625,7 @@ void RasterizerOpenGL::Clear() {
545 // true. 625 // true.
546 clear_state.depth.test_enabled = true; 626 clear_state.depth.test_enabled = true;
547 clear_state.depth.test_func = GL_ALWAYS; 627 clear_state.depth.test_func = GL_ALWAYS;
628 clear_state.depth.write_mask = GL_TRUE;
548 } 629 }
549 if (regs.clear_buffers.S) { 630 if (regs.clear_buffers.S) {
550 ASSERT_MSG(regs.zeta_enable != 0, "Tried to clear stencil but buffer is not enabled!"); 631 ASSERT_MSG(regs.zeta_enable != 0, "Tried to clear stencil but buffer is not enabled!");
@@ -581,8 +662,9 @@ void RasterizerOpenGL::Clear() {
581 return; 662 return;
582 } 663 }
583 664
584 const auto [clear_depth, clear_stencil] = ConfigureFramebuffers( 665 ConfigureClearFramebuffer(clear_state, use_color, use_depth, use_stencil);
585 clear_state, use_color, use_depth || use_stencil, false, regs.clear_buffers.RT.Value()); 666
667 SyncViewport(clear_state);
586 if (regs.clear_flags.scissor) { 668 if (regs.clear_flags.scissor) {
587 SyncScissorTest(clear_state); 669 SyncScissorTest(clear_state);
588 } 670 }
@@ -591,21 +673,18 @@ void RasterizerOpenGL::Clear() {
591 clear_state.EmulateViewportWithScissor(); 673 clear_state.EmulateViewportWithScissor();
592 } 674 }
593 675
594 clear_state.ApplyColorMask(); 676 clear_state.AllDirty();
595 clear_state.ApplyDepth(); 677 clear_state.Apply();
596 clear_state.ApplyStencilTest();
597 clear_state.ApplyViewport();
598 clear_state.ApplyFramebufferState();
599 678
600 if (use_color) { 679 if (use_color) {
601 glClearBufferfv(GL_COLOR, regs.clear_buffers.RT, regs.clear_color); 680 glClearBufferfv(GL_COLOR, 0, regs.clear_color);
602 } 681 }
603 682
604 if (clear_depth && clear_stencil) { 683 if (use_depth && use_stencil) {
605 glClearBufferfi(GL_DEPTH_STENCIL, 0, regs.clear_depth, regs.clear_stencil); 684 glClearBufferfi(GL_DEPTH_STENCIL, 0, regs.clear_depth, regs.clear_stencil);
606 } else if (clear_depth) { 685 } else if (use_depth) {
607 glClearBufferfv(GL_DEPTH, 0, &regs.clear_depth); 686 glClearBufferfv(GL_DEPTH, 0, &regs.clear_depth);
608 } else if (clear_stencil) { 687 } else if (use_stencil) {
609 glClearBufferiv(GL_STENCIL, 0, &regs.clear_stencil); 688 glClearBufferiv(GL_STENCIL, 0, &regs.clear_stencil);
610 } 689 }
611} 690}
@@ -661,6 +740,7 @@ void RasterizerOpenGL::DrawArrays() {
661 740
662 // Upload vertex and index data. 741 // Upload vertex and index data.
663 SetupVertexBuffer(vao); 742 SetupVertexBuffer(vao);
743 SetupVertexInstances(vao);
664 const GLintptr index_buffer_offset = SetupIndexBuffer(); 744 const GLintptr index_buffer_offset = SetupIndexBuffer();
665 745
666 // Setup draw parameters. It will automatically choose what glDraw* method to use. 746 // Setup draw parameters. It will automatically choose what glDraw* method to use.
@@ -687,7 +767,7 @@ void RasterizerOpenGL::DrawArrays() {
687 767
688 if (invalidate) { 768 if (invalidate) {
689 // As all cached buffers are invalidated, we need to recheck their state. 769 // As all cached buffers are invalidated, we need to recheck their state.
690 gpu.dirty_flags.vertex_array.set(); 770 gpu.dirty.ResetVertexArrays();
691 } 771 }
692 772
693 shader_program_manager->ApplyTo(state); 773 shader_program_manager->ApplyTo(state);
@@ -700,6 +780,7 @@ void RasterizerOpenGL::DrawArrays() {
700 params.DispatchDraw(); 780 params.DispatchDraw();
701 781
702 accelerate_draw = AccelDraw::Disabled; 782 accelerate_draw = AccelDraw::Disabled;
783 gpu.dirty.memory_general = false;
703} 784}
704 785
705void RasterizerOpenGL::FlushAll() {} 786void RasterizerOpenGL::FlushAll() {}
@@ -907,10 +988,11 @@ void RasterizerOpenGL::SyncClipCoef() {
907} 988}
908 989
909void RasterizerOpenGL::SyncCullMode() { 990void RasterizerOpenGL::SyncCullMode() {
910 const auto& regs = system.GPU().Maxwell3D().regs; 991 auto& maxwell3d = system.GPU().Maxwell3D();
911 992
912 state.cull.enabled = regs.cull.enabled != 0; 993 const auto& regs = maxwell3d.regs;
913 994
995 state.cull.enabled = regs.cull.enabled != 0;
914 if (state.cull.enabled) { 996 if (state.cull.enabled) {
915 state.cull.front_face = MaxwellToGL::FrontFace(regs.cull.front_face); 997 state.cull.front_face = MaxwellToGL::FrontFace(regs.cull.front_face);
916 state.cull.mode = MaxwellToGL::CullFace(regs.cull.cull_face); 998 state.cull.mode = MaxwellToGL::CullFace(regs.cull.cull_face);
@@ -943,16 +1025,21 @@ void RasterizerOpenGL::SyncDepthTestState() {
943 state.depth.test_enabled = regs.depth_test_enable != 0; 1025 state.depth.test_enabled = regs.depth_test_enable != 0;
944 state.depth.write_mask = regs.depth_write_enabled ? GL_TRUE : GL_FALSE; 1026 state.depth.write_mask = regs.depth_write_enabled ? GL_TRUE : GL_FALSE;
945 1027
946 if (!state.depth.test_enabled) 1028 if (!state.depth.test_enabled) {
947 return; 1029 return;
1030 }
948 1031
949 state.depth.test_func = MaxwellToGL::ComparisonOp(regs.depth_test_func); 1032 state.depth.test_func = MaxwellToGL::ComparisonOp(regs.depth_test_func);
950} 1033}
951 1034
952void RasterizerOpenGL::SyncStencilTestState() { 1035void RasterizerOpenGL::SyncStencilTestState() {
953 const auto& regs = system.GPU().Maxwell3D().regs; 1036 auto& maxwell3d = system.GPU().Maxwell3D();
954 state.stencil.test_enabled = regs.stencil_enable != 0; 1037 if (!maxwell3d.dirty.stencil_test) {
1038 return;
1039 }
1040 const auto& regs = maxwell3d.regs;
955 1041
1042 state.stencil.test_enabled = regs.stencil_enable != 0;
956 if (!regs.stencil_enable) { 1043 if (!regs.stencil_enable) {
957 return; 1044 return;
958 } 1045 }
@@ -981,10 +1068,17 @@ void RasterizerOpenGL::SyncStencilTestState() {
981 state.stencil.back.action_depth_fail = GL_KEEP; 1068 state.stencil.back.action_depth_fail = GL_KEEP;
982 state.stencil.back.action_depth_pass = GL_KEEP; 1069 state.stencil.back.action_depth_pass = GL_KEEP;
983 } 1070 }
1071 state.MarkDirtyStencilState();
1072 maxwell3d.dirty.stencil_test = false;
984} 1073}
985 1074
986void RasterizerOpenGL::SyncColorMask() { 1075void RasterizerOpenGL::SyncColorMask() {
987 const auto& regs = system.GPU().Maxwell3D().regs; 1076 auto& maxwell3d = system.GPU().Maxwell3D();
1077 if (!maxwell3d.dirty.color_mask) {
1078 return;
1079 }
1080 const auto& regs = maxwell3d.regs;
1081
988 const std::size_t count = 1082 const std::size_t count =
989 regs.independent_blend_enable ? Tegra::Engines::Maxwell3D::Regs::NumRenderTargets : 1; 1083 regs.independent_blend_enable ? Tegra::Engines::Maxwell3D::Regs::NumRenderTargets : 1;
990 for (std::size_t i = 0; i < count; i++) { 1084 for (std::size_t i = 0; i < count; i++) {
@@ -995,6 +1089,9 @@ void RasterizerOpenGL::SyncColorMask() {
995 dest.blue_enabled = (source.B == 0) ? GL_FALSE : GL_TRUE; 1089 dest.blue_enabled = (source.B == 0) ? GL_FALSE : GL_TRUE;
996 dest.alpha_enabled = (source.A == 0) ? GL_FALSE : GL_TRUE; 1090 dest.alpha_enabled = (source.A == 0) ? GL_FALSE : GL_TRUE;
997 } 1091 }
1092
1093 state.MarkDirtyColorMask();
1094 maxwell3d.dirty.color_mask = false;
998} 1095}
999 1096
1000void RasterizerOpenGL::SyncMultiSampleState() { 1097void RasterizerOpenGL::SyncMultiSampleState() {
@@ -1009,7 +1106,11 @@ void RasterizerOpenGL::SyncFragmentColorClampState() {
1009} 1106}
1010 1107
1011void RasterizerOpenGL::SyncBlendState() { 1108void RasterizerOpenGL::SyncBlendState() {
1012 const auto& regs = system.GPU().Maxwell3D().regs; 1109 auto& maxwell3d = system.GPU().Maxwell3D();
1110 if (!maxwell3d.dirty.blend_state) {
1111 return;
1112 }
1113 const auto& regs = maxwell3d.regs;
1013 1114
1014 state.blend_color.red = regs.blend_color.r; 1115 state.blend_color.red = regs.blend_color.r;
1015 state.blend_color.green = regs.blend_color.g; 1116 state.blend_color.green = regs.blend_color.g;
@@ -1032,6 +1133,8 @@ void RasterizerOpenGL::SyncBlendState() {
1032 for (std::size_t i = 1; i < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets; i++) { 1133 for (std::size_t i = 1; i < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets; i++) {
1033 state.blend[i].enabled = false; 1134 state.blend[i].enabled = false;
1034 } 1135 }
1136 maxwell3d.dirty.blend_state = false;
1137 state.MarkDirtyBlendState();
1035 return; 1138 return;
1036 } 1139 }
1037 1140
@@ -1048,6 +1151,9 @@ void RasterizerOpenGL::SyncBlendState() {
1048 blend.src_a_func = MaxwellToGL::BlendFunc(src.factor_source_a); 1151 blend.src_a_func = MaxwellToGL::BlendFunc(src.factor_source_a);
1049 blend.dst_a_func = MaxwellToGL::BlendFunc(src.factor_dest_a); 1152 blend.dst_a_func = MaxwellToGL::BlendFunc(src.factor_dest_a);
1050 } 1153 }
1154
1155 state.MarkDirtyBlendState();
1156 maxwell3d.dirty.blend_state = false;
1051} 1157}
1052 1158
1053void RasterizerOpenGL::SyncLogicOpState() { 1159void RasterizerOpenGL::SyncLogicOpState() {
@@ -1099,13 +1205,21 @@ void RasterizerOpenGL::SyncPointState() {
1099} 1205}
1100 1206
1101void RasterizerOpenGL::SyncPolygonOffset() { 1207void RasterizerOpenGL::SyncPolygonOffset() {
1102 const auto& regs = system.GPU().Maxwell3D().regs; 1208 auto& maxwell3d = system.GPU().Maxwell3D();
1209 if (!maxwell3d.dirty.polygon_offset) {
1210 return;
1211 }
1212 const auto& regs = maxwell3d.regs;
1213
1103 state.polygon_offset.fill_enable = regs.polygon_offset_fill_enable != 0; 1214 state.polygon_offset.fill_enable = regs.polygon_offset_fill_enable != 0;
1104 state.polygon_offset.line_enable = regs.polygon_offset_line_enable != 0; 1215 state.polygon_offset.line_enable = regs.polygon_offset_line_enable != 0;
1105 state.polygon_offset.point_enable = regs.polygon_offset_point_enable != 0; 1216 state.polygon_offset.point_enable = regs.polygon_offset_point_enable != 0;
1106 state.polygon_offset.units = regs.polygon_offset_units; 1217 state.polygon_offset.units = regs.polygon_offset_units;
1107 state.polygon_offset.factor = regs.polygon_offset_factor; 1218 state.polygon_offset.factor = regs.polygon_offset_factor;
1108 state.polygon_offset.clamp = regs.polygon_offset_clamp; 1219 state.polygon_offset.clamp = regs.polygon_offset_clamp;
1220
1221 state.MarkDirtyPolygonOffset();
1222 maxwell3d.dirty.polygon_offset = false;
1109} 1223}
1110 1224
1111void RasterizerOpenGL::SyncAlphaTest() { 1225void RasterizerOpenGL::SyncAlphaTest() {
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index 40b571d58..ef34d3f54 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -108,6 +108,9 @@ private:
108 OpenGLState& current_state, bool using_color_fb = true, bool using_depth_fb = true, 108 OpenGLState& current_state, bool using_color_fb = true, bool using_depth_fb = true,
109 bool preserve_contents = true, std::optional<std::size_t> single_color_target = {}); 109 bool preserve_contents = true, std::optional<std::size_t> single_color_target = {});
110 110
111 void ConfigureClearFramebuffer(OpenGLState& current_state, bool using_color_fb,
112 bool using_depth_fb, bool using_stencil_fb);
113
111 /// Configures the current constbuffers to use for the draw command. 114 /// Configures the current constbuffers to use for the draw command.
112 void SetupDrawConstBuffers(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage, 115 void SetupDrawConstBuffers(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage,
113 const Shader& shader); 116 const Shader& shader);
@@ -216,6 +219,7 @@ private:
216 GLuint SetupVertexFormat(); 219 GLuint SetupVertexFormat();
217 220
218 void SetupVertexBuffer(GLuint vao); 221 void SetupVertexBuffer(GLuint vao);
222 void SetupVertexInstances(GLuint vao);
219 223
220 GLintptr SetupIndexBuffer(); 224 GLintptr SetupIndexBuffer();
221 225
@@ -226,6 +230,8 @@ private:
226 enum class AccelDraw { Disabled, Arrays, Indexed }; 230 enum class AccelDraw { Disabled, Arrays, Indexed };
227 AccelDraw accelerate_draw = AccelDraw::Disabled; 231 AccelDraw accelerate_draw = AccelDraw::Disabled;
228 232
233 OGLFramebuffer clear_framebuffer;
234
229 using CachedPageMap = boost::icl::interval_map<u64, int>; 235 using CachedPageMap = boost::icl::interval_map<u64, int>;
230 CachedPageMap cached_pages; 236 CachedPageMap cached_pages;
231}; 237};
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp
index 32dd9eae7..456ba0403 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp
@@ -572,7 +572,7 @@ std::unordered_map<u64, UnspecializedShader> ShaderCacheOpenGL::GenerateUnspecia
572} 572}
573 573
574Shader ShaderCacheOpenGL::GetStageProgram(Maxwell::ShaderProgram program) { 574Shader ShaderCacheOpenGL::GetStageProgram(Maxwell::ShaderProgram program) {
575 if (!system.GPU().Maxwell3D().dirty_flags.shaders) { 575 if (!system.GPU().Maxwell3D().dirty.shaders) {
576 return last_shaders[static_cast<std::size_t>(program)]; 576 return last_shaders[static_cast<std::size_t>(program)];
577 } 577 }
578 578
diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp
index 0eae98afe..f4777d0b0 100644
--- a/src/video_core/renderer_opengl/gl_state.cpp
+++ b/src/video_core/renderer_opengl/gl_state.cpp
@@ -165,6 +165,25 @@ OpenGLState::OpenGLState() {
165 alpha_test.ref = 0.0f; 165 alpha_test.ref = 0.0f;
166} 166}
167 167
168void OpenGLState::SetDefaultViewports() {
169 for (auto& item : viewports) {
170 item.x = 0;
171 item.y = 0;
172 item.width = 0;
173 item.height = 0;
174 item.depth_range_near = 0.0f;
175 item.depth_range_far = 1.0f;
176 item.scissor.enabled = false;
177 item.scissor.x = 0;
178 item.scissor.y = 0;
179 item.scissor.width = 0;
180 item.scissor.height = 0;
181 }
182
183 depth_clamp.far_plane = false;
184 depth_clamp.near_plane = false;
185}
186
168void OpenGLState::ApplyDefaultState() { 187void OpenGLState::ApplyDefaultState() {
169 glEnable(GL_BLEND); 188 glEnable(GL_BLEND);
170 glDisable(GL_FRAMEBUFFER_SRGB); 189 glDisable(GL_FRAMEBUFFER_SRGB);
@@ -526,7 +545,7 @@ void OpenGLState::ApplySamplers() const {
526 } 545 }
527} 546}
528 547
529void OpenGLState::Apply() const { 548void OpenGLState::Apply() {
530 MICROPROFILE_SCOPE(OpenGL_State); 549 MICROPROFILE_SCOPE(OpenGL_State);
531 ApplyFramebufferState(); 550 ApplyFramebufferState();
532 ApplyVertexArrayState(); 551 ApplyVertexArrayState();
@@ -536,19 +555,31 @@ void OpenGLState::Apply() const {
536 ApplyPointSize(); 555 ApplyPointSize();
537 ApplyFragmentColorClamp(); 556 ApplyFragmentColorClamp();
538 ApplyMultisample(); 557 ApplyMultisample();
558 if (dirty.color_mask) {
559 ApplyColorMask();
560 dirty.color_mask = false;
561 }
539 ApplyDepthClamp(); 562 ApplyDepthClamp();
540 ApplyColorMask();
541 ApplyViewport(); 563 ApplyViewport();
542 ApplyStencilTest(); 564 if (dirty.stencil_state) {
565 ApplyStencilTest();
566 dirty.stencil_state = false;
567 }
543 ApplySRgb(); 568 ApplySRgb();
544 ApplyCulling(); 569 ApplyCulling();
545 ApplyDepth(); 570 ApplyDepth();
546 ApplyPrimitiveRestart(); 571 ApplyPrimitiveRestart();
547 ApplyBlending(); 572 if (dirty.blend_state) {
573 ApplyBlending();
574 dirty.blend_state = false;
575 }
548 ApplyLogicOp(); 576 ApplyLogicOp();
549 ApplyTextures(); 577 ApplyTextures();
550 ApplySamplers(); 578 ApplySamplers();
551 ApplyPolygonOffset(); 579 if (dirty.polygon_offset) {
580 ApplyPolygonOffset();
581 dirty.polygon_offset = false;
582 }
552 ApplyAlphaTest(); 583 ApplyAlphaTest();
553} 584}
554 585
diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h
index b0140495d..fdf9a8a12 100644
--- a/src/video_core/renderer_opengl/gl_state.h
+++ b/src/video_core/renderer_opengl/gl_state.h
@@ -195,8 +195,9 @@ public:
195 s_rgb_used = false; 195 s_rgb_used = false;
196 } 196 }
197 197
198 void SetDefaultViewports();
198 /// Apply this state as the current OpenGL state 199 /// Apply this state as the current OpenGL state
199 void Apply() const; 200 void Apply();
200 201
201 void ApplyFramebufferState() const; 202 void ApplyFramebufferState() const;
202 void ApplyVertexArrayState() const; 203 void ApplyVertexArrayState() const;
@@ -237,11 +238,41 @@ public:
237 /// Viewport does not affects glClearBuffer so emulate viewport using scissor test 238 /// Viewport does not affects glClearBuffer so emulate viewport using scissor test
238 void EmulateViewportWithScissor(); 239 void EmulateViewportWithScissor();
239 240
241 void MarkDirtyBlendState() {
242 dirty.blend_state = true;
243 }
244
245 void MarkDirtyStencilState() {
246 dirty.stencil_state = true;
247 }
248
249 void MarkDirtyPolygonOffset() {
250 dirty.polygon_offset = true;
251 }
252
253 void MarkDirtyColorMask() {
254 dirty.color_mask = true;
255 }
256
257 void AllDirty() {
258 dirty.blend_state = true;
259 dirty.stencil_state = true;
260 dirty.polygon_offset = true;
261 dirty.color_mask = true;
262 }
263
240private: 264private:
241 static OpenGLState cur_state; 265 static OpenGLState cur_state;
242 266
243 // Workaround for sRGB problems caused by QT not supporting srgb output 267 // Workaround for sRGB problems caused by QT not supporting srgb output
244 static bool s_rgb_used; 268 static bool s_rgb_used;
269 struct {
270 bool blend_state;
271 bool stencil_state;
272 bool viewport_state;
273 bool polygon_offset;
274 bool color_mask;
275 } dirty{};
245}; 276};
246 277
247} // namespace OpenGL 278} // namespace OpenGL
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp
index b1f6bc7c2..8fcd39a69 100644
--- a/src/video_core/renderer_opengl/gl_texture_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp
@@ -485,11 +485,15 @@ void TextureCacheOpenGL::ImageBlit(View& src_view, View& dst_view,
485 const auto& dst_params{dst_view->GetSurfaceParams()}; 485 const auto& dst_params{dst_view->GetSurfaceParams()};
486 486
487 OpenGLState prev_state{OpenGLState::GetCurState()}; 487 OpenGLState prev_state{OpenGLState::GetCurState()};
488 SCOPE_EXIT({ prev_state.Apply(); }); 488 SCOPE_EXIT({
489 prev_state.AllDirty();
490 prev_state.Apply();
491 });
489 492
490 OpenGLState state; 493 OpenGLState state;
491 state.draw.read_framebuffer = src_framebuffer.handle; 494 state.draw.read_framebuffer = src_framebuffer.handle;
492 state.draw.draw_framebuffer = dst_framebuffer.handle; 495 state.draw.draw_framebuffer = dst_framebuffer.handle;
496 state.AllDirty();
493 state.Apply(); 497 state.Apply();
494 498
495 u32 buffers{}; 499 u32 buffers{};
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index 9ecdddb0d..a05cef3b9 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -108,6 +108,7 @@ void RendererOpenGL::SwapBuffers(
108 108
109 // Maintain the rasterizer's state as a priority 109 // Maintain the rasterizer's state as a priority
110 OpenGLState prev_state = OpenGLState::GetCurState(); 110 OpenGLState prev_state = OpenGLState::GetCurState();
111 state.AllDirty();
111 state.Apply(); 112 state.Apply();
112 113
113 if (framebuffer) { 114 if (framebuffer) {
@@ -140,6 +141,7 @@ void RendererOpenGL::SwapBuffers(
140 system.GetPerfStats().BeginSystemFrame(); 141 system.GetPerfStats().BeginSystemFrame();
141 142
142 // Restore the rasterizer state 143 // Restore the rasterizer state
144 prev_state.AllDirty();
143 prev_state.Apply(); 145 prev_state.Apply();
144} 146}
145 147
@@ -206,6 +208,7 @@ void RendererOpenGL::InitOpenGLObjects() {
206 // Link shaders and get variable locations 208 // Link shaders and get variable locations
207 shader.CreateFromSource(vertex_shader, nullptr, fragment_shader); 209 shader.CreateFromSource(vertex_shader, nullptr, fragment_shader);
208 state.draw.shader_program = shader.handle; 210 state.draw.shader_program = shader.handle;
211 state.AllDirty();
209 state.Apply(); 212 state.Apply();
210 uniform_modelview_matrix = glGetUniformLocation(shader.handle, "modelview_matrix"); 213 uniform_modelview_matrix = glGetUniformLocation(shader.handle, "modelview_matrix");
211 uniform_color_texture = glGetUniformLocation(shader.handle, "color_texture"); 214 uniform_color_texture = glGetUniformLocation(shader.handle, "color_texture");
@@ -338,12 +341,14 @@ void RendererOpenGL::DrawScreenTriangles(const ScreenInfo& screen_info, float x,
338 // Workaround brigthness problems in SMO by enabling sRGB in the final output 341 // Workaround brigthness problems in SMO by enabling sRGB in the final output
339 // if it has been used in the frame. Needed because of this bug in QT: QTBUG-50987 342 // if it has been used in the frame. Needed because of this bug in QT: QTBUG-50987
340 state.framebuffer_srgb.enabled = OpenGLState::GetsRGBUsed(); 343 state.framebuffer_srgb.enabled = OpenGLState::GetsRGBUsed();
344 state.AllDirty();
341 state.Apply(); 345 state.Apply();
342 glNamedBufferSubData(vertex_buffer.handle, 0, sizeof(vertices), vertices.data()); 346 glNamedBufferSubData(vertex_buffer.handle, 0, sizeof(vertices), vertices.data());
343 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 347 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
344 // Restore default state 348 // Restore default state
345 state.framebuffer_srgb.enabled = false; 349 state.framebuffer_srgb.enabled = false;
346 state.texture_units[0].texture = 0; 350 state.texture_units[0].texture = 0;
351 state.AllDirty();
347 state.Apply(); 352 state.Apply();
348 // Clear sRGB state for the next frame 353 // Clear sRGB state for the next frame
349 OpenGLState::ClearsRGBUsed(); 354 OpenGLState::ClearsRGBUsed();
@@ -388,6 +393,7 @@ void RendererOpenGL::CaptureScreenshot() {
388 GLuint old_read_fb = state.draw.read_framebuffer; 393 GLuint old_read_fb = state.draw.read_framebuffer;
389 GLuint old_draw_fb = state.draw.draw_framebuffer; 394 GLuint old_draw_fb = state.draw.draw_framebuffer;
390 state.draw.read_framebuffer = state.draw.draw_framebuffer = screenshot_framebuffer.handle; 395 state.draw.read_framebuffer = state.draw.draw_framebuffer = screenshot_framebuffer.handle;
396 state.AllDirty();
391 state.Apply(); 397 state.Apply();
392 398
393 Layout::FramebufferLayout layout{renderer_settings.screenshot_framebuffer_layout}; 399 Layout::FramebufferLayout layout{renderer_settings.screenshot_framebuffer_layout};
@@ -407,6 +413,7 @@ void RendererOpenGL::CaptureScreenshot() {
407 screenshot_framebuffer.Release(); 413 screenshot_framebuffer.Release();
408 state.draw.read_framebuffer = old_read_fb; 414 state.draw.read_framebuffer = old_read_fb;
409 state.draw.draw_framebuffer = old_draw_fb; 415 state.draw.draw_framebuffer = old_draw_fb;
416 state.AllDirty();
410 state.Apply(); 417 state.Apply();
411 glDeleteRenderbuffers(1, &renderbuffer); 418 glDeleteRenderbuffers(1, &renderbuffer);
412 419