vk_graphics_pipeline: Manage primitive topology as fixed state
Vulkan has requirements for primitive topologies that don't play nicely with yuzu's. Since it's only 4 bits, we can move it to fixed state without changing the size of the pipeline key. - Fixes a regression on recent Nvidia drivers on Fire Emblem: Three Houses.
This commit is contained in:
parent
4c348f4069
commit
e4e0abc418
6 changed files with 7 additions and 26 deletions
|
@ -58,6 +58,7 @@ void FixedPipelineState::Fill(const Maxwell& regs, bool has_extended_dynamic_sta
|
|||
logic_op_enable.Assign(regs.logic_op.enable != 0 ? 1 : 0);
|
||||
logic_op.Assign(PackLogicOp(regs.logic_op.operation));
|
||||
rasterize_enable.Assign(regs.rasterize_enable != 0 ? 1 : 0);
|
||||
topology.Assign(regs.draw.topology);
|
||||
|
||||
std::memcpy(&point_size, ®s.point_size, sizeof(point_size)); // TODO: C++20 std::bit_cast
|
||||
|
||||
|
@ -131,7 +132,6 @@ void FixedPipelineState::BlendingAttachment::Fill(const Maxwell& regs, std::size
|
|||
}
|
||||
|
||||
void FixedPipelineState::DynamicState::Fill(const Maxwell& regs) {
|
||||
const u32 topology_index = static_cast<u32>(regs.draw.topology.Value());
|
||||
u32 packed_front_face = PackFrontFace(regs.front_face);
|
||||
if (regs.screen_y_control.triangle_rast_flip != 0) {
|
||||
// Flip front face
|
||||
|
@ -161,7 +161,6 @@ void FixedPipelineState::DynamicState::Fill(const Maxwell& regs) {
|
|||
depth_test_enable.Assign(regs.depth_test_enable);
|
||||
front_face.Assign(packed_front_face);
|
||||
depth_test_func.Assign(PackComparisonOp(regs.depth_test_func));
|
||||
topology.Assign(topology_index);
|
||||
cull_face.Assign(PackCullFace(regs.cull_face));
|
||||
cull_enable.Assign(regs.cull_test_enabled != 0 ? 1 : 0);
|
||||
|
||||
|
|
|
@ -150,9 +150,8 @@ struct FixedPipelineState {
|
|||
};
|
||||
union {
|
||||
u32 raw2;
|
||||
BitField<0, 4, u32> topology;
|
||||
BitField<4, 2, u32> cull_face;
|
||||
BitField<6, 1, u32> cull_enable;
|
||||
BitField<0, 2, u32> cull_face;
|
||||
BitField<2, 1, u32> cull_enable;
|
||||
};
|
||||
std::array<VertexBinding, Maxwell::NumVertexArrays> vertex_bindings;
|
||||
|
||||
|
@ -169,10 +168,6 @@ struct FixedPipelineState {
|
|||
Maxwell::FrontFace FrontFace() const noexcept {
|
||||
return UnpackFrontFace(front_face.Value());
|
||||
}
|
||||
|
||||
constexpr Maxwell::PrimitiveTopology Topology() const noexcept {
|
||||
return static_cast<Maxwell::PrimitiveTopology>(topology.Value());
|
||||
}
|
||||
};
|
||||
|
||||
union {
|
||||
|
@ -190,6 +185,7 @@ struct FixedPipelineState {
|
|||
BitField<18, 1, u32> logic_op_enable;
|
||||
BitField<19, 4, u32> logic_op;
|
||||
BitField<23, 1, u32> rasterize_enable;
|
||||
BitField<24, 4, Maxwell::PrimitiveTopology> topology;
|
||||
};
|
||||
u32 point_size;
|
||||
std::array<u32, Maxwell::NumVertexArrays> binding_divisors;
|
||||
|
|
|
@ -261,12 +261,12 @@ vk::Pipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& renderpa
|
|||
vertex_input_ci.pNext = &input_divisor_ci;
|
||||
}
|
||||
|
||||
const auto input_assembly_topology = MaxwellToVK::PrimitiveTopology(device, dynamic.Topology());
|
||||
const auto input_assembly_topology = MaxwellToVK::PrimitiveTopology(device, state.topology);
|
||||
const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci{
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.flags = 0,
|
||||
.topology = MaxwellToVK::PrimitiveTopology(device, dynamic.Topology()),
|
||||
.topology = MaxwellToVK::PrimitiveTopology(device, state.topology),
|
||||
.primitiveRestartEnable = state.primitive_restart_enable != 0 &&
|
||||
SupportsPrimitiveRestart(input_assembly_topology),
|
||||
};
|
||||
|
@ -400,7 +400,6 @@ vk::Pipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& renderpa
|
|||
static constexpr std::array extended{
|
||||
VK_DYNAMIC_STATE_CULL_MODE_EXT,
|
||||
VK_DYNAMIC_STATE_FRONT_FACE_EXT,
|
||||
VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT,
|
||||
VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT,
|
||||
VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE_EXT,
|
||||
VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT,
|
||||
|
|
|
@ -331,8 +331,7 @@ void VKPipelineCache::OnShaderRemoval(Shader* shader) {
|
|||
std::pair<SPIRVProgram, std::vector<VkDescriptorSetLayoutBinding>>
|
||||
VKPipelineCache::DecompileShaders(const FixedPipelineState& fixed_state) {
|
||||
Specialization specialization;
|
||||
if (fixed_state.dynamic_state.Topology() == Maxwell::PrimitiveTopology::Points ||
|
||||
device.IsExtExtendedDynamicStateSupported()) {
|
||||
if (fixed_state.topology == Maxwell::PrimitiveTopology::Points) {
|
||||
float point_size;
|
||||
std::memcpy(&point_size, &fixed_state.point_size, sizeof(float));
|
||||
specialization.point_size = point_size;
|
||||
|
|
|
@ -948,7 +948,6 @@ void RasterizerVulkan::UpdateDynamicStates() {
|
|||
UpdateDepthWriteEnable(regs);
|
||||
UpdateDepthCompareOp(regs);
|
||||
UpdateFrontFace(regs);
|
||||
UpdatePrimitiveTopology(regs);
|
||||
UpdateStencilOp(regs);
|
||||
UpdateStencilTestEnable(regs);
|
||||
}
|
||||
|
@ -1418,16 +1417,6 @@ void RasterizerVulkan::UpdateFrontFace(Tegra::Engines::Maxwell3D::Regs& regs) {
|
|||
[front_face](vk::CommandBuffer cmdbuf) { cmdbuf.SetFrontFaceEXT(front_face); });
|
||||
}
|
||||
|
||||
void RasterizerVulkan::UpdatePrimitiveTopology(Tegra::Engines::Maxwell3D::Regs& regs) {
|
||||
const Maxwell::PrimitiveTopology primitive_topology = regs.draw.topology.Value();
|
||||
if (!state_tracker.ChangePrimitiveTopology(primitive_topology)) {
|
||||
return;
|
||||
}
|
||||
scheduler.Record([this, primitive_topology](vk::CommandBuffer cmdbuf) {
|
||||
cmdbuf.SetPrimitiveTopologyEXT(MaxwellToVK::PrimitiveTopology(device, primitive_topology));
|
||||
});
|
||||
}
|
||||
|
||||
void RasterizerVulkan::UpdateStencilOp(Tegra::Engines::Maxwell3D::Regs& regs) {
|
||||
if (!state_tracker.TouchStencilOp()) {
|
||||
return;
|
||||
|
|
|
@ -259,7 +259,6 @@ private:
|
|||
void UpdateDepthWriteEnable(Tegra::Engines::Maxwell3D::Regs& regs);
|
||||
void UpdateDepthCompareOp(Tegra::Engines::Maxwell3D::Regs& regs);
|
||||
void UpdateFrontFace(Tegra::Engines::Maxwell3D::Regs& regs);
|
||||
void UpdatePrimitiveTopology(Tegra::Engines::Maxwell3D::Regs& regs);
|
||||
void UpdateStencilOp(Tegra::Engines::Maxwell3D::Regs& regs);
|
||||
void UpdateStencilTestEnable(Tegra::Engines::Maxwell3D::Regs& regs);
|
||||
|
||||
|
|
Loading…
Reference in a new issue