summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2020-12-25 23:34:38 -0300
committerGravatar ReinUsesLisp2020-12-25 23:34:38 -0300
commit661483f313a7dbbbebd4f233acecb06b6505a636 (patch)
tree4d549417a89e271cd1d66295c1993ed7704e6d2e
parentMerge pull request #5226 from ReinUsesLisp/c4715-vc (diff)
downloadyuzu-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).
-rw-r--r--src/video_core/renderer_vulkan/fixed_pipeline_state.cpp14
-rw-r--r--src/video_core/renderer_vulkan/fixed_pipeline_state.h11
-rw-r--r--src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp13
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
184std::size_t FixedPipelineState::Hash() const noexcept { 180std::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),