Browse Source

[vulkan] Adjusted dynamic state handling + update state tracker for extended dynamic states

vkexperiments1
CamilleLaVey 5 days ago
parent
commit
6985aaf614
  1. 8
      src/video_core/renderer_vulkan/fixed_pipeline_state.cpp
  2. 8
      src/video_core/renderer_vulkan/fixed_pipeline_state.h
  3. 21
      src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
  4. 67
      src/video_core/renderer_vulkan/vk_rasterizer.cpp
  5. 11
      src/video_core/renderer_vulkan/vk_scheduler.cpp
  6. 4
      src/video_core/renderer_vulkan/vk_state_tracker.h

8
src/video_core/renderer_vulkan/fixed_pipeline_state.cpp

@ -131,15 +131,11 @@ void FixedPipelineState::Refresh(Tegra::Engines::Maxwell3D& maxwell3d, DynamicFe
}
dynamic_state.raw1 = 0;
dynamic_state.raw2 = 0;
if (!extended_dynamic_state) {
dynamic_state.Refresh(regs);
}
dynamic_state.Refresh(regs);
std::ranges::transform(regs.vertex_streams, vertex_strides.begin(), [](const auto& array) {
return static_cast<u16>(array.stride.Value());
});
if (!extended_dynamic_state_2) {
dynamic_state.Refresh2(regs, topology_, extended_dynamic_state_2);
}
dynamic_state.Refresh2(regs, topology_, false);
if (maxwell3d.dirty.flags[Dirty::Blending]) {
maxwell3d.dirty.flags[Dirty::Blending] = false;
for (size_t index = 0; index < attachments.size(); ++index) {

8
src/video_core/renderer_vulkan/fixed_pipeline_state.h

@ -254,11 +254,9 @@ struct FixedPipelineState {
// When transform feedback is enabled, use the whole struct
return sizeof(*this);
}
if (extended_dynamic_state) {
// Exclude dynamic state
return offsetof(FixedPipelineState, vertex_strides);
}
// Default
// Always include the cached dynamic-state payload in the key. Some members of
// `dynamic_state` still feed static pipeline state even when EDS is enabled,
// and excluding the whole block causes incorrect pipeline reuse.
return offsetof(FixedPipelineState, xfb_state);
}
};

21
src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp

@ -531,12 +531,7 @@ void GraphicsPipeline::ConfigureDraw(const RescalingPushConstant& rescaling,
}
const void* const descriptor_data{guest_descriptor_queue.UpdateData()};
FixedPipelineState::DynamicState dynamic_state{};
if (!key.state.extended_dynamic_state) {
dynamic_state = key.state.dynamic_state;
} else {
dynamic_state.raw1 = key.state.dynamic_state.raw1;
}
const FixedPipelineState::DynamicState dynamic_state{key.state.dynamic_state};
scheduler.Record([this, descriptor_data, bind_pipeline, rescaling_data = rescaling.Data(),
is_rescaling, update_rescaling,
uses_render_area = render_area.uses_render_area,
@ -687,9 +682,9 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.viewportCount = num_viewports,
.viewportCount = key.state.extended_dynamic_state ? 0u : num_viewports,
.pViewports = nullptr,
.scissorCount = num_viewports,
.scissorCount = key.state.extended_dynamic_state ? 0u : num_viewports,
.pScissors = nullptr,
};
if (device.IsNvViewportSwizzleSupported()) {
@ -901,6 +896,11 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
}
if (key.state.extended_dynamic_state) {
static constexpr std::array extended{
VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT_EXT,
VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT_EXT,
VK_DYNAMIC_STATE_CULL_MODE_EXT,
VK_DYNAMIC_STATE_FRONT_FACE_EXT,
VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT,
VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE_EXT,
VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT,
VK_DYNAMIC_STATE_DEPTH_COMPARE_OP_EXT,
@ -914,11 +914,6 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
dynamic_states.push_back(VK_DYNAMIC_STATE_SCISSOR);
}
if (key.state.extended_dynamic_state) {
dynamic_states.push_back(VK_DYNAMIC_STATE_VIEWPORT);
dynamic_states.push_back(VK_DYNAMIC_STATE_SCISSOR);
}
// EDS2 - Core (3 states)
if (key.state.extended_dynamic_state_2) {
static constexpr std::array extended2{

67
src/video_core/renderer_vulkan/vk_rasterizer.cpp

@ -277,8 +277,9 @@ void RasterizerVulkan::PrepareDraw(bool is_indexed, Func&& draw_func) {
if (!pipeline->Configure(is_indexed))
return;
if (pipeline->UsesExtendedDynamicState()) {
state_tracker.InvalidateStateEnableFlag();
if (pipeline->UsesExtendedDynamicState() || pipeline->UsesExtendedDynamicState2() ||
pipeline->UsesExtendedDynamicState2LogicOp()) {
state_tracker.InvalidateExtendedDynamicStates();
}
HandleTransformFeedback();
@ -1078,16 +1079,18 @@ void RasterizerVulkan::UpdateDynamicStates() {
UpdateLineWidth(regs);
UpdateLineStipple(regs);
// EDS1: DepthCompare, StencilOp, DepthBoundsTest, DepthTest, DepthWrite, StencilTest
// EDS1: CullMode, DepthCompare, FrontFace, PrimitiveTopology, StencilOp,
// DepthBoundsTest, DepthTest, DepthWrite, StencilTest
if (device.IsExtExtendedDynamicStateSupported() && pipeline && pipeline->UsesExtendedDynamicState()) {
UpdateCullMode(regs);
UpdateDepthCompareOp(regs);
UpdateFrontFace(regs);
UpdatePrimitiveTopology(regs);
UpdateStencilOp(regs);
if (state_tracker.TouchStateEnable()) {
UpdateDepthBoundsTestEnable(regs);
UpdateDepthTestEnable(regs);
UpdateDepthWriteEnable(regs);
UpdateStencilTestEnable(regs);
}
UpdateDepthBoundsTestEnable(regs);
UpdateDepthTestEnable(regs);
UpdateDepthWriteEnable(regs);
UpdateStencilTestEnable(regs);
}
UpdateStencilFaces(regs);
@ -1157,8 +1160,16 @@ void RasterizerVulkan::UpdateViewportsState(Tegra::Engines::Maxwell3D::Regs& reg
.minDepth = 0.0f,
.maxDepth = 1.0f,
};
scheduler.Record([viewport](vk::CommandBuffer cmdbuf) {
cmdbuf.SetViewport(0, viewport);
GraphicsPipeline* pipeline = pipeline_cache.CurrentGraphicsPipeline();
const bool use_viewport_with_count = device.IsExtExtendedDynamicStateSupported() &&
pipeline && pipeline->UsesExtendedDynamicState();
scheduler.Record([viewport, use_viewport_with_count](vk::CommandBuffer cmdbuf) {
if (use_viewport_with_count) {
std::array viewports{viewport};
cmdbuf.SetViewportWithCountEXT(viewports);
} else {
cmdbuf.SetViewport(0, viewport);
}
});
return;
}
@ -1174,10 +1185,17 @@ void RasterizerVulkan::UpdateViewportsState(Tegra::Engines::Maxwell3D::Regs& reg
GetViewportState(device, regs, 12, scale), GetViewportState(device, regs, 13, scale),
GetViewportState(device, regs, 14, scale), GetViewportState(device, regs, 15, scale),
};
scheduler.Record([this, viewport_list](vk::CommandBuffer cmdbuf) {
GraphicsPipeline* pipeline = pipeline_cache.CurrentGraphicsPipeline();
const bool use_viewport_with_count = device.IsExtExtendedDynamicStateSupported() &&
pipeline && pipeline->UsesExtendedDynamicState();
scheduler.Record([this, viewport_list, use_viewport_with_count](vk::CommandBuffer cmdbuf) {
const u32 num_viewports = std::min<u32>(device.GetMaxViewports(), Maxwell::NumViewports);
const vk::Span<VkViewport> viewports(viewport_list.data(), num_viewports);
cmdbuf.SetViewport(0, viewports);
if (use_viewport_with_count) {
cmdbuf.SetViewportWithCountEXT(viewports);
} else {
cmdbuf.SetViewport(0, viewports);
}
});
}
@ -1198,8 +1216,16 @@ void RasterizerVulkan::UpdateScissorsState(Tegra::Engines::Maxwell3D::Regs& regs
scissor.offset.y = static_cast<int32_t>(y);
scissor.extent.width = width;
scissor.extent.height = height;
scheduler.Record([scissor](vk::CommandBuffer cmdbuf) {
cmdbuf.SetScissor(0, scissor);
GraphicsPipeline* pipeline = pipeline_cache.CurrentGraphicsPipeline();
const bool use_scissor_with_count = device.IsExtExtendedDynamicStateSupported() &&
pipeline && pipeline->UsesExtendedDynamicState();
scheduler.Record([scissor, use_scissor_with_count](vk::CommandBuffer cmdbuf) {
if (use_scissor_with_count) {
std::array scissors{scissor};
cmdbuf.SetScissorWithCountEXT(scissors);
} else {
cmdbuf.SetScissor(0, scissor);
}
});
return;
}
@ -1227,10 +1253,17 @@ void RasterizerVulkan::UpdateScissorsState(Tegra::Engines::Maxwell3D::Regs& regs
GetScissorState(regs, 14, up_scale, down_shift),
GetScissorState(regs, 15, up_scale, down_shift),
};
scheduler.Record([this, scissor_list](vk::CommandBuffer cmdbuf) {
GraphicsPipeline* pipeline = pipeline_cache.CurrentGraphicsPipeline();
const bool use_scissor_with_count = device.IsExtExtendedDynamicStateSupported() &&
pipeline && pipeline->UsesExtendedDynamicState();
scheduler.Record([this, scissor_list, use_scissor_with_count](vk::CommandBuffer cmdbuf) {
const u32 num_scissors = std::min<u32>(device.GetMaxViewports(), Maxwell::NumViewports);
const vk::Span<VkRect2D> scissors(scissor_list.data(), num_scissors);
cmdbuf.SetScissor(0, scissors);
if (use_scissor_with_count) {
cmdbuf.SetScissorWithCountEXT(scissors);
} else {
cmdbuf.SetScissor(0, scissors);
}
});
}

11
src/video_core/renderer_vulkan/vk_scheduler.cpp

@ -154,9 +154,11 @@ void Scheduler::RequestOutsideRenderPassOperationContext() {
bool Scheduler::UpdateGraphicsPipeline(GraphicsPipeline* pipeline) {
if (state.graphics_pipeline == pipeline) {
if (pipeline && pipeline->UsesExtendedDynamicState() &&
if (pipeline &&
(pipeline->UsesExtendedDynamicState() || pipeline->UsesExtendedDynamicState2() ||
pipeline->UsesExtendedDynamicState2LogicOp()) &&
state.needs_state_enable_refresh) {
state_tracker.InvalidateStateEnableFlag();
state_tracker.InvalidateExtendedDynamicStates();
state.needs_state_enable_refresh = false;
}
return false;
@ -173,10 +175,11 @@ bool Scheduler::UpdateGraphicsPipeline(GraphicsPipeline* pipeline) {
state_tracker.InvalidateExtendedDynamicStates();
}
if (!pipeline->UsesExtendedDynamicState()) {
if (!pipeline->UsesExtendedDynamicState() && !pipeline->UsesExtendedDynamicState2() &&
!pipeline->UsesExtendedDynamicState2LogicOp()) {
state.needs_state_enable_refresh = true;
} else if (state.needs_state_enable_refresh) {
state_tracker.InvalidateStateEnableFlag();
state_tracker.InvalidateExtendedDynamicStates();
state.needs_state_enable_refresh = false;
}

4
src/video_core/renderer_vulkan/vk_state_tracker.h

@ -98,9 +98,13 @@ public:
(*flags)[Dirty::Viewports] = true;
(*flags)[Dirty::Scissors] = true;
(*flags)[Dirty::CullMode] = true;
(*flags)[Dirty::DepthBoundsEnable] = true;
(*flags)[Dirty::DepthTestEnable] = true;
(*flags)[Dirty::DepthWriteEnable] = true;
(*flags)[Dirty::DepthCompareOp] = true;
(*flags)[Dirty::FrontFace] = true;
(*flags)[Dirty::StencilOp] = true;
(*flags)[Dirty::StencilTestEnable] = true;
(*flags)[Dirty::StateEnable] = true;
(*flags)[Dirty::PrimitiveRestartEnable] = true;
(*flags)[Dirty::RasterizerDiscardEnable] = true;

Loading…
Cancel
Save