summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/video_core/engines/maxwell_3d.h12
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp44
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h29
-rw-r--r--src/video_core/renderer_opengl/gl_state.cpp29
-rw-r--r--src/video_core/renderer_opengl/gl_state.h9
5 files changed, 95 insertions, 28 deletions
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h
index eff6abd55..4f137e693 100644
--- a/src/video_core/engines/maxwell_3d.h
+++ b/src/video_core/engines/maxwell_3d.h
@@ -631,7 +631,16 @@ public:
631 } 631 }
632 } zeta; 632 } zeta;
633 633
634 INSERT_PADDING_WORDS(0x5B); 634 INSERT_PADDING_WORDS(0x41);
635
636 union {
637 BitField<0, 4, u32> stencil;
638 BitField<4, 4, u32> unknown;
639 BitField<8, 4, u32> scissor;
640 BitField<12, 4, u32> viewport;
641 } clear_flags;
642
643 INSERT_PADDING_WORDS(0x19);
635 644
636 std::array<VertexAttribute, NumVertexAttributes> vertex_attrib_format; 645 std::array<VertexAttribute, NumVertexAttributes> vertex_attrib_format;
637 646
@@ -1134,6 +1143,7 @@ ASSERT_REG_POSITION(stencil_back_func_mask, 0x3D7);
1134ASSERT_REG_POSITION(color_mask_common, 0x3E4); 1143ASSERT_REG_POSITION(color_mask_common, 0x3E4);
1135ASSERT_REG_POSITION(rt_separate_frag_data, 0x3EB); 1144ASSERT_REG_POSITION(rt_separate_frag_data, 0x3EB);
1136ASSERT_REG_POSITION(zeta, 0x3F8); 1145ASSERT_REG_POSITION(zeta, 0x3F8);
1146ASSERT_REG_POSITION(clear_flags, 0x43E);
1137ASSERT_REG_POSITION(vertex_attrib_format, 0x458); 1147ASSERT_REG_POSITION(vertex_attrib_format, 0x458);
1138ASSERT_REG_POSITION(rt_control, 0x487); 1148ASSERT_REG_POSITION(rt_control, 0x487);
1139ASSERT_REG_POSITION(zeta_width, 0x48a); 1149ASSERT_REG_POSITION(zeta_width, 0x48a);
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index ae6aaee4c..714330e80 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -542,6 +542,30 @@ void RasterizerOpenGL::Clear() {
542 ASSERT_MSG(regs.zeta_enable != 0, "Tried to clear stencil but buffer is not enabled!"); 542 ASSERT_MSG(regs.zeta_enable != 0, "Tried to clear stencil but buffer is not enabled!");
543 use_stencil = true; 543 use_stencil = true;
544 clear_state.stencil.test_enabled = true; 544 clear_state.stencil.test_enabled = true;
545 if (regs.clear_flags.stencil) {
546 // Stencil affects the clear so fill it with the used masks
547 clear_state.stencil.front.test_func = GL_ALWAYS;
548 clear_state.stencil.front.test_mask = regs.stencil_front_func_mask;
549 clear_state.stencil.front.action_stencil_fail = GL_KEEP;
550 clear_state.stencil.front.action_depth_fail = GL_KEEP;
551 clear_state.stencil.front.action_depth_pass = GL_KEEP;
552 clear_state.stencil.front.write_mask = regs.stencil_front_mask;
553 if (regs.stencil_two_side_enable) {
554 clear_state.stencil.back.test_func = GL_ALWAYS;
555 clear_state.stencil.back.test_mask = regs.stencil_back_func_mask;
556 clear_state.stencil.back.action_stencil_fail = GL_KEEP;
557 clear_state.stencil.back.action_depth_fail = GL_KEEP;
558 clear_state.stencil.back.action_depth_pass = GL_KEEP;
559 clear_state.stencil.back.write_mask = regs.stencil_back_mask;
560 } else {
561 clear_state.stencil.back.test_func = GL_ALWAYS;
562 clear_state.stencil.back.test_mask = 0xFFFFFFFF;
563 clear_state.stencil.back.write_mask = 0xFFFFFFFF;
564 clear_state.stencil.back.action_stencil_fail = GL_KEEP;
565 clear_state.stencil.back.action_depth_fail = GL_KEEP;
566 clear_state.stencil.back.action_depth_pass = GL_KEEP;
567 }
568 }
545 } 569 }
546 570
547 if (!use_color && !use_depth && !use_stencil) { 571 if (!use_color && !use_depth && !use_stencil) {
@@ -553,6 +577,14 @@ void RasterizerOpenGL::Clear() {
553 577
554 ConfigureFramebuffers(clear_state, use_color, use_depth || use_stencil, false, 578 ConfigureFramebuffers(clear_state, use_color, use_depth || use_stencil, false,
555 regs.clear_buffers.RT.Value()); 579 regs.clear_buffers.RT.Value());
580 if (regs.clear_flags.scissor) {
581 SyncScissorTest(clear_state);
582 }
583
584 if (regs.clear_flags.viewport) {
585 clear_state.EmulateViewportWithScissor();
586 }
587
556 clear_state.Apply(); 588 clear_state.Apply();
557 589
558 if (use_color) { 590 if (use_color) {
@@ -588,7 +620,7 @@ void RasterizerOpenGL::DrawArrays() {
588 SyncLogicOpState(); 620 SyncLogicOpState();
589 SyncCullMode(); 621 SyncCullMode();
590 SyncPrimitiveRestart(); 622 SyncPrimitiveRestart();
591 SyncScissorTest(); 623 SyncScissorTest(state);
592 // Alpha Testing is synced on shaders. 624 // Alpha Testing is synced on shaders.
593 SyncTransformFeedback(); 625 SyncTransformFeedback();
594 SyncPointState(); 626 SyncPointState();
@@ -815,7 +847,7 @@ void RasterizerOpenGL::SamplerInfo::SyncWithConfig(const Tegra::Texture::TSCEntr
815 } 847 }
816 const u32 bias = config.mip_lod_bias.Value(); 848 const u32 bias = config.mip_lod_bias.Value();
817 // Sign extend the 13-bit value. 849 // Sign extend the 13-bit value.
818 const u32 mask = 1U << (13 - 1); 850 constexpr u32 mask = 1U << (13 - 1);
819 const float bias_lod = static_cast<s32>((bias ^ mask) - mask) / 256.f; 851 const float bias_lod = static_cast<s32>((bias ^ mask) - mask) / 256.f;
820 if (lod_bias != bias_lod) { 852 if (lod_bias != bias_lod) {
821 lod_bias = bias_lod; 853 lod_bias = bias_lod;
@@ -947,8 +979,8 @@ void RasterizerOpenGL::SyncViewport(OpenGLState& current_state) {
947 auto& viewport = current_state.viewports[i]; 979 auto& viewport = current_state.viewports[i];
948 viewport.x = viewport_rect.left; 980 viewport.x = viewport_rect.left;
949 viewport.y = viewport_rect.bottom; 981 viewport.y = viewport_rect.bottom;
950 viewport.width = static_cast<GLfloat>(viewport_rect.GetWidth()); 982 viewport.width = viewport_rect.GetWidth();
951 viewport.height = static_cast<GLfloat>(viewport_rect.GetHeight()); 983 viewport.height = viewport_rect.GetHeight();
952 viewport.depth_range_far = regs.viewports[i].depth_range_far; 984 viewport.depth_range_far = regs.viewports[i].depth_range_far;
953 viewport.depth_range_near = regs.viewports[i].depth_range_near; 985 viewport.depth_range_near = regs.viewports[i].depth_range_near;
954 } 986 }
@@ -1120,11 +1152,11 @@ void RasterizerOpenGL::SyncLogicOpState() {
1120 state.logic_op.operation = MaxwellToGL::LogicOp(regs.logic_op.operation); 1152 state.logic_op.operation = MaxwellToGL::LogicOp(regs.logic_op.operation);
1121} 1153}
1122 1154
1123void RasterizerOpenGL::SyncScissorTest() { 1155void RasterizerOpenGL::SyncScissorTest(OpenGLState& current_state) {
1124 const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs; 1156 const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
1125 for (std::size_t i = 0; i < Tegra::Engines::Maxwell3D::Regs::NumViewports; i++) { 1157 for (std::size_t i = 0; i < Tegra::Engines::Maxwell3D::Regs::NumViewports; i++) {
1126 const auto& src = regs.scissor_test[i]; 1158 const auto& src = regs.scissor_test[i];
1127 auto& dst = state.viewports[i].scissor; 1159 auto& dst = current_state.viewports[i].scissor;
1128 dst.enabled = (src.enable != 0); 1160 dst.enabled = (src.enable != 0);
1129 if (dst.enabled == 0) { 1161 if (dst.enabled == 0) {
1130 return; 1162 return;
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index 6e78ab4cd..d3192c47d 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -91,19 +91,20 @@ private:
91 void SyncWithConfig(const Tegra::Texture::TSCEntry& info); 91 void SyncWithConfig(const Tegra::Texture::TSCEntry& info);
92 92
93 private: 93 private:
94 Tegra::Texture::TextureFilter mag_filter; 94 Tegra::Texture::TextureFilter mag_filter = Tegra::Texture::TextureFilter::Nearest;
95 Tegra::Texture::TextureFilter min_filter; 95 Tegra::Texture::TextureFilter min_filter = Tegra::Texture::TextureFilter::Nearest;
96 Tegra::Texture::TextureMipmapFilter mip_filter; 96 Tegra::Texture::TextureMipmapFilter mip_filter = Tegra::Texture::TextureMipmapFilter::None;
97 Tegra::Texture::WrapMode wrap_u; 97 Tegra::Texture::WrapMode wrap_u = Tegra::Texture::WrapMode::ClampToEdge;
98 Tegra::Texture::WrapMode wrap_v; 98 Tegra::Texture::WrapMode wrap_v = Tegra::Texture::WrapMode::ClampToEdge;
99 Tegra::Texture::WrapMode wrap_p; 99 Tegra::Texture::WrapMode wrap_p = Tegra::Texture::WrapMode::ClampToEdge;
100 bool uses_depth_compare; 100 bool uses_depth_compare = false;
101 Tegra::Texture::DepthCompareFunc depth_compare_func; 101 Tegra::Texture::DepthCompareFunc depth_compare_func =
102 GLvec4 border_color; 102 Tegra::Texture::DepthCompareFunc::Always;
103 float min_lod; 103 GLvec4 border_color = {};
104 float max_lod; 104 float min_lod = 0.0f;
105 float lod_bias; 105 float max_lod = 16.0f;
106 float max_anisotropic; 106 float lod_bias = 0.0f;
107 float max_anisotropic = 1.0f;
107 }; 108 };
108 109
109 /** 110 /**
@@ -171,7 +172,7 @@ private:
171 void SyncMultiSampleState(); 172 void SyncMultiSampleState();
172 173
173 /// Syncs the scissor test state to match the guest state 174 /// Syncs the scissor test state to match the guest state
174 void SyncScissorTest(); 175 void SyncScissorTest(OpenGLState& current_state);
175 176
176 /// Syncs the transform feedback state to match the guest state 177 /// Syncs the transform feedback state to match the guest state
177 void SyncTransformFeedback(); 178 void SyncTransformFeedback();
diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp
index d9910c6e8..41beb176d 100644
--- a/src/video_core/renderer_opengl/gl_state.cpp
+++ b/src/video_core/renderer_opengl/gl_state.cpp
@@ -233,6 +233,28 @@ void OpenGLState::ApplyStencilTest() const {
233 config_stencil(GL_BACK, stencil.back, cur_state.stencil.back); 233 config_stencil(GL_BACK, stencil.back, cur_state.stencil.back);
234 } 234 }
235} 235}
236// Viewport does not affects glClearBuffer so emulate viewport using scissor test
237void OpenGLState::EmulateViewportWithScissor() {
238 auto& current = viewports[0];
239 if (current.scissor.enabled) {
240 const GLint left = std::max(current.x, current.scissor.x);
241 const GLint right =
242 std::max(current.x + current.width, current.scissor.x + current.scissor.width);
243 const GLint bottom = std::max(current.y, current.scissor.y);
244 const GLint top =
245 std::max(current.y + current.height, current.scissor.y + current.scissor.height);
246 current.scissor.x = std::max(left, 0);
247 current.scissor.y = std::max(bottom, 0);
248 current.scissor.width = std::max(right - left, 0);
249 current.scissor.height = std::max(top - bottom, 0);
250 } else {
251 current.scissor.enabled = true;
252 current.scissor.x = current.x;
253 current.scissor.y = current.y;
254 current.scissor.width = current.width;
255 current.scissor.height = current.height;
256 }
257}
236 258
237void OpenGLState::ApplyViewport() const { 259void OpenGLState::ApplyViewport() const {
238 if (GLAD_GL_ARB_viewport_array && geometry_shaders.enabled) { 260 if (GLAD_GL_ARB_viewport_array && geometry_shaders.enabled) {
@@ -242,7 +264,9 @@ void OpenGLState::ApplyViewport() const {
242 const auto& updated = viewports[i]; 264 const auto& updated = viewports[i];
243 if (updated.x != current.x || updated.y != current.y || 265 if (updated.x != current.x || updated.y != current.y ||
244 updated.width != current.width || updated.height != current.height) { 266 updated.width != current.width || updated.height != current.height) {
245 glViewportIndexedf(i, updated.x, updated.y, updated.width, updated.height); 267 glViewportIndexedf(
268 i, static_cast<GLfloat>(updated.x), static_cast<GLfloat>(updated.y),
269 static_cast<GLfloat>(updated.width), static_cast<GLfloat>(updated.height));
246 } 270 }
247 if (updated.depth_range_near != current.depth_range_near || 271 if (updated.depth_range_near != current.depth_range_near ||
248 updated.depth_range_far != current.depth_range_far) { 272 updated.depth_range_far != current.depth_range_far) {
@@ -270,8 +294,7 @@ void OpenGLState::ApplyViewport() const {
270 const auto& updated = viewports[0]; 294 const auto& updated = viewports[0];
271 if (updated.x != current.x || updated.y != current.y || updated.width != current.width || 295 if (updated.x != current.x || updated.y != current.y || updated.width != current.width ||
272 updated.height != current.height) { 296 updated.height != current.height) {
273 glViewport(static_cast<GLint>(updated.x), static_cast<GLint>(updated.y), 297 glViewport(updated.x, updated.y, updated.width, updated.height);
274 static_cast<GLsizei>(updated.width), static_cast<GLsizei>(updated.height));
275 } 298 }
276 if (updated.depth_range_near != current.depth_range_near || 299 if (updated.depth_range_near != current.depth_range_near ||
277 updated.depth_range_far != current.depth_range_far) { 300 updated.depth_range_far != current.depth_range_far) {
diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h
index bdc743b0f..032fc43f0 100644
--- a/src/video_core/renderer_opengl/gl_state.h
+++ b/src/video_core/renderer_opengl/gl_state.h
@@ -156,10 +156,10 @@ public:
156 } draw; 156 } draw;
157 157
158 struct viewport { 158 struct viewport {
159 GLfloat x; 159 GLint x;
160 GLfloat y; 160 GLint y;
161 GLfloat width; 161 GLint width;
162 GLfloat height; 162 GLint height;
163 GLfloat depth_range_near; // GL_DEPTH_RANGE 163 GLfloat depth_range_near; // GL_DEPTH_RANGE
164 GLfloat depth_range_far; // GL_DEPTH_RANGE 164 GLfloat depth_range_far; // GL_DEPTH_RANGE
165 struct { 165 struct {
@@ -206,6 +206,7 @@ public:
206 OpenGLState& ResetBuffer(GLuint handle); 206 OpenGLState& ResetBuffer(GLuint handle);
207 OpenGLState& ResetVertexArray(GLuint handle); 207 OpenGLState& ResetVertexArray(GLuint handle);
208 OpenGLState& ResetFramebuffer(GLuint handle); 208 OpenGLState& ResetFramebuffer(GLuint handle);
209 void EmulateViewportWithScissor();
209 210
210private: 211private:
211 static OpenGLState cur_state; 212 static OpenGLState cur_state;