Vulkan Implement Dynamic State 2 LogicOp and PatchVertices

This commit is contained in:
Fernando Sahmkow 2022-12-05 17:14:34 +01:00
parent c897c55e3c
commit f800e485c9
12 changed files with 75 additions and 27 deletions

View File

@ -124,6 +124,7 @@ void Maxwell3D::InitializeRegisterDefaults() {
regs.gl_front_face = Maxwell3D::Regs::FrontFace::ClockWise;
regs.polygon_mode_back = Maxwell3D::Regs::PolygonMode::Fill;
regs.polygon_mode_front = Maxwell3D::Regs::PolygonMode::Fill;
regs.logic_op.op = Maxwell3D::Regs::LogicOp::Op::Clear;
shadow_state = regs;
}

View File

@ -55,6 +55,7 @@ void FixedPipelineState::Refresh(Tegra::Engines::Maxwell3D& maxwell3d, DynamicFe
raw1 = 0;
extended_dynamic_state.Assign(features.has_extended_dynamic_state ? 1 : 0);
extended_dynamic_state_2.Assign(features.has_extended_dynamic_state_2 ? 1 : 0);
extended_dynamic_state_2_extra.Assign(features.has_extended_dynamic_state_2_extra ? 1 : 0);
extended_dynamic_state_3.Assign(features.has_extended_dynamic_state_3 ? 1 : 0);
dynamic_vertex_input.Assign(features.has_dynamic_vertex_input ? 1 : 0);
xfb_enabled.Assign(regs.transform_feedback_enabled != 0);
@ -66,13 +67,12 @@ void FixedPipelineState::Refresh(Tegra::Engines::Maxwell3D& maxwell3d, DynamicFe
Maxwell::ViewportClipControl::GeometryClip::FrustumZ);
ndc_minus_one_to_one.Assign(regs.depth_mode == Maxwell::DepthMode::MinusOneToOne ? 1 : 0);
polygon_mode.Assign(PackPolygonMode(regs.polygon_mode_front));
patch_control_points_minus_one.Assign(regs.patch_vertices - 1);
tessellation_primitive.Assign(static_cast<u32>(regs.tessellation.params.domain_type.Value()));
tessellation_spacing.Assign(static_cast<u32>(regs.tessellation.params.spacing.Value()));
tessellation_clockwise.Assign(regs.tessellation.params.output_primitives.Value() ==
Maxwell::Tessellation::OutputPrimitives::Triangles_CW);
logic_op_enable.Assign(regs.logic_op.enable != 0 ? 1 : 0);
logic_op.Assign(PackLogicOp(regs.logic_op.op));
patch_control_points_minus_one.Assign(regs.patch_vertices - 1);
topology.Assign(topology_);
msaa_mode.Assign(regs.anti_alias_samples_mode);
@ -156,8 +156,8 @@ void FixedPipelineState::Refresh(Tegra::Engines::Maxwell3D& maxwell3d, DynamicFe
if (!extended_dynamic_state) {
dynamic_state.Refresh(regs);
}
if (!extended_dynamic_state_2) {
dynamic_state.Refresh2(regs, topology);
if (!extended_dynamic_state_2_extra) {
dynamic_state.Refresh2(regs, topology, extended_dynamic_state_2);
}
if (!extended_dynamic_state_3) {
dynamic_state.Refresh3(regs);
@ -241,7 +241,13 @@ void FixedPipelineState::DynamicState::Refresh(const Maxwell& regs) {
});
}
void FixedPipelineState::DynamicState::Refresh2(const Maxwell& regs, Maxwell::PrimitiveTopology topology_) {
void FixedPipelineState::DynamicState::Refresh2(const Maxwell& regs, Maxwell::PrimitiveTopology topology_, bool base_feautures_supported) {
logic_op.Assign(PackLogicOp(regs.logic_op.op));
if (base_feautures_supported) {
return;
}
const std::array enabled_lut{
regs.polygon_offset_point_enable,
regs.polygon_offset_line_enable,

View File

@ -146,6 +146,7 @@ struct FixedPipelineState {
BitField<3, 1, u32> primitive_restart_enable;
BitField<4, 1, u32> depth_bias_enable;
BitField<5, 1, u32> rasterize_enable;
BitField<6, 4, u32> logic_op;
};
union {
u32 raw2;
@ -162,7 +163,7 @@ struct FixedPipelineState {
std::array<u16, Maxwell::NumVertexArrays> vertex_strides;
void Refresh(const Maxwell& regs);
void Refresh2(const Maxwell& regs, Maxwell::PrimitiveTopology topology);
void Refresh2(const Maxwell& regs, Maxwell::PrimitiveTopology topology, bool base_feautures_supported);
void Refresh3(const Maxwell& regs);
Maxwell::ComparisonOp DepthTestFunc() const noexcept {
@ -182,18 +183,19 @@ struct FixedPipelineState {
u32 raw1;
BitField<0, 1, u32> extended_dynamic_state;
BitField<1, 1, u32> extended_dynamic_state_2;
BitField<2, 1, u32> extended_dynamic_state_3;
BitField<3, 1, u32> dynamic_vertex_input;
BitField<4, 1, u32> xfb_enabled;
BitField<5, 1, u32> depth_clamp_disabled;
BitField<6, 1, u32> ndc_minus_one_to_one;
BitField<7, 2, u32> polygon_mode;
BitField<9, 5, u32> patch_control_points_minus_one;
BitField<14, 2, u32> tessellation_primitive;
BitField<16, 2, u32> tessellation_spacing;
BitField<18, 1, u32> tessellation_clockwise;
BitField<19, 1, u32> logic_op_enable;
BitField<20, 4, u32> logic_op;
BitField<2, 1, u32> extended_dynamic_state_2_extra;
BitField<3, 1, u32> extended_dynamic_state_3;
BitField<4, 1, u32> dynamic_vertex_input;
BitField<5, 1, u32> xfb_enabled;
BitField<6, 1, u32> depth_clamp_disabled;
BitField<7, 1, u32> ndc_minus_one_to_one;
BitField<8, 2, u32> polygon_mode;
BitField<10, 2, u32> tessellation_primitive;
BitField<12, 2, u32> tessellation_spacing;
BitField<14, 1, u32> tessellation_clockwise;
BitField<15, 1, u32> logic_op_enable;
BitField<16, 5, u32> patch_control_points_minus_one;
BitField<24, 4, Maxwell::PrimitiveTopology> topology;
BitField<28, 4, Tegra::Texture::MsaaMode> msaa_mode;
};
@ -246,7 +248,7 @@ struct FixedPipelineState {
// Exclude dynamic state and attributes
return offsetof(FixedPipelineState, attributes);
}
if (extended_dynamic_state_2) {
if (extended_dynamic_state_2_extra) {
// Exclude dynamic state
return offsetof(FixedPipelineState, dynamic_state);
}

View File

@ -628,7 +628,7 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
.pNext = nullptr,
.flags = 0,
.topology = input_assembly_topology,
.primitiveRestartEnable = key.state.dynamic_state.primitive_restart_enable != 0 &&
.primitiveRestartEnable = dynamic.primitive_restart_enable != 0 &&
((input_assembly_topology != VK_PRIMITIVE_TOPOLOGY_PATCH_LIST &&
device.IsTopologyListPrimitiveRestartSupported()) ||
SupportsPrimitiveRestart(input_assembly_topology) ||
@ -786,12 +786,12 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
.pNext = nullptr,
.flags = 0,
.logicOpEnable = key.state.logic_op_enable != 0,
.logicOp = static_cast<VkLogicOp>(key.state.logic_op.Value()),
.logicOp = static_cast<VkLogicOp>(dynamic.logic_op.Value()),
.attachmentCount = static_cast<u32>(cb_attachments.size()),
.pAttachments = cb_attachments.data(),
.blendConstants = {},
};
static_vector<VkDynamicState, 22> dynamic_states{
static_vector<VkDynamicState, 23> dynamic_states{
VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR,
VK_DYNAMIC_STATE_DEPTH_BIAS, VK_DYNAMIC_STATE_BLEND_CONSTANTS,
VK_DYNAMIC_STATE_DEPTH_BOUNDS, VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK,
@ -822,6 +822,9 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
};
dynamic_states.insert(dynamic_states.end(), extended2.begin(), extended2.end());
}
if (key.state.extended_dynamic_state_2_extra) {
dynamic_states.push_back(VK_DYNAMIC_STATE_LOGIC_OP_EXT);
}
}
const VkPipelineDynamicStateCreateInfo dynamic_state_ci{
.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,

View File

@ -454,6 +454,8 @@ void PipelineCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading
dynamic_features.has_extended_dynamic_state ||
(key.state.extended_dynamic_state_2 != 0) !=
dynamic_features.has_extended_dynamic_state_2 ||
(key.state.extended_dynamic_state_2_extra != 0) !=
dynamic_features.has_extended_dynamic_state_2_extra ||
(key.state.extended_dynamic_state_3 != 0) !=
dynamic_features.has_extended_dynamic_state_3 ||
(key.state.dynamic_vertex_input != 0) != dynamic_features.has_dynamic_vertex_input) {

View File

@ -680,7 +680,6 @@ void RasterizerVulkan::UpdateDynamicStates() {
UpdateLineWidth(regs);
if (device.IsExtExtendedDynamicStateSupported()) {
UpdateCullMode(regs);
UpdateDepthCompareOp(regs);
UpdateFrontFace(regs);
UpdateStencilOp(regs);
@ -700,6 +699,9 @@ void RasterizerVulkan::UpdateDynamicStates() {
UpdateDepthBiasEnable(regs);
}
}
if (device.IsExtExtendedDynamicState2ExtrasSupported()) {
UpdateLogicOp(regs);
}
}
}
@ -1028,6 +1030,17 @@ void RasterizerVulkan::UpdateStencilOp(Tegra::Engines::Maxwell3D::Regs& regs) {
}
}
void RasterizerVulkan::UpdateLogicOp(Tegra::Engines::Maxwell3D::Regs& regs) {
if (!regs.logic_op.enable) {
return;
}
if (!state_tracker.TouchLogicOp()) {
return;
}
auto op = static_cast<VkLogicOp>(static_cast<u32>(regs.logic_op.op) - 0x1500);
scheduler.Record([op](vk::CommandBuffer cmdbuf) { cmdbuf.SetLogicOpEXT(op); });
}
void RasterizerVulkan::UpdateStencilTestEnable(Tegra::Engines::Maxwell3D::Regs& regs) {
if (!state_tracker.TouchStencilTestEnable()) {
return;

View File

@ -145,6 +145,7 @@ private:
void UpdateFrontFace(Tegra::Engines::Maxwell3D::Regs& regs);
void UpdateStencilOp(Tegra::Engines::Maxwell3D::Regs& regs);
void UpdateStencilTestEnable(Tegra::Engines::Maxwell3D::Regs& regs);
void UpdateLogicOp(Tegra::Engines::Maxwell3D::Regs& regs);
void UpdateVertexInput(Tegra::Engines::Maxwell3D::Regs& regs);

View File

@ -48,6 +48,7 @@ Flags MakeInvalidationFlags() {
PrimitiveRestartEnable,
RasterizerDiscardEnable,
DepthBiasEnable,
LogicOp,
};
Flags flags{};
for (const int flag : INVALIDATION_FLAGS) {
@ -162,6 +163,10 @@ void SetupDirtyBlending(Tables& tables) {
FillBlock(tables[0], OFF(blend_per_target), NUM(blend_per_target), Blending);
}
void SetupDirtySpecialOps(Tables& tables) {
tables[0][OFF(logic_op.op)] = LogicOp;
}
void SetupDirtyViewportSwizzles(Tables& tables) {
static constexpr size_t swizzle_offset = 6;
for (size_t index = 0; index < Regs::NumViewports; ++index) {
@ -210,6 +215,7 @@ void StateTracker::SetupTables(Tegra::Control::ChannelState& channel_state) {
SetupDirtyViewportSwizzles(tables);
SetupDirtyVertexAttributes(tables);
SetupDirtyVertexBindings(tables);
SetupDirtySpecialOps(tables);
}
void StateTracker::ChangeChannel(Tegra::Control::ChannelState& channel_state) {

View File

@ -49,6 +49,7 @@ enum : u8 {
RasterizerDiscardEnable,
DepthBiasEnable,
StateEnable,
LogicOp,
Blending,
ViewportSwizzles,
@ -159,6 +160,10 @@ public:
return Exchange(Dirty::StencilTestEnable, false);
}
bool TouchLogicOp() {
return Exchange(Dirty::LogicOp, false);
}
bool ChangePrimitiveTopology(Maxwell::PrimitiveTopology new_topology) {
const bool has_changed = current_topology != new_topology;
current_topology = new_topology;

View File

@ -576,8 +576,6 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
.pNext = nullptr,
.extendedDynamicState2 = VK_TRUE,
.extendedDynamicState2LogicOp = ext_extended_dynamic_state2_extra ? VK_TRUE : VK_FALSE,
.extendedDynamicState2PatchControlPoints =
ext_extended_dynamic_state2_extra ? VK_TRUE : VK_FALSE,
};
SetNext(next, dynamic_state2);
} else {
@ -1330,8 +1328,7 @@ std::vector<const char*> Device::LoadExtensions(bool requires_surface) {
extensions.push_back(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
ext_extended_dynamic_state2 = true;
ext_extended_dynamic_state2_extra =
extended_dynamic_state2.extendedDynamicState2LogicOp &&
extended_dynamic_state2.extendedDynamicState2PatchControlPoints;
extended_dynamic_state2.extendedDynamicState2LogicOp;
}
}
if (has_ext_extended_dynamic_state3) {

View File

@ -126,6 +126,8 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept {
X(vkCmdSetRasterizerDiscardEnableEXT);
X(vkCmdSetDepthBiasEnableEXT);
X(vkCmdSetFrontFaceEXT);
X(vkCmdSetLogicOpEXT);
X(vkCmdSetPatchControlPointsEXT);
X(vkCmdSetLineWidth);
X(vkCmdSetPrimitiveTopologyEXT);
X(vkCmdSetStencilOpEXT);

View File

@ -239,6 +239,8 @@ struct DeviceDispatch : InstanceDispatch {
PFN_vkCmdSetDepthBiasEnableEXT vkCmdSetDepthBiasEnableEXT{};
PFN_vkCmdSetEvent vkCmdSetEvent{};
PFN_vkCmdSetFrontFaceEXT vkCmdSetFrontFaceEXT{};
PFN_vkCmdSetPatchControlPointsEXT vkCmdSetPatchControlPointsEXT{};
PFN_vkCmdSetLogicOpEXT vkCmdSetLogicOpEXT{};
PFN_vkCmdSetLineWidth vkCmdSetLineWidth{};
PFN_vkCmdSetPrimitiveTopologyEXT vkCmdSetPrimitiveTopologyEXT{};
PFN_vkCmdSetScissor vkCmdSetScissor{};
@ -1238,6 +1240,14 @@ public:
dld->vkCmdSetFrontFaceEXT(handle, front_face);
}
void SetLogicOpEXT(VkLogicOp logic_op) const noexcept {
dld->vkCmdSetLogicOpEXT(handle, logic_op);
}
void SetPatchControlPointsEXT(uint32_t patch_control_points) const noexcept {
dld->vkCmdSetPatchControlPointsEXT(handle, patch_control_points);
}
void SetLineWidth(float line_width) const noexcept {
dld->vkCmdSetLineWidth(handle, line_width);
}