renderer: validate depth swizzles by available channels

Co-authored-by: Mac <me@itsmemac.com>
Co-authored-by: Senaxx <michelbeld@gmail.com>
Co-authored-by: Ali Almohaya <AliAlmohaya@gmail.com>
This commit is contained in:
nmzik
2026-09-30 05:46:24 +04:00
parent 44798085bd
commit 44ba657573
2 changed files with 22 additions and 23 deletions
@@ -31,20 +31,14 @@ namespace ImageViewOps {
ImageViewOps::IsFormatDepthCompatible(view_format); ImageViewOps::IsFormatDepthCompatible(view_format);
} }
[[nodiscard]] inline bool IsValidImageSwizzle(uint32_t swizzle) noexcept { [[nodiscard]] inline bool IsValidImageSwizzle(uint32_t swizzle,
uint32_t component_count = 4) noexcept {
if ((swizzle & ~0xfffu) != 0) { if ((swizzle & ~0xfffu) != 0) {
return false; return false;
} }
for (uint32_t channel = 0; channel < 4; channel++) { for (uint32_t channel = 0; channel < 4; channel++) {
switch (GetDstSel(swizzle, channel)) { const auto selector = GetDstSel(swizzle, channel);
case 0: if (selector > 1 && (selector < 4 || selector >= 4 + component_count)) return false;
case 1:
case 4:
case 5:
case 6:
case 7: break;
default: return false;
}
} }
return true; return true;
} }
@@ -81,15 +75,8 @@ SelectSampledColorView(vk::Format image_format, vk::Format view_format, uint32_t
[[nodiscard]] inline bool IsSupportedSampledDepthView(vk::Format image_format, [[nodiscard]] inline bool IsSupportedSampledDepthView(vk::Format image_format,
vk::Format view_format, vk::Format view_format,
uint32_t swizzle) noexcept { uint32_t swizzle) noexcept {
if (!IsSupportedSampledDepthFormat(image_format, view_format)) { return IsSupportedSampledDepthFormat(image_format, view_format) &&
return false; IsValidImageSwizzle(swizzle, 1);
}
switch (swizzle) {
case DstSel(4, 4, 4, 4):
case DstSel(4, 0, 0, 0):
case DstSel(4, 0, 0, 1): return true;
default: return false;
}
} }
[[nodiscard]] inline bool [[nodiscard]] inline bool
+16 -4
View File
@@ -10108,7 +10108,7 @@ public:
allocation_size) == 0 && mapped == reinterpret_cast<void *>(base), allocation_size) == 0 && mapped == reinterpret_cast<void *>(base),
"comparison texture mapping failed"); "comparison texture mapping failed");
// Sea of Stars' 1D comparison texture and the existing six-face cube. // Sea of Stars' 1D comparison texture and the existing six-face cube.
const auto check_layout = [&](bool cube) { const auto check_layout = [&](bool cube, uint32_t swizzle) {
const uint32_t layers = cube ? depths.size() : 1; const uint32_t layers = cube ? depths.size() : 1;
const auto depth_at = [&](uint32_t layer, bool reversed) { const auto depth_at = [&](uint32_t layer, bool reversed) {
const auto index = cube ? layer : 2u; const auto index = cube ? layer : 2u;
@@ -10134,7 +10134,7 @@ public:
auto &executor = context.GetRenderExecutor(); auto &executor = context.GetRenderExecutor();
resources.MapMemory(base, allocation_size); resources.MapMemory(base, allocation_size);
ShaderTextureResource descriptor{{static_cast<uint32_t>(base >> 8u), ShaderTextureResource descriptor{{static_cast<uint32_t>(base >> 8u),
0x00700000u, 0, cube ? 0xb0100204u : 0x81800924u, 0x00700000u, 0, (cube ? 0xb0100000u : 0x81800000u) | swizzle,
layers - 1u, 0x00700000u, 0, 0}}; layers - 1u, 0x00700000u, 0, 0}};
ShaderSamplerResource sampler_descriptor{{1u << 12u, 0, 1u << 24u, 0}}; ShaderSamplerResource sampler_descriptor{{1u << 12u, 0, 1u << 24u, 0}};
TestCase test; TestCase test;
@@ -10185,6 +10185,13 @@ public:
executor, compiled.program.info.images[0], value); executor, compiled.program.info.images[0], value);
const auto view = cache.FindTexture(binding.image_id, binding.desc); const auto view = cache.FindTexture(binding.image_id, binding.desc);
auto &image = cache.GetImage(binding.image_id); auto &image = cache.GetImage(binding.image_id);
if (swizzle == DstSel(4, 4, 4, 1)) {
const vk::ComponentMapping mapping{vk::ComponentSwizzle::eR, vk::ComponentSwizzle::eR,
vk::ComponentSwizzle::eR, vk::ComponentSwizzle::eOne};
Require(name, "RRR1 depth view", std::ranges::any_of(image.views, [&](const auto &cached) {
return cached.view == view && cached.info.mapping == mapping;
}), "comparison depth view lost its replicated depth or constant alpha");
}
Require(name, "fresh depth backing", view != nullptr && Require(name, "fresh depth backing", view != nullptr &&
image.info.pixel_format == vk::Format::eD16Unorm && image.info.pixel_format == vk::Format::eD16Unorm &&
image.info.guest_format == Prospero::BufferFormat::k16UNorm && image.info.guest_format == Prospero::BufferFormat::k16UNorm &&
@@ -10263,8 +10270,9 @@ public:
resources.UnmapMemory(base, allocation_size); resources.UnmapMemory(base, allocation_size);
scheduler.Finish(); scheduler.Finish();
}; };
check_layout(false); check_layout(false, DstSel(4, 4, 4, 4));
check_layout(true); check_layout(false, DstSel(4, 4, 4, 1));
check_layout(true, DstSel(4, 0, 0, 1));
Require(name, "unmap", Libs::LibKernel::Memory::KernelMunmap(base, allocation_size) == 0, Require(name, "unmap", Libs::LibKernel::Memory::KernelMunmap(base, allocation_size) == 0,
"comparison texture unmap failed"); "comparison texture unmap failed");
Require(name, "release", Libs::LibKernel::Memory::KernelReleaseDirectMemory( Require(name, "release", Libs::LibKernel::Memory::KernelReleaseDirectMemory(
@@ -31874,6 +31882,10 @@ void CheckSampledColorViews() {
IsSupportedSampledDepthView( IsSupportedSampledDepthView(
vk::Format::eD16Unorm, vk::Format::eR16Unorm, DstSel(4, 0, 0, 0)), vk::Format::eD16Unorm, vk::Format::eR16Unorm, DstSel(4, 0, 0, 0)),
"D16 depth target did not select its R000 depth-aspect view"); "D16 depth target did not select its R000 depth-aspect view");
Require("SampledColorViews", "D16 RRR1 depth target",
IsSupportedSampledDepthView(
vk::Format::eD16Unorm, vk::Format::eR16Unorm, DstSel(4, 4, 4, 1)),
"D16 depth target rejected replicated depth with constant alpha");
Require("SampledColorViews", "D16S8 R001 depth target", Require("SampledColorViews", "D16S8 R001 depth target",
IsSupportedSampledDepthView(vk::Format::eD16UnormS8Uint, IsSupportedSampledDepthView(vk::Format::eD16UnormS8Uint,
vk::Format::eR16Unorm, vk::Format::eR16Unorm,