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
|
@ -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_enable.Assign(regs.logic_op.enable != 0 ? 1 : 0);
|
||||||
logic_op.Assign(PackLogicOp(regs.logic_op.operation));
|
logic_op.Assign(PackLogicOp(regs.logic_op.operation));
|
||||||
rasterize_enable.Assign(regs.rasterize_enable != 0 ? 1 : 0);
|
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
|
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) {
|
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);
|
u32 packed_front_face = PackFrontFace(regs.front_face);
|
||||||
if (regs.screen_y_control.triangle_rast_flip != 0) {
|
if (regs.screen_y_control.triangle_rast_flip != 0) {
|
||||||
// Flip front face
|
// Flip front face
|
||||||
|
@ -161,7 +161,6 @@ void FixedPipelineState::DynamicState::Fill(const Maxwell& regs) {
|
||||||
depth_test_enable.Assign(regs.depth_test_enable);
|
depth_test_enable.Assign(regs.depth_test_enable);
|
||||||
front_face.Assign(packed_front_face);
|
front_face.Assign(packed_front_face);
|
||||||
depth_test_func.Assign(PackComparisonOp(regs.depth_test_func));
|
depth_test_func.Assign(PackComparisonOp(regs.depth_test_func));
|
||||||
topology.Assign(topology_index);
|
|
||||||
cull_face.Assign(PackCullFace(regs.cull_face));
|
cull_face.Assign(PackCullFace(regs.cull_face));
|
||||||
cull_enable.Assign(regs.cull_test_enabled != 0 ? 1 : 0);
|
cull_enable.Assign(regs.cull_test_enabled != 0 ? 1 : 0);
|
||||||
|
|
||||||
|
|
|
@ -150,9 +150,8 @@ struct FixedPipelineState {
|
||||||
};
|
};
|
||||||
union {
|
union {
|
||||||
u32 raw2;
|
u32 raw2;
|
||||||
BitField<0, 4, u32> topology;
|
BitField<0, 2, u32> cull_face;
|
||||||
BitField<4, 2, u32> cull_face;
|
BitField<2, 1, u32> cull_enable;
|
||||||
BitField<6, 1, u32> cull_enable;
|
|
||||||
};
|
};
|
||||||
std::array<VertexBinding, Maxwell::NumVertexArrays> vertex_bindings;
|
std::array<VertexBinding, Maxwell::NumVertexArrays> vertex_bindings;
|
||||||
|
|
||||||
|
@ -169,10 +168,6 @@ struct FixedPipelineState {
|
||||||
Maxwell::FrontFace FrontFace() const noexcept {
|
Maxwell::FrontFace FrontFace() const noexcept {
|
||||||
return UnpackFrontFace(front_face.Value());
|
return UnpackFrontFace(front_face.Value());
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr Maxwell::PrimitiveTopology Topology() const noexcept {
|
|
||||||
return static_cast<Maxwell::PrimitiveTopology>(topology.Value());
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
union {
|
union {
|
||||||
|
@ -190,6 +185,7 @@ struct FixedPipelineState {
|
||||||
BitField<18, 1, u32> logic_op_enable;
|
BitField<18, 1, u32> logic_op_enable;
|
||||||
BitField<19, 4, u32> logic_op;
|
BitField<19, 4, u32> logic_op;
|
||||||
BitField<23, 1, u32> rasterize_enable;
|
BitField<23, 1, u32> rasterize_enable;
|
||||||
|
BitField<24, 4, Maxwell::PrimitiveTopology> topology;
|
||||||
};
|
};
|
||||||
u32 point_size;
|
u32 point_size;
|
||||||
std::array<u32, Maxwell::NumVertexArrays> binding_divisors;
|
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;
|
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{
|
const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci{
|
||||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.topology = MaxwellToVK::PrimitiveTopology(device, dynamic.Topology()),
|
.topology = MaxwellToVK::PrimitiveTopology(device, state.topology),
|
||||||
.primitiveRestartEnable = state.primitive_restart_enable != 0 &&
|
.primitiveRestartEnable = state.primitive_restart_enable != 0 &&
|
||||||
SupportsPrimitiveRestart(input_assembly_topology),
|
SupportsPrimitiveRestart(input_assembly_topology),
|
||||||
};
|
};
|
||||||
|
@ -400,7 +400,6 @@ vk::Pipeline VKGraphicsPipeline::CreatePipeline(const RenderPassParams& renderpa
|
||||||
static constexpr std::array extended{
|
static constexpr std::array extended{
|
||||||
VK_DYNAMIC_STATE_CULL_MODE_EXT,
|
VK_DYNAMIC_STATE_CULL_MODE_EXT,
|
||||||
VK_DYNAMIC_STATE_FRONT_FACE_EXT,
|
VK_DYNAMIC_STATE_FRONT_FACE_EXT,
|
||||||
VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT,
|
|
||||||
VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT,
|
VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT,
|
||||||
VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE_EXT,
|
VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE_EXT,
|
||||||
VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT,
|
VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT,
|
||||||
|
|
|
@ -331,8 +331,7 @@ void VKPipelineCache::OnShaderRemoval(Shader* shader) {
|
||||||
std::pair<SPIRVProgram, std::vector<VkDescriptorSetLayoutBinding>>
|
std::pair<SPIRVProgram, std::vector<VkDescriptorSetLayoutBinding>>
|
||||||
VKPipelineCache::DecompileShaders(const FixedPipelineState& fixed_state) {
|
VKPipelineCache::DecompileShaders(const FixedPipelineState& fixed_state) {
|
||||||
Specialization specialization;
|
Specialization specialization;
|
||||||
if (fixed_state.dynamic_state.Topology() == Maxwell::PrimitiveTopology::Points ||
|
if (fixed_state.topology == Maxwell::PrimitiveTopology::Points) {
|
||||||
device.IsExtExtendedDynamicStateSupported()) {
|
|
||||||
float point_size;
|
float point_size;
|
||||||
std::memcpy(&point_size, &fixed_state.point_size, sizeof(float));
|
std::memcpy(&point_size, &fixed_state.point_size, sizeof(float));
|
||||||
specialization.point_size = point_size;
|
specialization.point_size = point_size;
|
||||||
|
|
|
@ -948,7 +948,6 @@ void RasterizerVulkan::UpdateDynamicStates() {
|
||||||
UpdateDepthWriteEnable(regs);
|
UpdateDepthWriteEnable(regs);
|
||||||
UpdateDepthCompareOp(regs);
|
UpdateDepthCompareOp(regs);
|
||||||
UpdateFrontFace(regs);
|
UpdateFrontFace(regs);
|
||||||
UpdatePrimitiveTopology(regs);
|
|
||||||
UpdateStencilOp(regs);
|
UpdateStencilOp(regs);
|
||||||
UpdateStencilTestEnable(regs);
|
UpdateStencilTestEnable(regs);
|
||||||
}
|
}
|
||||||
|
@ -1418,16 +1417,6 @@ void RasterizerVulkan::UpdateFrontFace(Tegra::Engines::Maxwell3D::Regs& regs) {
|
||||||
[front_face](vk::CommandBuffer cmdbuf) { cmdbuf.SetFrontFaceEXT(front_face); });
|
[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) {
|
void RasterizerVulkan::UpdateStencilOp(Tegra::Engines::Maxwell3D::Regs& regs) {
|
||||||
if (!state_tracker.TouchStencilOp()) {
|
if (!state_tracker.TouchStencilOp()) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -259,7 +259,6 @@ private:
|
||||||
void UpdateDepthWriteEnable(Tegra::Engines::Maxwell3D::Regs& regs);
|
void UpdateDepthWriteEnable(Tegra::Engines::Maxwell3D::Regs& regs);
|
||||||
void UpdateDepthCompareOp(Tegra::Engines::Maxwell3D::Regs& regs);
|
void UpdateDepthCompareOp(Tegra::Engines::Maxwell3D::Regs& regs);
|
||||||
void UpdateFrontFace(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 UpdateStencilOp(Tegra::Engines::Maxwell3D::Regs& regs);
|
||||||
void UpdateStencilTestEnable(Tegra::Engines::Maxwell3D::Regs& regs);
|
void UpdateStencilTestEnable(Tegra::Engines::Maxwell3D::Regs& regs);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue