diff options
Diffstat (limited to 'src/video_core')
| -rw-r--r-- | src/video_core/engines/maxwell_3d.cpp | 82 | ||||
| -rw-r--r-- | src/video_core/engines/maxwell_3d.h | 10 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 86 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_state.cpp | 22 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_state.h | 37 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_texture_cache.cpp | 6 |
6 files changed, 199 insertions, 44 deletions
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index 7d3a550f8..cfa98f528 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp | |||
| @@ -159,6 +159,88 @@ void Maxwell3D::InitDirtySettings() { | |||
| 159 | sizeof(regs.shader_config[0]) * Regs::MaxShaderProgram / sizeof(u32); | 159 | sizeof(regs.shader_config[0]) * Regs::MaxShaderProgram / sizeof(u32); |
| 160 | set_block(MAXWELL3D_REG_INDEX(shader_config[0]), shader_registers_count, | 160 | set_block(MAXWELL3D_REG_INDEX(shader_config[0]), shader_registers_count, |
| 161 | DIRTY_REGS_POS(shaders)); | 161 | DIRTY_REGS_POS(shaders)); |
| 162 | |||
| 163 | // State | ||
| 164 | |||
| 165 | // Viewport | ||
| 166 | constexpr u32 viewport_dirty_reg = DIRTY_REGS_POS(viewport); | ||
| 167 | constexpr u32 viewport_start = MAXWELL3D_REG_INDEX(viewports); | ||
| 168 | constexpr u32 viewport_size = sizeof(regs.viewports) / sizeof(u32); | ||
| 169 | set_block(viewport_start, viewport_size, viewport_dirty_reg); | ||
| 170 | constexpr u32 view_volume_start = MAXWELL3D_REG_INDEX(view_volume_clip_control); | ||
| 171 | constexpr u32 view_volume_size = sizeof(regs.view_volume_clip_control) / sizeof(u32); | ||
| 172 | set_block(view_volume_start, view_volume_size, viewport_dirty_reg); | ||
| 173 | |||
| 174 | // Viewport transformation | ||
| 175 | constexpr u32 viewport_trans_start = MAXWELL3D_REG_INDEX(viewport_transform); | ||
| 176 | constexpr u32 viewport_trans_size = sizeof(regs.viewport_transform) / sizeof(u32); | ||
| 177 | set_block(viewport_trans_start, viewport_trans_size, DIRTY_REGS_POS(viewport_transform)); | ||
| 178 | |||
| 179 | // Cullmode | ||
| 180 | constexpr u32 cull_mode_start = MAXWELL3D_REG_INDEX(cull); | ||
| 181 | constexpr u32 cull_mode_size = sizeof(regs.cull) / sizeof(u32); | ||
| 182 | set_block(cull_mode_start, cull_mode_size, DIRTY_REGS_POS(cull_mode)); | ||
| 183 | |||
| 184 | // Screen y control | ||
| 185 | dirty_pointers[MAXWELL3D_REG_INDEX(screen_y_control)] = DIRTY_REGS_POS(screen_y_control); | ||
| 186 | |||
| 187 | // Primitive Restart | ||
| 188 | constexpr u32 primitive_restart_start = MAXWELL3D_REG_INDEX(primitive_restart); | ||
| 189 | constexpr u32 primitive_restart_size = sizeof(regs.primitive_restart) / sizeof(u32); | ||
| 190 | set_block(primitive_restart_start, primitive_restart_size, DIRTY_REGS_POS(primitive_restart)); | ||
| 191 | |||
| 192 | // Depth Test | ||
| 193 | constexpr u32 depth_test_dirty_reg = DIRTY_REGS_POS(depth_test); | ||
| 194 | dirty_pointers[MAXWELL3D_REG_INDEX(depth_test_enable)] = depth_test_dirty_reg; | ||
| 195 | dirty_pointers[MAXWELL3D_REG_INDEX(depth_write_enabled)] = depth_test_dirty_reg; | ||
| 196 | dirty_pointers[MAXWELL3D_REG_INDEX(depth_test_func)] = depth_test_dirty_reg; | ||
| 197 | |||
| 198 | // Stencil Test | ||
| 199 | constexpr u32 stencil_test_dirty_reg = DIRTY_REGS_POS(stencil_test); | ||
| 200 | dirty_pointers[MAXWELL3D_REG_INDEX(stencil_enable)] = stencil_test_dirty_reg; | ||
| 201 | dirty_pointers[MAXWELL3D_REG_INDEX(stencil_front_func_func)] = stencil_test_dirty_reg; | ||
| 202 | dirty_pointers[MAXWELL3D_REG_INDEX(stencil_front_func_ref)] = stencil_test_dirty_reg; | ||
| 203 | dirty_pointers[MAXWELL3D_REG_INDEX(stencil_front_func_mask)] = stencil_test_dirty_reg; | ||
| 204 | dirty_pointers[MAXWELL3D_REG_INDEX(stencil_front_op_fail)] = stencil_test_dirty_reg; | ||
| 205 | dirty_pointers[MAXWELL3D_REG_INDEX(stencil_front_op_zfail)] = stencil_test_dirty_reg; | ||
| 206 | dirty_pointers[MAXWELL3D_REG_INDEX(stencil_front_op_zpass)] = stencil_test_dirty_reg; | ||
| 207 | dirty_pointers[MAXWELL3D_REG_INDEX(stencil_front_mask)] = stencil_test_dirty_reg; | ||
| 208 | dirty_pointers[MAXWELL3D_REG_INDEX(stencil_two_side_enable)] = stencil_test_dirty_reg; | ||
| 209 | dirty_pointers[MAXWELL3D_REG_INDEX(stencil_back_func_func)] = stencil_test_dirty_reg; | ||
| 210 | dirty_pointers[MAXWELL3D_REG_INDEX(stencil_back_func_ref)] = stencil_test_dirty_reg; | ||
| 211 | dirty_pointers[MAXWELL3D_REG_INDEX(stencil_back_func_mask)] = stencil_test_dirty_reg; | ||
| 212 | dirty_pointers[MAXWELL3D_REG_INDEX(stencil_back_op_fail)] = stencil_test_dirty_reg; | ||
| 213 | dirty_pointers[MAXWELL3D_REG_INDEX(stencil_back_op_zfail)] = stencil_test_dirty_reg; | ||
| 214 | dirty_pointers[MAXWELL3D_REG_INDEX(stencil_back_op_zpass)] = stencil_test_dirty_reg; | ||
| 215 | dirty_pointers[MAXWELL3D_REG_INDEX(stencil_back_mask)] = stencil_test_dirty_reg; | ||
| 216 | |||
| 217 | // Color Mask | ||
| 218 | constexpr u32 color_mask_dirty_reg = DIRTY_REGS_POS(color_mask); | ||
| 219 | dirty_pointers[MAXWELL3D_REG_INDEX(color_mask_common)] = color_mask_dirty_reg; | ||
| 220 | set_block(MAXWELL3D_REG_INDEX(color_mask), sizeof(regs.color_mask) / sizeof(u32), | ||
| 221 | color_mask_dirty_reg); | ||
| 222 | // Blend State | ||
| 223 | constexpr u32 blend_state_dirty_reg = DIRTY_REGS_POS(blend_state); | ||
| 224 | set_block(MAXWELL3D_REG_INDEX(blend_color), sizeof(regs.blend_color) / sizeof(u32), | ||
| 225 | blend_state_dirty_reg); | ||
| 226 | dirty_pointers[MAXWELL3D_REG_INDEX(independent_blend_enable)] = blend_state_dirty_reg; | ||
| 227 | set_block(MAXWELL3D_REG_INDEX(blend), sizeof(regs.blend) / sizeof(u32), blend_state_dirty_reg); | ||
| 228 | set_block(MAXWELL3D_REG_INDEX(independent_blend), sizeof(regs.independent_blend) / sizeof(u32), | ||
| 229 | blend_state_dirty_reg); | ||
| 230 | |||
| 231 | // Scissor State | ||
| 232 | constexpr u32 scissor_test_dirty_reg = DIRTY_REGS_POS(scissor_test); | ||
| 233 | set_block(MAXWELL3D_REG_INDEX(scissor_test), sizeof(regs.scissor_test) / sizeof(u32), | ||
| 234 | scissor_test_dirty_reg); | ||
| 235 | |||
| 236 | // Polygon Offset | ||
| 237 | constexpr u32 polygon_offset_dirty_reg = DIRTY_REGS_POS(polygon_offset); | ||
| 238 | dirty_pointers[MAXWELL3D_REG_INDEX(polygon_offset_fill_enable)] = polygon_offset_dirty_reg; | ||
| 239 | dirty_pointers[MAXWELL3D_REG_INDEX(polygon_offset_line_enable)] = polygon_offset_dirty_reg; | ||
| 240 | dirty_pointers[MAXWELL3D_REG_INDEX(polygon_offset_point_enable)] = polygon_offset_dirty_reg; | ||
| 241 | dirty_pointers[MAXWELL3D_REG_INDEX(polygon_offset_units)] = polygon_offset_dirty_reg; | ||
| 242 | dirty_pointers[MAXWELL3D_REG_INDEX(polygon_offset_factor)] = polygon_offset_dirty_reg; | ||
| 243 | dirty_pointers[MAXWELL3D_REG_INDEX(polygon_offset_clamp)] = polygon_offset_dirty_reg; | ||
| 162 | } | 244 | } |
| 163 | 245 | ||
| 164 | void Maxwell3D::CallMacroMethod(u32 method, std::vector<u32> parameters) { | 246 | void Maxwell3D::CallMacroMethod(u32 method, std::vector<u32> parameters) { |
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index 318078f36..abc69cc65 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h | |||
| @@ -1148,22 +1148,20 @@ public: | |||
| 1148 | bool shaders; | 1148 | bool shaders; |
| 1149 | // State | 1149 | // State |
| 1150 | bool viewport; | 1150 | bool viewport; |
| 1151 | bool clip_enabled; | ||
| 1152 | bool clip_coefficient; | 1151 | bool clip_coefficient; |
| 1153 | bool cull_mode; | 1152 | bool cull_mode; |
| 1154 | bool primitive_restart; | 1153 | bool primitive_restart; |
| 1155 | bool depth_test; | 1154 | bool depth_test; |
| 1156 | bool stencil_test; | 1155 | bool stencil_test; |
| 1157 | bool blend_state; | 1156 | bool blend_state; |
| 1158 | bool logic_op; | ||
| 1159 | bool fragment_color_clamp; | ||
| 1160 | bool multi_sample; | ||
| 1161 | bool scissor_test; | 1157 | bool scissor_test; |
| 1162 | bool transform_feedback; | 1158 | bool transform_feedback; |
| 1163 | bool point; | ||
| 1164 | bool color_mask; | 1159 | bool color_mask; |
| 1165 | bool polygon_offset; | 1160 | bool polygon_offset; |
| 1166 | bool alpha_test; | 1161 | |
| 1162 | // Complementary | ||
| 1163 | bool viewport_transform; | ||
| 1164 | bool screen_y_control; | ||
| 1167 | 1165 | ||
| 1168 | bool memory_general; | 1166 | bool memory_general; |
| 1169 | }; | 1167 | }; |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index c2b5cbff4..76f0f98eb 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -936,56 +936,53 @@ void RasterizerOpenGL::SyncClipCoef() { | |||
| 936 | } | 936 | } |
| 937 | 937 | ||
| 938 | void RasterizerOpenGL::SyncCullMode() { | 938 | void RasterizerOpenGL::SyncCullMode() { |
| 939 | const auto& regs = system.GPU().Maxwell3D().regs; | 939 | auto& maxwell3d = system.GPU().Maxwell3D(); |
| 940 | 940 | ||
| 941 | state.cull.enabled = regs.cull.enabled != 0; | 941 | const auto& regs = maxwell3d.regs; |
| 942 | 942 | ||
| 943 | if (state.cull.enabled) { | 943 | state.cull.enabled = regs.cull.enabled != 0; |
| 944 | state.cull.front_face = MaxwellToGL::FrontFace(regs.cull.front_face); | 944 | state.cull.front_face = MaxwellToGL::FrontFace(regs.cull.front_face); |
| 945 | state.cull.mode = MaxwellToGL::CullFace(regs.cull.cull_face); | 945 | state.cull.mode = MaxwellToGL::CullFace(regs.cull.cull_face); |
| 946 | 946 | ||
| 947 | const bool flip_triangles{regs.screen_y_control.triangle_rast_flip == 0 || | 947 | const bool flip_triangles{regs.screen_y_control.triangle_rast_flip == 0 || |
| 948 | regs.viewport_transform[0].scale_y < 0.0f}; | 948 | regs.viewport_transform[0].scale_y < 0.0f}; |
| 949 | 949 | ||
| 950 | // If the GPU is configured to flip the rasterized triangles, then we need to flip the | 950 | // If the GPU is configured to flip the rasterized triangles, then we need to flip the |
| 951 | // notion of front and back. Note: We flip the triangles when the value of the register is 0 | 951 | // notion of front and back. Note: We flip the triangles when the value of the register is 0 |
| 952 | // because OpenGL already does it for us. | 952 | // because OpenGL already does it for us. |
| 953 | if (flip_triangles) { | 953 | if (flip_triangles) { |
| 954 | if (state.cull.front_face == GL_CCW) | 954 | if (state.cull.front_face == GL_CCW) |
| 955 | state.cull.front_face = GL_CW; | 955 | state.cull.front_face = GL_CW; |
| 956 | else if (state.cull.front_face == GL_CW) | 956 | else if (state.cull.front_face == GL_CW) |
| 957 | state.cull.front_face = GL_CCW; | 957 | state.cull.front_face = GL_CCW; |
| 958 | } | ||
| 959 | } | 958 | } |
| 960 | } | 959 | } |
| 961 | 960 | ||
| 962 | void RasterizerOpenGL::SyncPrimitiveRestart() { | 961 | void RasterizerOpenGL::SyncPrimitiveRestart() { |
| 963 | const auto& regs = system.GPU().Maxwell3D().regs; | 962 | auto& maxwell3d = system.GPU().Maxwell3D(); |
| 963 | const auto& regs = maxwell3d.regs; | ||
| 964 | 964 | ||
| 965 | state.primitive_restart.enabled = regs.primitive_restart.enabled; | 965 | state.primitive_restart.enabled = regs.primitive_restart.enabled; |
| 966 | state.primitive_restart.index = regs.primitive_restart.index; | 966 | state.primitive_restart.index = regs.primitive_restart.index; |
| 967 | } | 967 | } |
| 968 | 968 | ||
| 969 | void RasterizerOpenGL::SyncDepthTestState() { | 969 | void RasterizerOpenGL::SyncDepthTestState() { |
| 970 | const auto& regs = system.GPU().Maxwell3D().regs; | 970 | auto& maxwell3d = system.GPU().Maxwell3D(); |
| 971 | const auto& regs = maxwell3d.regs; | ||
| 971 | 972 | ||
| 972 | state.depth.test_enabled = regs.depth_test_enable != 0; | 973 | state.depth.test_enabled = regs.depth_test_enable != 0; |
| 973 | state.depth.write_mask = regs.depth_write_enabled ? GL_TRUE : GL_FALSE; | 974 | state.depth.write_mask = regs.depth_write_enabled ? GL_TRUE : GL_FALSE; |
| 974 | |||
| 975 | if (!state.depth.test_enabled) | ||
| 976 | return; | ||
| 977 | |||
| 978 | state.depth.test_func = MaxwellToGL::ComparisonOp(regs.depth_test_func); | 975 | state.depth.test_func = MaxwellToGL::ComparisonOp(regs.depth_test_func); |
| 979 | } | 976 | } |
| 980 | 977 | ||
| 981 | void RasterizerOpenGL::SyncStencilTestState() { | 978 | void RasterizerOpenGL::SyncStencilTestState() { |
| 982 | const auto& regs = system.GPU().Maxwell3D().regs; | 979 | auto& maxwell3d = system.GPU().Maxwell3D(); |
| 983 | state.stencil.test_enabled = regs.stencil_enable != 0; | 980 | if (!maxwell3d.dirty.stencil_test) { |
| 984 | |||
| 985 | if (!regs.stencil_enable) { | ||
| 986 | return; | 981 | return; |
| 987 | } | 982 | } |
| 983 | const auto& regs = maxwell3d.regs; | ||
| 988 | 984 | ||
| 985 | state.stencil.test_enabled = regs.stencil_enable != 0; | ||
| 989 | state.stencil.front.test_func = MaxwellToGL::ComparisonOp(regs.stencil_front_func_func); | 986 | state.stencil.front.test_func = MaxwellToGL::ComparisonOp(regs.stencil_front_func_func); |
| 990 | state.stencil.front.test_ref = regs.stencil_front_func_ref; | 987 | state.stencil.front.test_ref = regs.stencil_front_func_ref; |
| 991 | state.stencil.front.test_mask = regs.stencil_front_func_mask; | 988 | state.stencil.front.test_mask = regs.stencil_front_func_mask; |
| @@ -1010,10 +1007,17 @@ void RasterizerOpenGL::SyncStencilTestState() { | |||
| 1010 | state.stencil.back.action_depth_fail = GL_KEEP; | 1007 | state.stencil.back.action_depth_fail = GL_KEEP; |
| 1011 | state.stencil.back.action_depth_pass = GL_KEEP; | 1008 | state.stencil.back.action_depth_pass = GL_KEEP; |
| 1012 | } | 1009 | } |
| 1010 | state.MarkDirtyStencilState(true); | ||
| 1011 | maxwell3d.dirty.stencil_test = false; | ||
| 1013 | } | 1012 | } |
| 1014 | 1013 | ||
| 1015 | void RasterizerOpenGL::SyncColorMask() { | 1014 | void RasterizerOpenGL::SyncColorMask() { |
| 1016 | const auto& regs = system.GPU().Maxwell3D().regs; | 1015 | auto& maxwell3d = system.GPU().Maxwell3D(); |
| 1016 | if (!maxwell3d.dirty.color_mask) { | ||
| 1017 | return; | ||
| 1018 | } | ||
| 1019 | const auto& regs = maxwell3d.regs; | ||
| 1020 | |||
| 1017 | const std::size_t count = | 1021 | const std::size_t count = |
| 1018 | regs.independent_blend_enable ? Tegra::Engines::Maxwell3D::Regs::NumRenderTargets : 1; | 1022 | regs.independent_blend_enable ? Tegra::Engines::Maxwell3D::Regs::NumRenderTargets : 1; |
| 1019 | for (std::size_t i = 0; i < count; i++) { | 1023 | for (std::size_t i = 0; i < count; i++) { |
| @@ -1024,6 +1028,9 @@ void RasterizerOpenGL::SyncColorMask() { | |||
| 1024 | dest.blue_enabled = (source.B == 0) ? GL_FALSE : GL_TRUE; | 1028 | dest.blue_enabled = (source.B == 0) ? GL_FALSE : GL_TRUE; |
| 1025 | dest.alpha_enabled = (source.A == 0) ? GL_FALSE : GL_TRUE; | 1029 | dest.alpha_enabled = (source.A == 0) ? GL_FALSE : GL_TRUE; |
| 1026 | } | 1030 | } |
| 1031 | |||
| 1032 | state.MarkDirtyColorMask(true); | ||
| 1033 | maxwell3d.dirty.color_mask = false; | ||
| 1027 | } | 1034 | } |
| 1028 | 1035 | ||
| 1029 | void RasterizerOpenGL::SyncMultiSampleState() { | 1036 | void RasterizerOpenGL::SyncMultiSampleState() { |
| @@ -1038,7 +1045,11 @@ void RasterizerOpenGL::SyncFragmentColorClampState() { | |||
| 1038 | } | 1045 | } |
| 1039 | 1046 | ||
| 1040 | void RasterizerOpenGL::SyncBlendState() { | 1047 | void RasterizerOpenGL::SyncBlendState() { |
| 1041 | const auto& regs = system.GPU().Maxwell3D().regs; | 1048 | auto& maxwell3d = system.GPU().Maxwell3D(); |
| 1049 | if (!maxwell3d.dirty.blend_state) { | ||
| 1050 | return; | ||
| 1051 | } | ||
| 1052 | const auto& regs = maxwell3d.regs; | ||
| 1042 | 1053 | ||
| 1043 | state.blend_color.red = regs.blend_color.r; | 1054 | state.blend_color.red = regs.blend_color.r; |
| 1044 | state.blend_color.green = regs.blend_color.g; | 1055 | state.blend_color.green = regs.blend_color.g; |
| @@ -1061,6 +1072,8 @@ void RasterizerOpenGL::SyncBlendState() { | |||
| 1061 | for (std::size_t i = 1; i < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets; i++) { | 1072 | for (std::size_t i = 1; i < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets; i++) { |
| 1062 | state.blend[i].enabled = false; | 1073 | state.blend[i].enabled = false; |
| 1063 | } | 1074 | } |
| 1075 | maxwell3d.dirty.blend_state = false; | ||
| 1076 | state.MarkDirtyBlendState(true); | ||
| 1064 | return; | 1077 | return; |
| 1065 | } | 1078 | } |
| 1066 | 1079 | ||
| @@ -1077,6 +1090,9 @@ void RasterizerOpenGL::SyncBlendState() { | |||
| 1077 | blend.src_a_func = MaxwellToGL::BlendFunc(src.factor_source_a); | 1090 | blend.src_a_func = MaxwellToGL::BlendFunc(src.factor_source_a); |
| 1078 | blend.dst_a_func = MaxwellToGL::BlendFunc(src.factor_dest_a); | 1091 | blend.dst_a_func = MaxwellToGL::BlendFunc(src.factor_dest_a); |
| 1079 | } | 1092 | } |
| 1093 | |||
| 1094 | state.MarkDirtyBlendState(true); | ||
| 1095 | maxwell3d.dirty.blend_state = false; | ||
| 1080 | } | 1096 | } |
| 1081 | 1097 | ||
| 1082 | void RasterizerOpenGL::SyncLogicOpState() { | 1098 | void RasterizerOpenGL::SyncLogicOpState() { |
| @@ -1128,13 +1144,21 @@ void RasterizerOpenGL::SyncPointState() { | |||
| 1128 | } | 1144 | } |
| 1129 | 1145 | ||
| 1130 | void RasterizerOpenGL::SyncPolygonOffset() { | 1146 | void RasterizerOpenGL::SyncPolygonOffset() { |
| 1131 | const auto& regs = system.GPU().Maxwell3D().regs; | 1147 | auto& maxwell3d = system.GPU().Maxwell3D(); |
| 1148 | if (!maxwell3d.dirty.polygon_offset) { | ||
| 1149 | return; | ||
| 1150 | } | ||
| 1151 | const auto& regs = maxwell3d.regs; | ||
| 1152 | |||
| 1132 | state.polygon_offset.fill_enable = regs.polygon_offset_fill_enable != 0; | 1153 | state.polygon_offset.fill_enable = regs.polygon_offset_fill_enable != 0; |
| 1133 | state.polygon_offset.line_enable = regs.polygon_offset_line_enable != 0; | 1154 | state.polygon_offset.line_enable = regs.polygon_offset_line_enable != 0; |
| 1134 | state.polygon_offset.point_enable = regs.polygon_offset_point_enable != 0; | 1155 | state.polygon_offset.point_enable = regs.polygon_offset_point_enable != 0; |
| 1135 | state.polygon_offset.units = regs.polygon_offset_units; | 1156 | state.polygon_offset.units = regs.polygon_offset_units; |
| 1136 | state.polygon_offset.factor = regs.polygon_offset_factor; | 1157 | state.polygon_offset.factor = regs.polygon_offset_factor; |
| 1137 | state.polygon_offset.clamp = regs.polygon_offset_clamp; | 1158 | state.polygon_offset.clamp = regs.polygon_offset_clamp; |
| 1159 | |||
| 1160 | state.MarkDirtyPolygonOffset(true); | ||
| 1161 | maxwell3d.dirty.polygon_offset = false; | ||
| 1138 | } | 1162 | } |
| 1139 | 1163 | ||
| 1140 | void RasterizerOpenGL::SyncAlphaTest() { | 1164 | void RasterizerOpenGL::SyncAlphaTest() { |
diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp index 0eae98afe..cac03dc31 100644 --- a/src/video_core/renderer_opengl/gl_state.cpp +++ b/src/video_core/renderer_opengl/gl_state.cpp | |||
| @@ -526,7 +526,7 @@ void OpenGLState::ApplySamplers() const { | |||
| 526 | } | 526 | } |
| 527 | } | 527 | } |
| 528 | 528 | ||
| 529 | void OpenGLState::Apply() const { | 529 | void OpenGLState::Apply() { |
| 530 | MICROPROFILE_SCOPE(OpenGL_State); | 530 | MICROPROFILE_SCOPE(OpenGL_State); |
| 531 | ApplyFramebufferState(); | 531 | ApplyFramebufferState(); |
| 532 | ApplyVertexArrayState(); | 532 | ApplyVertexArrayState(); |
| @@ -536,19 +536,31 @@ void OpenGLState::Apply() const { | |||
| 536 | ApplyPointSize(); | 536 | ApplyPointSize(); |
| 537 | ApplyFragmentColorClamp(); | 537 | ApplyFragmentColorClamp(); |
| 538 | ApplyMultisample(); | 538 | ApplyMultisample(); |
| 539 | if (dirty.color_mask) { | ||
| 540 | ApplyColorMask(); | ||
| 541 | dirty.color_mask = false; | ||
| 542 | } | ||
| 539 | ApplyDepthClamp(); | 543 | ApplyDepthClamp(); |
| 540 | ApplyColorMask(); | ||
| 541 | ApplyViewport(); | 544 | ApplyViewport(); |
| 542 | ApplyStencilTest(); | 545 | if (dirty.stencil_state) { |
| 546 | ApplyStencilTest(); | ||
| 547 | dirty.stencil_state = false; | ||
| 548 | } | ||
| 543 | ApplySRgb(); | 549 | ApplySRgb(); |
| 544 | ApplyCulling(); | 550 | ApplyCulling(); |
| 545 | ApplyDepth(); | 551 | ApplyDepth(); |
| 546 | ApplyPrimitiveRestart(); | 552 | ApplyPrimitiveRestart(); |
| 547 | ApplyBlending(); | 553 | if (dirty.blend_state) { |
| 554 | ApplyBlending(); | ||
| 555 | dirty.blend_state = false; | ||
| 556 | } | ||
| 548 | ApplyLogicOp(); | 557 | ApplyLogicOp(); |
| 549 | ApplyTextures(); | 558 | ApplyTextures(); |
| 550 | ApplySamplers(); | 559 | ApplySamplers(); |
| 551 | ApplyPolygonOffset(); | 560 | if (dirty.polygon_offset) { |
| 561 | ApplyPolygonOffset(); | ||
| 562 | dirty.polygon_offset = false; | ||
| 563 | } | ||
| 552 | ApplyAlphaTest(); | 564 | ApplyAlphaTest(); |
| 553 | } | 565 | } |
| 554 | 566 | ||
diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h index b0140495d..3d0f6747f 100644 --- a/src/video_core/renderer_opengl/gl_state.h +++ b/src/video_core/renderer_opengl/gl_state.h | |||
| @@ -196,7 +196,7 @@ public: | |||
| 196 | } | 196 | } |
| 197 | 197 | ||
| 198 | /// Apply this state as the current OpenGL state | 198 | /// Apply this state as the current OpenGL state |
| 199 | void Apply() const; | 199 | void Apply(); |
| 200 | 200 | ||
| 201 | void ApplyFramebufferState() const; | 201 | void ApplyFramebufferState() const; |
| 202 | void ApplyVertexArrayState() const; | 202 | void ApplyVertexArrayState() const; |
| @@ -237,11 +237,46 @@ public: | |||
| 237 | /// Viewport does not affects glClearBuffer so emulate viewport using scissor test | 237 | /// Viewport does not affects glClearBuffer so emulate viewport using scissor test |
| 238 | void EmulateViewportWithScissor(); | 238 | void EmulateViewportWithScissor(); |
| 239 | 239 | ||
| 240 | void MarkDirtyBlendState(const bool is_dirty) { | ||
| 241 | dirty.blend_state = is_dirty; | ||
| 242 | } | ||
| 243 | |||
| 244 | void MarkDirtyStencilState(const bool is_dirty) { | ||
| 245 | dirty.stencil_state = is_dirty; | ||
| 246 | } | ||
| 247 | |||
| 248 | void MarkDirtyViewportState(const bool is_dirty) { | ||
| 249 | dirty.viewport_state = is_dirty; | ||
| 250 | } | ||
| 251 | |||
| 252 | void MarkDirtyPolygonOffset(const bool is_dirty) { | ||
| 253 | dirty.polygon_offset = is_dirty; | ||
| 254 | } | ||
| 255 | |||
| 256 | void MarkDirtyColorMask(const bool is_dirty) { | ||
| 257 | dirty.color_mask = is_dirty; | ||
| 258 | } | ||
| 259 | |||
| 260 | void AllDirty() { | ||
| 261 | dirty.blend_state = true; | ||
| 262 | dirty.stencil_state = true; | ||
| 263 | dirty.viewport_state = true; | ||
| 264 | dirty.polygon_offset = true; | ||
| 265 | dirty.color_mask = true; | ||
| 266 | } | ||
| 267 | |||
| 240 | private: | 268 | private: |
| 241 | static OpenGLState cur_state; | 269 | static OpenGLState cur_state; |
| 242 | 270 | ||
| 243 | // Workaround for sRGB problems caused by QT not supporting srgb output | 271 | // Workaround for sRGB problems caused by QT not supporting srgb output |
| 244 | static bool s_rgb_used; | 272 | static bool s_rgb_used; |
| 273 | struct { | ||
| 274 | bool blend_state; | ||
| 275 | bool stencil_state; | ||
| 276 | bool viewport_state; | ||
| 277 | bool polygon_offset; | ||
| 278 | bool color_mask; | ||
| 279 | } dirty{}; | ||
| 245 | }; | 280 | }; |
| 246 | 281 | ||
| 247 | } // namespace OpenGL | 282 | } // 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{}; |