summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFernando Sahmkow <fsahmkow27@gmail.com>2022-12-05 17:14:34 +0100
committerFernando Sahmkow <fsahmkow27@gmail.com>2023-01-01 22:43:58 +0100
commitf800e485c9bcd98e08128db974540e7ba0324128 (patch)
treec931bf1f7e8aa04d6f0ea6c110dedc1c10642cab
parentVulkan: Implement Dynamic States 2 (diff)
downloadyuzu-f800e485c9bcd98e08128db974540e7ba0324128.tar
yuzu-f800e485c9bcd98e08128db974540e7ba0324128.tar.gz
yuzu-f800e485c9bcd98e08128db974540e7ba0324128.tar.bz2
yuzu-f800e485c9bcd98e08128db974540e7ba0324128.tar.lz
yuzu-f800e485c9bcd98e08128db974540e7ba0324128.tar.xz
yuzu-f800e485c9bcd98e08128db974540e7ba0324128.tar.zst
yuzu-f800e485c9bcd98e08128db974540e7ba0324128.zip
-rw-r--r--src/video_core/engines/maxwell_3d.cpp1
-rw-r--r--src/video_core/renderer_vulkan/fixed_pipeline_state.cpp16
-rw-r--r--src/video_core/renderer_vulkan/fixed_pipeline_state.h30
-rw-r--r--src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp9
-rw-r--r--src/video_core/renderer_vulkan/vk_pipeline_cache.cpp2
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.cpp15
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.h1
-rw-r--r--src/video_core/renderer_vulkan/vk_state_tracker.cpp6
-rw-r--r--src/video_core/renderer_vulkan/vk_state_tracker.h5
-rw-r--r--src/video_core/vulkan_common/vulkan_device.cpp5
-rw-r--r--src/video_core/vulkan_common/vulkan_wrapper.cpp2
-rw-r--r--src/video_core/vulkan_common/vulkan_wrapper.h10
12 files changed, 75 insertions, 27 deletions
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp
index d44a5cabf..7f406e171 100644
--- a/src/video_core/engines/maxwell_3d.cpp
+++ b/src/video_core/engines/maxwell_3d.cpp
@@ -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;
}
diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp
index f13ff09c6..b1623b882 100644
--- a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp
+++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp
@@ -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,
diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.h b/src/video_core/renderer_vulkan/fixed_pipeline_state.h
index ac2ec3edc..88680e448 100644
--- a/src/video_core/renderer_vulkan/fixed_pipeline_state.h
+++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.h
@@ -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);
}
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
index d21d5aaf4..ce82a9c65 100644
--- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
+++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
@@ -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,
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
index 1292b6bdf..ee1ad744f 100644
--- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
@@ -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) {
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index f52cebc22..3cf6b796b 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -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;
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h
index c09415a6a..67d35eff7 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.h
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.h
@@ -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);
diff --git a/src/video_core/renderer_vulkan/vk_state_tracker.cpp b/src/video_core/renderer_vulkan/vk_state_tracker.cpp
index 339679ff9..1f8528e3e 100644
--- a/src/video_core/renderer_vulkan/vk_state_tracker.cpp
+++ b/src/video_core/renderer_vulkan/vk_state_tracker.cpp
@@ -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) {
diff --git a/src/video_core/renderer_vulkan/vk_state_tracker.h b/src/video_core/renderer_vulkan/vk_state_tracker.h
index 583bfe135..6050f5d26 100644
--- a/src/video_core/renderer_vulkan/vk_state_tracker.h
+++ b/src/video_core/renderer_vulkan/vk_state_tracker.h
@@ -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;
diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp
index 9a420a293..7294fcfe3 100644
--- a/src/video_core/vulkan_common/vulkan_device.cpp
+++ b/src/video_core/vulkan_common/vulkan_device.cpp
@@ -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) {
diff --git a/src/video_core/vulkan_common/vulkan_wrapper.cpp b/src/video_core/vulkan_common/vulkan_wrapper.cpp
index 4dde325ff..8745cf80f 100644
--- a/src/video_core/vulkan_common/vulkan_wrapper.cpp
+++ b/src/video_core/vulkan_common/vulkan_wrapper.cpp
@@ -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);
diff --git a/src/video_core/vulkan_common/vulkan_wrapper.h b/src/video_core/vulkan_common/vulkan_wrapper.h
index 0d3f71460..c4b7051fc 100644
--- a/src/video_core/vulkan_common/vulkan_wrapper.h
+++ b/src/video_core/vulkan_common/vulkan_wrapper.h
@@ -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);
}