mirror of
https://git.eden-emu.dev/eden-emu/eden
synced 2026-04-21 16:48:58 +02:00
[vk:fp] properly differentiate attributes from the fixed pipeline dirty tracker
Signed-off-by: lizzie <lizzie@eden-emu.dev>
This commit is contained in:
parent
8ed0ed5828
commit
951432028a
3 changed files with 66 additions and 65 deletions
|
|
@ -105,22 +105,24 @@ void FixedPipelineState::Refresh(Tegra::Engines::Maxwell3D& maxwell3d, DynamicFe
|
|||
if (maxwell3d.dirty.flags[Dirty::VertexInput]) {
|
||||
if (features.has_dynamic_vertex_input) {
|
||||
// Dirty flag will be reset by the command buffer update
|
||||
static constexpr std::array LUT{
|
||||
0u, // Invalid
|
||||
1u, // SignedNorm
|
||||
1u, // UnsignedNorm
|
||||
2u, // SignedInt
|
||||
3u, // UnsignedInt
|
||||
1u, // UnsignedScaled
|
||||
1u, // SignedScaled
|
||||
1u, // Float
|
||||
};
|
||||
// 0u, // Invalid
|
||||
// 1u, // SignedNorm
|
||||
// 2u, // UnsignedNorm
|
||||
// 3u, // SignedInt
|
||||
// 4u, // UnsignedInt
|
||||
// 5u, // UnsignedScaled
|
||||
// 6u, // SignedScaled
|
||||
// 7u, // Float
|
||||
// We sparsely store the bits for each of them, so if they clash we don't deal
|
||||
// with the fixed pipeline taking in invalid vertices! :)
|
||||
const auto& attrs = regs.vertex_attrib_format;
|
||||
attribute_types = 0;
|
||||
attribute_types[0] = attribute_types[1] = attribute_types[2] = attribute_types[3] = 0;
|
||||
for (size_t i = 0; i < Maxwell::NumVertexAttributes; ++i) {
|
||||
const u32 mask = attrs[i].constant != 0 ? 0 : 3;
|
||||
const u32 type = LUT[static_cast<size_t>(attrs[i].type.Value())];
|
||||
attribute_types |= static_cast<u64>(type & mask) << (i * 2);
|
||||
u32 const mask = attrs[i].constant != 0 ? 0 : 0x07; // non-constant equates invalid
|
||||
u32 const type = size_t(attrs[i].type.Value());
|
||||
attribute_types[0] |= u64((type >> 0) & 1) << i;
|
||||
attribute_types[1] |= u64((type >> 1) & 1) << i;
|
||||
attribute_types[2] |= u64((type >> 2) & 1) << i;
|
||||
}
|
||||
} else {
|
||||
maxwell3d.dirty.flags[Dirty::VertexInput] = false;
|
||||
|
|
|
|||
|
|
@ -226,7 +226,7 @@ struct FixedPipelineState {
|
|||
|
||||
std::array<u16, Maxwell::NumViewports> viewport_swizzles;
|
||||
union {
|
||||
u64 attribute_types; // Used with VK_EXT_vertex_input_dynamic_state
|
||||
u64 attribute_types[3]; // Used with VK_EXT_vertex_input_dynamic_state
|
||||
u64 enabled_divisors;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1758,61 +1758,60 @@ void RasterizerVulkan::UpdateStencilTestEnable(Tegra::Engines::Maxwell3D::Regs&
|
|||
}
|
||||
|
||||
void RasterizerVulkan::UpdateVertexInput(Tegra::Engines::Maxwell3D::Regs& regs) {
|
||||
auto& dirty{maxwell3d->dirty.flags};
|
||||
if (!dirty[Dirty::VertexInput]) {
|
||||
return;
|
||||
}
|
||||
dirty[Dirty::VertexInput] = false;
|
||||
|
||||
boost::container::static_vector<VkVertexInputBindingDescription2EXT, 32> bindings;
|
||||
boost::container::static_vector<VkVertexInputAttributeDescription2EXT, 32> attributes;
|
||||
|
||||
// There seems to be a bug on Nvidia's driver where updating only higher attributes ends up
|
||||
// generating dirty state. Track the highest dirty attribute and update all attributes until
|
||||
// that one.
|
||||
size_t highest_dirty_attr{};
|
||||
for (size_t index = 0; index < Maxwell::NumVertexAttributes; ++index) {
|
||||
if (dirty[Dirty::VertexAttribute0 + index]) {
|
||||
highest_dirty_attr = index;
|
||||
auto& dirty = maxwell3d->dirty.flags;
|
||||
if (dirty[Dirty::VertexInput]) {
|
||||
dirty[Dirty::VertexInput] = false;
|
||||
boost::container::static_vector<VkVertexInputBindingDescription2EXT, Maxwell::NumVertexAttributes> bindings;
|
||||
boost::container::static_vector<VkVertexInputAttributeDescription2EXT, Maxwell::NumVertexAttributes> attributes;
|
||||
// There seems to be a bug on Nvidia's driver where updating only higher attributes ends up
|
||||
// generating dirty state. Track the highest dirty attribute and update all attributes until
|
||||
// that one.
|
||||
size_t highest_dirty_attr = 0;
|
||||
if (device.IsNvidia()) {
|
||||
for (size_t i = 0; i < Maxwell::NumVertexAttributes; ++i)
|
||||
if (dirty[Dirty::VertexAttribute0 + i])
|
||||
highest_dirty_attr = i;
|
||||
} else {
|
||||
highest_dirty_attr = Maxwell::NumVertexAttributes;
|
||||
}
|
||||
}
|
||||
for (size_t index = 0; index < highest_dirty_attr; ++index) {
|
||||
const Maxwell::VertexAttribute attribute{regs.vertex_attrib_format[index]};
|
||||
const u32 binding{attribute.buffer};
|
||||
dirty[Dirty::VertexAttribute0 + index] = false;
|
||||
dirty[Dirty::VertexBinding0 + static_cast<size_t>(binding)] = true;
|
||||
if (!attribute.constant) {
|
||||
attributes.push_back({
|
||||
.sType = VK_STRUCTURE_TYPE_VERTEX_INPUT_ATTRIBUTE_DESCRIPTION_2_EXT,
|
||||
.pNext = nullptr,
|
||||
.location = static_cast<u32>(index),
|
||||
.binding = binding,
|
||||
.format = MaxwellToVK::VertexFormat(device, attribute.type, attribute.size),
|
||||
.offset = attribute.offset,
|
||||
});
|
||||
for (size_t i = 0; i < highest_dirty_attr; ++i) {
|
||||
if (dirty[Dirty::VertexAttribute0 + i]) {
|
||||
dirty[Dirty::VertexAttribute0 + i] = false;
|
||||
Maxwell::VertexAttribute const attribute = regs.vertex_attrib_format[i];
|
||||
u32 const binding = attribute.buffer;
|
||||
dirty[Dirty::VertexBinding0 + size_t(binding)] = true;
|
||||
if (!attribute.constant) {
|
||||
attributes.push_back({
|
||||
.sType = VK_STRUCTURE_TYPE_VERTEX_INPUT_ATTRIBUTE_DESCRIPTION_2_EXT,
|
||||
.pNext = nullptr,
|
||||
.location = u32(i),
|
||||
.binding = binding,
|
||||
.format = MaxwellToVK::VertexFormat(device, attribute.type, attribute.size),
|
||||
.offset = attribute.offset,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (size_t index = 0; index < Maxwell::NumVertexAttributes; ++index) {
|
||||
if (!dirty[Dirty::VertexBinding0 + index]) {
|
||||
continue;
|
||||
for (size_t i = 0; i < Maxwell::NumVertexAttributes; ++i) {
|
||||
if (dirty[Dirty::VertexBinding0 + i]) {
|
||||
dirty[Dirty::VertexBinding0 + i] = false;
|
||||
const u32 binding = u32(i);
|
||||
const auto& input_binding = regs.vertex_streams[binding];
|
||||
const bool is_instanced = regs.vertex_stream_instances.IsInstancingEnabled(binding);
|
||||
bindings.push_back({
|
||||
.sType = VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT,
|
||||
.pNext = nullptr,
|
||||
.binding = binding,
|
||||
.stride = input_binding.stride,
|
||||
.inputRate = is_instanced ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX,
|
||||
.divisor = is_instanced ? input_binding.frequency : 1,
|
||||
});
|
||||
}
|
||||
}
|
||||
dirty[Dirty::VertexBinding0 + index] = false;
|
||||
|
||||
const u32 binding{static_cast<u32>(index)};
|
||||
const auto& input_binding{regs.vertex_streams[binding]};
|
||||
const bool is_instanced{regs.vertex_stream_instances.IsInstancingEnabled(binding)};
|
||||
bindings.push_back({
|
||||
.sType = VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT,
|
||||
.pNext = nullptr,
|
||||
.binding = binding,
|
||||
.stride = input_binding.stride,
|
||||
.inputRate = is_instanced ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX,
|
||||
.divisor = is_instanced ? input_binding.frequency : 1,
|
||||
scheduler.Record([bindings, attributes](vk::CommandBuffer cmdbuf) {
|
||||
cmdbuf.SetVertexInputEXT(bindings, attributes);
|
||||
});
|
||||
}
|
||||
scheduler.Record([bindings, attributes](vk::CommandBuffer cmdbuf) {
|
||||
cmdbuf.SetVertexInputEXT(bindings, attributes);
|
||||
});
|
||||
}
|
||||
|
||||
void RasterizerVulkan::InitializeChannel(Tegra::Control::ChannelState& channel) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue