mirror of
https://github.com/yuzu-emu/yuzu.git
synced 2024-07-04 23:31:19 +01:00
Vulkan Implement Dynamic State 2 LogicOp and PatchVertices
This commit is contained in:
parent
c897c55e3c
commit
f800e485c9
12 changed files with 75 additions and 27 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue