mirror of
https://git.eden-emu.dev/eden-emu/eden
synced 2026-04-15 17:38:57 +02:00
[vulkan] Adjustment Viewport/Scissor in DynamicState
This commit is contained in:
parent
12c022fec2
commit
1bb15b285e
5 changed files with 86 additions and 22 deletions
|
|
@ -190,9 +190,7 @@ void FixedPipelineState::Refresh(Tegra::Engines::Maxwell3D& maxwell3d, DynamicFe
|
|||
}
|
||||
}
|
||||
}
|
||||
if (!extended_dynamic_state_3_enables) {
|
||||
dynamic_state.Refresh3(regs);
|
||||
}
|
||||
dynamic_state.Refresh3(regs, features);
|
||||
if (xfb_enabled) {
|
||||
RefreshXfbState(xfb_state, regs);
|
||||
}
|
||||
|
|
@ -295,16 +293,22 @@ void FixedPipelineState::DynamicState::Refresh2(const Maxwell& regs,
|
|||
depth_bias_enable.Assign(enabled_lut[POLYGON_OFFSET_ENABLE_LUT[topology_index]] != 0 ? 1 : 0);
|
||||
}
|
||||
|
||||
void FixedPipelineState::DynamicState::Refresh3(const Maxwell& regs) {
|
||||
logic_op_enable.Assign(regs.logic_op.enable != 0 ? 1 : 0);
|
||||
depth_clamp_disabled.Assign(regs.viewport_clip_control.geometry_clip ==
|
||||
Maxwell::ViewportClipControl::GeometryClip::Passthrough ||
|
||||
regs.viewport_clip_control.geometry_clip ==
|
||||
Maxwell::ViewportClipControl::GeometryClip::FrustumXYZ ||
|
||||
regs.viewport_clip_control.geometry_clip ==
|
||||
Maxwell::ViewportClipControl::GeometryClip::FrustumZ);
|
||||
|
||||
line_stipple_enable.Assign(regs.line_stipple_enable);
|
||||
void FixedPipelineState::DynamicState::Refresh3(const Maxwell& regs,
|
||||
const DynamicFeatures& features) {
|
||||
if (!features.has_dynamic_state3_logic_op_enable) {
|
||||
logic_op_enable.Assign(regs.logic_op.enable != 0 ? 1 : 0);
|
||||
}
|
||||
if (!features.has_dynamic_state3_depth_clamp_enable) {
|
||||
depth_clamp_disabled.Assign(regs.viewport_clip_control.geometry_clip ==
|
||||
Maxwell::ViewportClipControl::GeometryClip::Passthrough ||
|
||||
regs.viewport_clip_control.geometry_clip ==
|
||||
Maxwell::ViewportClipControl::GeometryClip::FrustumXYZ ||
|
||||
regs.viewport_clip_control.geometry_clip ==
|
||||
Maxwell::ViewportClipControl::GeometryClip::FrustumZ);
|
||||
}
|
||||
if (!features.has_dynamic_state3_line_stipple_enable) {
|
||||
line_stipple_enable.Assign(regs.line_stipple_enable);
|
||||
}
|
||||
}
|
||||
|
||||
size_t FixedPipelineState::Hash() const noexcept {
|
||||
|
|
|
|||
|
|
@ -27,6 +27,9 @@ struct DynamicFeatures {
|
|||
bool has_extended_dynamic_state_2_patch_control_points;
|
||||
bool has_extended_dynamic_state_3_blend;
|
||||
bool has_extended_dynamic_state_3_enables;
|
||||
bool has_dynamic_state3_depth_clamp_enable;
|
||||
bool has_dynamic_state3_logic_op_enable;
|
||||
bool has_dynamic_state3_line_stipple_enable;
|
||||
bool has_dynamic_vertex_input;
|
||||
bool has_provoking_vertex;
|
||||
bool has_provoking_vertex_first_mode;
|
||||
|
|
@ -175,7 +178,7 @@ struct FixedPipelineState {
|
|||
void Refresh(const Maxwell& regs);
|
||||
void Refresh2(const Maxwell& regs, Maxwell::PrimitiveTopology topology,
|
||||
bool base_features_supported);
|
||||
void Refresh3(const Maxwell& regs);
|
||||
void Refresh3(const Maxwell& regs, const DynamicFeatures& features);
|
||||
|
||||
Maxwell::ComparisonOp DepthTestFunc() const noexcept {
|
||||
return UnpackComparisonOp(depth_test_func);
|
||||
|
|
@ -265,8 +268,7 @@ struct FixedPipelineState {
|
|||
return sizeof(*this);
|
||||
}
|
||||
if (dynamic_vertex_input && extended_dynamic_state_3_blend) {
|
||||
// Exclude dynamic state and attributes
|
||||
return offsetof(FixedPipelineState, dynamic_state);
|
||||
return offsetof(FixedPipelineState, attachments);
|
||||
}
|
||||
if (dynamic_vertex_input) {
|
||||
// Exclude dynamic state
|
||||
|
|
|
|||
|
|
@ -485,6 +485,12 @@ PipelineCache::PipelineCache(Tegra::MaxwellDeviceMemoryManager& device_memory_,
|
|||
device.IsExtExtendedDynamicState3BlendingSupported();
|
||||
dynamic_features.has_extended_dynamic_state_3_enables =
|
||||
device.IsExtExtendedDynamicState3EnablesSupported();
|
||||
dynamic_features.has_dynamic_state3_depth_clamp_enable =
|
||||
device.SupportsDynamicState3DepthClampEnable();
|
||||
dynamic_features.has_dynamic_state3_logic_op_enable =
|
||||
device.SupportsDynamicState3LogicOpEnable();
|
||||
dynamic_features.has_dynamic_state3_line_stipple_enable =
|
||||
device.SupportsDynamicState3LineStippleEnable();
|
||||
|
||||
// VIDS: Independent toggle (not affected by dyna_state levels)
|
||||
dynamic_features.has_dynamic_vertex_input =
|
||||
|
|
|
|||
|
|
@ -173,6 +173,28 @@ DrawParams MakeDrawParams(const MaxwellDrawState& draw_state, u32 num_instances,
|
|||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
bool SupportsPrimitiveRestart(VkPrimitiveTopology topology) {
|
||||
switch (topology) {
|
||||
case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
|
||||
case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
|
||||
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
|
||||
case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
|
||||
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
|
||||
case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsPrimitiveRestartSupported(const Device& device, VkPrimitiveTopology topology) {
|
||||
return ((topology != VK_PRIMITIVE_TOPOLOGY_PATCH_LIST &&
|
||||
device.IsTopologyListPrimitiveRestartSupported()) ||
|
||||
SupportsPrimitiveRestart(topology) ||
|
||||
(topology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST &&
|
||||
device.IsPatchListPrimitiveRestartSupported()));
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
RasterizerVulkan::RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_,
|
||||
|
|
@ -991,6 +1013,12 @@ bool AccelerateDMA::BufferToImage(const Tegra::DMA::ImageCopy& copy_info,
|
|||
|
||||
void RasterizerVulkan::UpdateDynamicStates() {
|
||||
auto& regs = maxwell3d->regs;
|
||||
auto& flags = maxwell3d->dirty.flags;
|
||||
const auto topology = maxwell3d->draw_manager->GetDrawState().topology;
|
||||
if (state_tracker.ChangePrimitiveTopology(topology)) {
|
||||
flags[Dirty::DepthBiasEnable] = true;
|
||||
flags[Dirty::PrimitiveRestartEnable] = true;
|
||||
}
|
||||
|
||||
// Core Dynamic States (Vulkan 1.0) - Always active regardless of dyna_state setting
|
||||
UpdateViewportsState(regs);
|
||||
|
|
@ -1099,6 +1127,9 @@ void RasterizerVulkan::UpdateViewportsState(Tegra::Engines::Maxwell3D::Regs& reg
|
|||
if (!state_tracker.TouchViewports()) {
|
||||
return;
|
||||
}
|
||||
|
||||
maxwell3d->dirty.flags[Dirty::Scissors] = true;
|
||||
|
||||
if (!regs.viewport_scale_offset_enabled) {
|
||||
float x = static_cast<float>(regs.surface_clip.x);
|
||||
float y = static_cast<float>(regs.surface_clip.y);
|
||||
|
|
@ -1116,8 +1147,12 @@ void RasterizerVulkan::UpdateViewportsState(Tegra::Engines::Maxwell3D::Regs& reg
|
|||
.minDepth = 0.0f,
|
||||
.maxDepth = 1.0f,
|
||||
};
|
||||
scheduler.Record([viewport](vk::CommandBuffer cmdbuf) {
|
||||
cmdbuf.SetViewport(0, viewport);
|
||||
scheduler.Record([this, viewport](vk::CommandBuffer cmdbuf) {
|
||||
const u32 num_viewports = std::min<u32>(device.GetMaxViewports(), Maxwell::NumViewports);
|
||||
std::array<VkViewport, Maxwell::NumViewports> viewport_list{};
|
||||
viewport_list.fill(viewport);
|
||||
const vk::Span<VkViewport> viewports(viewport_list.data(), num_viewports);
|
||||
cmdbuf.SetViewport(0, viewports);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
|
@ -1157,8 +1192,12 @@ 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);
|
||||
scheduler.Record([this, scissor](vk::CommandBuffer cmdbuf) {
|
||||
const u32 num_scissors = std::min<u32>(device.GetMaxViewports(), Maxwell::NumViewports);
|
||||
std::array<VkRect2D, Maxwell::NumViewports> scissor_list{};
|
||||
scissor_list.fill(scissor);
|
||||
const vk::Span<VkRect2D> scissors(scissor_list.data(), num_scissors);
|
||||
cmdbuf.SetScissor(0, scissors);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
|
@ -1403,7 +1442,17 @@ void RasterizerVulkan::UpdatePrimitiveRestartEnable(Tegra::Engines::Maxwell3D::R
|
|||
if (!state_tracker.TouchPrimitiveRestartEnable()) {
|
||||
return;
|
||||
}
|
||||
scheduler.Record([enable = regs.primitive_restart.enabled](vk::CommandBuffer cmdbuf) {
|
||||
|
||||
bool enable = regs.primitive_restart.enabled != 0;
|
||||
if (device.IsMoltenVK()) {
|
||||
enable = true;
|
||||
} else if (enable) {
|
||||
const auto topology =
|
||||
MaxwellToVK::PrimitiveTopology(device, maxwell3d->draw_manager->GetDrawState().topology);
|
||||
enable = IsPrimitiveRestartSupported(device, topology);
|
||||
}
|
||||
|
||||
scheduler.Record([enable](vk::CommandBuffer cmdbuf) {
|
||||
cmdbuf.SetPrimitiveRestartEnableEXT(enable);
|
||||
});
|
||||
}
|
||||
|
|
@ -1742,7 +1791,9 @@ void RasterizerVulkan::UpdateStencilTestEnable(Tegra::Engines::Maxwell3D::Regs&
|
|||
|
||||
void RasterizerVulkan::UpdateVertexInput(Tegra::Engines::Maxwell3D::Regs& regs) {
|
||||
auto& dirty{maxwell3d->dirty.flags};
|
||||
if (!dirty[Dirty::VertexInput]) {
|
||||
const bool vertex_input_dirty = dirty[Dirty::VertexInput];
|
||||
const bool vertex_buffers_dirty = dirty[VideoCommon::Dirty::VertexBuffers];
|
||||
if (!vertex_input_dirty && !vertex_buffers_dirty) {
|
||||
return;
|
||||
}
|
||||
dirty[Dirty::VertexInput] = false;
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@ Flags MakeInvalidationFlags() {
|
|||
void SetupDirtyViewports(Tables& tables) {
|
||||
FillBlock(tables[0], OFF(viewport_transform), NUM(viewport_transform), Viewports);
|
||||
FillBlock(tables[0], OFF(viewports), NUM(viewports), Viewports);
|
||||
FillBlock(tables[1], OFF(surface_clip), NUM(surface_clip), Viewports);
|
||||
tables[0][OFF(viewport_scale_offset_enabled)] = Viewports;
|
||||
tables[1][OFF(window_origin)] = Viewports;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue