graphics: honor read-only stencil targets

This commit is contained in:
nmzik
2026-08-20 09:47:03 +02:00
parent 8021150ea2
commit 1190d5de7d
3 changed files with 59 additions and 16 deletions
+2 -6
View File
@@ -567,13 +567,9 @@ static void ZCheck(const HW::DepthRenderTarget& z, const HW::DepthControl& dc,
}
EXIT_NOT_IMPLEMENTED(!z.depth_view.depth_write_disable &&
z.z_read_base_addr != z.z_write_base_addr);
EXIT_NOT_IMPLEMENTED(z.stencil_read_base_addr != z.stencil_write_base_addr);
EXIT_NOT_IMPLEMENTED(!z.depth_view.stencil_write_disable &&
z.stencil_read_base_addr != z.stencil_write_base_addr);
EXIT_NOT_IMPLEMENTED(!z.depth_view.depth_write_disable && z.z_write_base_addr == 0);
if (z.stencil_info.format != Prospero::StencilFormat::kInvalid &&
z.stencil_write_base_addr == 0) {
LOGF("\t warning: stencil format is set without a stencil base address, continuing "
"without stencil attachment\n");
}
// EXIT_NOT_IMPLEMENTED(z.pitch_div8_minus1 != 0x000000ff);
// EXIT_NOT_IMPLEMENTED(z.height_div8_minus1 != 0x0000008f);
// EXIT_NOT_IMPLEMENTED(z.slice_div64_minus1 != 0x00008fff);
@@ -185,8 +185,9 @@ void RenderExecutor::ResolveRenderDepthTarget(uint64_t submit_id, RenderCommandB
if (has_stencil) {
if (z.stencil_info.format != Prospero::StencilFormat::k8UInt || !htile_stencil_compat ||
z.stencil_read_base_addr == 0 ||
z.stencil_write_base_addr != z.stencil_read_base_addr ||
(z.stencil_read_base_addr & 0xffffu) != 0 || z.depth_view.stencil_write_disable) {
(!z.depth_view.stencil_write_disable &&
z.stencil_write_base_addr != z.stencil_read_base_addr) ||
(z.stencil_read_base_addr & 0xffffu) != 0) {
DepthFatal("unsupported stencil attachment state");
}
} else if (z.stencil_read_base_addr != 0 || z.stencil_write_base_addr != 0 ||
@@ -287,18 +288,22 @@ void RenderExecutor::ResolveRenderDepthTarget(uint64_t submit_id, RenderCommandB
r.depth_min_bounds = hw.GetDepthBoundsMin();
r.depth_max_bounds = hw.GetDepthBoundsMax();
r.stencil_clear_enable = has_stencil && rc.stencil_clear_enable;
r.stencil_clear_enable =
has_stencil && rc.stencil_clear_enable && !z.depth_view.stencil_write_disable;
r.stencil_clear_value = hw.GetStencilClearValue();
r.stencil_test_enable = has_stencil && dc.stencil_enable;
if (r.stencil_test_enable) {
const uint8_t front_write_mask = rc.stencil_clear_enable ? 0 : sm.stencil_writemask;
const uint8_t back_write_mask = rc.stencil_clear_enable ? 0 : sm.stencil_writemask_bf;
const bool stencil_ops_disabled =
rc.stencil_clear_enable || z.depth_view.stencil_write_disable;
const uint8_t front_write_mask = stencil_ops_disabled ? 0 : sm.stencil_writemask;
const uint8_t back_write_mask = stencil_ops_disabled ? 0 : sm.stencil_writemask_bf;
if (dc.stencilfunc > static_cast<uint8_t>(vk::CompareOp::eAlways) ||
(dc.backface_enable &&
dc.stencilfunc_bf > static_cast<uint8_t>(vk::CompareOp::eAlways)) ||
(UsesStencilOpValue(sc.stencil_fail, sc.stencil_zpass, sc.stencil_zfail) &&
(front_write_mask != 0 &&
UsesStencilOpValue(sc.stencil_fail, sc.stencil_zpass, sc.stencil_zfail) &&
sm.stencil_opval != sm.stencil_testval) ||
(dc.backface_enable &&
(dc.backface_enable && back_write_mask != 0 &&
UsesStencilOpValue(sc.stencil_fail_bf, sc.stencil_zpass_bf, sc.stencil_zfail_bf) &&
sm.stencil_opval_bf != sm.stencil_testval_bf)) {
DepthFatal("unsupported stencil compare or replacement state");
+45 -3
View File
@@ -7651,27 +7651,69 @@ public:
auto read_only_depth_target = phased_depth_target;
read_only_depth_target.z_write_base_addr = 0;
read_only_depth_target.stencil_write_base_addr = 0;
read_only_depth_target.depth_view.depth_write_disable = true;
read_only_depth_target.depth_view.stencil_write_disable = true;
registers.SetDepthRenderTarget(read_only_depth_target);
auto read_only_depth_control = phased_depth_control;
read_only_depth_control.z_write_enable = false;
read_only_depth_control.zfunc =
static_cast<uint8_t>(vk::CompareOp::eAlways);
read_only_depth_control.stencil_enable = true;
read_only_depth_control.stencilfunc =
static_cast<uint8_t>(vk::CompareOp::eAlways);
registers.SetDepthControl(read_only_depth_control);
HW::StencilControl read_only_stencil_control{};
read_only_stencil_control.stencil_zpass =
static_cast<uint8_t>(Prospero::StencilOp::kReplaceOp);
registers.SetStencilControl(read_only_stencil_control);
HW::StencilMask read_only_stencil_mask{};
read_only_stencil_mask.stencil_testval = 0x12;
read_only_stencil_mask.stencil_mask = 0xff;
read_only_stencil_mask.stencil_writemask = 0xff;
read_only_stencil_mask.stencil_opval = 0x34;
registers.SetStencilMask(read_only_stencil_mask);
RenderDepthInfo read_only_depth{};
RenderExecutorTestAccess::ResolveRenderDepthTarget(
executor, 1, scheduler.Current(), read_only_depth);
Require(
name, "read-only depth target without write address",
name, "read-only depth/stencil target without write addresses",
read_only_depth.image_id == phased_depth.image_id &&
read_only_depth.depth_buffer_vaddr == phased_depth_address &&
read_only_depth.stencil_buffer_vaddr == phased_stencil_address &&
!read_only_depth.depth_write_enable &&
!read_only_depth.stencil_clear_enable &&
read_only_depth.stencil_test_enable &&
read_only_depth.stencil_dynamic_front.writeMask == 0 &&
read_only_depth.stencil_dynamic_back.writeMask == 0 &&
read_only_depth.stencil_static_front.passOp ==
vk::StencilOp::eKeep &&
!read_only_depth.AttachmentWriteAspects() &&
depth_attachment_layout(read_only_depth) ==
vk::ImageLayout::eDepthStencilReadOnlyOptimal,
"a PS5 read-only depth target required a depth write address or "
"selected a writable host layout");
"a PS5 read-only depth/stencil target required write addresses or "
"retained host writes");
auto read_only_render_control = phased_render_control;
read_only_render_control.stencil_clear_enable = true;
registers.SetRenderControl(read_only_render_control);
RenderDepthInfo read_only_clear_depth{};
RenderExecutorTestAccess::ResolveRenderDepthTarget(
executor, 1, scheduler.Current(), read_only_clear_depth);
Require(
name, "read-only stencil clear suppression",
read_only_clear_depth.image_id == phased_depth.image_id &&
!read_only_clear_depth.stencil_clear_enable &&
!read_only_clear_depth.AttachmentWriteAspects() &&
depth_attachment_layout(read_only_clear_depth) ==
vk::ImageLayout::eDepthStencilReadOnlyOptimal,
"a PS5 target-level stencil write disable retained a host clear");
registers.SetDepthRenderTarget(phased_depth_target);
registers.SetDepthControl(phased_depth_control);
registers.SetStencilControl({});
registers.SetStencilMask({});
registers.SetRenderControl(phased_render_control);
RenderColorInfo no_color{};
auto phased_rendering = RenderExecutorTestAccess::AcquireRenderTargets(
executor, scheduler.Current(), &no_color, 0, phased_depth);