diff options
| author | 2020-12-25 23:34:38 -0300 | |
|---|---|---|
| committer | 2020-12-25 23:34:38 -0300 | |
| commit | 661483f313a7dbbbebd4f233acecb06b6505a636 (patch) | |
| tree | 4d549417a89e271cd1d66295c1993ed7704e6d2e | |
| parent | Merge pull request #5226 from ReinUsesLisp/c4715-vc (diff) | |
| download | yuzu-661483f313a7dbbbebd4f233acecb06b6505a636.tar.gz yuzu-661483f313a7dbbbebd4f233acecb06b6505a636.tar.xz yuzu-661483f313a7dbbbebd4f233acecb06b6505a636.zip | |
renderer_vulkan/fixed_pipeline_state: Move enabled bindings to static state
Without using VK_EXT_robustness2, we can't consider the 'enabled' (not
null) vertex buffers as dynamic state, as this leads to invalid Vulkan
state. Move this to static state that is always hashed and compared in
the pipeline key.
The bits for enabled vertex buffers are moved into the attribute state
bitfield. This is not 'correct' as it's not an attribute state, but that
struct has bits to spare, and it's used in an array of 32 elements (the
exact same number of vertex buffer bindings).
3 files changed, 12 insertions, 26 deletions
diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp index 5ec43db11..08662f4a8 100644 --- a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp +++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp | |||
| @@ -75,7 +75,7 @@ void FixedPipelineState::Fill(const Maxwell& regs, bool has_extended_dynamic_sta | |||
| 75 | regs.instanced_arrays.IsInstancingEnabled(index) ? regs.vertex_array[index].divisor : 0; | 75 | regs.instanced_arrays.IsInstancingEnabled(index) ? regs.vertex_array[index].divisor : 0; |
| 76 | } | 76 | } |
| 77 | 77 | ||
| 78 | for (std::size_t index = 0; index < Maxwell::NumVertexAttributes; ++index) { | 78 | for (size_t index = 0; index < Maxwell::NumVertexAttributes; ++index) { |
| 79 | const auto& input = regs.vertex_attrib_format[index]; | 79 | const auto& input = regs.vertex_attrib_format[index]; |
| 80 | auto& attribute = attributes[index]; | 80 | auto& attribute = attributes[index]; |
| 81 | attribute.raw = 0; | 81 | attribute.raw = 0; |
| @@ -84,6 +84,7 @@ void FixedPipelineState::Fill(const Maxwell& regs, bool has_extended_dynamic_sta | |||
| 84 | attribute.offset.Assign(input.offset); | 84 | attribute.offset.Assign(input.offset); |
| 85 | attribute.type.Assign(static_cast<u32>(input.type.Value())); | 85 | attribute.type.Assign(static_cast<u32>(input.type.Value())); |
| 86 | attribute.size.Assign(static_cast<u32>(input.size.Value())); | 86 | attribute.size.Assign(static_cast<u32>(input.size.Value())); |
| 87 | attribute.binding_index_enabled.Assign(regs.vertex_array[index].IsEnabled() ? 1 : 0); | ||
| 87 | } | 88 | } |
| 88 | 89 | ||
| 89 | for (std::size_t index = 0; index < std::size(attachments); ++index) { | 90 | for (std::size_t index = 0; index < std::size(attachments); ++index) { |
| @@ -171,14 +172,9 @@ void FixedPipelineState::DynamicState::Fill(const Maxwell& regs) { | |||
| 171 | depth_test_func.Assign(PackComparisonOp(regs.depth_test_func)); | 172 | depth_test_func.Assign(PackComparisonOp(regs.depth_test_func)); |
| 172 | cull_face.Assign(PackCullFace(regs.cull_face)); | 173 | cull_face.Assign(PackCullFace(regs.cull_face)); |
| 173 | cull_enable.Assign(regs.cull_test_enabled != 0 ? 1 : 0); | 174 | cull_enable.Assign(regs.cull_test_enabled != 0 ? 1 : 0); |
| 174 | 175 | std::ranges::transform(regs.vertex_array, vertex_strides.begin(), [](const auto& array) { | |
| 175 | for (std::size_t index = 0; index < Maxwell::NumVertexArrays; ++index) { | 176 | return static_cast<u16>(array.stride.Value()); |
| 176 | const auto& input = regs.vertex_array[index]; | 177 | }); |
| 177 | VertexBinding& binding = vertex_bindings[index]; | ||
| 178 | binding.raw = 0; | ||
| 179 | binding.enabled.Assign(input.IsEnabled() ? 1 : 0); | ||
| 180 | binding.stride.Assign(static_cast<u16>(input.stride.Value())); | ||
| 181 | } | ||
| 182 | } | 178 | } |
| 183 | 179 | ||
| 184 | std::size_t FixedPipelineState::Hash() const noexcept { | 180 | std::size_t FixedPipelineState::Hash() 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 c26b77790..9b18301c1 100644 --- a/src/video_core/renderer_vulkan/fixed_pipeline_state.h +++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.h | |||
| @@ -96,6 +96,8 @@ 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; | ||
| 99 | 101 | ||
| 100 | constexpr Maxwell::VertexAttribute::Type Type() const noexcept { | 102 | constexpr Maxwell::VertexAttribute::Type Type() const noexcept { |
| 101 | return static_cast<Maxwell::VertexAttribute::Type>(type.Value()); | 103 | return static_cast<Maxwell::VertexAttribute::Type>(type.Value()); |
| @@ -130,12 +132,6 @@ struct FixedPipelineState { | |||
| 130 | } | 132 | } |
| 131 | }; | 133 | }; |
| 132 | 134 | ||
| 133 | union VertexBinding { | ||
| 134 | u16 raw; | ||
| 135 | BitField<0, 12, u16> stride; | ||
| 136 | BitField<12, 1, u16> enabled; | ||
| 137 | }; | ||
| 138 | |||
| 139 | struct DynamicState { | 135 | struct DynamicState { |
| 140 | union { | 136 | union { |
| 141 | u32 raw1; | 137 | u32 raw1; |
| @@ -153,7 +149,8 @@ struct FixedPipelineState { | |||
| 153 | BitField<0, 2, u32> cull_face; | 149 | BitField<0, 2, u32> cull_face; |
| 154 | BitField<2, 1, u32> cull_enable; | 150 | BitField<2, 1, u32> cull_enable; |
| 155 | }; | 151 | }; |
| 156 | std::array<VertexBinding, Maxwell::NumVertexArrays> vertex_bindings; | 152 | // Vertex stride is a 12 bits value, we have 4 bits to spare per element |
| 153 | std::array<u16, Maxwell::NumVertexArrays> vertex_strides; | ||
| 157 | 154 | ||
| 158 | void Fill(const Maxwell& regs); | 155 | void Fill(const Maxwell& regs); |
| 159 | 156 | ||
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index 970979fa1..a1a217b7c 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp | |||
| @@ -190,11 +190,7 @@ vk::Pipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& renderpa | |||
| 190 | // state is ignored | 190 | // state is ignored |
| 191 | dynamic.raw1 = 0; | 191 | dynamic.raw1 = 0; |
| 192 | dynamic.raw2 = 0; | 192 | dynamic.raw2 = 0; |
| 193 | for (FixedPipelineState::VertexBinding& binding : dynamic.vertex_bindings) { | 193 | dynamic.vertex_strides.fill(0); |
| 194 | // Enable all vertex bindings | ||
| 195 | binding.raw = 0; | ||
| 196 | binding.enabled.Assign(1); | ||
| 197 | } | ||
| 198 | } else { | 194 | } else { |
| 199 | dynamic = state.dynamic_state; | 195 | dynamic = state.dynamic_state; |
| 200 | } | 196 | } |
| @@ -202,19 +198,16 @@ vk::Pipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& renderpa | |||
| 202 | std::vector<VkVertexInputBindingDescription> vertex_bindings; | 198 | std::vector<VkVertexInputBindingDescription> vertex_bindings; |
| 203 | std::vector<VkVertexInputBindingDivisorDescriptionEXT> vertex_binding_divisors; | 199 | std::vector<VkVertexInputBindingDivisorDescriptionEXT> vertex_binding_divisors; |
| 204 | for (std::size_t index = 0; index < Maxwell::NumVertexArrays; ++index) { | 200 | for (std::size_t index = 0; index < Maxwell::NumVertexArrays; ++index) { |
| 205 | const auto& binding = dynamic.vertex_bindings[index]; | 201 | if (state.attributes[index].binding_index_enabled == 0) { |
| 206 | if (!binding.enabled) { | ||
| 207 | continue; | 202 | continue; |
| 208 | } | 203 | } |
| 209 | const bool instanced = state.binding_divisors[index] != 0; | 204 | const bool instanced = state.binding_divisors[index] != 0; |
| 210 | const auto rate = instanced ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX; | 205 | const auto rate = instanced ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX; |
| 211 | |||
| 212 | vertex_bindings.push_back({ | 206 | vertex_bindings.push_back({ |
| 213 | .binding = static_cast<u32>(index), | 207 | .binding = static_cast<u32>(index), |
| 214 | .stride = binding.stride, | 208 | .stride = dynamic.vertex_strides[index], |
| 215 | .inputRate = rate, | 209 | .inputRate = rate, |
| 216 | }); | 210 | }); |
| 217 | |||
| 218 | if (instanced) { | 211 | if (instanced) { |
| 219 | vertex_binding_divisors.push_back({ | 212 | vertex_binding_divisors.push_back({ |
| 220 | .binding = static_cast<u32>(index), | 213 | .binding = static_cast<u32>(index), |