forked from suyu/suyu
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).
This commit is contained in:
parent
0dc4ab42cc
commit
661483f313
3 changed files with 12 additions and 26 deletions
|
@ -75,7 +75,7 @@ void FixedPipelineState::Fill(const Maxwell& regs, bool has_extended_dynamic_sta
|
|||
regs.instanced_arrays.IsInstancingEnabled(index) ? regs.vertex_array[index].divisor : 0;
|
||||
}
|
||||
|
||||
for (std::size_t index = 0; index < Maxwell::NumVertexAttributes; ++index) {
|
||||
for (size_t index = 0; index < Maxwell::NumVertexAttributes; ++index) {
|
||||
const auto& input = regs.vertex_attrib_format[index];
|
||||
auto& attribute = attributes[index];
|
||||
attribute.raw = 0;
|
||||
|
@ -84,6 +84,7 @@ void FixedPipelineState::Fill(const Maxwell& regs, bool has_extended_dynamic_sta
|
|||
attribute.offset.Assign(input.offset);
|
||||
attribute.type.Assign(static_cast<u32>(input.type.Value()));
|
||||
attribute.size.Assign(static_cast<u32>(input.size.Value()));
|
||||
attribute.binding_index_enabled.Assign(regs.vertex_array[index].IsEnabled() ? 1 : 0);
|
||||
}
|
||||
|
||||
for (std::size_t index = 0; index < std::size(attachments); ++index) {
|
||||
|
@ -171,14 +172,9 @@ void FixedPipelineState::DynamicState::Fill(const Maxwell& regs) {
|
|||
depth_test_func.Assign(PackComparisonOp(regs.depth_test_func));
|
||||
cull_face.Assign(PackCullFace(regs.cull_face));
|
||||
cull_enable.Assign(regs.cull_test_enabled != 0 ? 1 : 0);
|
||||
|
||||
for (std::size_t index = 0; index < Maxwell::NumVertexArrays; ++index) {
|
||||
const auto& input = regs.vertex_array[index];
|
||||
VertexBinding& binding = vertex_bindings[index];
|
||||
binding.raw = 0;
|
||||
binding.enabled.Assign(input.IsEnabled() ? 1 : 0);
|
||||
binding.stride.Assign(static_cast<u16>(input.stride.Value()));
|
||||
}
|
||||
std::ranges::transform(regs.vertex_array, vertex_strides.begin(), [](const auto& array) {
|
||||
return static_cast<u16>(array.stride.Value());
|
||||
});
|
||||
}
|
||||
|
||||
std::size_t FixedPipelineState::Hash() const noexcept {
|
||||
|
|
|
@ -96,6 +96,8 @@ struct FixedPipelineState {
|
|||
BitField<6, 14, u32> offset;
|
||||
BitField<20, 3, u32> type;
|
||||
BitField<23, 6, u32> size;
|
||||
// Not really an element of a vertex attribute, but it can be packed here
|
||||
BitField<29, 1, u32> binding_index_enabled;
|
||||
|
||||
constexpr Maxwell::VertexAttribute::Type Type() const noexcept {
|
||||
return static_cast<Maxwell::VertexAttribute::Type>(type.Value());
|
||||
|
@ -130,12 +132,6 @@ struct FixedPipelineState {
|
|||
}
|
||||
};
|
||||
|
||||
union VertexBinding {
|
||||
u16 raw;
|
||||
BitField<0, 12, u16> stride;
|
||||
BitField<12, 1, u16> enabled;
|
||||
};
|
||||
|
||||
struct DynamicState {
|
||||
union {
|
||||
u32 raw1;
|
||||
|
@ -153,7 +149,8 @@ struct FixedPipelineState {
|
|||
BitField<0, 2, u32> cull_face;
|
||||
BitField<2, 1, u32> cull_enable;
|
||||
};
|
||||
std::array<VertexBinding, Maxwell::NumVertexArrays> vertex_bindings;
|
||||
// Vertex stride is a 12 bits value, we have 4 bits to spare per element
|
||||
std::array<u16, Maxwell::NumVertexArrays> vertex_strides;
|
||||
|
||||
void Fill(const Maxwell& regs);
|
||||
|
||||
|
|
|
@ -190,11 +190,7 @@ vk::Pipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& renderpa
|
|||
// state is ignored
|
||||
dynamic.raw1 = 0;
|
||||
dynamic.raw2 = 0;
|
||||
for (FixedPipelineState::VertexBinding& binding : dynamic.vertex_bindings) {
|
||||
// Enable all vertex bindings
|
||||
binding.raw = 0;
|
||||
binding.enabled.Assign(1);
|
||||
}
|
||||
dynamic.vertex_strides.fill(0);
|
||||
} else {
|
||||
dynamic = state.dynamic_state;
|
||||
}
|
||||
|
@ -202,19 +198,16 @@ vk::Pipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& renderpa
|
|||
std::vector<VkVertexInputBindingDescription> vertex_bindings;
|
||||
std::vector<VkVertexInputBindingDivisorDescriptionEXT> vertex_binding_divisors;
|
||||
for (std::size_t index = 0; index < Maxwell::NumVertexArrays; ++index) {
|
||||
const auto& binding = dynamic.vertex_bindings[index];
|
||||
if (!binding.enabled) {
|
||||
if (state.attributes[index].binding_index_enabled == 0) {
|
||||
continue;
|
||||
}
|
||||
const bool instanced = state.binding_divisors[index] != 0;
|
||||
const auto rate = instanced ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX;
|
||||
|
||||
vertex_bindings.push_back({
|
||||
.binding = static_cast<u32>(index),
|
||||
.stride = binding.stride,
|
||||
.stride = dynamic.vertex_strides[index],
|
||||
.inputRate = rate,
|
||||
});
|
||||
|
||||
if (instanced) {
|
||||
vertex_binding_divisors.push_back({
|
||||
.binding = static_cast<u32>(index),
|
||||
|
|
Loading…
Reference in a new issue