diff options
| author | 2018-11-18 19:59:10 -0800 | |
|---|---|---|
| committer | 2018-11-18 19:59:10 -0800 | |
| commit | 6dc33fb812a668487c0652673977a63ada2632ee (patch) | |
| tree | d658210e06996f9b157b552d78f9b542d202d357 /src | |
| parent | Merge pull request #1555 from ccawley2011/clang-format-docker (diff) | |
| parent | drop support for non separate alpha as it seems to cause issues in some games (diff) | |
| download | yuzu-6dc33fb812a668487c0652673977a63ada2632ee.tar.gz yuzu-6dc33fb812a668487c0652673977a63ada2632ee.tar.xz yuzu-6dc33fb812a668487c0652673977a63ada2632ee.zip | |
Merge pull request #1693 from Tinob/master
Missing ogl states
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/engines/maxwell_3d.cpp | 7 | ||||
| -rw-r--r-- | src/video_core/engines/maxwell_3d.h | 142 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 159 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.h | 12 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_manager.h | 1 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_state.cpp | 152 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_state.h | 32 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/maxwell_to_gl.h | 6 | ||||
| -rw-r--r-- | src/video_core/textures/texture.h | 15 |
9 files changed, 315 insertions, 211 deletions
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index 6de07ea56..a04e00ecb 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp | |||
| @@ -34,8 +34,8 @@ void Maxwell3D::InitializeRegisterDefaults() { | |||
| 34 | // Depth range near/far is not always set, but is expected to be the default 0.0f, 1.0f. This is | 34 | // Depth range near/far is not always set, but is expected to be the default 0.0f, 1.0f. This is |
| 35 | // needed for ARMS. | 35 | // needed for ARMS. |
| 36 | for (std::size_t viewport{}; viewport < Regs::NumViewports; ++viewport) { | 36 | for (std::size_t viewport{}; viewport < Regs::NumViewports; ++viewport) { |
| 37 | regs.viewport[viewport].depth_range_near = 0.0f; | 37 | regs.viewports[viewport].depth_range_near = 0.0f; |
| 38 | regs.viewport[viewport].depth_range_far = 1.0f; | 38 | regs.viewports[viewport].depth_range_far = 1.0f; |
| 39 | } | 39 | } |
| 40 | // Doom and Bomberman seems to use the uninitialized registers and just enable blend | 40 | // Doom and Bomberman seems to use the uninitialized registers and just enable blend |
| 41 | // so initialize blend registers with sane values | 41 | // so initialize blend registers with sane values |
| @@ -66,6 +66,9 @@ void Maxwell3D::InitializeRegisterDefaults() { | |||
| 66 | regs.stencil_back_func_func = Regs::ComparisonOp::Always; | 66 | regs.stencil_back_func_func = Regs::ComparisonOp::Always; |
| 67 | regs.stencil_back_func_mask = 0xFFFFFFFF; | 67 | regs.stencil_back_func_mask = 0xFFFFFFFF; |
| 68 | regs.stencil_back_mask = 0xFFFFFFFF; | 68 | regs.stencil_back_mask = 0xFFFFFFFF; |
| 69 | // TODO(Rodrigo): Most games do not set a point size. I think this is a case of a | ||
| 70 | // register carrying a default value. Assume it's OpenGL's default (1). | ||
| 71 | regs.point_size = 1.0f; | ||
| 69 | } | 72 | } |
| 70 | 73 | ||
| 71 | void Maxwell3D::CallMacroMethod(u32 method, std::vector<u32> parameters) { | 74 | 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 91ca57883..9e480dc39 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h | |||
| @@ -480,6 +480,67 @@ public: | |||
| 480 | }; | 480 | }; |
| 481 | }; | 481 | }; |
| 482 | 482 | ||
| 483 | struct ViewportTransform { | ||
| 484 | f32 scale_x; | ||
| 485 | f32 scale_y; | ||
| 486 | f32 scale_z; | ||
| 487 | f32 translate_x; | ||
| 488 | f32 translate_y; | ||
| 489 | f32 translate_z; | ||
| 490 | INSERT_PADDING_WORDS(2); | ||
| 491 | |||
| 492 | MathUtil::Rectangle<s32> GetRect() const { | ||
| 493 | return { | ||
| 494 | GetX(), // left | ||
| 495 | GetY() + GetHeight(), // top | ||
| 496 | GetX() + GetWidth(), // right | ||
| 497 | GetY() // bottom | ||
| 498 | }; | ||
| 499 | }; | ||
| 500 | |||
| 501 | s32 GetX() const { | ||
| 502 | return static_cast<s32>(std::max(0.0f, translate_x - std::fabs(scale_x))); | ||
| 503 | } | ||
| 504 | |||
| 505 | s32 GetY() const { | ||
| 506 | return static_cast<s32>(std::max(0.0f, translate_y - std::fabs(scale_y))); | ||
| 507 | } | ||
| 508 | |||
| 509 | s32 GetWidth() const { | ||
| 510 | return static_cast<s32>(translate_x + std::fabs(scale_x)) - GetX(); | ||
| 511 | } | ||
| 512 | |||
| 513 | s32 GetHeight() const { | ||
| 514 | return static_cast<s32>(translate_y + std::fabs(scale_y)) - GetY(); | ||
| 515 | } | ||
| 516 | }; | ||
| 517 | |||
| 518 | struct ScissorTest { | ||
| 519 | u32 enable; | ||
| 520 | union { | ||
| 521 | BitField<0, 16, u32> min_x; | ||
| 522 | BitField<16, 16, u32> max_x; | ||
| 523 | }; | ||
| 524 | union { | ||
| 525 | BitField<0, 16, u32> min_y; | ||
| 526 | BitField<16, 16, u32> max_y; | ||
| 527 | }; | ||
| 528 | u32 fill; | ||
| 529 | }; | ||
| 530 | |||
| 531 | struct ViewPort { | ||
| 532 | union { | ||
| 533 | BitField<0, 16, u32> x; | ||
| 534 | BitField<16, 16, u32> width; | ||
| 535 | }; | ||
| 536 | union { | ||
| 537 | BitField<0, 16, u32> y; | ||
| 538 | BitField<16, 16, u32> height; | ||
| 539 | }; | ||
| 540 | float depth_range_near; | ||
| 541 | float depth_range_far; | ||
| 542 | }; | ||
| 543 | |||
| 483 | bool IsShaderConfigEnabled(std::size_t index) const { | 544 | bool IsShaderConfigEnabled(std::size_t index) const { |
| 484 | // The VertexB is always enabled. | 545 | // The VertexB is always enabled. |
| 485 | if (index == static_cast<std::size_t>(Regs::ShaderProgram::VertexB)) { | 546 | if (index == static_cast<std::size_t>(Regs::ShaderProgram::VertexB)) { |
| @@ -505,55 +566,11 @@ public: | |||
| 505 | 566 | ||
| 506 | INSERT_PADDING_WORDS(0x2E); | 567 | INSERT_PADDING_WORDS(0x2E); |
| 507 | 568 | ||
| 508 | RenderTargetConfig rt[NumRenderTargets]; | 569 | std::array<RenderTargetConfig, NumRenderTargets> rt; |
| 509 | |||
| 510 | struct { | ||
| 511 | f32 scale_x; | ||
| 512 | f32 scale_y; | ||
| 513 | f32 scale_z; | ||
| 514 | f32 translate_x; | ||
| 515 | f32 translate_y; | ||
| 516 | f32 translate_z; | ||
| 517 | INSERT_PADDING_WORDS(2); | ||
| 518 | |||
| 519 | MathUtil::Rectangle<s32> GetRect() const { | ||
| 520 | return { | ||
| 521 | GetX(), // left | ||
| 522 | GetY() + GetHeight(), // top | ||
| 523 | GetX() + GetWidth(), // right | ||
| 524 | GetY() // bottom | ||
| 525 | }; | ||
| 526 | }; | ||
| 527 | |||
| 528 | s32 GetX() const { | ||
| 529 | return static_cast<s32>(std::max(0.0f, translate_x - std::fabs(scale_x))); | ||
| 530 | } | ||
| 531 | 570 | ||
| 532 | s32 GetY() const { | 571 | std::array<ViewportTransform, NumViewports> viewport_transform; |
| 533 | return static_cast<s32>(std::max(0.0f, translate_y - std::fabs(scale_y))); | ||
| 534 | } | ||
| 535 | 572 | ||
| 536 | s32 GetWidth() const { | 573 | std::array<ViewPort, NumViewports> viewports; |
| 537 | return static_cast<s32>(translate_x + std::fabs(scale_x)) - GetX(); | ||
| 538 | } | ||
| 539 | |||
| 540 | s32 GetHeight() const { | ||
| 541 | return static_cast<s32>(translate_y + std::fabs(scale_y)) - GetY(); | ||
| 542 | } | ||
| 543 | } viewport_transform[NumViewports]; | ||
| 544 | |||
| 545 | struct { | ||
| 546 | union { | ||
| 547 | BitField<0, 16, u32> x; | ||
| 548 | BitField<16, 16, u32> width; | ||
| 549 | }; | ||
| 550 | union { | ||
| 551 | BitField<0, 16, u32> y; | ||
| 552 | BitField<16, 16, u32> height; | ||
| 553 | }; | ||
| 554 | float depth_range_near; | ||
| 555 | float depth_range_far; | ||
| 556 | } viewport[NumViewports]; | ||
| 557 | 574 | ||
| 558 | INSERT_PADDING_WORDS(0x1D); | 575 | INSERT_PADDING_WORDS(0x1D); |
| 559 | 576 | ||
| @@ -571,19 +588,9 @@ public: | |||
| 571 | 588 | ||
| 572 | INSERT_PADDING_WORDS(0x17); | 589 | INSERT_PADDING_WORDS(0x17); |
| 573 | 590 | ||
| 574 | struct { | 591 | std::array<ScissorTest, NumViewports> scissor_test; |
| 575 | u32 enable; | ||
| 576 | union { | ||
| 577 | BitField<0, 16, u32> min_x; | ||
| 578 | BitField<16, 16, u32> max_x; | ||
| 579 | }; | ||
| 580 | union { | ||
| 581 | BitField<0, 16, u32> min_y; | ||
| 582 | BitField<16, 16, u32> max_y; | ||
| 583 | }; | ||
| 584 | } scissor_test; | ||
| 585 | 592 | ||
| 586 | INSERT_PADDING_WORDS(0x52); | 593 | INSERT_PADDING_WORDS(0x15); |
| 587 | 594 | ||
| 588 | s32 stencil_back_func_ref; | 595 | s32 stencil_back_func_ref; |
| 589 | u32 stencil_back_mask; | 596 | u32 stencil_back_mask; |
| @@ -700,7 +707,9 @@ public: | |||
| 700 | u32 stencil_front_func_mask; | 707 | u32 stencil_front_func_mask; |
| 701 | u32 stencil_front_mask; | 708 | u32 stencil_front_mask; |
| 702 | 709 | ||
| 703 | INSERT_PADDING_WORDS(0x3); | 710 | INSERT_PADDING_WORDS(0x2); |
| 711 | |||
| 712 | u32 frag_color_clamp; | ||
| 704 | 713 | ||
| 705 | union { | 714 | union { |
| 706 | BitField<4, 1, u32> triangle_rast_flip; | 715 | BitField<4, 1, u32> triangle_rast_flip; |
| @@ -718,7 +727,12 @@ public: | |||
| 718 | 727 | ||
| 719 | u32 zeta_enable; | 728 | u32 zeta_enable; |
| 720 | 729 | ||
| 721 | INSERT_PADDING_WORDS(0x8); | 730 | union { |
| 731 | BitField<0, 1, u32> alpha_to_coverage; | ||
| 732 | BitField<4, 1, u32> alpha_to_one; | ||
| 733 | } multisample_control; | ||
| 734 | |||
| 735 | INSERT_PADDING_WORDS(0x7); | ||
| 722 | 736 | ||
| 723 | struct { | 737 | struct { |
| 724 | u32 tsc_address_high; | 738 | u32 tsc_address_high; |
| @@ -1100,8 +1114,8 @@ private: | |||
| 1100 | ASSERT_REG_POSITION(macros, 0x45); | 1114 | ASSERT_REG_POSITION(macros, 0x45); |
| 1101 | ASSERT_REG_POSITION(tfb_enabled, 0x1D1); | 1115 | ASSERT_REG_POSITION(tfb_enabled, 0x1D1); |
| 1102 | ASSERT_REG_POSITION(rt, 0x200); | 1116 | ASSERT_REG_POSITION(rt, 0x200); |
| 1103 | ASSERT_REG_POSITION(viewport_transform[0], 0x280); | 1117 | ASSERT_REG_POSITION(viewport_transform, 0x280); |
| 1104 | ASSERT_REG_POSITION(viewport, 0x300); | 1118 | ASSERT_REG_POSITION(viewports, 0x300); |
| 1105 | ASSERT_REG_POSITION(vertex_buffer, 0x35D); | 1119 | ASSERT_REG_POSITION(vertex_buffer, 0x35D); |
| 1106 | ASSERT_REG_POSITION(clear_color[0], 0x360); | 1120 | ASSERT_REG_POSITION(clear_color[0], 0x360); |
| 1107 | ASSERT_REG_POSITION(clear_depth, 0x364); | 1121 | ASSERT_REG_POSITION(clear_depth, 0x364); |
| @@ -1136,10 +1150,12 @@ ASSERT_REG_POSITION(stencil_front_func_func, 0x4E4); | |||
| 1136 | ASSERT_REG_POSITION(stencil_front_func_ref, 0x4E5); | 1150 | ASSERT_REG_POSITION(stencil_front_func_ref, 0x4E5); |
| 1137 | ASSERT_REG_POSITION(stencil_front_func_mask, 0x4E6); | 1151 | ASSERT_REG_POSITION(stencil_front_func_mask, 0x4E6); |
| 1138 | ASSERT_REG_POSITION(stencil_front_mask, 0x4E7); | 1152 | ASSERT_REG_POSITION(stencil_front_mask, 0x4E7); |
| 1153 | ASSERT_REG_POSITION(frag_color_clamp, 0x4EA); | ||
| 1139 | ASSERT_REG_POSITION(screen_y_control, 0x4EB); | 1154 | ASSERT_REG_POSITION(screen_y_control, 0x4EB); |
| 1140 | ASSERT_REG_POSITION(vb_element_base, 0x50D); | 1155 | ASSERT_REG_POSITION(vb_element_base, 0x50D); |
| 1141 | ASSERT_REG_POSITION(point_size, 0x546); | 1156 | ASSERT_REG_POSITION(point_size, 0x546); |
| 1142 | ASSERT_REG_POSITION(zeta_enable, 0x54E); | 1157 | ASSERT_REG_POSITION(zeta_enable, 0x54E); |
| 1158 | ASSERT_REG_POSITION(multisample_control, 0x54F); | ||
| 1143 | ASSERT_REG_POSITION(tsc, 0x557); | 1159 | ASSERT_REG_POSITION(tsc, 0x557); |
| 1144 | ASSERT_REG_POSITION(tic, 0x55D); | 1160 | ASSERT_REG_POSITION(tic, 0x55D); |
| 1145 | ASSERT_REG_POSITION(stencil_two_side_enable, 0x565); | 1161 | ASSERT_REG_POSITION(stencil_two_side_enable, 0x565); |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 84bd91eed..ae6aaee4c 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -580,6 +580,8 @@ void RasterizerOpenGL::DrawArrays() { | |||
| 580 | 580 | ||
| 581 | ConfigureFramebuffers(state); | 581 | ConfigureFramebuffers(state); |
| 582 | SyncColorMask(); | 582 | SyncColorMask(); |
| 583 | SyncFragmentColorClampState(); | ||
| 584 | SyncMultiSampleState(); | ||
| 583 | SyncDepthTestState(); | 585 | SyncDepthTestState(); |
| 584 | SyncStencilTestState(); | 586 | SyncStencilTestState(); |
| 585 | SyncBlendState(); | 587 | SyncBlendState(); |
| @@ -640,7 +642,7 @@ void RasterizerOpenGL::DrawArrays() { | |||
| 640 | params.DispatchDraw(); | 642 | params.DispatchDraw(); |
| 641 | 643 | ||
| 642 | // Disable scissor test | 644 | // Disable scissor test |
| 643 | state.scissor.enabled = false; | 645 | state.viewports[0].scissor.enabled = false; |
| 644 | 646 | ||
| 645 | accelerate_draw = AccelDraw::Disabled; | 647 | accelerate_draw = AccelDraw::Disabled; |
| 646 | 648 | ||
| @@ -731,9 +733,8 @@ void RasterizerOpenGL::SamplerInfo::Create() { | |||
| 731 | glSamplerParameteri(sampler.handle, GL_TEXTURE_COMPARE_FUNC, GL_NEVER); | 733 | glSamplerParameteri(sampler.handle, GL_TEXTURE_COMPARE_FUNC, GL_NEVER); |
| 732 | } | 734 | } |
| 733 | 735 | ||
| 734 | void RasterizerOpenGL::SamplerInfo::SyncWithConfig(const Tegra::Texture::FullTextureInfo& info) { | 736 | void RasterizerOpenGL::SamplerInfo::SyncWithConfig(const Tegra::Texture::TSCEntry& config) { |
| 735 | const GLuint s = sampler.handle; | 737 | const GLuint s = sampler.handle; |
| 736 | const Tegra::Texture::TSCEntry& config = info.tsc; | ||
| 737 | if (mag_filter != config.mag_filter) { | 738 | if (mag_filter != config.mag_filter) { |
| 738 | mag_filter = config.mag_filter; | 739 | mag_filter = config.mag_filter; |
| 739 | glSamplerParameteri( | 740 | glSamplerParameteri( |
| @@ -775,30 +776,50 @@ void RasterizerOpenGL::SamplerInfo::SyncWithConfig(const Tegra::Texture::FullTex | |||
| 775 | MaxwellToGL::DepthCompareFunc(depth_compare_func)); | 776 | MaxwellToGL::DepthCompareFunc(depth_compare_func)); |
| 776 | } | 777 | } |
| 777 | 778 | ||
| 778 | if (wrap_u == Tegra::Texture::WrapMode::Border || wrap_v == Tegra::Texture::WrapMode::Border || | 779 | GLvec4 new_border_color; |
| 779 | wrap_p == Tegra::Texture::WrapMode::Border) { | 780 | if (config.srgb_conversion) { |
| 780 | const GLvec4 new_border_color = {{config.border_color_r, config.border_color_g, | 781 | new_border_color[0] = config.srgb_border_color_r / 255.0f; |
| 781 | config.border_color_b, config.border_color_a}}; | 782 | new_border_color[1] = config.srgb_border_color_g / 255.0f; |
| 782 | if (border_color != new_border_color) { | 783 | new_border_color[2] = config.srgb_border_color_g / 255.0f; |
| 783 | border_color = new_border_color; | 784 | } else { |
| 784 | glSamplerParameterfv(s, GL_TEXTURE_BORDER_COLOR, border_color.data()); | 785 | new_border_color[0] = config.border_color_r; |
| 785 | } | 786 | new_border_color[1] = config.border_color_g; |
| 787 | new_border_color[2] = config.border_color_b; | ||
| 786 | } | 788 | } |
| 787 | if (info.tic.use_header_opt_control == 0) { | 789 | new_border_color[3] = config.border_color_a; |
| 790 | |||
| 791 | if (border_color != new_border_color) { | ||
| 792 | border_color = new_border_color; | ||
| 793 | glSamplerParameterfv(s, GL_TEXTURE_BORDER_COLOR, border_color.data()); | ||
| 794 | } | ||
| 795 | |||
| 796 | const float anisotropic_max = static_cast<float>(1 << config.max_anisotropy.Value()); | ||
| 797 | if (anisotropic_max != max_anisotropic) { | ||
| 798 | max_anisotropic = anisotropic_max; | ||
| 788 | if (GLAD_GL_ARB_texture_filter_anisotropic) { | 799 | if (GLAD_GL_ARB_texture_filter_anisotropic) { |
| 789 | glSamplerParameterf(s, GL_TEXTURE_MAX_ANISOTROPY, | 800 | glSamplerParameterf(s, GL_TEXTURE_MAX_ANISOTROPY, max_anisotropic); |
| 790 | static_cast<float>(1 << info.tic.max_anisotropy.Value())); | ||
| 791 | } else if (GLAD_GL_EXT_texture_filter_anisotropic) { | 801 | } else if (GLAD_GL_EXT_texture_filter_anisotropic) { |
| 792 | glSamplerParameterf(s, GL_TEXTURE_MAX_ANISOTROPY_EXT, | 802 | glSamplerParameterf(s, GL_TEXTURE_MAX_ANISOTROPY_EXT, max_anisotropic); |
| 793 | static_cast<float>(1 << info.tic.max_anisotropy.Value())); | ||
| 794 | } | 803 | } |
| 795 | glSamplerParameterf(s, GL_TEXTURE_MIN_LOD, | 804 | } |
| 796 | static_cast<float>(info.tic.res_min_mip_level.Value())); | 805 | const float lod_min = static_cast<float>(config.min_lod_clamp.Value()) / 256.0f; |
| 797 | glSamplerParameterf(s, GL_TEXTURE_MAX_LOD, | 806 | if (lod_min != min_lod) { |
| 798 | static_cast<float>(info.tic.res_max_mip_level.Value() == 0 | 807 | min_lod = lod_min; |
| 799 | ? 16 | 808 | glSamplerParameterf(s, GL_TEXTURE_MIN_LOD, min_lod); |
| 800 | : info.tic.res_max_mip_level.Value())); | 809 | } |
| 801 | glSamplerParameterf(s, GL_TEXTURE_LOD_BIAS, info.tic.mip_lod_bias.Value() / 256.f); | 810 | |
| 811 | const float lod_max = static_cast<float>(config.max_lod_clamp.Value()) / 256.0f; | ||
| 812 | if (lod_max != max_lod) { | ||
| 813 | max_lod = lod_max; | ||
| 814 | glSamplerParameterf(s, GL_TEXTURE_MAX_LOD, max_lod); | ||
| 815 | } | ||
| 816 | const u32 bias = config.mip_lod_bias.Value(); | ||
| 817 | // Sign extend the 13-bit value. | ||
| 818 | const u32 mask = 1U << (13 - 1); | ||
| 819 | const float bias_lod = static_cast<s32>((bias ^ mask) - mask) / 256.f; | ||
| 820 | if (lod_bias != bias_lod) { | ||
| 821 | lod_bias = bias_lod; | ||
| 822 | glSamplerParameterf(s, GL_TEXTURE_LOD_BIAS, lod_bias); | ||
| 802 | } | 823 | } |
| 803 | } | 824 | } |
| 804 | 825 | ||
| @@ -897,7 +918,7 @@ u32 RasterizerOpenGL::SetupTextures(Maxwell::ShaderStage stage, Shader& shader, | |||
| 897 | continue; | 918 | continue; |
| 898 | } | 919 | } |
| 899 | 920 | ||
| 900 | texture_samplers[current_bindpoint].SyncWithConfig(texture); | 921 | texture_samplers[current_bindpoint].SyncWithConfig(texture.tsc); |
| 901 | Surface surface = res_cache.GetTextureSurface(texture, entry); | 922 | Surface surface = res_cache.GetTextureSurface(texture, entry); |
| 902 | if (surface != nullptr) { | 923 | if (surface != nullptr) { |
| 903 | state.texture_units[current_bindpoint].texture = surface->Texture().handle; | 924 | state.texture_units[current_bindpoint].texture = surface->Texture().handle; |
| @@ -921,15 +942,15 @@ u32 RasterizerOpenGL::SetupTextures(Maxwell::ShaderStage stage, Shader& shader, | |||
| 921 | 942 | ||
| 922 | void RasterizerOpenGL::SyncViewport(OpenGLState& current_state) { | 943 | void RasterizerOpenGL::SyncViewport(OpenGLState& current_state) { |
| 923 | const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs; | 944 | const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs; |
| 924 | for (size_t i = 0; i < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets; i++) { | 945 | for (std::size_t i = 0; i < Tegra::Engines::Maxwell3D::Regs::NumViewports; i++) { |
| 925 | const MathUtil::Rectangle<s32> viewport_rect{regs.viewport_transform[i].GetRect()}; | 946 | const MathUtil::Rectangle<s32> viewport_rect{regs.viewport_transform[i].GetRect()}; |
| 926 | auto& viewport = current_state.viewports[i]; | 947 | auto& viewport = current_state.viewports[i]; |
| 927 | viewport.x = viewport_rect.left; | 948 | viewport.x = viewport_rect.left; |
| 928 | viewport.y = viewport_rect.bottom; | 949 | viewport.y = viewport_rect.bottom; |
| 929 | viewport.width = static_cast<GLfloat>(viewport_rect.GetWidth()); | 950 | viewport.width = static_cast<GLfloat>(viewport_rect.GetWidth()); |
| 930 | viewport.height = static_cast<GLfloat>(viewport_rect.GetHeight()); | 951 | viewport.height = static_cast<GLfloat>(viewport_rect.GetHeight()); |
| 931 | viewport.depth_range_far = regs.viewport[i].depth_range_far; | 952 | viewport.depth_range_far = regs.viewports[i].depth_range_far; |
| 932 | viewport.depth_range_near = regs.viewport[i].depth_range_near; | 953 | viewport.depth_range_near = regs.viewports[i].depth_range_near; |
| 933 | } | 954 | } |
| 934 | } | 955 | } |
| 935 | 956 | ||
| @@ -1020,7 +1041,9 @@ void RasterizerOpenGL::SyncStencilTestState() { | |||
| 1020 | 1041 | ||
| 1021 | void RasterizerOpenGL::SyncColorMask() { | 1042 | void RasterizerOpenGL::SyncColorMask() { |
| 1022 | const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs; | 1043 | const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs; |
| 1023 | for (size_t i = 0; i < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets; i++) { | 1044 | const std::size_t count = |
| 1045 | regs.independent_blend_enable ? Tegra::Engines::Maxwell3D::Regs::NumRenderTargets : 1; | ||
| 1046 | for (std::size_t i = 0; i < count; i++) { | ||
| 1024 | const auto& source = regs.color_mask[regs.color_mask_common ? 0 : i]; | 1047 | const auto& source = regs.color_mask[regs.color_mask_common ? 0 : i]; |
| 1025 | auto& dest = state.color_mask[i]; | 1048 | auto& dest = state.color_mask[i]; |
| 1026 | dest.red_enabled = (source.R == 0) ? GL_FALSE : GL_TRUE; | 1049 | dest.red_enabled = (source.R == 0) ? GL_FALSE : GL_TRUE; |
| @@ -1030,6 +1053,17 @@ void RasterizerOpenGL::SyncColorMask() { | |||
| 1030 | } | 1053 | } |
| 1031 | } | 1054 | } |
| 1032 | 1055 | ||
| 1056 | void RasterizerOpenGL::SyncMultiSampleState() { | ||
| 1057 | const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs; | ||
| 1058 | state.multisample_control.alpha_to_coverage = regs.multisample_control.alpha_to_coverage != 0; | ||
| 1059 | state.multisample_control.alpha_to_one = regs.multisample_control.alpha_to_one != 0; | ||
| 1060 | } | ||
| 1061 | |||
| 1062 | void RasterizerOpenGL::SyncFragmentColorClampState() { | ||
| 1063 | const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs; | ||
| 1064 | state.fragment_color_clamp.enabled = regs.frag_color_clamp != 0; | ||
| 1065 | } | ||
| 1066 | |||
| 1033 | void RasterizerOpenGL::SyncBlendState() { | 1067 | void RasterizerOpenGL::SyncBlendState() { |
| 1034 | const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs; | 1068 | const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs; |
| 1035 | 1069 | ||
| @@ -1041,43 +1075,40 @@ void RasterizerOpenGL::SyncBlendState() { | |||
| 1041 | state.independant_blend.enabled = regs.independent_blend_enable; | 1075 | state.independant_blend.enabled = regs.independent_blend_enable; |
| 1042 | if (!state.independant_blend.enabled) { | 1076 | if (!state.independant_blend.enabled) { |
| 1043 | auto& blend = state.blend[0]; | 1077 | auto& blend = state.blend[0]; |
| 1044 | blend.enabled = regs.blend.enable[0] != 0; | 1078 | const auto& src = regs.blend; |
| 1045 | blend.separate_alpha = regs.blend.separate_alpha; | 1079 | blend.enabled = src.enable[0] != 0; |
| 1046 | blend.rgb_equation = MaxwellToGL::BlendEquation(regs.blend.equation_rgb); | 1080 | if (blend.enabled) { |
| 1047 | blend.src_rgb_func = MaxwellToGL::BlendFunc(regs.blend.factor_source_rgb); | 1081 | blend.rgb_equation = MaxwellToGL::BlendEquation(src.equation_rgb); |
| 1048 | blend.dst_rgb_func = MaxwellToGL::BlendFunc(regs.blend.factor_dest_rgb); | 1082 | blend.src_rgb_func = MaxwellToGL::BlendFunc(src.factor_source_rgb); |
| 1049 | if (blend.separate_alpha) { | 1083 | blend.dst_rgb_func = MaxwellToGL::BlendFunc(src.factor_dest_rgb); |
| 1050 | blend.a_equation = MaxwellToGL::BlendEquation(regs.blend.equation_a); | 1084 | blend.a_equation = MaxwellToGL::BlendEquation(src.equation_a); |
| 1051 | blend.src_a_func = MaxwellToGL::BlendFunc(regs.blend.factor_source_a); | 1085 | blend.src_a_func = MaxwellToGL::BlendFunc(src.factor_source_a); |
| 1052 | blend.dst_a_func = MaxwellToGL::BlendFunc(regs.blend.factor_dest_a); | 1086 | blend.dst_a_func = MaxwellToGL::BlendFunc(src.factor_dest_a); |
| 1053 | } | 1087 | } |
| 1054 | for (size_t i = 1; i < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets; i++) { | 1088 | for (std::size_t i = 1; i < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets; i++) { |
| 1055 | state.blend[i].enabled = false; | 1089 | state.blend[i].enabled = false; |
| 1056 | } | 1090 | } |
| 1057 | return; | 1091 | return; |
| 1058 | } | 1092 | } |
| 1059 | 1093 | ||
| 1060 | for (size_t i = 0; i < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets; i++) { | 1094 | for (std::size_t i = 0; i < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets; i++) { |
| 1061 | auto& blend = state.blend[i]; | 1095 | auto& blend = state.blend[i]; |
| 1096 | const auto& src = regs.independent_blend[i]; | ||
| 1062 | blend.enabled = regs.blend.enable[i] != 0; | 1097 | blend.enabled = regs.blend.enable[i] != 0; |
| 1063 | if (!blend.enabled) | 1098 | if (!blend.enabled) |
| 1064 | continue; | 1099 | continue; |
| 1065 | blend.separate_alpha = regs.independent_blend[i].separate_alpha; | 1100 | blend.rgb_equation = MaxwellToGL::BlendEquation(src.equation_rgb); |
| 1066 | blend.rgb_equation = MaxwellToGL::BlendEquation(regs.independent_blend[i].equation_rgb); | 1101 | blend.src_rgb_func = MaxwellToGL::BlendFunc(src.factor_source_rgb); |
| 1067 | blend.src_rgb_func = MaxwellToGL::BlendFunc(regs.independent_blend[i].factor_source_rgb); | 1102 | blend.dst_rgb_func = MaxwellToGL::BlendFunc(src.factor_dest_rgb); |
| 1068 | blend.dst_rgb_func = MaxwellToGL::BlendFunc(regs.independent_blend[i].factor_dest_rgb); | 1103 | blend.a_equation = MaxwellToGL::BlendEquation(src.equation_a); |
| 1069 | if (blend.separate_alpha) { | 1104 | blend.src_a_func = MaxwellToGL::BlendFunc(src.factor_source_a); |
| 1070 | blend.a_equation = MaxwellToGL::BlendEquation(regs.independent_blend[i].equation_a); | 1105 | blend.dst_a_func = MaxwellToGL::BlendFunc(src.factor_dest_a); |
| 1071 | blend.src_a_func = MaxwellToGL::BlendFunc(regs.independent_blend[i].factor_source_a); | ||
| 1072 | blend.dst_a_func = MaxwellToGL::BlendFunc(regs.independent_blend[i].factor_dest_a); | ||
| 1073 | } | ||
| 1074 | } | 1106 | } |
| 1075 | } | 1107 | } |
| 1076 | 1108 | ||
| 1077 | void RasterizerOpenGL::SyncLogicOpState() { | 1109 | void RasterizerOpenGL::SyncLogicOpState() { |
| 1078 | const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs; | 1110 | const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs; |
| 1079 | 1111 | ||
| 1080 | // TODO(Subv): Support more than just render target 0. | ||
| 1081 | state.logic_op.enabled = regs.logic_op.enable != 0; | 1112 | state.logic_op.enabled = regs.logic_op.enable != 0; |
| 1082 | 1113 | ||
| 1083 | if (!state.logic_op.enabled) | 1114 | if (!state.logic_op.enabled) |
| @@ -1090,19 +1121,21 @@ void RasterizerOpenGL::SyncLogicOpState() { | |||
| 1090 | } | 1121 | } |
| 1091 | 1122 | ||
| 1092 | void RasterizerOpenGL::SyncScissorTest() { | 1123 | void RasterizerOpenGL::SyncScissorTest() { |
| 1093 | // TODO: what is the correct behavior here, a single scissor for all targets | ||
| 1094 | // or scissor disabled for the rest of the targets? | ||
| 1095 | const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs; | 1124 | const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs; |
| 1096 | state.scissor.enabled = (regs.scissor_test.enable != 0); | 1125 | for (std::size_t i = 0; i < Tegra::Engines::Maxwell3D::Regs::NumViewports; i++) { |
| 1097 | if (regs.scissor_test.enable == 0) { | 1126 | const auto& src = regs.scissor_test[i]; |
| 1098 | return; | 1127 | auto& dst = state.viewports[i].scissor; |
| 1128 | dst.enabled = (src.enable != 0); | ||
| 1129 | if (dst.enabled == 0) { | ||
| 1130 | return; | ||
| 1131 | } | ||
| 1132 | const u32 width = src.max_x - src.min_x; | ||
| 1133 | const u32 height = src.max_y - src.min_y; | ||
| 1134 | dst.x = src.min_x; | ||
| 1135 | dst.y = src.min_y; | ||
| 1136 | dst.width = width; | ||
| 1137 | dst.height = height; | ||
| 1099 | } | 1138 | } |
| 1100 | const u32 width = regs.scissor_test.max_x - regs.scissor_test.min_x; | ||
| 1101 | const u32 height = regs.scissor_test.max_y - regs.scissor_test.min_y; | ||
| 1102 | state.scissor.x = regs.scissor_test.min_x; | ||
| 1103 | state.scissor.y = regs.scissor_test.min_y; | ||
| 1104 | state.scissor.width = width; | ||
| 1105 | state.scissor.height = height; | ||
| 1106 | } | 1139 | } |
| 1107 | 1140 | ||
| 1108 | void RasterizerOpenGL::SyncTransformFeedback() { | 1141 | void RasterizerOpenGL::SyncTransformFeedback() { |
| @@ -1116,11 +1149,7 @@ void RasterizerOpenGL::SyncTransformFeedback() { | |||
| 1116 | 1149 | ||
| 1117 | void RasterizerOpenGL::SyncPointState() { | 1150 | void RasterizerOpenGL::SyncPointState() { |
| 1118 | const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs; | 1151 | const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs; |
| 1119 | 1152 | state.point.size = regs.point_size; | |
| 1120 | // TODO(Rodrigo): Most games do not set a point size. I think this is a case of a | ||
| 1121 | // register carrying a default value. For now, if the point size is zero, assume it's | ||
| 1122 | // OpenGL's default (1). | ||
| 1123 | state.point.size = regs.point_size == 0 ? 1 : regs.point_size; | ||
| 1124 | } | 1153 | } |
| 1125 | 1154 | ||
| 1126 | void RasterizerOpenGL::CheckAlphaTests() { | 1155 | void RasterizerOpenGL::CheckAlphaTests() { |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index 8ef0f6c12..6e78ab4cd 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::FullTextureInfo& 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; |
| @@ -100,6 +100,10 @@ private: | |||
| 100 | bool uses_depth_compare; | 100 | bool uses_depth_compare; |
| 101 | Tegra::Texture::DepthCompareFunc depth_compare_func; | 101 | Tegra::Texture::DepthCompareFunc depth_compare_func; |
| 102 | GLvec4 border_color; | 102 | GLvec4 border_color; |
| 103 | float min_lod; | ||
| 104 | float max_lod; | ||
| 105 | float lod_bias; | ||
| 106 | float max_anisotropic; | ||
| 103 | }; | 107 | }; |
| 104 | 108 | ||
| 105 | /** | 109 | /** |
| @@ -160,6 +164,12 @@ private: | |||
| 160 | /// Syncs the LogicOp state to match the guest state | 164 | /// Syncs the LogicOp state to match the guest state |
| 161 | void SyncLogicOpState(); | 165 | void SyncLogicOpState(); |
| 162 | 166 | ||
| 167 | /// Syncs the the color clamp state | ||
| 168 | void SyncFragmentColorClampState(); | ||
| 169 | |||
| 170 | /// Syncs the alpha coverage and alpha to one | ||
| 171 | void SyncMultiSampleState(); | ||
| 172 | |||
| 163 | /// Syncs the scissor test state to match the guest state | 173 | /// Syncs the scissor test state to match the guest state |
| 164 | void SyncScissorTest(); | 174 | void SyncScissorTest(); |
| 165 | 175 | ||
diff --git a/src/video_core/renderer_opengl/gl_shader_manager.h b/src/video_core/renderer_opengl/gl_shader_manager.h index 2a069cdd8..9a5d7e289 100644 --- a/src/video_core/renderer_opengl/gl_shader_manager.h +++ b/src/video_core/renderer_opengl/gl_shader_manager.h | |||
| @@ -67,6 +67,7 @@ public: | |||
| 67 | glUseProgramStages(pipeline.handle, GL_FRAGMENT_SHADER_BIT, fs); | 67 | glUseProgramStages(pipeline.handle, GL_FRAGMENT_SHADER_BIT, fs); |
| 68 | state.draw.shader_program = 0; | 68 | state.draw.shader_program = 0; |
| 69 | state.draw.program_pipeline = pipeline.handle; | 69 | state.draw.program_pipeline = pipeline.handle; |
| 70 | state.geometry_shaders.enabled = (gs != 0); | ||
| 70 | } | 71 | } |
| 71 | 72 | ||
| 72 | private: | 73 | private: |
diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp index 98622a058..d9910c6e8 100644 --- a/src/video_core/renderer_opengl/gl_state.cpp +++ b/src/video_core/renderer_opengl/gl_state.cpp | |||
| @@ -14,7 +14,10 @@ OpenGLState OpenGLState::cur_state; | |||
| 14 | bool OpenGLState::s_rgb_used; | 14 | bool OpenGLState::s_rgb_used; |
| 15 | OpenGLState::OpenGLState() { | 15 | OpenGLState::OpenGLState() { |
| 16 | // These all match default OpenGL values | 16 | // These all match default OpenGL values |
| 17 | geometry_shaders.enabled = false; | ||
| 17 | framebuffer_srgb.enabled = false; | 18 | framebuffer_srgb.enabled = false; |
| 19 | multisample_control.alpha_to_coverage = false; | ||
| 20 | multisample_control.alpha_to_one = false; | ||
| 18 | cull.enabled = false; | 21 | cull.enabled = false; |
| 19 | cull.mode = GL_BACK; | 22 | cull.mode = GL_BACK; |
| 20 | cull.front_face = GL_CCW; | 23 | cull.front_face = GL_CCW; |
| @@ -50,12 +53,12 @@ OpenGLState::OpenGLState() { | |||
| 50 | item.height = 0; | 53 | item.height = 0; |
| 51 | item.depth_range_near = 0.0f; | 54 | item.depth_range_near = 0.0f; |
| 52 | item.depth_range_far = 1.0f; | 55 | item.depth_range_far = 1.0f; |
| 56 | item.scissor.enabled = false; | ||
| 57 | item.scissor.x = 0; | ||
| 58 | item.scissor.y = 0; | ||
| 59 | item.scissor.width = 0; | ||
| 60 | item.scissor.height = 0; | ||
| 53 | } | 61 | } |
| 54 | scissor.enabled = false; | ||
| 55 | scissor.x = 0; | ||
| 56 | scissor.y = 0; | ||
| 57 | scissor.width = 0; | ||
| 58 | scissor.height = 0; | ||
| 59 | for (auto& item : blend) { | 62 | for (auto& item : blend) { |
| 60 | item.enabled = true; | 63 | item.enabled = true; |
| 61 | item.rgb_equation = GL_FUNC_ADD; | 64 | item.rgb_equation = GL_FUNC_ADD; |
| @@ -88,6 +91,7 @@ OpenGLState::OpenGLState() { | |||
| 88 | clip_distance = {}; | 91 | clip_distance = {}; |
| 89 | 92 | ||
| 90 | point.size = 1; | 93 | point.size = 1; |
| 94 | fragment_color_clamp.enabled = false; | ||
| 91 | } | 95 | } |
| 92 | 96 | ||
| 93 | void OpenGLState::ApplyDefaultState() { | 97 | void OpenGLState::ApplyDefaultState() { |
| @@ -136,7 +140,7 @@ void OpenGLState::ApplyCulling() const { | |||
| 136 | } | 140 | } |
| 137 | 141 | ||
| 138 | void OpenGLState::ApplyColorMask() const { | 142 | void OpenGLState::ApplyColorMask() const { |
| 139 | if (GLAD_GL_ARB_viewport_array) { | 143 | if (GLAD_GL_ARB_viewport_array && independant_blend.enabled) { |
| 140 | for (size_t i = 0; i < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets; i++) { | 144 | for (size_t i = 0; i < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets; i++) { |
| 141 | const auto& updated = color_mask[i]; | 145 | const auto& updated = color_mask[i]; |
| 142 | const auto& current = cur_state.color_mask[i]; | 146 | const auto& current = cur_state.color_mask[i]; |
| @@ -230,26 +234,10 @@ void OpenGLState::ApplyStencilTest() const { | |||
| 230 | } | 234 | } |
| 231 | } | 235 | } |
| 232 | 236 | ||
| 233 | void OpenGLState::ApplyScissor() const { | ||
| 234 | const bool scissor_changed = scissor.enabled != cur_state.scissor.enabled; | ||
| 235 | if (scissor_changed) { | ||
| 236 | if (scissor.enabled) { | ||
| 237 | glEnable(GL_SCISSOR_TEST); | ||
| 238 | } else { | ||
| 239 | glDisable(GL_SCISSOR_TEST); | ||
| 240 | } | ||
| 241 | } | ||
| 242 | if (scissor.enabled && | ||
| 243 | (scissor_changed || scissor.x != cur_state.scissor.x || scissor.y != cur_state.scissor.y || | ||
| 244 | scissor.width != cur_state.scissor.width || scissor.height != cur_state.scissor.height)) { | ||
| 245 | glScissor(scissor.x, scissor.y, scissor.width, scissor.height); | ||
| 246 | } | ||
| 247 | } | ||
| 248 | |||
| 249 | void OpenGLState::ApplyViewport() const { | 237 | void OpenGLState::ApplyViewport() const { |
| 250 | if (GLAD_GL_ARB_viewport_array) { | 238 | if (GLAD_GL_ARB_viewport_array && geometry_shaders.enabled) { |
| 251 | for (GLuint i = 0; | 239 | for (GLuint i = 0; i < static_cast<GLuint>(Tegra::Engines::Maxwell3D::Regs::NumViewports); |
| 252 | i < static_cast<GLuint>(Tegra::Engines::Maxwell3D::Regs::NumRenderTargets); i++) { | 240 | i++) { |
| 253 | const auto& current = cur_state.viewports[i]; | 241 | const auto& current = cur_state.viewports[i]; |
| 254 | const auto& updated = viewports[i]; | 242 | const auto& updated = viewports[i]; |
| 255 | if (updated.x != current.x || updated.y != current.y || | 243 | if (updated.x != current.x || updated.y != current.y || |
| @@ -260,6 +248,22 @@ void OpenGLState::ApplyViewport() const { | |||
| 260 | updated.depth_range_far != current.depth_range_far) { | 248 | updated.depth_range_far != current.depth_range_far) { |
| 261 | glDepthRangeIndexed(i, updated.depth_range_near, updated.depth_range_far); | 249 | glDepthRangeIndexed(i, updated.depth_range_near, updated.depth_range_far); |
| 262 | } | 250 | } |
| 251 | const bool scissor_changed = updated.scissor.enabled != current.scissor.enabled; | ||
| 252 | if (scissor_changed) { | ||
| 253 | if (updated.scissor.enabled) { | ||
| 254 | glEnablei(GL_SCISSOR_TEST, i); | ||
| 255 | } else { | ||
| 256 | glDisablei(GL_SCISSOR_TEST, i); | ||
| 257 | } | ||
| 258 | } | ||
| 259 | if (updated.scissor.enabled && | ||
| 260 | (scissor_changed || updated.scissor.x != current.scissor.x || | ||
| 261 | updated.scissor.y != current.scissor.y || | ||
| 262 | updated.scissor.width != current.scissor.width || | ||
| 263 | updated.scissor.height != current.scissor.height)) { | ||
| 264 | glScissorIndexed(i, updated.scissor.x, updated.scissor.y, updated.scissor.width, | ||
| 265 | updated.scissor.height); | ||
| 266 | } | ||
| 263 | } | 267 | } |
| 264 | } else { | 268 | } else { |
| 265 | const auto& current = cur_state.viewports[0]; | 269 | const auto& current = cur_state.viewports[0]; |
| @@ -273,6 +277,21 @@ void OpenGLState::ApplyViewport() const { | |||
| 273 | updated.depth_range_far != current.depth_range_far) { | 277 | updated.depth_range_far != current.depth_range_far) { |
| 274 | glDepthRange(updated.depth_range_near, updated.depth_range_far); | 278 | glDepthRange(updated.depth_range_near, updated.depth_range_far); |
| 275 | } | 279 | } |
| 280 | const bool scissor_changed = updated.scissor.enabled != current.scissor.enabled; | ||
| 281 | if (scissor_changed) { | ||
| 282 | if (updated.scissor.enabled) { | ||
| 283 | glEnable(GL_SCISSOR_TEST); | ||
| 284 | } else { | ||
| 285 | glDisable(GL_SCISSOR_TEST); | ||
| 286 | } | ||
| 287 | } | ||
| 288 | if (updated.scissor.enabled && (scissor_changed || updated.scissor.x != current.scissor.x || | ||
| 289 | updated.scissor.y != current.scissor.y || | ||
| 290 | updated.scissor.width != current.scissor.width || | ||
| 291 | updated.scissor.height != current.scissor.height)) { | ||
| 292 | glScissor(updated.scissor.x, updated.scissor.y, updated.scissor.width, | ||
| 293 | updated.scissor.height); | ||
| 294 | } | ||
| 276 | } | 295 | } |
| 277 | } | 296 | } |
| 278 | 297 | ||
| @@ -290,27 +309,16 @@ void OpenGLState::ApplyGlobalBlending() const { | |||
| 290 | if (!updated.enabled) { | 309 | if (!updated.enabled) { |
| 291 | return; | 310 | return; |
| 292 | } | 311 | } |
| 293 | if (updated.separate_alpha) { | 312 | if (blend_changed || updated.src_rgb_func != current.src_rgb_func || |
| 294 | if (blend_changed || updated.src_rgb_func != current.src_rgb_func || | 313 | updated.dst_rgb_func != current.dst_rgb_func || updated.src_a_func != current.src_a_func || |
| 295 | updated.dst_rgb_func != current.dst_rgb_func || | 314 | updated.dst_a_func != current.dst_a_func) { |
| 296 | updated.src_a_func != current.src_a_func || updated.dst_a_func != current.dst_a_func) { | 315 | glBlendFuncSeparate(updated.src_rgb_func, updated.dst_rgb_func, updated.src_a_func, |
| 297 | glBlendFuncSeparate(updated.src_rgb_func, updated.dst_rgb_func, updated.src_a_func, | 316 | updated.dst_a_func); |
| 298 | updated.dst_a_func); | 317 | } |
| 299 | } | ||
| 300 | |||
| 301 | if (blend_changed || updated.rgb_equation != current.rgb_equation || | ||
| 302 | updated.a_equation != current.a_equation) { | ||
| 303 | glBlendEquationSeparate(updated.rgb_equation, updated.a_equation); | ||
| 304 | } | ||
| 305 | } else { | ||
| 306 | if (blend_changed || updated.src_rgb_func != current.src_rgb_func || | ||
| 307 | updated.dst_rgb_func != current.dst_rgb_func) { | ||
| 308 | glBlendFunc(updated.src_rgb_func, updated.dst_rgb_func); | ||
| 309 | } | ||
| 310 | 318 | ||
| 311 | if (blend_changed || updated.rgb_equation != current.rgb_equation) { | 319 | if (blend_changed || updated.rgb_equation != current.rgb_equation || |
| 312 | glBlendEquation(updated.rgb_equation); | 320 | updated.a_equation != current.a_equation) { |
| 313 | } | 321 | glBlendEquationSeparate(updated.rgb_equation, updated.a_equation); |
| 314 | } | 322 | } |
| 315 | } | 323 | } |
| 316 | 324 | ||
| @@ -328,29 +336,17 @@ void OpenGLState::ApplyTargetBlending(std::size_t target, bool force) const { | |||
| 328 | if (!updated.enabled) { | 336 | if (!updated.enabled) { |
| 329 | return; | 337 | return; |
| 330 | } | 338 | } |
| 331 | if (updated.separate_alpha) { | 339 | if (blend_changed || updated.src_rgb_func != current.src_rgb_func || |
| 332 | if (blend_changed || updated.src_rgb_func != current.src_rgb_func || | 340 | updated.dst_rgb_func != current.dst_rgb_func || updated.src_a_func != current.src_a_func || |
| 333 | updated.dst_rgb_func != current.dst_rgb_func || | 341 | updated.dst_a_func != current.dst_a_func) { |
| 334 | updated.src_a_func != current.src_a_func || updated.dst_a_func != current.dst_a_func) { | 342 | glBlendFuncSeparateiARB(static_cast<GLuint>(target), updated.src_rgb_func, |
| 335 | glBlendFuncSeparateiARB(static_cast<GLuint>(target), updated.src_rgb_func, | 343 | updated.dst_rgb_func, updated.src_a_func, updated.dst_a_func); |
| 336 | updated.dst_rgb_func, updated.src_a_func, updated.dst_a_func); | 344 | } |
| 337 | } | ||
| 338 | |||
| 339 | if (blend_changed || updated.rgb_equation != current.rgb_equation || | ||
| 340 | updated.a_equation != current.a_equation) { | ||
| 341 | glBlendEquationSeparateiARB(static_cast<GLuint>(target), updated.rgb_equation, | ||
| 342 | updated.a_equation); | ||
| 343 | } | ||
| 344 | } else { | ||
| 345 | if (blend_changed || updated.src_rgb_func != current.src_rgb_func || | ||
| 346 | updated.dst_rgb_func != current.dst_rgb_func) { | ||
| 347 | glBlendFunciARB(static_cast<GLuint>(target), updated.src_rgb_func, | ||
| 348 | updated.dst_rgb_func); | ||
| 349 | } | ||
| 350 | 345 | ||
| 351 | if (blend_changed || updated.rgb_equation != current.rgb_equation) { | 346 | if (blend_changed || updated.rgb_equation != current.rgb_equation || |
| 352 | glBlendEquationiARB(static_cast<GLuint>(target), updated.rgb_equation); | 347 | updated.a_equation != current.a_equation) { |
| 353 | } | 348 | glBlendEquationSeparateiARB(static_cast<GLuint>(target), updated.rgb_equation, |
| 349 | updated.a_equation); | ||
| 354 | } | 350 | } |
| 355 | } | 351 | } |
| 356 | 352 | ||
| @@ -481,9 +477,29 @@ void OpenGLState::Apply() const { | |||
| 481 | if (point.size != cur_state.point.size) { | 477 | if (point.size != cur_state.point.size) { |
| 482 | glPointSize(point.size); | 478 | glPointSize(point.size); |
| 483 | } | 479 | } |
| 480 | if (GLAD_GL_ARB_color_buffer_float) { | ||
| 481 | if (fragment_color_clamp.enabled != cur_state.fragment_color_clamp.enabled) { | ||
| 482 | glClampColor(GL_CLAMP_FRAGMENT_COLOR_ARB, | ||
| 483 | fragment_color_clamp.enabled ? GL_TRUE : GL_FALSE); | ||
| 484 | } | ||
| 485 | } | ||
| 486 | if (multisample_control.alpha_to_coverage != cur_state.multisample_control.alpha_to_coverage) { | ||
| 487 | if (multisample_control.alpha_to_coverage) { | ||
| 488 | glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE); | ||
| 489 | } else { | ||
| 490 | glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE); | ||
| 491 | } | ||
| 492 | } | ||
| 493 | if (multisample_control.alpha_to_one != cur_state.multisample_control.alpha_to_one) { | ||
| 494 | if (multisample_control.alpha_to_one) { | ||
| 495 | glEnable(GL_SAMPLE_ALPHA_TO_ONE); | ||
| 496 | } else { | ||
| 497 | glDisable(GL_SAMPLE_ALPHA_TO_ONE); | ||
| 498 | } | ||
| 499 | } | ||
| 500 | |||
| 484 | ApplyColorMask(); | 501 | ApplyColorMask(); |
| 485 | ApplyViewport(); | 502 | ApplyViewport(); |
| 486 | ApplyScissor(); | ||
| 487 | ApplyStencilTest(); | 503 | ApplyStencilTest(); |
| 488 | ApplySRgb(); | 504 | ApplySRgb(); |
| 489 | ApplyCulling(); | 505 | ApplyCulling(); |
diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h index e5d1baae6..bdc743b0f 100644 --- a/src/video_core/renderer_opengl/gl_state.h +++ b/src/video_core/renderer_opengl/gl_state.h | |||
| @@ -40,6 +40,19 @@ public: | |||
| 40 | } framebuffer_srgb; | 40 | } framebuffer_srgb; |
| 41 | 41 | ||
| 42 | struct { | 42 | struct { |
| 43 | bool alpha_to_coverage; // GL_ALPHA_TO_COVERAGE | ||
| 44 | bool alpha_to_one; // GL_ALPHA_TO_ONE | ||
| 45 | } multisample_control; | ||
| 46 | |||
| 47 | struct { | ||
| 48 | bool enabled; // GL_CLAMP_FRAGMENT_COLOR_ARB | ||
| 49 | } fragment_color_clamp; | ||
| 50 | |||
| 51 | struct { | ||
| 52 | bool enabled; // viewports arrays are only supported when geometry shaders are enabled. | ||
| 53 | } geometry_shaders; | ||
| 54 | |||
| 55 | struct { | ||
| 43 | bool enabled; // GL_CULL_FACE | 56 | bool enabled; // GL_CULL_FACE |
| 44 | GLenum mode; // GL_CULL_FACE_MODE | 57 | GLenum mode; // GL_CULL_FACE_MODE |
| 45 | GLenum front_face; // GL_FRONT_FACE | 58 | GLenum front_face; // GL_FRONT_FACE |
| @@ -79,7 +92,6 @@ public: | |||
| 79 | 92 | ||
| 80 | struct Blend { | 93 | struct Blend { |
| 81 | bool enabled; // GL_BLEND | 94 | bool enabled; // GL_BLEND |
| 82 | bool separate_alpha; // Independent blend enabled | ||
| 83 | GLenum rgb_equation; // GL_BLEND_EQUATION_RGB | 95 | GLenum rgb_equation; // GL_BLEND_EQUATION_RGB |
| 84 | GLenum a_equation; // GL_BLEND_EQUATION_ALPHA | 96 | GLenum a_equation; // GL_BLEND_EQUATION_ALPHA |
| 85 | GLenum src_rgb_func; // GL_BLEND_SRC_RGB | 97 | GLenum src_rgb_func; // GL_BLEND_SRC_RGB |
| @@ -150,16 +162,15 @@ public: | |||
| 150 | GLfloat height; | 162 | GLfloat height; |
| 151 | GLfloat depth_range_near; // GL_DEPTH_RANGE | 163 | GLfloat depth_range_near; // GL_DEPTH_RANGE |
| 152 | GLfloat depth_range_far; // GL_DEPTH_RANGE | 164 | GLfloat depth_range_far; // GL_DEPTH_RANGE |
| 165 | struct { | ||
| 166 | bool enabled; // GL_SCISSOR_TEST | ||
| 167 | GLint x; | ||
| 168 | GLint y; | ||
| 169 | GLsizei width; | ||
| 170 | GLsizei height; | ||
| 171 | } scissor; | ||
| 153 | }; | 172 | }; |
| 154 | std::array<viewport, Tegra::Engines::Maxwell3D::Regs::NumRenderTargets> viewports; | 173 | std::array<viewport, Tegra::Engines::Maxwell3D::Regs::NumViewports> viewports; |
| 155 | |||
| 156 | struct { | ||
| 157 | bool enabled; // GL_SCISSOR_TEST | ||
| 158 | GLint x; | ||
| 159 | GLint y; | ||
| 160 | GLsizei width; | ||
| 161 | GLsizei height; | ||
| 162 | } scissor; | ||
| 163 | 174 | ||
| 164 | struct { | 175 | struct { |
| 165 | float size; // GL_POINT_SIZE | 176 | float size; // GL_POINT_SIZE |
| @@ -214,7 +225,6 @@ private: | |||
| 214 | void ApplyLogicOp() const; | 225 | void ApplyLogicOp() const; |
| 215 | void ApplyTextures() const; | 226 | void ApplyTextures() const; |
| 216 | void ApplySamplers() const; | 227 | void ApplySamplers() const; |
| 217 | void ApplyScissor() const; | ||
| 218 | }; | 228 | }; |
| 219 | 229 | ||
| 220 | } // namespace OpenGL | 230 | } // namespace OpenGL |
diff --git a/src/video_core/renderer_opengl/maxwell_to_gl.h b/src/video_core/renderer_opengl/maxwell_to_gl.h index 3ce2cc6d2..065b3929c 100644 --- a/src/video_core/renderer_opengl/maxwell_to_gl.h +++ b/src/video_core/renderer_opengl/maxwell_to_gl.h | |||
| @@ -180,6 +180,12 @@ inline GLenum WrapMode(Tegra::Texture::WrapMode wrap_mode) { | |||
| 180 | return GL_CLAMP_TO_BORDER; | 180 | return GL_CLAMP_TO_BORDER; |
| 181 | case Tegra::Texture::WrapMode::MirrorOnceClampToEdge: | 181 | case Tegra::Texture::WrapMode::MirrorOnceClampToEdge: |
| 182 | return GL_MIRROR_CLAMP_TO_EDGE; | 182 | return GL_MIRROR_CLAMP_TO_EDGE; |
| 183 | case Tegra::Texture::WrapMode::MirrorOnceBorder: | ||
| 184 | if (GL_EXT_texture_mirror_clamp) { | ||
| 185 | return GL_MIRROR_CLAMP_TO_BORDER_EXT; | ||
| 186 | } else { | ||
| 187 | return GL_MIRROR_CLAMP_TO_EDGE; | ||
| 188 | } | ||
| 183 | } | 189 | } |
| 184 | LOG_ERROR(Render_OpenGL, "Unimplemented texture wrap mode={}", static_cast<u32>(wrap_mode)); | 190 | LOG_ERROR(Render_OpenGL, "Unimplemented texture wrap mode={}", static_cast<u32>(wrap_mode)); |
| 185 | return GL_REPEAT; | 191 | return GL_REPEAT; |
diff --git a/src/video_core/textures/texture.h b/src/video_core/textures/texture.h index e199d019a..ffa08f5c1 100644 --- a/src/video_core/textures/texture.h +++ b/src/video_core/textures/texture.h | |||
| @@ -190,6 +190,7 @@ struct TICEntry { | |||
| 190 | union { | 190 | union { |
| 191 | BitField<0, 4, u32> res_min_mip_level; | 191 | BitField<0, 4, u32> res_min_mip_level; |
| 192 | BitField<4, 4, u32> res_max_mip_level; | 192 | BitField<4, 4, u32> res_max_mip_level; |
| 193 | BitField<12, 12, u32> min_lod_clamp; | ||
| 193 | }; | 194 | }; |
| 194 | 195 | ||
| 195 | GPUVAddr Address() const { | 196 | GPUVAddr Address() const { |
| @@ -284,13 +285,25 @@ struct TSCEntry { | |||
| 284 | BitField<6, 3, WrapMode> wrap_p; | 285 | BitField<6, 3, WrapMode> wrap_p; |
| 285 | BitField<9, 1, u32> depth_compare_enabled; | 286 | BitField<9, 1, u32> depth_compare_enabled; |
| 286 | BitField<10, 3, DepthCompareFunc> depth_compare_func; | 287 | BitField<10, 3, DepthCompareFunc> depth_compare_func; |
| 288 | BitField<13, 1, u32> srgb_conversion; | ||
| 289 | BitField<20, 3, u32> max_anisotropy; | ||
| 287 | }; | 290 | }; |
| 288 | union { | 291 | union { |
| 289 | BitField<0, 2, TextureFilter> mag_filter; | 292 | BitField<0, 2, TextureFilter> mag_filter; |
| 290 | BitField<4, 2, TextureFilter> min_filter; | 293 | BitField<4, 2, TextureFilter> min_filter; |
| 291 | BitField<6, 2, TextureMipmapFilter> mip_filter; | 294 | BitField<6, 2, TextureMipmapFilter> mip_filter; |
| 295 | BitField<9, 1, u32> cubemap_interface_filtering; | ||
| 296 | BitField<12, 13, u32> mip_lod_bias; | ||
| 297 | }; | ||
| 298 | union { | ||
| 299 | BitField<0, 12, u32> min_lod_clamp; | ||
| 300 | BitField<12, 12, u32> max_lod_clamp; | ||
| 301 | BitField<24, 8, u32> srgb_border_color_r; | ||
| 302 | }; | ||
| 303 | union { | ||
| 304 | BitField<12, 8, u32> srgb_border_color_g; | ||
| 305 | BitField<20, 8, u32> srgb_border_color_b; | ||
| 292 | }; | 306 | }; |
| 293 | INSERT_PADDING_BYTES(8); | ||
| 294 | float border_color_r; | 307 | float border_color_r; |
| 295 | float border_color_g; | 308 | float border_color_g; |
| 296 | float border_color_b; | 309 | float border_color_b; |