mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 02:47:02 +02:00
Use dynamic stencil state
This commit is contained in:
@@ -71,19 +71,19 @@ static vk::StencilOp ConvertStencilOp(uint8_t value, uint8_t write_mask, uint8_t
|
||||
}
|
||||
}
|
||||
|
||||
static PipelineStencilStaticState ConvertStencilState(
|
||||
static vk::StencilOpState ConvertStencilState(
|
||||
uint8_t compare, const std::array<uint8_t, 3>& operations, uint8_t op_value,
|
||||
PipelineStencilDynamicState& dynamic) {
|
||||
const auto test_value = dynamic.reference;
|
||||
const vk::StencilOpState& state) {
|
||||
const auto test_value = state.reference;
|
||||
auto reference = test_value;
|
||||
auto required_bits = dynamic.compareMask;
|
||||
auto required_bits = state.compareMask;
|
||||
if (compare == static_cast<uint8_t>(vk::CompareOp::eAlways) ||
|
||||
compare == static_cast<uint8_t>(vk::CompareOp::eNever)) {
|
||||
required_bits = 0;
|
||||
}
|
||||
std::array<vk::StencilOp, 3> converted {};
|
||||
for (size_t i = 0; i < operations.size(); i++) {
|
||||
converted[i] = ConvertStencilOp(operations[i], dynamic.writeMask, op_value);
|
||||
converted[i] = ConvertStencilOp(operations[i], state.writeMask, op_value);
|
||||
if (converted[i] != vk::StencilOp::eReplace) {
|
||||
continue;
|
||||
}
|
||||
@@ -91,18 +91,18 @@ static PipelineStencilStaticState ConvertStencilState(
|
||||
if (static_cast<Prospero::StencilOp>(operations[i]) == Prospero::StencilOp::kReplaceOp) {
|
||||
replacement = op_value;
|
||||
}
|
||||
if (((reference ^ replacement) & required_bits & dynamic.writeMask) != 0) {
|
||||
if (((reference ^ replacement) & required_bits & state.writeMask) != 0) {
|
||||
DepthFatal("unsupported stencil replacement: compare=%u, compare mask=0x%02" PRIx32
|
||||
", write mask=0x%02" PRIx32 ", operation value=0x%02" PRIx8
|
||||
", test value=0x%02" PRIx32,
|
||||
compare, dynamic.compareMask, dynamic.writeMask, op_value, test_value);
|
||||
compare, state.compareMask, state.writeMask, op_value, test_value);
|
||||
}
|
||||
// Vulkan shares one reference between comparison and every replacement on this face.
|
||||
reference = (reference & ~dynamic.writeMask) | (replacement & dynamic.writeMask);
|
||||
required_bits |= dynamic.writeMask;
|
||||
reference = (reference & ~state.writeMask) | (replacement & state.writeMask);
|
||||
required_bits |= state.writeMask;
|
||||
}
|
||||
dynamic.reference = reference;
|
||||
return {converted[0], converted[1], converted[2], static_cast<vk::CompareOp>(compare)};
|
||||
return {converted[0], converted[1], converted[2], static_cast<vk::CompareOp>(compare),
|
||||
state.compareMask, state.writeMask, reference};
|
||||
}
|
||||
|
||||
[[nodiscard]] static vk::Format ResolveHostDepthAttachmentFormat(const CommandBuffer& buffer,
|
||||
@@ -333,18 +333,17 @@ void RenderExecutor::ResolveRenderDepthTarget(CommandBuffer& buffer, RenderDepth
|
||||
dc.stencilfunc_bf > static_cast<uint8_t>(vk::CompareOp::eAlways))) {
|
||||
DepthFatal("unsupported stencil compare state");
|
||||
}
|
||||
r.stencil_dynamic_front = {sm.stencil_mask, front_write_mask, sm.stencil_testval};
|
||||
r.stencil_static_front = ConvertStencilState(
|
||||
r.stencil_front = ConvertStencilState(
|
||||
dc.stencilfunc, {sc.stencil_fail, sc.stencil_zpass, sc.stencil_zfail},
|
||||
sm.stencil_opval, r.stencil_dynamic_front);
|
||||
sm.stencil_opval, {.compareMask = sm.stencil_mask, .writeMask = front_write_mask,
|
||||
.reference = sm.stencil_testval});
|
||||
if (dc.backface_enable) {
|
||||
r.stencil_dynamic_back = {sm.stencil_mask_bf, back_write_mask, sm.stencil_testval_bf};
|
||||
r.stencil_static_back = ConvertStencilState(
|
||||
r.stencil_back = ConvertStencilState(
|
||||
dc.stencilfunc_bf, {sc.stencil_fail_bf, sc.stencil_zpass_bf, sc.stencil_zfail_bf},
|
||||
sm.stencil_opval_bf, r.stencil_dynamic_back);
|
||||
sm.stencil_opval_bf, {.compareMask = sm.stencil_mask_bf, .writeMask = back_write_mask,
|
||||
.reference = sm.stencil_testval_bf});
|
||||
} else {
|
||||
r.stencil_static_back = r.stencil_static_front;
|
||||
r.stencil_dynamic_back = r.stencil_dynamic_front;
|
||||
r.stencil_back = r.stencil_front;
|
||||
}
|
||||
}
|
||||
auto& cache = m_context.GetTextureCache();
|
||||
@@ -430,14 +429,13 @@ vk::ImageAspectFlags RenderDepthInfo::AttachmentWriteAspects() const {
|
||||
return writes;
|
||||
}
|
||||
|
||||
const auto face_writes = [&](const PipelineStencilStaticState& state,
|
||||
const PipelineStencilDynamicState& dynamic) {
|
||||
if (dynamic.writeMask == 0) {
|
||||
const auto face_writes = [&](const vk::StencilOpState& state) {
|
||||
if (state.writeMask == 0) {
|
||||
return false;
|
||||
}
|
||||
bool can_pass = state.compareOp != vk::CompareOp::eNever;
|
||||
bool can_fail = state.compareOp != vk::CompareOp::eAlways;
|
||||
if (dynamic.compareMask == 0) {
|
||||
if (state.compareMask == 0) {
|
||||
switch (state.compareOp) {
|
||||
case vk::CompareOp::eEqual:
|
||||
case vk::CompareOp::eLessOrEqual:
|
||||
@@ -463,8 +461,7 @@ vk::ImageAspectFlags RenderDepthInfo::AttachmentWriteAspects() const {
|
||||
(can_pass && depth_fail && state.depthFailOp != vk::StencilOp::eKeep);
|
||||
};
|
||||
if (stencil_clear_enable ||
|
||||
(stencil_test_enable && (face_writes(stencil_static_front, stencil_dynamic_front) ||
|
||||
face_writes(stencil_static_back, stencil_dynamic_back)))) {
|
||||
(stencil_test_enable && (face_writes(stencil_front) || face_writes(stencil_back)))) {
|
||||
writes |= vk::ImageAspectFlagBits::eStencil;
|
||||
}
|
||||
return writes;
|
||||
|
||||
@@ -34,10 +34,8 @@ struct RenderDepthInfo {
|
||||
bool stencil_clear_enable = false;
|
||||
uint8_t stencil_clear_value = 0;
|
||||
bool stencil_test_enable = false;
|
||||
PipelineStencilStaticState stencil_static_front;
|
||||
PipelineStencilStaticState stencil_static_back;
|
||||
PipelineStencilDynamicState stencil_dynamic_front;
|
||||
PipelineStencilDynamicState stencil_dynamic_back;
|
||||
vk::StencilOpState stencil_front;
|
||||
vk::StencilOpState stencil_back;
|
||||
ImageId image_id;
|
||||
|
||||
[[nodiscard]] vk::ImageAspectFlags AttachmentWriteAspects() const;
|
||||
|
||||
@@ -742,9 +742,6 @@ PipelineCache::Pipeline& PipelineCache::GetGraphicsPipeline(
|
||||
static_params.depth_bounds_test_enable = depth.depth_bounds_test_enable;
|
||||
static_params.depth_min_bounds = depth.depth_min_bounds;
|
||||
static_params.depth_max_bounds = depth.depth_max_bounds;
|
||||
static_params.stencil_test_enable = depth.stencil_test_enable;
|
||||
static_params.stencil_front = depth.stencil_static_front;
|
||||
static_params.stencil_back = depth.stencil_static_back;
|
||||
const bool rect_list =
|
||||
command.GetUserConfig().GetPrimType() == Prospero::PrimitiveType::kRectList;
|
||||
static_params.cull_back = !rect_list && mc.cull_back;
|
||||
|
||||
@@ -42,9 +42,6 @@ struct PipelineStaticParameters {
|
||||
bool depth_bounds_test_enable = false;
|
||||
float depth_min_bounds = 0.0f;
|
||||
float depth_max_bounds = 0.0f;
|
||||
bool stencil_test_enable = false;
|
||||
PipelineStencilStaticState stencil_front;
|
||||
PipelineStencilStaticState stencil_back;
|
||||
uint32_t color_mask[RENDER_COLOR_ATTACHMENTS_MAX] = {};
|
||||
bool cull_front = false;
|
||||
bool cull_back = false;
|
||||
@@ -68,7 +65,7 @@ struct PipelineStaticParameters {
|
||||
static_assert(std::is_trivially_copyable_v<PipelineStaticParameters>);
|
||||
static_assert(std::is_standard_layout_v<PipelineStaticParameters>);
|
||||
static_assert(alignof(PipelineStaticParameters) == 1);
|
||||
static_assert(sizeof(PipelineStaticParameters) == 158);
|
||||
static_assert(sizeof(PipelineStaticParameters) == 125);
|
||||
|
||||
struct PipelineRenderingState {
|
||||
std::array<vk::Format, RENDER_COLOR_ATTACHMENTS_MAX> color_formats {};
|
||||
|
||||
@@ -477,15 +477,6 @@ void CreatePipelineInternal(GraphicContext& graphics, PipelineCache::Pipeline& p
|
||||
#else
|
||||
(static_params.depth_bounds_test_enable ? VK_TRUE : VK_FALSE);
|
||||
#endif
|
||||
depth_stencil_info.stencilTestEnable = (static_params.stencil_test_enable ? VK_TRUE : VK_FALSE);
|
||||
depth_stencil_info.front.failOp = static_params.stencil_front.failOp;
|
||||
depth_stencil_info.front.passOp = static_params.stencil_front.passOp;
|
||||
depth_stencil_info.front.depthFailOp = static_params.stencil_front.depthFailOp;
|
||||
depth_stencil_info.front.compareOp = static_params.stencil_front.compareOp;
|
||||
depth_stencil_info.back.failOp = static_params.stencil_back.failOp;
|
||||
depth_stencil_info.back.passOp = static_params.stencil_back.passOp;
|
||||
depth_stencil_info.back.depthFailOp = static_params.stencil_back.depthFailOp;
|
||||
depth_stencil_info.back.compareOp = static_params.stencil_back.compareOp;
|
||||
depth_stencil_info.minDepthBounds = static_params.depth_min_bounds;
|
||||
depth_stencil_info.maxDepthBounds = static_params.depth_max_bounds;
|
||||
|
||||
@@ -498,6 +489,8 @@ void CreatePipelineInternal(GraphicContext& graphics, PipelineCache::Pipeline& p
|
||||
vk::DynamicState::eDepthCompareOp,
|
||||
vk::DynamicState::eDepthBiasEnable,
|
||||
vk::DynamicState::eDepthBias,
|
||||
vk::DynamicState::eStencilTestEnable,
|
||||
vk::DynamicState::eStencilOp,
|
||||
vk::DynamicState::eStencilCompareMask,
|
||||
vk::DynamicState::eStencilReference,
|
||||
vk::DynamicState::eStencilWriteMask,
|
||||
|
||||
@@ -403,19 +403,16 @@ static void SetGraphicsDynamicParams(const CommandBuffer& buffer, vk::CommandBuf
|
||||
vk_buffer.setDepthBias(constant_factor, poly_offset.clamp, slope_factor);
|
||||
}
|
||||
|
||||
vk_buffer.setStencilTestEnable(depth.stencil_test_enable ? VK_TRUE : VK_FALSE);
|
||||
if (depth.stencil_test_enable) {
|
||||
vk_buffer.setStencilCompareMask(vk::StencilFaceFlagBits::eFront,
|
||||
depth.stencil_dynamic_front.compareMask);
|
||||
vk_buffer.setStencilCompareMask(vk::StencilFaceFlagBits::eBack,
|
||||
depth.stencil_dynamic_back.compareMask);
|
||||
vk_buffer.setStencilWriteMask(vk::StencilFaceFlagBits::eFront,
|
||||
depth.stencil_dynamic_front.writeMask);
|
||||
vk_buffer.setStencilWriteMask(vk::StencilFaceFlagBits::eBack,
|
||||
depth.stencil_dynamic_back.writeMask);
|
||||
vk_buffer.setStencilReference(vk::StencilFaceFlagBits::eFront,
|
||||
depth.stencil_dynamic_front.reference);
|
||||
vk_buffer.setStencilReference(vk::StencilFaceFlagBits::eBack,
|
||||
depth.stencil_dynamic_back.reference);
|
||||
const auto set_stencil = [&](vk::StencilFaceFlagBits face, const vk::StencilOpState& state) {
|
||||
vk_buffer.setStencilOp(face, state.failOp, state.passOp, state.depthFailOp, state.compareOp);
|
||||
vk_buffer.setStencilCompareMask(face, state.compareMask);
|
||||
vk_buffer.setStencilWriteMask(face, state.writeMask);
|
||||
vk_buffer.setStencilReference(face, state.reference);
|
||||
};
|
||||
set_stencil(vk::StencilFaceFlagBits::eFront, depth.stencil_front);
|
||||
set_stencil(vk::StencilFaceFlagBits::eBack, depth.stencil_back);
|
||||
}
|
||||
|
||||
#if defined(__APPLE__)
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
|
||||
namespace Libs::Graphics {
|
||||
|
||||
@@ -67,33 +66,6 @@ inline constexpr TargetViewInfo ResolveTargetViewInfo(uint32_t base_layer, uint3
|
||||
base_layer, last_layer - base_layer + 1u, last_layer + 1u};
|
||||
}
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
struct PipelineStencilStaticState {
|
||||
vk::StencilOp failOp = vk::StencilOp::eKeep;
|
||||
vk::StencilOp passOp = vk::StencilOp::eKeep;
|
||||
vk::StencilOp depthFailOp = vk::StencilOp::eKeep;
|
||||
vk::CompareOp compareOp = vk::CompareOp::eNever;
|
||||
};
|
||||
|
||||
struct PipelineStencilDynamicState {
|
||||
uint32_t compareMask = 0;
|
||||
uint32_t writeMask = 0;
|
||||
uint32_t reference = 0;
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
static_assert(std::is_trivially_copyable_v<PipelineStencilStaticState>);
|
||||
static_assert(std::is_standard_layout_v<PipelineStencilStaticState>);
|
||||
static_assert(alignof(PipelineStencilStaticState) == 1);
|
||||
static_assert(sizeof(PipelineStencilStaticState) ==
|
||||
sizeof(vk::StencilOp) * 3 + sizeof(vk::CompareOp));
|
||||
static_assert(std::is_trivially_copyable_v<PipelineStencilDynamicState>);
|
||||
static_assert(std::is_standard_layout_v<PipelineStencilDynamicState>);
|
||||
static_assert(alignof(PipelineStencilDynamicState) == 1);
|
||||
static_assert(sizeof(PipelineStencilDynamicState) == sizeof(uint32_t) * 3);
|
||||
|
||||
} // namespace Libs::Graphics
|
||||
|
||||
#endif // EMULATOR_SRC_GRAPHICS_HOST_GPU_RENDERER_RENDERTARGET_H_
|
||||
|
||||
@@ -10275,9 +10275,9 @@ public:
|
||||
!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 ==
|
||||
read_only_depth.stencil_front.writeMask == 0 &&
|
||||
read_only_depth.stencil_back.writeMask == 0 &&
|
||||
read_only_depth.stencil_front.passOp ==
|
||||
vk::StencilOp::eKeep &&
|
||||
!read_only_depth.AttachmentWriteAspects() &&
|
||||
depth_attachment_layout(read_only_depth) ==
|
||||
@@ -12501,15 +12501,18 @@ public:
|
||||
cmd.setDepthWriteEnable(depth.depth_write_enable);
|
||||
cmd.setDepthCompareOp(depth.depth_compare_op);
|
||||
cmd.setDepthBiasEnable(false);
|
||||
cmd.setStencilTestEnable(depth.stencil_test_enable);
|
||||
if (depth.stencil_test_enable) {
|
||||
const auto set_stencil = [&](vk::StencilFaceFlagBits face,
|
||||
const PipelineStencilDynamicState &state) {
|
||||
const vk::StencilOpState &state) {
|
||||
cmd.setStencilOp(face, state.failOp, state.passOp, state.depthFailOp,
|
||||
state.compareOp);
|
||||
cmd.setStencilCompareMask(face, state.compareMask);
|
||||
cmd.setStencilWriteMask(face, state.writeMask);
|
||||
cmd.setStencilReference(face, state.reference);
|
||||
};
|
||||
set_stencil(vk::StencilFaceFlagBits::eFront, depth.stencil_dynamic_front);
|
||||
set_stencil(vk::StencilFaceFlagBits::eBack, depth.stencil_dynamic_back);
|
||||
set_stencil(vk::StencilFaceFlagBits::eFront, depth.stencil_front);
|
||||
set_stencil(vk::StencilFaceFlagBits::eBack, depth.stencil_back);
|
||||
}
|
||||
const vk::Bool32 write = true;
|
||||
cmd.setColorWriteEnableEXT(1, &write);
|
||||
@@ -12624,6 +12627,9 @@ public:
|
||||
static_cast<uint16_t>(extent - 1), true};
|
||||
registers.SetDepthRenderTarget(stencil_target);
|
||||
HW::DepthControl stencil_control{};
|
||||
// Keep the same depth/stencil attachment active when stencil testing is disabled.
|
||||
stencil_control.z_enable = true;
|
||||
stencil_control.zfunc = static_cast<uint8_t>(vk::CompareOp::eAlways);
|
||||
stencil_control.stencil_enable = stencil_control.backface_enable = true;
|
||||
stencil_control.stencilfunc = stencil_control.stencilfunc_bf =
|
||||
static_cast<uint8_t>(vk::CompareOp::eAlways);
|
||||
@@ -12651,6 +12657,9 @@ public:
|
||||
scheduler.Finish();
|
||||
return ReadBuffer(name, stencil_readback, extent * extent / 4);
|
||||
};
|
||||
const std::array stencil_pipelines{
|
||||
pipeline(true, 2, 2, false, true).pipeline,
|
||||
pipeline(true, 2, 2, false, false).pipeline};
|
||||
const auto check_stencil = [&](const char *label, bool back_face,
|
||||
uint8_t initial, uint8_t written) {
|
||||
vk::ClearValue clear{};
|
||||
@@ -12658,7 +12667,11 @@ public:
|
||||
TextureCacheTestAccess::ClearImage(cache, scheduler.Current(), depth.image_id,
|
||||
{vk::ImageAspectFlagBits::eDepth | vk::ImageAspectFlagBits::eStencil,
|
||||
0, 1, 0, 1}, clear);
|
||||
draw(pipeline(true, 2, 2, false, !back_face));
|
||||
const auto &selected = pipeline(true, 2, 2, false, !back_face);
|
||||
Require(name, "dynamic stencil pipeline reuse",
|
||||
selected.pipeline == stencil_pipelines[back_face],
|
||||
"stencil enable, operations or references changed the graphics pipeline");
|
||||
draw(selected);
|
||||
const auto result = read_stencil();
|
||||
const auto *stencil_bytes = reinterpret_cast<const uint8_t *>(result.data());
|
||||
for (uint32_t texel = 0; texel < extent * extent; ++texel) {
|
||||
@@ -12671,6 +12684,17 @@ public:
|
||||
check_stencil("front-face ReplaceTest", false, 0x35, 0xb5);
|
||||
check_stencil("back-face masked ReplaceOp", true, 0xb5, 0x35);
|
||||
|
||||
stencil_control.stencil_enable = false;
|
||||
registers.SetDepthControl(stencil_control);
|
||||
RenderExecutorTestAccess::ResolveRenderDepthTarget(executor, scheduler.Current(), depth);
|
||||
check_stencil("disabled front stencil", false, 0x35, 0x35);
|
||||
check_stencil("disabled back stencil", true, 0xb5, 0xb5);
|
||||
stencil_control.stencil_enable = true;
|
||||
registers.SetDepthControl(stencil_control);
|
||||
RenderExecutorTestAccess::ResolveRenderDepthTarget(executor, scheduler.Current(), depth);
|
||||
check_stencil("re-enabled front stencil", false, 0x35, 0xb5);
|
||||
check_stencil("re-enabled back stencil", true, 0xb5, 0x35);
|
||||
|
||||
// Frame 6115 uses separate test/op replacement values with Always comparisons.
|
||||
stencil_control.z_enable = stencil_control.z_write_enable = true;
|
||||
stencil_control.zfunc = static_cast<uint8_t>(vk::CompareOp::eLessOrEqual);
|
||||
@@ -12679,8 +12703,8 @@ public:
|
||||
registers.SetStencilMask({8, 0xff, 0xff, 1, 8, 0xff, 0xff, 1});
|
||||
RenderExecutorTestAccess::ResolveRenderDepthTarget(executor, scheduler.Current(), depth);
|
||||
Require(name, "independent stencil references",
|
||||
depth.stencil_dynamic_front.reference == 8 &&
|
||||
depth.stencil_dynamic_back.reference == 1,
|
||||
depth.stencil_front.reference == 8 &&
|
||||
depth.stencil_back.reference == 1,
|
||||
"always-pass faces must preserve their distinct replacement values");
|
||||
check_stencil("front test-value replacement", false, 0x35, 8);
|
||||
check_stencil("back operation-value replacement", true, 0x35, 1);
|
||||
@@ -12700,8 +12724,8 @@ public:
|
||||
registers.SetStencilMask({8, 8, 1, 1, 8, 8, 1, 1});
|
||||
RenderExecutorTestAccess::ResolveRenderDepthTarget(executor, scheduler.Current(), depth);
|
||||
Require(name, "masked compare and replace reference",
|
||||
depth.stencil_dynamic_front.reference == 9 &&
|
||||
depth.stencil_dynamic_back.reference == 9,
|
||||
depth.stencil_front.reference == 9 &&
|
||||
depth.stencil_back.reference == 9,
|
||||
"disjoint comparison and replacement bits must combine into one reference");
|
||||
check_stencil("masked compare passes", false, 0xb8, 0xb9);
|
||||
check_stencil("masked compare fails", false, 0xb0, 0xb0);
|
||||
@@ -28499,27 +28523,25 @@ void CheckDepthAttachmentWrites() {
|
||||
|
||||
target.depth_load_clear_enable = false;
|
||||
target.stencil_test_enable = true;
|
||||
target.stencil_dynamic_front = {0xff, 0xff, 0};
|
||||
target.stencil_dynamic_back = target.stencil_dynamic_front;
|
||||
target.stencil_static_front = {vk::StencilOp::eKeep, vk::StencilOp::eKeep,
|
||||
vk::StencilOp::eKeep, vk::CompareOp::eAlways};
|
||||
target.stencil_static_back = target.stencil_static_front;
|
||||
target.stencil_front = {vk::StencilOp::eKeep, vk::StencilOp::eKeep,
|
||||
vk::StencilOp::eKeep, vk::CompareOp::eAlways, 0xff, 0xff, 0};
|
||||
target.stencil_back = target.stencil_front;
|
||||
Require("DepthAttachmentWrites", "stencil keep",
|
||||
!target.AttachmentWriteAspects(),
|
||||
"KEEP-only stencil state claimed a stencil write");
|
||||
|
||||
target.stencil_static_front.failOp = vk::StencilOp::eZero;
|
||||
target.stencil_front.failOp = vk::StencilOp::eZero;
|
||||
Require("DepthAttachmentWrites", "unreachable stencil fail",
|
||||
!target.AttachmentWriteAspects(),
|
||||
"ALWAYS comparison claimed an unreachable fail operation");
|
||||
|
||||
target.stencil_static_front.failOp = vk::StencilOp::eKeep;
|
||||
target.stencil_static_front.passOp = vk::StencilOp::eReplace;
|
||||
target.stencil_front.failOp = vk::StencilOp::eKeep;
|
||||
target.stencil_front.passOp = vk::StencilOp::eReplace;
|
||||
Require("DepthAttachmentWrites", "stencil pass write",
|
||||
target.AttachmentWriteAspects() == vk::ImageAspectFlagBits::eStencil,
|
||||
"write-capable stencil pass did not claim stencil");
|
||||
|
||||
target.stencil_dynamic_front.writeMask = 0;
|
||||
target.stencil_front.writeMask = 0;
|
||||
Require("DepthAttachmentWrites", "back-face keep",
|
||||
!target.AttachmentWriteAspects(),
|
||||
"masked front write or KEEP-only back face claimed stencil");
|
||||
|
||||
Reference in New Issue
Block a user