diff options
Diffstat (limited to 'src')
7 files changed, 103 insertions, 56 deletions
diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp index 5be6dabd9..362278f01 100644 --- a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp +++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp | |||
| @@ -12,14 +12,15 @@ | |||
| 12 | #include "common/cityhash.h" | 12 | #include "common/cityhash.h" |
| 13 | #include "common/common_types.h" | 13 | #include "common/common_types.h" |
| 14 | #include "video_core/renderer_vulkan/fixed_pipeline_state.h" | 14 | #include "video_core/renderer_vulkan/fixed_pipeline_state.h" |
| 15 | #include "video_core/renderer_vulkan/vk_state_tracker.h" | ||
| 15 | 16 | ||
| 16 | namespace Vulkan { | 17 | namespace Vulkan { |
| 17 | 18 | ||
| 18 | namespace { | 19 | namespace { |
| 19 | 20 | ||
| 20 | constexpr std::size_t POINT = 0; | 21 | constexpr size_t POINT = 0; |
| 21 | constexpr std::size_t LINE = 1; | 22 | constexpr size_t LINE = 1; |
| 22 | constexpr std::size_t POLYGON = 2; | 23 | constexpr size_t POLYGON = 2; |
| 23 | constexpr std::array POLYGON_OFFSET_ENABLE_LUT = { | 24 | constexpr std::array POLYGON_OFFSET_ENABLE_LUT = { |
| 24 | POINT, // Points | 25 | POINT, // Points |
| 25 | LINE, // Lines | 26 | LINE, // Lines |
| @@ -40,10 +41,14 @@ constexpr std::array POLYGON_OFFSET_ENABLE_LUT = { | |||
| 40 | 41 | ||
| 41 | } // Anonymous namespace | 42 | } // Anonymous namespace |
| 42 | 43 | ||
| 43 | void FixedPipelineState::Fill(const Maxwell& regs, bool has_extended_dynamic_state) { | 44 | void FixedPipelineState::Refresh(Tegra::Engines::Maxwell3D& maxwell3d, |
| 44 | const std::array enabled_lut = {regs.polygon_offset_point_enable, | 45 | bool has_extended_dynamic_state) { |
| 45 | regs.polygon_offset_line_enable, | 46 | const Maxwell& regs = maxwell3d.regs; |
| 46 | regs.polygon_offset_fill_enable}; | 47 | const std::array enabled_lut{ |
| 48 | regs.polygon_offset_point_enable, | ||
| 49 | regs.polygon_offset_line_enable, | ||
| 50 | regs.polygon_offset_fill_enable, | ||
| 51 | }; | ||
| 47 | const u32 topology_index = static_cast<u32>(regs.draw.topology.Value()); | 52 | const u32 topology_index = static_cast<u32>(regs.draw.topology.Value()); |
| 48 | 53 | ||
| 49 | raw1 = 0; | 54 | raw1 = 0; |
| @@ -64,45 +69,53 @@ void FixedPipelineState::Fill(const Maxwell& regs, bool has_extended_dynamic_sta | |||
| 64 | 69 | ||
| 65 | raw2 = 0; | 70 | raw2 = 0; |
| 66 | const auto test_func = | 71 | const auto test_func = |
| 67 | regs.alpha_test_enabled == 1 ? regs.alpha_test_func : Maxwell::ComparisonOp::Always; | 72 | regs.alpha_test_enabled != 0 ? regs.alpha_test_func : Maxwell::ComparisonOp::Always; |
| 68 | alpha_test_func.Assign(PackComparisonOp(test_func)); | 73 | alpha_test_func.Assign(PackComparisonOp(test_func)); |
| 69 | early_z.Assign(regs.force_early_fragment_tests != 0 ? 1 : 0); | 74 | early_z.Assign(regs.force_early_fragment_tests != 0 ? 1 : 0); |
| 70 | 75 | ||
| 71 | alpha_test_ref = Common::BitCast<u32>(regs.alpha_test_ref); | 76 | alpha_test_ref = Common::BitCast<u32>(regs.alpha_test_ref); |
| 72 | point_size = Common::BitCast<u32>(regs.point_size); | 77 | point_size = Common::BitCast<u32>(regs.point_size); |
| 73 | 78 | ||
| 74 | for (std::size_t index = 0; index < Maxwell::NumVertexArrays; ++index) { | 79 | if (maxwell3d.dirty.flags[Dirty::InstanceDivisors]) { |
| 75 | binding_divisors[index] = | 80 | maxwell3d.dirty.flags[Dirty::InstanceDivisors] = false; |
| 76 | regs.instanced_arrays.IsInstancingEnabled(index) ? regs.vertex_array[index].divisor : 0; | 81 | for (size_t index = 0; index < Maxwell::NumVertexArrays; ++index) { |
| 82 | const bool is_enabled = regs.instanced_arrays.IsInstancingEnabled(index); | ||
| 83 | binding_divisors[index] = is_enabled ? regs.vertex_array[index].divisor : 0; | ||
| 84 | } | ||
| 77 | } | 85 | } |
| 78 | 86 | if (maxwell3d.dirty.flags[Dirty::VertexAttributes]) { | |
| 79 | for (size_t index = 0; index < Maxwell::NumVertexAttributes; ++index) { | 87 | maxwell3d.dirty.flags[Dirty::VertexAttributes] = false; |
| 80 | const auto& input = regs.vertex_attrib_format[index]; | 88 | for (size_t index = 0; index < Maxwell::NumVertexAttributes; ++index) { |
| 81 | auto& attribute = attributes[index]; | 89 | const auto& input = regs.vertex_attrib_format[index]; |
| 82 | attribute.raw = 0; | 90 | auto& attribute = attributes[index]; |
| 83 | attribute.enabled.Assign(input.IsConstant() ? 0 : 1); | 91 | attribute.raw = 0; |
| 84 | attribute.buffer.Assign(input.buffer); | 92 | attribute.enabled.Assign(input.IsConstant() ? 0 : 1); |
| 85 | attribute.offset.Assign(input.offset); | 93 | attribute.buffer.Assign(input.buffer); |
| 86 | attribute.type.Assign(static_cast<u32>(input.type.Value())); | 94 | attribute.offset.Assign(input.offset); |
| 87 | attribute.size.Assign(static_cast<u32>(input.size.Value())); | 95 | attribute.type.Assign(static_cast<u32>(input.type.Value())); |
| 88 | attribute.binding_index_enabled.Assign(regs.vertex_array[index].IsEnabled() ? 1 : 0); | 96 | attribute.size.Assign(static_cast<u32>(input.size.Value())); |
| 97 | } | ||
| 89 | } | 98 | } |
| 90 | 99 | if (maxwell3d.dirty.flags[Dirty::Blending]) { | |
| 91 | for (std::size_t index = 0; index < std::size(attachments); ++index) { | 100 | maxwell3d.dirty.flags[Dirty::Blending] = false; |
| 92 | attachments[index].Fill(regs, index); | 101 | for (size_t index = 0; index < attachments.size(); ++index) { |
| 102 | attachments[index].Refresh(regs, index); | ||
| 103 | } | ||
| 104 | } | ||
| 105 | if (maxwell3d.dirty.flags[Dirty::ViewportSwizzles]) { | ||
| 106 | maxwell3d.dirty.flags[Dirty::ViewportSwizzles] = false; | ||
| 107 | const auto& transform = regs.viewport_transform; | ||
| 108 | std::ranges::transform(transform, viewport_swizzles.begin(), [](const auto& viewport) { | ||
| 109 | return static_cast<u16>(viewport.swizzle.raw); | ||
| 110 | }); | ||
| 93 | } | 111 | } |
| 94 | |||
| 95 | const auto& transform = regs.viewport_transform; | ||
| 96 | std::transform(transform.begin(), transform.end(), viewport_swizzles.begin(), | ||
| 97 | [](const auto& viewport) { return static_cast<u16>(viewport.swizzle.raw); }); | ||
| 98 | |||
| 99 | if (!has_extended_dynamic_state) { | 112 | if (!has_extended_dynamic_state) { |
| 100 | no_extended_dynamic_state.Assign(1); | 113 | no_extended_dynamic_state.Assign(1); |
| 101 | dynamic_state.Fill(regs); | 114 | dynamic_state.Refresh(regs); |
| 102 | } | 115 | } |
| 103 | } | 116 | } |
| 104 | 117 | ||
| 105 | void FixedPipelineState::BlendingAttachment::Fill(const Maxwell& regs, std::size_t index) { | 118 | void FixedPipelineState::BlendingAttachment::Refresh(const Maxwell& regs, size_t index) { |
| 106 | const auto& mask = regs.color_mask[regs.color_mask_common ? 0 : index]; | 119 | const auto& mask = regs.color_mask[regs.color_mask_common ? 0 : index]; |
| 107 | 120 | ||
| 108 | raw = 0; | 121 | raw = 0; |
| @@ -141,7 +154,7 @@ void FixedPipelineState::BlendingAttachment::Fill(const Maxwell& regs, std::size | |||
| 141 | enable.Assign(1); | 154 | enable.Assign(1); |
| 142 | } | 155 | } |
| 143 | 156 | ||
| 144 | void FixedPipelineState::DynamicState::Fill(const Maxwell& regs) { | 157 | void FixedPipelineState::DynamicState::Refresh(const Maxwell& regs) { |
| 145 | u32 packed_front_face = PackFrontFace(regs.front_face); | 158 | u32 packed_front_face = PackFrontFace(regs.front_face); |
| 146 | if (regs.screen_y_control.triangle_rast_flip != 0) { | 159 | if (regs.screen_y_control.triangle_rast_flip != 0) { |
| 147 | // Flip front face | 160 | // Flip front face |
| @@ -178,9 +191,9 @@ void FixedPipelineState::DynamicState::Fill(const Maxwell& regs) { | |||
| 178 | }); | 191 | }); |
| 179 | } | 192 | } |
| 180 | 193 | ||
| 181 | std::size_t FixedPipelineState::Hash() const noexcept { | 194 | size_t FixedPipelineState::Hash() const noexcept { |
| 182 | const u64 hash = Common::CityHash64(reinterpret_cast<const char*>(this), Size()); | 195 | const u64 hash = Common::CityHash64(reinterpret_cast<const char*>(this), Size()); |
| 183 | return static_cast<std::size_t>(hash); | 196 | return static_cast<size_t>(hash); |
| 184 | } | 197 | } |
| 185 | 198 | ||
| 186 | bool FixedPipelineState::operator==(const FixedPipelineState& rhs) const noexcept { | 199 | bool FixedPipelineState::operator==(const FixedPipelineState& rhs) const noexcept { |
diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.h b/src/video_core/renderer_vulkan/fixed_pipeline_state.h index 465a55fdb..a0eb83a68 100644 --- a/src/video_core/renderer_vulkan/fixed_pipeline_state.h +++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.h | |||
| @@ -58,7 +58,7 @@ struct FixedPipelineState { | |||
| 58 | BitField<30, 1, u32> enable; | 58 | BitField<30, 1, u32> enable; |
| 59 | }; | 59 | }; |
| 60 | 60 | ||
| 61 | void Fill(const Maxwell& regs, std::size_t index); | 61 | void Refresh(const Maxwell& regs, size_t index); |
| 62 | 62 | ||
| 63 | constexpr std::array<bool, 4> Mask() const noexcept { | 63 | constexpr std::array<bool, 4> Mask() const noexcept { |
| 64 | return {mask_r != 0, mask_g != 0, mask_b != 0, mask_a != 0}; | 64 | return {mask_r != 0, mask_g != 0, mask_b != 0, mask_a != 0}; |
| @@ -96,8 +96,6 @@ struct FixedPipelineState { | |||
| 96 | BitField<6, 14, u32> offset; | 96 | BitField<6, 14, u32> offset; |
| 97 | BitField<20, 3, u32> type; | 97 | BitField<20, 3, u32> type; |
| 98 | BitField<23, 6, u32> size; | 98 | BitField<23, 6, u32> size; |
| 99 | // Not really an element of a vertex attribute, but it can be packed here | ||
| 100 | BitField<29, 1, u32> binding_index_enabled; | ||
| 101 | 99 | ||
| 102 | constexpr Maxwell::VertexAttribute::Type Type() const noexcept { | 100 | constexpr Maxwell::VertexAttribute::Type Type() const noexcept { |
| 103 | return static_cast<Maxwell::VertexAttribute::Type>(type.Value()); | 101 | return static_cast<Maxwell::VertexAttribute::Type>(type.Value()); |
| @@ -108,7 +106,7 @@ struct FixedPipelineState { | |||
| 108 | } | 106 | } |
| 109 | }; | 107 | }; |
| 110 | 108 | ||
| 111 | template <std::size_t Position> | 109 | template <size_t Position> |
| 112 | union StencilFace { | 110 | union StencilFace { |
| 113 | BitField<Position + 0, 3, u32> action_stencil_fail; | 111 | BitField<Position + 0, 3, u32> action_stencil_fail; |
| 114 | BitField<Position + 3, 3, u32> action_depth_fail; | 112 | BitField<Position + 3, 3, u32> action_depth_fail; |
| @@ -152,7 +150,7 @@ struct FixedPipelineState { | |||
| 152 | // Vertex stride is a 12 bits value, we have 4 bits to spare per element | 150 | // Vertex stride is a 12 bits value, we have 4 bits to spare per element |
| 153 | std::array<u16, Maxwell::NumVertexArrays> vertex_strides; | 151 | std::array<u16, Maxwell::NumVertexArrays> vertex_strides; |
| 154 | 152 | ||
| 155 | void Fill(const Maxwell& regs); | 153 | void Refresh(const Maxwell& regs); |
| 156 | 154 | ||
| 157 | Maxwell::ComparisonOp DepthTestFunc() const noexcept { | 155 | Maxwell::ComparisonOp DepthTestFunc() const noexcept { |
| 158 | return UnpackComparisonOp(depth_test_func); | 156 | return UnpackComparisonOp(depth_test_func); |
| @@ -199,9 +197,9 @@ struct FixedPipelineState { | |||
| 199 | std::array<u16, Maxwell::NumViewports> viewport_swizzles; | 197 | std::array<u16, Maxwell::NumViewports> viewport_swizzles; |
| 200 | DynamicState dynamic_state; | 198 | DynamicState dynamic_state; |
| 201 | 199 | ||
| 202 | void Fill(const Maxwell& regs, bool has_extended_dynamic_state); | 200 | void Refresh(Tegra::Engines::Maxwell3D& maxwell3d, bool has_extended_dynamic_state); |
| 203 | 201 | ||
| 204 | std::size_t Hash() const noexcept; | 202 | size_t Hash() const noexcept; |
| 205 | 203 | ||
| 206 | bool operator==(const FixedPipelineState& rhs) const noexcept; | 204 | bool operator==(const FixedPipelineState& rhs) const noexcept; |
| 207 | 205 | ||
| @@ -209,8 +207,8 @@ struct FixedPipelineState { | |||
| 209 | return !operator==(rhs); | 207 | return !operator==(rhs); |
| 210 | } | 208 | } |
| 211 | 209 | ||
| 212 | std::size_t Size() const noexcept { | 210 | size_t Size() const noexcept { |
| 213 | const std::size_t total_size = sizeof *this; | 211 | const size_t total_size = sizeof *this; |
| 214 | return total_size - (no_extended_dynamic_state != 0 ? 0 : sizeof(DynamicState)); | 212 | return total_size - (no_extended_dynamic_state != 0 ? 0 : sizeof(DynamicState)); |
| 215 | } | 213 | } |
| 216 | }; | 214 | }; |
| @@ -224,7 +222,7 @@ namespace std { | |||
| 224 | 222 | ||
| 225 | template <> | 223 | template <> |
| 226 | struct hash<Vulkan::FixedPipelineState> { | 224 | struct hash<Vulkan::FixedPipelineState> { |
| 227 | std::size_t operator()(const Vulkan::FixedPipelineState& k) const noexcept { | 225 | size_t operator()(const Vulkan::FixedPipelineState& k) const noexcept { |
| 228 | return k.Hash(); | 226 | return k.Hash(); |
| 229 | } | 227 | } |
| 230 | }; | 228 | }; |
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index d50dca604..fc6dd83eb 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp | |||
| @@ -221,9 +221,6 @@ vk::Pipeline VKGraphicsPipeline::CreatePipeline(const SPIRVProgram& program, | |||
| 221 | std::vector<VkVertexInputBindingDescription> vertex_bindings; | 221 | std::vector<VkVertexInputBindingDescription> vertex_bindings; |
| 222 | std::vector<VkVertexInputBindingDivisorDescriptionEXT> vertex_binding_divisors; | 222 | std::vector<VkVertexInputBindingDivisorDescriptionEXT> vertex_binding_divisors; |
| 223 | for (std::size_t index = 0; index < Maxwell::NumVertexArrays; ++index) { | 223 | for (std::size_t index = 0; index < Maxwell::NumVertexArrays; ++index) { |
| 224 | if (state.attributes[index].binding_index_enabled == 0) { | ||
| 225 | continue; | ||
| 226 | } | ||
| 227 | const bool instanced = state.binding_divisors[index] != 0; | 224 | const bool instanced = state.binding_divisors[index] != 0; |
| 228 | const auto rate = instanced ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX; | 225 | const auto rate = instanced ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX; |
| 229 | vertex_bindings.push_back({ | 226 | vertex_bindings.push_back({ |
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 684d4e3a6..394a1c4e9 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp | |||
| @@ -267,8 +267,7 @@ void RasterizerVulkan::Draw(bool is_indexed, bool is_instanced) { | |||
| 267 | 267 | ||
| 268 | query_cache.UpdateCounters(); | 268 | query_cache.UpdateCounters(); |
| 269 | 269 | ||
| 270 | GraphicsPipelineCacheKey key; | 270 | graphics_key.fixed_state.Refresh(maxwell3d, device.IsExtExtendedDynamicStateSupported()); |
| 271 | key.fixed_state.Fill(maxwell3d.regs, device.IsExtExtendedDynamicStateSupported()); | ||
| 272 | 271 | ||
| 273 | std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex}; | 272 | std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex}; |
| 274 | 273 | ||
| @@ -276,14 +275,16 @@ void RasterizerVulkan::Draw(bool is_indexed, bool is_instanced) { | |||
| 276 | texture_cache.UpdateRenderTargets(false); | 275 | texture_cache.UpdateRenderTargets(false); |
| 277 | 276 | ||
| 278 | const auto shaders = pipeline_cache.GetShaders(); | 277 | const auto shaders = pipeline_cache.GetShaders(); |
| 279 | key.shaders = GetShaderAddresses(shaders); | 278 | graphics_key.shaders = GetShaderAddresses(shaders); |
| 279 | |||
| 280 | graphics_key.shaders = GetShaderAddresses(shaders); | ||
| 280 | SetupShaderDescriptors(shaders, is_indexed); | 281 | SetupShaderDescriptors(shaders, is_indexed); |
| 281 | 282 | ||
| 282 | const Framebuffer* const framebuffer = texture_cache.GetFramebuffer(); | 283 | const Framebuffer* const framebuffer = texture_cache.GetFramebuffer(); |
| 283 | key.renderpass = framebuffer->RenderPass(); | 284 | graphics_key.renderpass = framebuffer->RenderPass(); |
| 284 | 285 | ||
| 285 | auto* const pipeline = | 286 | VKGraphicsPipeline* const pipeline = pipeline_cache.GetGraphicsPipeline( |
| 286 | pipeline_cache.GetGraphicsPipeline(key, framebuffer->NumColorBuffers(), async_shaders); | 287 | graphics_key, framebuffer->NumColorBuffers(), async_shaders); |
| 287 | if (pipeline == nullptr || pipeline->GetHandle() == VK_NULL_HANDLE) { | 288 | if (pipeline == nullptr || pipeline->GetHandle() == VK_NULL_HANDLE) { |
| 288 | // Async graphics pipeline was not ready. | 289 | // Async graphics pipeline was not ready. |
| 289 | return; | 290 | return; |
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h index 7fc6741da..acea1ba2d 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.h +++ b/src/video_core/renderer_vulkan/vk_rasterizer.h | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | #include "video_core/renderer_vulkan/vk_buffer_cache.h" | 20 | #include "video_core/renderer_vulkan/vk_buffer_cache.h" |
| 21 | #include "video_core/renderer_vulkan/vk_descriptor_pool.h" | 21 | #include "video_core/renderer_vulkan/vk_descriptor_pool.h" |
| 22 | #include "video_core/renderer_vulkan/vk_fence_manager.h" | 22 | #include "video_core/renderer_vulkan/vk_fence_manager.h" |
| 23 | #include "video_core/renderer_vulkan/vk_graphics_pipeline.h" | ||
| 23 | #include "video_core/renderer_vulkan/vk_pipeline_cache.h" | 24 | #include "video_core/renderer_vulkan/vk_pipeline_cache.h" |
| 24 | #include "video_core/renderer_vulkan/vk_query_cache.h" | 25 | #include "video_core/renderer_vulkan/vk_query_cache.h" |
| 25 | #include "video_core/renderer_vulkan/vk_scheduler.h" | 26 | #include "video_core/renderer_vulkan/vk_scheduler.h" |
| @@ -173,6 +174,8 @@ private: | |||
| 173 | VKUpdateDescriptorQueue update_descriptor_queue; | 174 | VKUpdateDescriptorQueue update_descriptor_queue; |
| 174 | BlitImageHelper blit_image; | 175 | BlitImageHelper blit_image; |
| 175 | 176 | ||
| 177 | GraphicsPipelineCacheKey graphics_key; | ||
| 178 | |||
| 176 | TextureCacheRuntime texture_cache_runtime; | 179 | TextureCacheRuntime texture_cache_runtime; |
| 177 | TextureCache texture_cache; | 180 | TextureCache texture_cache; |
| 178 | BufferCacheRuntime buffer_cache_runtime; | 181 | BufferCacheRuntime buffer_cache_runtime; |
diff --git a/src/video_core/renderer_vulkan/vk_state_tracker.cpp b/src/video_core/renderer_vulkan/vk_state_tracker.cpp index e81fad007..956f86845 100644 --- a/src/video_core/renderer_vulkan/vk_state_tracker.cpp +++ b/src/video_core/renderer_vulkan/vk_state_tracker.cpp | |||
| @@ -18,9 +18,7 @@ | |||
| 18 | #define NUM(field_name) (sizeof(Maxwell3D::Regs::field_name) / (sizeof(u32))) | 18 | #define NUM(field_name) (sizeof(Maxwell3D::Regs::field_name) / (sizeof(u32))) |
| 19 | 19 | ||
| 20 | namespace Vulkan { | 20 | namespace Vulkan { |
| 21 | |||
| 22 | namespace { | 21 | namespace { |
| 23 | |||
| 24 | using namespace Dirty; | 22 | using namespace Dirty; |
| 25 | using namespace VideoCommon::Dirty; | 23 | using namespace VideoCommon::Dirty; |
| 26 | using Tegra::Engines::Maxwell3D; | 24 | using Tegra::Engines::Maxwell3D; |
| @@ -128,6 +126,34 @@ void SetupDirtyStencilTestEnable(Tables& tables) { | |||
| 128 | tables[0][OFF(stencil_enable)] = StencilTestEnable; | 126 | tables[0][OFF(stencil_enable)] = StencilTestEnable; |
| 129 | } | 127 | } |
| 130 | 128 | ||
| 129 | void SetupDirtyBlending(Tables& tables) { | ||
| 130 | tables[0][OFF(color_mask_common)] = Blending; | ||
| 131 | tables[0][OFF(independent_blend_enable)] = Blending; | ||
| 132 | FillBlock(tables[0], OFF(color_mask), NUM(color_mask), Blending); | ||
| 133 | FillBlock(tables[0], OFF(blend), NUM(blend), Blending); | ||
| 134 | FillBlock(tables[0], OFF(independent_blend), NUM(independent_blend), Blending); | ||
| 135 | } | ||
| 136 | |||
| 137 | void SetupDirtyInstanceDivisors(Tables& tables) { | ||
| 138 | static constexpr size_t divisor_offset = 3; | ||
| 139 | for (size_t index = 0; index < Regs::NumVertexArrays; ++index) { | ||
| 140 | tables[0][OFF(instanced_arrays) + index] = InstanceDivisors; | ||
| 141 | tables[0][OFF(vertex_array) + index * NUM(vertex_array[0]) + divisor_offset] = | ||
| 142 | InstanceDivisors; | ||
| 143 | } | ||
| 144 | } | ||
| 145 | |||
| 146 | void SetupDirtyVertexAttributes(Tables& tables) { | ||
| 147 | FillBlock(tables[0], OFF(vertex_attrib_format), NUM(vertex_attrib_format), VertexAttributes); | ||
| 148 | } | ||
| 149 | |||
| 150 | void SetupDirtyViewportSwizzles(Tables& tables) { | ||
| 151 | static constexpr size_t swizzle_offset = 6; | ||
| 152 | for (size_t index = 0; index < Regs::NumViewports; ++index) { | ||
| 153 | tables[0][OFF(viewport_transform) + index * NUM(viewport_transform[0]) + swizzle_offset] = | ||
| 154 | ViewportSwizzles; | ||
| 155 | } | ||
| 156 | } | ||
| 131 | } // Anonymous namespace | 157 | } // Anonymous namespace |
| 132 | 158 | ||
| 133 | StateTracker::StateTracker(Tegra::GPU& gpu) | 159 | StateTracker::StateTracker(Tegra::GPU& gpu) |
| @@ -148,6 +174,10 @@ StateTracker::StateTracker(Tegra::GPU& gpu) | |||
| 148 | SetupDirtyFrontFace(tables); | 174 | SetupDirtyFrontFace(tables); |
| 149 | SetupDirtyStencilOp(tables); | 175 | SetupDirtyStencilOp(tables); |
| 150 | SetupDirtyStencilTestEnable(tables); | 176 | SetupDirtyStencilTestEnable(tables); |
| 177 | SetupDirtyBlending(tables); | ||
| 178 | SetupDirtyInstanceDivisors(tables); | ||
| 179 | SetupDirtyVertexAttributes(tables); | ||
| 180 | SetupDirtyViewportSwizzles(tables); | ||
| 151 | } | 181 | } |
| 152 | 182 | ||
| 153 | } // namespace Vulkan | 183 | } // namespace Vulkan |
diff --git a/src/video_core/renderer_vulkan/vk_state_tracker.h b/src/video_core/renderer_vulkan/vk_state_tracker.h index c335d2bdf..84e918a71 100644 --- a/src/video_core/renderer_vulkan/vk_state_tracker.h +++ b/src/video_core/renderer_vulkan/vk_state_tracker.h | |||
| @@ -35,6 +35,11 @@ enum : u8 { | |||
| 35 | StencilOp, | 35 | StencilOp, |
| 36 | StencilTestEnable, | 36 | StencilTestEnable, |
| 37 | 37 | ||
| 38 | Blending, | ||
| 39 | InstanceDivisors, | ||
| 40 | VertexAttributes, | ||
| 41 | ViewportSwizzles, | ||
| 42 | |||
| 38 | Last | 43 | Last |
| 39 | }; | 44 | }; |
| 40 | static_assert(Last <= std::numeric_limits<u8>::max()); | 45 | static_assert(Last <= std::numeric_limits<u8>::max()); |