summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar bunnei2018-11-11 19:58:16 -0800
committerGravatar GitHub2018-11-11 19:58:16 -0800
commit2c6efda2352a1133a1091d2aa206b1f044b7642a (patch)
tree2a1bbae2d93fb2a52f0ff3f7802919cef8b4d6d3 /src
parentMerge pull request #1652 from FreddyFunk/static-cast (diff)
parentUse core extensions when available to set max anisotropic filtering level (diff)
downloadyuzu-2c6efda2352a1133a1091d2aa206b1f044b7642a.tar.gz
yuzu-2c6efda2352a1133a1091d2aa206b1f044b7642a.tar.xz
yuzu-2c6efda2352a1133a1091d2aa206b1f044b7642a.zip
Merge pull request #1660 from Tinob/master
Map more missing opengl states
Diffstat (limited to '')
-rw-r--r--src/video_core/engines/maxwell_3d.cpp13
-rw-r--r--src/video_core/engines/maxwell_3d.h8
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp104
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h8
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.cpp2
-rw-r--r--src/video_core/renderer_opengl/gl_state.cpp8
-rw-r--r--src/video_core/renderer_opengl/gl_state.h4
-rw-r--r--src/video_core/renderer_opengl/maxwell_to_gl.h66
-rw-r--r--src/video_core/textures/texture.h13
9 files changed, 138 insertions, 88 deletions
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp
index 5ae836aca..d1777b25b 100644
--- a/src/video_core/engines/maxwell_3d.cpp
+++ b/src/video_core/engines/maxwell_3d.cpp
@@ -53,6 +53,19 @@ void Maxwell3D::InitializeRegisterDefaults() {
53 regs.independent_blend[blend_index].factor_source_a = Regs::Blend::Factor::One; 53 regs.independent_blend[blend_index].factor_source_a = Regs::Blend::Factor::One;
54 regs.independent_blend[blend_index].factor_dest_a = Regs::Blend::Factor::Zero; 54 regs.independent_blend[blend_index].factor_dest_a = Regs::Blend::Factor::Zero;
55 } 55 }
56 regs.stencil_front_op_fail = Regs::StencilOp::Keep;
57 regs.stencil_front_op_zfail = Regs::StencilOp::Keep;
58 regs.stencil_front_op_zpass = Regs::StencilOp::Keep;
59 regs.stencil_front_func_func = Regs::ComparisonOp::Always;
60 regs.stencil_front_func_mask = 0xFFFFFFFF;
61 regs.stencil_front_mask = 0xFFFFFFFF;
62 regs.stencil_two_side_enable = 1;
63 regs.stencil_back_op_fail = Regs::StencilOp::Keep;
64 regs.stencil_back_op_zfail = Regs::StencilOp::Keep;
65 regs.stencil_back_op_zpass = Regs::StencilOp::Keep;
66 regs.stencil_back_func_func = Regs::ComparisonOp::Always;
67 regs.stencil_back_func_mask = 0xFFFFFFFF;
68 regs.stencil_back_mask = 0xFFFFFFFF;
56} 69}
57 70
58void Maxwell3D::CallMacroMethod(u32 method, std::vector<u32> parameters) { 71void 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 557795d0f..91ca57883 100644
--- a/src/video_core/engines/maxwell_3d.h
+++ b/src/video_core/engines/maxwell_3d.h
@@ -345,6 +345,14 @@ public:
345 Invert = 6, 345 Invert = 6,
346 IncrWrap = 7, 346 IncrWrap = 7,
347 DecrWrap = 8, 347 DecrWrap = 8,
348 KeepOGL = 0x1E00,
349 ZeroOGL = 0,
350 ReplaceOGL = 0x1E01,
351 IncrOGL = 0x1E02,
352 DecrOGL = 0x1E03,
353 InvertOGL = 0x150A,
354 IncrWrapOGL = 0x8507,
355 DecrWrapOGL = 0x8508,
348 }; 356 };
349 357
350 enum class MemoryLayout : u32 { 358 enum class MemoryLayout : u32 {
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index a99f2b1f9..54cc47a9b 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -140,7 +140,7 @@ void RasterizerOpenGL::SetupVertexFormat() {
140 if (is_cache_miss) { 140 if (is_cache_miss) {
141 VAO.Create(); 141 VAO.Create();
142 state.draw.vertex_array = VAO.handle; 142 state.draw.vertex_array = VAO.handle;
143 state.Apply(); 143 state.ApplyVertexBufferState();
144 144
145 // The index buffer binding is stored within the VAO. Stupid OpenGL, but easy to work 145 // The index buffer binding is stored within the VAO. Stupid OpenGL, but easy to work
146 // around. 146 // around.
@@ -182,7 +182,7 @@ void RasterizerOpenGL::SetupVertexFormat() {
182 } 182 }
183 } 183 }
184 state.draw.vertex_array = VAO.handle; 184 state.draw.vertex_array = VAO.handle;
185 state.Apply(); 185 state.ApplyVertexBufferState();
186} 186}
187 187
188void RasterizerOpenGL::SetupVertexBuffer() { 188void RasterizerOpenGL::SetupVertexBuffer() {
@@ -342,8 +342,6 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) {
342 index++; 342 index++;
343 } 343 }
344 } 344 }
345
346 state.Apply();
347} 345}
348 346
349std::size_t RasterizerOpenGL::CalculateVertexArraysSize() const { 347std::size_t RasterizerOpenGL::CalculateVertexArraysSize() const {
@@ -412,8 +410,8 @@ void RasterizerOpenGL::UpdatePagesCachedCount(VAddr addr, u64 size, int delta) {
412 cached_pages.add({pages_interval, delta}); 410 cached_pages.add({pages_interval, delta});
413} 411}
414 412
415void RasterizerOpenGL::ConfigureFramebuffers(bool using_color_fb, bool using_depth_fb, 413void RasterizerOpenGL::ConfigureFramebuffers(OpenGLState& current_state, bool using_color_fb,
416 bool preserve_contents, 414 bool using_depth_fb, bool preserve_contents,
417 std::optional<std::size_t> single_color_target) { 415 std::optional<std::size_t> single_color_target) {
418 MICROPROFILE_SCOPE(OpenGL_Framebuffer); 416 MICROPROFILE_SCOPE(OpenGL_Framebuffer);
419 const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs; 417 const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
@@ -429,9 +427,9 @@ void RasterizerOpenGL::ConfigureFramebuffers(bool using_color_fb, bool using_dep
429 ASSERT_MSG(regs.rt_separate_frag_data == 0, "Unimplemented"); 427 ASSERT_MSG(regs.rt_separate_frag_data == 0, "Unimplemented");
430 428
431 // Bind the framebuffer surfaces 429 // Bind the framebuffer surfaces
432 state.draw.draw_framebuffer = framebuffer.handle; 430 current_state.draw.draw_framebuffer = framebuffer.handle;
433 state.Apply(); 431 current_state.ApplyFramebufferState();
434 state.framebuffer_srgb.enabled = regs.framebuffer_srgb != 0; 432 current_state.framebuffer_srgb.enabled = regs.framebuffer_srgb != 0;
435 433
436 if (using_color_fb) { 434 if (using_color_fb) {
437 if (single_color_target) { 435 if (single_color_target) {
@@ -509,10 +507,7 @@ void RasterizerOpenGL::ConfigureFramebuffers(bool using_color_fb, bool using_dep
509 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 507 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0,
510 0); 508 0);
511 } 509 }
512 510 SyncViewport(current_state);
513 SyncViewport();
514
515 state.Apply();
516} 511}
517 512
518void RasterizerOpenGL::Clear() { 513void RasterizerOpenGL::Clear() {
@@ -525,22 +520,23 @@ void RasterizerOpenGL::Clear() {
525 bool use_stencil{}; 520 bool use_stencil{};
526 521
527 OpenGLState clear_state; 522 OpenGLState clear_state;
528 clear_state.draw.draw_framebuffer = framebuffer.handle;
529 clear_state.color_mask[0].red_enabled = regs.clear_buffers.R ? GL_TRUE : GL_FALSE;
530 clear_state.color_mask[0].green_enabled = regs.clear_buffers.G ? GL_TRUE : GL_FALSE;
531 clear_state.color_mask[0].blue_enabled = regs.clear_buffers.B ? GL_TRUE : GL_FALSE;
532 clear_state.color_mask[0].alpha_enabled = regs.clear_buffers.A ? GL_TRUE : GL_FALSE;
533
534 if (regs.clear_buffers.R || regs.clear_buffers.G || regs.clear_buffers.B || 523 if (regs.clear_buffers.R || regs.clear_buffers.G || regs.clear_buffers.B ||
535 regs.clear_buffers.A) { 524 regs.clear_buffers.A) {
536 use_color = true; 525 use_color = true;
537 } 526 }
527 if (use_color) {
528 clear_state.color_mask[0].red_enabled = regs.clear_buffers.R ? GL_TRUE : GL_FALSE;
529 clear_state.color_mask[0].green_enabled = regs.clear_buffers.G ? GL_TRUE : GL_FALSE;
530 clear_state.color_mask[0].blue_enabled = regs.clear_buffers.B ? GL_TRUE : GL_FALSE;
531 clear_state.color_mask[0].alpha_enabled = regs.clear_buffers.A ? GL_TRUE : GL_FALSE;
532 }
538 if (regs.clear_buffers.Z) { 533 if (regs.clear_buffers.Z) {
539 ASSERT_MSG(regs.zeta_enable != 0, "Tried to clear Z but buffer is not enabled!"); 534 ASSERT_MSG(regs.zeta_enable != 0, "Tried to clear Z but buffer is not enabled!");
540 use_depth = true; 535 use_depth = true;
541 536
542 // Always enable the depth write when clearing the depth buffer. The depth write mask is 537 // Always enable the depth write when clearing the depth buffer. The depth write mask is
543 // ignored when clearing the buffer in the Switch, but OpenGL obeys it so we set it to true. 538 // ignored when clearing the buffer in the Switch, but OpenGL obeys it so we set it to
539 // true.
544 clear_state.depth.test_enabled = true; 540 clear_state.depth.test_enabled = true;
545 clear_state.depth.test_func = GL_ALWAYS; 541 clear_state.depth.test_func = GL_ALWAYS;
546 } 542 }
@@ -557,11 +553,8 @@ void RasterizerOpenGL::Clear() {
557 553
558 ScopeAcquireGLContext acquire_context{emu_window}; 554 ScopeAcquireGLContext acquire_context{emu_window};
559 555
560 ConfigureFramebuffers(use_color, use_depth || use_stencil, false, 556 ConfigureFramebuffers(clear_state, use_color, use_depth || use_stencil, false,
561 regs.clear_buffers.RT.Value()); 557 regs.clear_buffers.RT.Value());
562 // Copy the sRGB setting to the clear state to avoid problem with
563 // specific driver implementations
564 clear_state.framebuffer_srgb.enabled = state.framebuffer_srgb.enabled;
565 clear_state.Apply(); 558 clear_state.Apply();
566 559
567 if (use_color) { 560 if (use_color) {
@@ -587,7 +580,7 @@ void RasterizerOpenGL::DrawArrays() {
587 580
588 ScopeAcquireGLContext acquire_context{emu_window}; 581 ScopeAcquireGLContext acquire_context{emu_window};
589 582
590 ConfigureFramebuffers(); 583 ConfigureFramebuffers(state);
591 SyncColorMask(); 584 SyncColorMask();
592 SyncDepthTestState(); 585 SyncDepthTestState();
593 SyncStencilTestState(); 586 SyncStencilTestState();
@@ -608,7 +601,7 @@ void RasterizerOpenGL::DrawArrays() {
608 const bool is_indexed = accelerate_draw == AccelDraw::Indexed; 601 const bool is_indexed = accelerate_draw == AccelDraw::Indexed;
609 602
610 state.draw.vertex_buffer = buffer_cache.GetHandle(); 603 state.draw.vertex_buffer = buffer_cache.GetHandle();
611 state.Apply(); 604 state.ApplyVertexBufferState();
612 605
613 std::size_t buffer_size = CalculateVertexArraysSize(); 606 std::size_t buffer_size = CalculateVertexArraysSize();
614 607
@@ -740,9 +733,9 @@ void RasterizerOpenGL::SamplerInfo::Create() {
740 glSamplerParameteri(sampler.handle, GL_TEXTURE_COMPARE_FUNC, GL_NEVER); 733 glSamplerParameteri(sampler.handle, GL_TEXTURE_COMPARE_FUNC, GL_NEVER);
741} 734}
742 735
743void RasterizerOpenGL::SamplerInfo::SyncWithConfig(const Tegra::Texture::TSCEntry& config) { 736void RasterizerOpenGL::SamplerInfo::SyncWithConfig(const Tegra::Texture::FullTextureInfo& info) {
744 const GLuint s = sampler.handle; 737 const GLuint s = sampler.handle;
745 738 const Tegra::Texture::TSCEntry& config = info.tsc;
746 if (mag_filter != config.mag_filter) { 739 if (mag_filter != config.mag_filter) {
747 mag_filter = config.mag_filter; 740 mag_filter = config.mag_filter;
748 glSamplerParameteri( 741 glSamplerParameteri(
@@ -793,6 +786,22 @@ void RasterizerOpenGL::SamplerInfo::SyncWithConfig(const Tegra::Texture::TSCEntr
793 glSamplerParameterfv(s, GL_TEXTURE_BORDER_COLOR, border_color.data()); 786 glSamplerParameterfv(s, GL_TEXTURE_BORDER_COLOR, border_color.data());
794 } 787 }
795 } 788 }
789 if (info.tic.use_header_opt_control == 0) {
790 if (GLAD_GL_ARB_texture_filter_anisotropic) {
791 glSamplerParameterf(s, GL_TEXTURE_MAX_ANISOTROPY,
792 static_cast<float>(1 << info.tic.max_anisotropy.Value()));
793 } else if (GLAD_GL_EXT_texture_filter_anisotropic) {
794 glSamplerParameterf(s, GL_TEXTURE_MAX_ANISOTROPY_EXT,
795 static_cast<float>(1 << info.tic.max_anisotropy.Value()));
796 }
797 glSamplerParameterf(s, GL_TEXTURE_MIN_LOD,
798 static_cast<float>(info.tic.res_min_mip_level.Value()));
799 glSamplerParameterf(s, GL_TEXTURE_MAX_LOD,
800 static_cast<float>(info.tic.res_max_mip_level.Value() == 0
801 ? 16
802 : info.tic.res_max_mip_level.Value()));
803 glSamplerParameterf(s, GL_TEXTURE_LOD_BIAS, info.tic.mip_lod_bias.Value() / 256.f);
804 }
796} 805}
797 806
798u32 RasterizerOpenGL::SetupConstBuffers(Maxwell::ShaderStage stage, Shader& shader, 807u32 RasterizerOpenGL::SetupConstBuffers(Maxwell::ShaderStage stage, Shader& shader,
@@ -890,7 +899,7 @@ u32 RasterizerOpenGL::SetupTextures(Maxwell::ShaderStage stage, Shader& shader,
890 continue; 899 continue;
891 } 900 }
892 901
893 texture_samplers[current_bindpoint].SyncWithConfig(texture.tsc); 902 texture_samplers[current_bindpoint].SyncWithConfig(texture);
894 Surface surface = res_cache.GetTextureSurface(texture, entry); 903 Surface surface = res_cache.GetTextureSurface(texture, entry);
895 if (surface != nullptr) { 904 if (surface != nullptr) {
896 state.texture_units[current_bindpoint].texture = surface->Texture().handle; 905 state.texture_units[current_bindpoint].texture = surface->Texture().handle;
@@ -912,11 +921,11 @@ u32 RasterizerOpenGL::SetupTextures(Maxwell::ShaderStage stage, Shader& shader,
912 return current_unit + static_cast<u32>(entries.size()); 921 return current_unit + static_cast<u32>(entries.size());
913} 922}
914 923
915void RasterizerOpenGL::SyncViewport() { 924void RasterizerOpenGL::SyncViewport(OpenGLState& current_state) {
916 const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs; 925 const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
917 for (size_t i = 0; i < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets; i++) { 926 for (size_t i = 0; i < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets; i++) {
918 const MathUtil::Rectangle<s32> viewport_rect{regs.viewport_transform[i].GetRect()}; 927 const MathUtil::Rectangle<s32> viewport_rect{regs.viewport_transform[i].GetRect()};
919 auto& viewport = state.viewports[i]; 928 auto& viewport = current_state.viewports[i];
920 viewport.x = viewport_rect.left; 929 viewport.x = viewport_rect.left;
921 viewport.y = viewport_rect.bottom; 930 viewport.y = viewport_rect.bottom;
922 viewport.width = static_cast<GLfloat>(viewport_rect.GetWidth()); 931 viewport.width = static_cast<GLfloat>(viewport_rect.GetWidth());
@@ -985,9 +994,6 @@ void RasterizerOpenGL::SyncStencilTestState() {
985 return; 994 return;
986 } 995 }
987 996
988 // TODO(bunnei): Verify behavior when this is not set
989 ASSERT(regs.stencil_two_side_enable);
990
991 state.stencil.front.test_func = MaxwellToGL::ComparisonOp(regs.stencil_front_func_func); 997 state.stencil.front.test_func = MaxwellToGL::ComparisonOp(regs.stencil_front_func_func);
992 state.stencil.front.test_ref = regs.stencil_front_func_ref; 998 state.stencil.front.test_ref = regs.stencil_front_func_ref;
993 state.stencil.front.test_mask = regs.stencil_front_func_mask; 999 state.stencil.front.test_mask = regs.stencil_front_func_mask;
@@ -995,14 +1001,23 @@ void RasterizerOpenGL::SyncStencilTestState() {
995 state.stencil.front.action_depth_fail = MaxwellToGL::StencilOp(regs.stencil_front_op_zfail); 1001 state.stencil.front.action_depth_fail = MaxwellToGL::StencilOp(regs.stencil_front_op_zfail);
996 state.stencil.front.action_depth_pass = MaxwellToGL::StencilOp(regs.stencil_front_op_zpass); 1002 state.stencil.front.action_depth_pass = MaxwellToGL::StencilOp(regs.stencil_front_op_zpass);
997 state.stencil.front.write_mask = regs.stencil_front_mask; 1003 state.stencil.front.write_mask = regs.stencil_front_mask;
998 1004 if (regs.stencil_two_side_enable) {
999 state.stencil.back.test_func = MaxwellToGL::ComparisonOp(regs.stencil_back_func_func); 1005 state.stencil.back.test_func = MaxwellToGL::ComparisonOp(regs.stencil_back_func_func);
1000 state.stencil.back.test_ref = regs.stencil_back_func_ref; 1006 state.stencil.back.test_ref = regs.stencil_back_func_ref;
1001 state.stencil.back.test_mask = regs.stencil_back_func_mask; 1007 state.stencil.back.test_mask = regs.stencil_back_func_mask;
1002 state.stencil.back.action_stencil_fail = MaxwellToGL::StencilOp(regs.stencil_back_op_fail); 1008 state.stencil.back.action_stencil_fail = MaxwellToGL::StencilOp(regs.stencil_back_op_fail);
1003 state.stencil.back.action_depth_fail = MaxwellToGL::StencilOp(regs.stencil_back_op_zfail); 1009 state.stencil.back.action_depth_fail = MaxwellToGL::StencilOp(regs.stencil_back_op_zfail);
1004 state.stencil.back.action_depth_pass = MaxwellToGL::StencilOp(regs.stencil_back_op_zpass); 1010 state.stencil.back.action_depth_pass = MaxwellToGL::StencilOp(regs.stencil_back_op_zpass);
1005 state.stencil.back.write_mask = regs.stencil_back_mask; 1011 state.stencil.back.write_mask = regs.stencil_back_mask;
1012 } else {
1013 state.stencil.back.test_func = GL_ALWAYS;
1014 state.stencil.back.test_ref = 0;
1015 state.stencil.back.test_mask = 0xFFFFFFFF;
1016 state.stencil.back.write_mask = 0xFFFFFFFF;
1017 state.stencil.back.action_stencil_fail = GL_KEEP;
1018 state.stencil.back.action_depth_fail = GL_KEEP;
1019 state.stencil.back.action_depth_pass = GL_KEEP;
1020 }
1006} 1021}
1007 1022
1008void RasterizerOpenGL::SyncColorMask() { 1023void RasterizerOpenGL::SyncColorMask() {
@@ -1114,9 +1129,8 @@ void RasterizerOpenGL::CheckAlphaTests() {
1114 const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs; 1129 const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
1115 1130
1116 if (regs.alpha_test_enabled != 0 && regs.rt_control.count > 1) { 1131 if (regs.alpha_test_enabled != 0 && regs.rt_control.count > 1) {
1117 LOG_CRITICAL( 1132 LOG_CRITICAL(Render_OpenGL, "Alpha Testing is enabled with Multiple Render Targets, "
1118 Render_OpenGL, 1133 "this behavior is undefined.");
1119 "Alpha Testing is enabled with Multiple Render Targets, this behavior is undefined.");
1120 UNREACHABLE(); 1134 UNREACHABLE();
1121 } 1135 }
1122} 1136}
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index 5eee5f088..8ef0f6c12 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -88,7 +88,7 @@ private:
88 /// SamplerInfo struct. 88 /// SamplerInfo struct.
89 void Create(); 89 void Create();
90 /// Syncs the sampler object with the config, updating any necessary state. 90 /// Syncs the sampler object with the config, updating any necessary state.
91 void SyncWithConfig(const Tegra::Texture::TSCEntry& config); 91 void SyncWithConfig(const Tegra::Texture::FullTextureInfo& info);
92 92
93 private: 93 private:
94 Tegra::Texture::TextureFilter mag_filter; 94 Tegra::Texture::TextureFilter mag_filter;
@@ -109,8 +109,8 @@ private:
109 * @param preserve_contents If true, tries to preserve data from a previously used framebuffer. 109 * @param preserve_contents If true, tries to preserve data from a previously used framebuffer.
110 * @param single_color_target Specifies if a single color buffer target should be used. 110 * @param single_color_target Specifies if a single color buffer target should be used.
111 */ 111 */
112 void ConfigureFramebuffers(bool use_color_fb = true, bool using_depth_fb = true, 112 void ConfigureFramebuffers(OpenGLState& current_state, bool use_color_fb = true,
113 bool preserve_contents = true, 113 bool using_depth_fb = true, bool preserve_contents = true,
114 std::optional<std::size_t> single_color_target = {}); 114 std::optional<std::size_t> single_color_target = {});
115 115
116 /* 116 /*
@@ -134,7 +134,7 @@ private:
134 GLenum primitive_mode, u32 current_unit); 134 GLenum primitive_mode, u32 current_unit);
135 135
136 /// Syncs the viewport and depth range to match the guest state 136 /// Syncs the viewport and depth range to match the guest state
137 void SyncViewport(); 137 void SyncViewport(OpenGLState& current_state);
138 138
139 /// Syncs the clip enabled status to match the guest state 139 /// Syncs the clip enabled status to match the guest state
140 void SyncClipEnabled(); 140 void SyncClipEnabled();
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
index c8864cce8..894f4f294 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
@@ -580,7 +580,7 @@ static bool BlitSurface(const Surface& src_surface, const Surface& dst_surface,
580 state.draw.draw_framebuffer = draw_fb_handle; 580 state.draw.draw_framebuffer = draw_fb_handle;
581 // Set sRGB enabled if the destination surfaces need it 581 // Set sRGB enabled if the destination surfaces need it
582 state.framebuffer_srgb.enabled = dst_params.srgb_conversion; 582 state.framebuffer_srgb.enabled = dst_params.srgb_conversion;
583 state.Apply(); 583 state.ApplyFramebufferState();
584 584
585 u32 buffers{}; 585 u32 buffers{};
586 586
diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp
index 9517285e5..2635f2b0c 100644
--- a/src/video_core/renderer_opengl/gl_state.cpp
+++ b/src/video_core/renderer_opengl/gl_state.cpp
@@ -427,7 +427,7 @@ void OpenGLState::ApplySamplers() const {
427 } 427 }
428} 428}
429 429
430void OpenGLState::Apply() const { 430void OpenGLState::ApplyFramebufferState() const {
431 // Framebuffer 431 // Framebuffer
432 if (draw.read_framebuffer != cur_state.draw.read_framebuffer) { 432 if (draw.read_framebuffer != cur_state.draw.read_framebuffer) {
433 glBindFramebuffer(GL_READ_FRAMEBUFFER, draw.read_framebuffer); 433 glBindFramebuffer(GL_READ_FRAMEBUFFER, draw.read_framebuffer);
@@ -435,7 +435,9 @@ void OpenGLState::Apply() const {
435 if (draw.draw_framebuffer != cur_state.draw.draw_framebuffer) { 435 if (draw.draw_framebuffer != cur_state.draw.draw_framebuffer) {
436 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, draw.draw_framebuffer); 436 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, draw.draw_framebuffer);
437 } 437 }
438}
438 439
440void OpenGLState::ApplyVertexBufferState() const {
439 // Vertex array 441 // Vertex array
440 if (draw.vertex_array != cur_state.draw.vertex_array) { 442 if (draw.vertex_array != cur_state.draw.vertex_array) {
441 glBindVertexArray(draw.vertex_array); 443 glBindVertexArray(draw.vertex_array);
@@ -445,7 +447,11 @@ void OpenGLState::Apply() const {
445 if (draw.vertex_buffer != cur_state.draw.vertex_buffer) { 447 if (draw.vertex_buffer != cur_state.draw.vertex_buffer) {
446 glBindBuffer(GL_ARRAY_BUFFER, draw.vertex_buffer); 448 glBindBuffer(GL_ARRAY_BUFFER, draw.vertex_buffer);
447 } 449 }
450}
448 451
452void OpenGLState::Apply() const {
453 ApplyFramebufferState();
454 ApplyVertexBufferState();
449 // Uniform buffer 455 // Uniform buffer
450 if (draw.uniform_buffer != cur_state.draw.uniform_buffer) { 456 if (draw.uniform_buffer != cur_state.draw.uniform_buffer) {
451 glBindBuffer(GL_UNIFORM_BUFFER, draw.uniform_buffer); 457 glBindBuffer(GL_UNIFORM_BUFFER, draw.uniform_buffer);
diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h
index b8cf1f637..eacca0b9c 100644
--- a/src/video_core/renderer_opengl/gl_state.h
+++ b/src/video_core/renderer_opengl/gl_state.h
@@ -181,6 +181,10 @@ public:
181 } 181 }
182 /// Apply this state as the current OpenGL state 182 /// Apply this state as the current OpenGL state
183 void Apply() const; 183 void Apply() const;
184 /// Apply only the state afecting the framebuffer
185 void ApplyFramebufferState() const;
186 /// Apply only the state afecting the vertex buffer
187 void ApplyVertexBufferState() const;
184 /// Set the initial OpenGL state 188 /// Set the initial OpenGL state
185 static void ApplyDefaultState(); 189 static void ApplyDefaultState();
186 /// Resets any references to the given resource 190 /// Resets any references to the given resource
diff --git a/src/video_core/renderer_opengl/maxwell_to_gl.h b/src/video_core/renderer_opengl/maxwell_to_gl.h
index 87d511c38..3ce2cc6d2 100644
--- a/src/video_core/renderer_opengl/maxwell_to_gl.h
+++ b/src/video_core/renderer_opengl/maxwell_to_gl.h
@@ -159,10 +159,8 @@ inline GLenum TextureFilterMode(Tegra::Texture::TextureFilter filter_mode,
159 } 159 }
160 } 160 }
161 } 161 }
162 LOG_CRITICAL(Render_OpenGL, "Unimplemented texture filter mode={}", 162 LOG_ERROR(Render_OpenGL, "Unimplemented texture filter mode={}", static_cast<u32>(filter_mode));
163 static_cast<u32>(filter_mode)); 163 return GL_LINEAR;
164 UNREACHABLE();
165 return {};
166} 164}
167 165
168inline GLenum WrapMode(Tegra::Texture::WrapMode wrap_mode) { 166inline GLenum WrapMode(Tegra::Texture::WrapMode wrap_mode) {
@@ -183,9 +181,8 @@ inline GLenum WrapMode(Tegra::Texture::WrapMode wrap_mode) {
183 case Tegra::Texture::WrapMode::MirrorOnceClampToEdge: 181 case Tegra::Texture::WrapMode::MirrorOnceClampToEdge:
184 return GL_MIRROR_CLAMP_TO_EDGE; 182 return GL_MIRROR_CLAMP_TO_EDGE;
185 } 183 }
186 LOG_CRITICAL(Render_OpenGL, "Unimplemented texture wrap mode={}", static_cast<u32>(wrap_mode)); 184 LOG_ERROR(Render_OpenGL, "Unimplemented texture wrap mode={}", static_cast<u32>(wrap_mode));
187 UNREACHABLE(); 185 return GL_REPEAT;
188 return {};
189} 186}
190 187
191inline GLenum DepthCompareFunc(Tegra::Texture::DepthCompareFunc func) { 188inline GLenum DepthCompareFunc(Tegra::Texture::DepthCompareFunc func) {
@@ -207,10 +204,9 @@ inline GLenum DepthCompareFunc(Tegra::Texture::DepthCompareFunc func) {
207 case Tegra::Texture::DepthCompareFunc::Always: 204 case Tegra::Texture::DepthCompareFunc::Always:
208 return GL_ALWAYS; 205 return GL_ALWAYS;
209 } 206 }
210 LOG_CRITICAL(Render_OpenGL, "Unimplemented texture depth compare function ={}", 207 LOG_ERROR(Render_OpenGL, "Unimplemented texture depth compare function ={}",
211 static_cast<u32>(func)); 208 static_cast<u32>(func));
212 UNREACHABLE(); 209 return GL_GREATER;
213 return {};
214} 210}
215 211
216inline GLenum BlendEquation(Maxwell::Blend::Equation equation) { 212inline GLenum BlendEquation(Maxwell::Blend::Equation equation) {
@@ -226,9 +222,8 @@ inline GLenum BlendEquation(Maxwell::Blend::Equation equation) {
226 case Maxwell::Blend::Equation::Max: 222 case Maxwell::Blend::Equation::Max:
227 return GL_MAX; 223 return GL_MAX;
228 } 224 }
229 LOG_CRITICAL(Render_OpenGL, "Unimplemented blend equation={}", static_cast<u32>(equation)); 225 LOG_ERROR(Render_OpenGL, "Unimplemented blend equation={}", static_cast<u32>(equation));
230 UNREACHABLE(); 226 return GL_FUNC_ADD;
231 return {};
232} 227}
233 228
234inline GLenum BlendFunc(Maxwell::Blend::Factor factor) { 229inline GLenum BlendFunc(Maxwell::Blend::Factor factor) {
@@ -291,9 +286,8 @@ inline GLenum BlendFunc(Maxwell::Blend::Factor factor) {
291 case Maxwell::Blend::Factor::OneMinusConstantAlphaGL: 286 case Maxwell::Blend::Factor::OneMinusConstantAlphaGL:
292 return GL_ONE_MINUS_CONSTANT_ALPHA; 287 return GL_ONE_MINUS_CONSTANT_ALPHA;
293 } 288 }
294 LOG_CRITICAL(Render_OpenGL, "Unimplemented blend factor={}", static_cast<u32>(factor)); 289 LOG_ERROR(Render_OpenGL, "Unimplemented blend factor={}", static_cast<u32>(factor));
295 UNREACHABLE(); 290 return GL_ZERO;
296 return {};
297} 291}
298 292
299inline GLenum SwizzleSource(Tegra::Texture::SwizzleSource source) { 293inline GLenum SwizzleSource(Tegra::Texture::SwizzleSource source) {
@@ -312,9 +306,8 @@ inline GLenum SwizzleSource(Tegra::Texture::SwizzleSource source) {
312 case Tegra::Texture::SwizzleSource::OneFloat: 306 case Tegra::Texture::SwizzleSource::OneFloat:
313 return GL_ONE; 307 return GL_ONE;
314 } 308 }
315 LOG_CRITICAL(Render_OpenGL, "Unimplemented swizzle source={}", static_cast<u32>(source)); 309 LOG_ERROR(Render_OpenGL, "Unimplemented swizzle source={}", static_cast<u32>(source));
316 UNREACHABLE(); 310 return GL_ZERO;
317 return {};
318} 311}
319 312
320inline GLenum ComparisonOp(Maxwell::ComparisonOp comparison) { 313inline GLenum ComparisonOp(Maxwell::ComparisonOp comparison) {
@@ -344,33 +337,39 @@ inline GLenum ComparisonOp(Maxwell::ComparisonOp comparison) {
344 case Maxwell::ComparisonOp::AlwaysOld: 337 case Maxwell::ComparisonOp::AlwaysOld:
345 return GL_ALWAYS; 338 return GL_ALWAYS;
346 } 339 }
347 LOG_CRITICAL(Render_OpenGL, "Unimplemented comparison op={}", static_cast<u32>(comparison)); 340 LOG_ERROR(Render_OpenGL, "Unimplemented comparison op={}", static_cast<u32>(comparison));
348 UNREACHABLE(); 341 return GL_ALWAYS;
349 return {};
350} 342}
351 343
352inline GLenum StencilOp(Maxwell::StencilOp stencil) { 344inline GLenum StencilOp(Maxwell::StencilOp stencil) {
353 switch (stencil) { 345 switch (stencil) {
354 case Maxwell::StencilOp::Keep: 346 case Maxwell::StencilOp::Keep:
347 case Maxwell::StencilOp::KeepOGL:
355 return GL_KEEP; 348 return GL_KEEP;
356 case Maxwell::StencilOp::Zero: 349 case Maxwell::StencilOp::Zero:
350 case Maxwell::StencilOp::ZeroOGL:
357 return GL_ZERO; 351 return GL_ZERO;
358 case Maxwell::StencilOp::Replace: 352 case Maxwell::StencilOp::Replace:
353 case Maxwell::StencilOp::ReplaceOGL:
359 return GL_REPLACE; 354 return GL_REPLACE;
360 case Maxwell::StencilOp::Incr: 355 case Maxwell::StencilOp::Incr:
356 case Maxwell::StencilOp::IncrOGL:
361 return GL_INCR; 357 return GL_INCR;
362 case Maxwell::StencilOp::Decr: 358 case Maxwell::StencilOp::Decr:
359 case Maxwell::StencilOp::DecrOGL:
363 return GL_DECR; 360 return GL_DECR;
364 case Maxwell::StencilOp::Invert: 361 case Maxwell::StencilOp::Invert:
362 case Maxwell::StencilOp::InvertOGL:
365 return GL_INVERT; 363 return GL_INVERT;
366 case Maxwell::StencilOp::IncrWrap: 364 case Maxwell::StencilOp::IncrWrap:
365 case Maxwell::StencilOp::IncrWrapOGL:
367 return GL_INCR_WRAP; 366 return GL_INCR_WRAP;
368 case Maxwell::StencilOp::DecrWrap: 367 case Maxwell::StencilOp::DecrWrap:
368 case Maxwell::StencilOp::DecrWrapOGL:
369 return GL_DECR_WRAP; 369 return GL_DECR_WRAP;
370 } 370 }
371 LOG_CRITICAL(Render_OpenGL, "Unimplemented stencil op={}", static_cast<u32>(stencil)); 371 LOG_ERROR(Render_OpenGL, "Unimplemented stencil op={}", static_cast<u32>(stencil));
372 UNREACHABLE(); 372 return GL_KEEP;
373 return {};
374} 373}
375 374
376inline GLenum FrontFace(Maxwell::Cull::FrontFace front_face) { 375inline GLenum FrontFace(Maxwell::Cull::FrontFace front_face) {
@@ -380,9 +379,8 @@ inline GLenum FrontFace(Maxwell::Cull::FrontFace front_face) {
380 case Maxwell::Cull::FrontFace::CounterClockWise: 379 case Maxwell::Cull::FrontFace::CounterClockWise:
381 return GL_CCW; 380 return GL_CCW;
382 } 381 }
383 LOG_CRITICAL(Render_OpenGL, "Unimplemented front face cull={}", static_cast<u32>(front_face)); 382 LOG_ERROR(Render_OpenGL, "Unimplemented front face cull={}", static_cast<u32>(front_face));
384 UNREACHABLE(); 383 return GL_CCW;
385 return {};
386} 384}
387 385
388inline GLenum CullFace(Maxwell::Cull::CullFace cull_face) { 386inline GLenum CullFace(Maxwell::Cull::CullFace cull_face) {
@@ -394,9 +392,8 @@ inline GLenum CullFace(Maxwell::Cull::CullFace cull_face) {
394 case Maxwell::Cull::CullFace::FrontAndBack: 392 case Maxwell::Cull::CullFace::FrontAndBack:
395 return GL_FRONT_AND_BACK; 393 return GL_FRONT_AND_BACK;
396 } 394 }
397 LOG_CRITICAL(Render_OpenGL, "Unimplemented cull face={}", static_cast<u32>(cull_face)); 395 LOG_ERROR(Render_OpenGL, "Unimplemented cull face={}", static_cast<u32>(cull_face));
398 UNREACHABLE(); 396 return GL_BACK;
399 return {};
400} 397}
401 398
402inline GLenum LogicOp(Maxwell::LogicOperation operation) { 399inline GLenum LogicOp(Maxwell::LogicOperation operation) {
@@ -434,9 +431,8 @@ inline GLenum LogicOp(Maxwell::LogicOperation operation) {
434 case Maxwell::LogicOperation::Set: 431 case Maxwell::LogicOperation::Set:
435 return GL_SET; 432 return GL_SET;
436 } 433 }
437 LOG_CRITICAL(Render_OpenGL, "Unimplemented logic operation={}", static_cast<u32>(operation)); 434 LOG_ERROR(Render_OpenGL, "Unimplemented logic operation={}", static_cast<u32>(operation));
438 UNREACHABLE(); 435 return GL_COPY;
439 return {};
440} 436}
441 437
442} // namespace MaxwellToGL 438} // namespace MaxwellToGL
diff --git a/src/video_core/textures/texture.h b/src/video_core/textures/texture.h
index d12d2ecb8..e199d019a 100644
--- a/src/video_core/textures/texture.h
+++ b/src/video_core/textures/texture.h
@@ -168,20 +168,29 @@ struct TICEntry {
168 168
169 // High 16 bits of the pitch value 169 // High 16 bits of the pitch value
170 BitField<0, 16, u32> pitch_high; 170 BitField<0, 16, u32> pitch_high;
171 171 BitField<26, 1, u32> use_header_opt_control;
172 BitField<27, 1, u32> depth_texture;
172 BitField<28, 4, u32> max_mip_level; 173 BitField<28, 4, u32> max_mip_level;
173 }; 174 };
174 union { 175 union {
175 BitField<0, 16, u32> width_minus_1; 176 BitField<0, 16, u32> width_minus_1;
176 BitField<22, 1, u32> srgb_conversion; 177 BitField<22, 1, u32> srgb_conversion;
177 BitField<23, 4, TextureType> texture_type; 178 BitField<23, 4, TextureType> texture_type;
179 BitField<29, 3, u32> border_size;
178 }; 180 };
179 union { 181 union {
180 BitField<0, 16, u32> height_minus_1; 182 BitField<0, 16, u32> height_minus_1;
181 BitField<16, 15, u32> depth_minus_1; 183 BitField<16, 15, u32> depth_minus_1;
182 }; 184 };
185 union {
186 BitField<6, 13, u32> mip_lod_bias;
187 BitField<27, 3, u32> max_anisotropy;
188 };
183 189
184 INSERT_PADDING_BYTES(8); 190 union {
191 BitField<0, 4, u32> res_min_mip_level;
192 BitField<4, 4, u32> res_max_mip_level;
193 };
185 194
186 GPUVAddr Address() const { 195 GPUVAddr Address() const {
187 return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) | address_low); 196 return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) | address_low);