diff options
Diffstat (limited to '')
| -rw-r--r-- | src/video_core/engines/maxwell_3d.h | 8 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_rasterizer.cpp | 106 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_state_tracker.cpp | 26 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_state_tracker.h | 65 |
4 files changed, 169 insertions, 36 deletions
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index dbefcd715..a2dff0350 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h | |||
| @@ -2711,7 +2711,7 @@ public: | |||
| 2711 | u32 post_z_pixel_imask; ///< 0x0F1C | 2711 | u32 post_z_pixel_imask; ///< 0x0F1C |
| 2712 | INSERT_PADDING_BYTES_NOINIT(0x20); | 2712 | INSERT_PADDING_BYTES_NOINIT(0x20); |
| 2713 | ConstantColorRendering const_color_rendering; ///< 0x0F40 | 2713 | ConstantColorRendering const_color_rendering; ///< 0x0F40 |
| 2714 | s32 stencil_back_ref; ///< 0x0F54 | 2714 | u32 stencil_back_ref; ///< 0x0F54 |
| 2715 | u32 stencil_back_mask; ///< 0x0F58 | 2715 | u32 stencil_back_mask; ///< 0x0F58 |
| 2716 | u32 stencil_back_func_mask; ///< 0x0F5C | 2716 | u32 stencil_back_func_mask; ///< 0x0F5C |
| 2717 | INSERT_PADDING_BYTES_NOINIT(0x14); | 2717 | INSERT_PADDING_BYTES_NOINIT(0x14); |
| @@ -2835,9 +2835,9 @@ public: | |||
| 2835 | Blend blend; ///< 0x133C | 2835 | Blend blend; ///< 0x133C |
| 2836 | u32 stencil_enable; ///< 0x1380 | 2836 | u32 stencil_enable; ///< 0x1380 |
| 2837 | StencilOp stencil_front_op; ///< 0x1384 | 2837 | StencilOp stencil_front_op; ///< 0x1384 |
| 2838 | s32 stencil_front_ref; ///< 0x1394 | 2838 | u32 stencil_front_ref; ///< 0x1394 |
| 2839 | s32 stencil_front_func_mask; ///< 0x1398 | 2839 | u32 stencil_front_func_mask; ///< 0x1398 |
| 2840 | s32 stencil_front_mask; ///< 0x139C | 2840 | u32 stencil_front_mask; ///< 0x139C |
| 2841 | INSERT_PADDING_BYTES_NOINIT(0x4); | 2841 | INSERT_PADDING_BYTES_NOINIT(0x4); |
| 2842 | u32 draw_auto_start_byte_count; ///< 0x13A4 | 2842 | u32 draw_auto_start_byte_count; ///< 0x13A4 |
| 2843 | PsSaturate frag_color_clamp; ///< 0x13A8 | 2843 | PsSaturate frag_color_clamp; ///< 0x13A8 |
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index da76b9a22..fc746fe2c 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp | |||
| @@ -886,32 +886,92 @@ void RasterizerVulkan::UpdateStencilFaces(Tegra::Engines::Maxwell3D::Regs& regs) | |||
| 886 | if (!state_tracker.TouchStencilProperties()) { | 886 | if (!state_tracker.TouchStencilProperties()) { |
| 887 | return; | 887 | return; |
| 888 | } | 888 | } |
| 889 | if (regs.stencil_two_side_enable) { | 889 | bool update_references = state_tracker.TouchStencilReference(); |
| 890 | // Separate values per face | 890 | bool update_write_mask = state_tracker.TouchStencilWriteMask(); |
| 891 | scheduler.Record( | 891 | bool update_compare_masks = state_tracker.TouchStencilCompare(); |
| 892 | [front_ref = regs.stencil_front_ref, front_write_mask = regs.stencil_front_mask, | 892 | if (state_tracker.TouchStencilSide(regs.stencil_two_side_enable != 0)) { |
| 893 | front_test_mask = regs.stencil_front_func_mask, back_ref = regs.stencil_back_ref, | 893 | update_references = true; |
| 894 | back_write_mask = regs.stencil_back_mask, | 894 | update_write_mask = true; |
| 895 | back_test_mask = regs.stencil_back_func_mask](vk::CommandBuffer cmdbuf) { | 895 | update_compare_masks = true; |
| 896 | } | ||
| 897 | if (update_references) { | ||
| 898 | [&]() { | ||
| 899 | if (regs.stencil_two_side_enable) { | ||
| 900 | if (!state_tracker.CheckStencilReferenceFront(regs.stencil_front_ref) && | ||
| 901 | !state_tracker.CheckStencilReferenceBack(regs.stencil_back_ref)) { | ||
| 902 | return; | ||
| 903 | } | ||
| 904 | } else { | ||
| 905 | if (!state_tracker.CheckStencilReferenceFront(regs.stencil_front_ref)) { | ||
| 906 | return; | ||
| 907 | } | ||
| 908 | } | ||
| 909 | scheduler.Record([front_ref = regs.stencil_front_ref, back_ref = regs.stencil_back_ref, | ||
| 910 | two_sided = regs.stencil_two_side_enable](vk::CommandBuffer cmdbuf) { | ||
| 911 | const bool set_back = two_sided && front_ref != back_ref; | ||
| 896 | // Front face | 912 | // Front face |
| 897 | cmdbuf.SetStencilReference(VK_STENCIL_FACE_FRONT_BIT, front_ref); | 913 | cmdbuf.SetStencilReference(set_back ? VK_STENCIL_FACE_FRONT_BIT |
| 898 | cmdbuf.SetStencilWriteMask(VK_STENCIL_FACE_FRONT_BIT, front_write_mask); | 914 | : VK_STENCIL_FACE_FRONT_AND_BACK, |
| 899 | cmdbuf.SetStencilCompareMask(VK_STENCIL_FACE_FRONT_BIT, front_test_mask); | 915 | front_ref); |
| 900 | 916 | if (set_back) { | |
| 901 | // Back face | 917 | cmdbuf.SetStencilReference(VK_STENCIL_FACE_BACK_BIT, back_ref); |
| 902 | cmdbuf.SetStencilReference(VK_STENCIL_FACE_BACK_BIT, back_ref); | 918 | } |
| 903 | cmdbuf.SetStencilWriteMask(VK_STENCIL_FACE_BACK_BIT, back_write_mask); | ||
| 904 | cmdbuf.SetStencilCompareMask(VK_STENCIL_FACE_BACK_BIT, back_test_mask); | ||
| 905 | }); | 919 | }); |
| 906 | } else { | 920 | }(); |
| 907 | // Front face defines both faces | 921 | } |
| 908 | scheduler.Record([ref = regs.stencil_front_ref, write_mask = regs.stencil_front_mask, | 922 | if (update_write_mask) { |
| 909 | test_mask = regs.stencil_front_func_mask](vk::CommandBuffer cmdbuf) { | 923 | [&]() { |
| 910 | cmdbuf.SetStencilReference(VK_STENCIL_FACE_FRONT_AND_BACK, ref); | 924 | if (regs.stencil_two_side_enable) { |
| 911 | cmdbuf.SetStencilWriteMask(VK_STENCIL_FACE_FRONT_AND_BACK, write_mask); | 925 | if (!state_tracker.CheckStencilWriteMaskFront(regs.stencil_front_mask) && |
| 912 | cmdbuf.SetStencilCompareMask(VK_STENCIL_FACE_FRONT_AND_BACK, test_mask); | 926 | !state_tracker.CheckStencilWriteMaskBack(regs.stencil_back_mask)) { |
| 913 | }); | 927 | return; |
| 928 | } | ||
| 929 | } else { | ||
| 930 | if (!state_tracker.CheckStencilWriteMaskFront(regs.stencil_front_mask)) { | ||
| 931 | return; | ||
| 932 | } | ||
| 933 | } | ||
| 934 | scheduler.Record([front_write_mask = regs.stencil_front_mask, | ||
| 935 | back_write_mask = regs.stencil_back_mask, | ||
| 936 | two_sided = regs.stencil_two_side_enable](vk::CommandBuffer cmdbuf) { | ||
| 937 | const bool set_back = two_sided && front_write_mask != back_write_mask; | ||
| 938 | // Front face | ||
| 939 | cmdbuf.SetStencilWriteMask(set_back ? VK_STENCIL_FACE_FRONT_BIT | ||
| 940 | : VK_STENCIL_FACE_FRONT_AND_BACK, | ||
| 941 | front_write_mask); | ||
| 942 | if (set_back) { | ||
| 943 | cmdbuf.SetStencilWriteMask(VK_STENCIL_FACE_BACK_BIT, back_write_mask); | ||
| 944 | } | ||
| 945 | }); | ||
| 946 | }(); | ||
| 947 | } | ||
| 948 | if (update_compare_masks) { | ||
| 949 | [&]() { | ||
| 950 | if (regs.stencil_two_side_enable) { | ||
| 951 | if (!state_tracker.CheckStencilCompareMaskFront(regs.stencil_front_func_mask) && | ||
| 952 | !state_tracker.CheckStencilCompareMaskBack(regs.stencil_back_func_mask)) { | ||
| 953 | return; | ||
| 954 | } | ||
| 955 | } else { | ||
| 956 | if (!state_tracker.CheckStencilCompareMaskFront(regs.stencil_front_func_mask)) { | ||
| 957 | return; | ||
| 958 | } | ||
| 959 | } | ||
| 960 | scheduler.Record([front_test_mask = regs.stencil_front_func_mask, | ||
| 961 | back_test_mask = regs.stencil_back_func_mask, | ||
| 962 | two_sided = regs.stencil_two_side_enable](vk::CommandBuffer cmdbuf) { | ||
| 963 | const bool set_back = two_sided && front_test_mask != back_test_mask; | ||
| 964 | // Front face | ||
| 965 | cmdbuf.SetStencilCompareMask(set_back ? VK_STENCIL_FACE_FRONT_BIT | ||
| 966 | : VK_STENCIL_FACE_FRONT_AND_BACK, | ||
| 967 | front_test_mask); | ||
| 968 | if (set_back) { | ||
| 969 | cmdbuf.SetStencilCompareMask(VK_STENCIL_FACE_BACK_BIT, back_test_mask); | ||
| 970 | } | ||
| 971 | }); | ||
| 972 | }(); | ||
| 914 | } | 973 | } |
| 974 | state_tracker.ClearStencilReset(); | ||
| 915 | } | 975 | } |
| 916 | 976 | ||
| 917 | void RasterizerVulkan::UpdateLineWidth(Tegra::Engines::Maxwell3D::Regs& regs) { | 977 | void RasterizerVulkan::UpdateLineWidth(Tegra::Engines::Maxwell3D::Regs& regs) { |
diff --git a/src/video_core/renderer_vulkan/vk_state_tracker.cpp b/src/video_core/renderer_vulkan/vk_state_tracker.cpp index bfea503de..e5cf97472 100644 --- a/src/video_core/renderer_vulkan/vk_state_tracker.cpp +++ b/src/video_core/renderer_vulkan/vk_state_tracker.cpp | |||
| @@ -33,6 +33,9 @@ Flags MakeInvalidationFlags() { | |||
| 33 | BlendConstants, | 33 | BlendConstants, |
| 34 | DepthBounds, | 34 | DepthBounds, |
| 35 | StencilProperties, | 35 | StencilProperties, |
| 36 | StencilReference, | ||
| 37 | StencilWriteMask, | ||
| 38 | StencilCompare, | ||
| 36 | LineWidth, | 39 | LineWidth, |
| 37 | CullMode, | 40 | CullMode, |
| 38 | DepthBoundsEnable, | 41 | DepthBoundsEnable, |
| @@ -99,14 +102,17 @@ void SetupDirtyDepthBounds(Tables& tables) { | |||
| 99 | } | 102 | } |
| 100 | 103 | ||
| 101 | void SetupDirtyStencilProperties(Tables& tables) { | 104 | void SetupDirtyStencilProperties(Tables& tables) { |
| 102 | auto& table = tables[0]; | 105 | const auto setup = [&](size_t position, u8 flag) { |
| 103 | table[OFF(stencil_two_side_enable)] = StencilProperties; | 106 | tables[0][position] = flag; |
| 104 | table[OFF(stencil_front_ref)] = StencilProperties; | 107 | tables[1][position] = StencilProperties; |
| 105 | table[OFF(stencil_front_mask)] = StencilProperties; | 108 | }; |
| 106 | table[OFF(stencil_front_func_mask)] = StencilProperties; | 109 | tables[0][OFF(stencil_two_side_enable)] = StencilProperties; |
| 107 | table[OFF(stencil_back_ref)] = StencilProperties; | 110 | setup(OFF(stencil_front_ref), StencilReference); |
| 108 | table[OFF(stencil_back_mask)] = StencilProperties; | 111 | setup(OFF(stencil_front_mask), StencilWriteMask); |
| 109 | table[OFF(stencil_back_func_mask)] = StencilProperties; | 112 | setup(OFF(stencil_front_func_mask), StencilCompare); |
| 113 | setup(OFF(stencil_back_ref), StencilReference); | ||
| 114 | setup(OFF(stencil_back_mask), StencilWriteMask); | ||
| 115 | setup(OFF(stencil_back_func_mask), StencilCompare); | ||
| 110 | } | 116 | } |
| 111 | 117 | ||
| 112 | void SetupDirtyLineWidth(Tables& tables) { | 118 | void SetupDirtyLineWidth(Tables& tables) { |
| @@ -238,9 +244,11 @@ void StateTracker::ChangeChannel(Tegra::Control::ChannelState& channel_state) { | |||
| 238 | 244 | ||
| 239 | void StateTracker::InvalidateState() { | 245 | void StateTracker::InvalidateState() { |
| 240 | flags->set(); | 246 | flags->set(); |
| 247 | current_topology = INVALID_TOPOLOGY; | ||
| 248 | stencil_reset = true; | ||
| 241 | } | 249 | } |
| 242 | 250 | ||
| 243 | StateTracker::StateTracker() | 251 | StateTracker::StateTracker() |
| 244 | : flags{&default_flags}, default_flags{}, invalidation_flags{MakeInvalidationFlags()} {} | 252 | : flags{&default_flags}, default_flags{}, invalidation_flags{MakeInvalidationFlags()} {} |
| 245 | 253 | ||
| 246 | } // namespace Vulkan | 254 | } // namespace Vulkan \ No newline at end of file |
diff --git a/src/video_core/renderer_vulkan/vk_state_tracker.h b/src/video_core/renderer_vulkan/vk_state_tracker.h index 7cdc70c60..8010ad26c 100644 --- a/src/video_core/renderer_vulkan/vk_state_tracker.h +++ b/src/video_core/renderer_vulkan/vk_state_tracker.h | |||
| @@ -35,6 +35,9 @@ enum : u8 { | |||
| 35 | BlendConstants, | 35 | BlendConstants, |
| 36 | DepthBounds, | 36 | DepthBounds, |
| 37 | StencilProperties, | 37 | StencilProperties, |
| 38 | StencilReference, | ||
| 39 | StencilWriteMask, | ||
| 40 | StencilCompare, | ||
| 38 | LineWidth, | 41 | LineWidth, |
| 39 | 42 | ||
| 40 | CullMode, | 43 | CullMode, |
| @@ -74,6 +77,7 @@ public: | |||
| 74 | void InvalidateCommandBufferState() { | 77 | void InvalidateCommandBufferState() { |
| 75 | (*flags) |= invalidation_flags; | 78 | (*flags) |= invalidation_flags; |
| 76 | current_topology = INVALID_TOPOLOGY; | 79 | current_topology = INVALID_TOPOLOGY; |
| 80 | stencil_reset = true; | ||
| 77 | } | 81 | } |
| 78 | 82 | ||
| 79 | void InvalidateViewports() { | 83 | void InvalidateViewports() { |
| @@ -113,6 +117,57 @@ public: | |||
| 113 | return Exchange(Dirty::StencilProperties, false); | 117 | return Exchange(Dirty::StencilProperties, false); |
| 114 | } | 118 | } |
| 115 | 119 | ||
| 120 | bool TouchStencilReference() { | ||
| 121 | return Exchange(Dirty::StencilReference, false); | ||
| 122 | } | ||
| 123 | |||
| 124 | bool TouchStencilWriteMask() { | ||
| 125 | return Exchange(Dirty::StencilWriteMask, false); | ||
| 126 | } | ||
| 127 | |||
| 128 | bool TouchStencilCompare() { | ||
| 129 | return Exchange(Dirty::StencilCompare, false); | ||
| 130 | } | ||
| 131 | |||
| 132 | template <typename T> | ||
| 133 | bool ExchangeCheck(T& old_value, T new_value) { | ||
| 134 | bool result = old_value != new_value; | ||
| 135 | old_value = new_value; | ||
| 136 | return result; | ||
| 137 | } | ||
| 138 | |||
| 139 | bool TouchStencilSide(bool two_sided_stencil_new) { | ||
| 140 | return ExchangeCheck(two_sided_stencil, two_sided_stencil_new) || stencil_reset; | ||
| 141 | } | ||
| 142 | |||
| 143 | bool CheckStencilReferenceFront(u32 new_value) { | ||
| 144 | return ExchangeCheck(front.ref, new_value) || stencil_reset; | ||
| 145 | } | ||
| 146 | |||
| 147 | bool CheckStencilReferenceBack(u32 new_value) { | ||
| 148 | return ExchangeCheck(back.ref, new_value) || stencil_reset; | ||
| 149 | } | ||
| 150 | |||
| 151 | bool CheckStencilWriteMaskFront(u32 new_value) { | ||
| 152 | return ExchangeCheck(front.write_mask, new_value) || stencil_reset; | ||
| 153 | } | ||
| 154 | |||
| 155 | bool CheckStencilWriteMaskBack(u32 new_value) { | ||
| 156 | return ExchangeCheck(back.write_mask, new_value) || stencil_reset; | ||
| 157 | } | ||
| 158 | |||
| 159 | bool CheckStencilCompareMaskFront(u32 new_value) { | ||
| 160 | return ExchangeCheck(front.compare_mask, new_value) || stencil_reset; | ||
| 161 | } | ||
| 162 | |||
| 163 | bool CheckStencilCompareMaskBack(u32 new_value) { | ||
| 164 | return ExchangeCheck(back.compare_mask, new_value) || stencil_reset; | ||
| 165 | } | ||
| 166 | |||
| 167 | void ClearStencilReset() { | ||
| 168 | stencil_reset = false; | ||
| 169 | } | ||
| 170 | |||
| 116 | bool TouchLineWidth() const { | 171 | bool TouchLineWidth() const { |
| 117 | return Exchange(Dirty::LineWidth, false); | 172 | return Exchange(Dirty::LineWidth, false); |
| 118 | } | 173 | } |
| @@ -214,10 +269,20 @@ private: | |||
| 214 | return is_dirty; | 269 | return is_dirty; |
| 215 | } | 270 | } |
| 216 | 271 | ||
| 272 | struct StencilProperties { | ||
| 273 | u32 ref = 0; | ||
| 274 | u32 write_mask = 0; | ||
| 275 | u32 compare_mask = 0; | ||
| 276 | }; | ||
| 277 | |||
| 217 | Tegra::Engines::Maxwell3D::DirtyState::Flags* flags; | 278 | Tegra::Engines::Maxwell3D::DirtyState::Flags* flags; |
| 218 | Tegra::Engines::Maxwell3D::DirtyState::Flags default_flags; | 279 | Tegra::Engines::Maxwell3D::DirtyState::Flags default_flags; |
| 219 | Tegra::Engines::Maxwell3D::DirtyState::Flags invalidation_flags; | 280 | Tegra::Engines::Maxwell3D::DirtyState::Flags invalidation_flags; |
| 220 | Maxwell::PrimitiveTopology current_topology = INVALID_TOPOLOGY; | 281 | Maxwell::PrimitiveTopology current_topology = INVALID_TOPOLOGY; |
| 282 | bool two_sided_stencil = false; | ||
| 283 | StencilProperties front{}; | ||
| 284 | StencilProperties back{}; | ||
| 285 | bool stencil_reset = false; | ||
| 221 | }; | 286 | }; |
| 222 | 287 | ||
| 223 | } // namespace Vulkan | 288 | } // namespace Vulkan |