From 846002c5ebce88fafcafc90aafce9dd7da1451fe Mon Sep 17 00:00:00 2001 From: nmzik Date: Fri, 31 Jul 2026 17:29:44 +0200 Subject: [PATCH] shader: fix invalid texture descriptors and add missing format --- src/graphics/guest_gpu/gpu_defs.h | 1 + .../host_gpu/renderer/cache/samplerCache.cpp | 5 ++++- .../host_gpu/renderer/image/textureCommon.cpp | 4 ++++ .../recompiler/ir/ResourceMaterialization.cpp | 13 +++++++++---- tests/ResourceTrackingTests.cpp | 13 +++++++++++++ tests/ShaderRecompilerComputeTests.cpp | 6 ++++++ 6 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/graphics/guest_gpu/gpu_defs.h b/src/graphics/guest_gpu/gpu_defs.h index 7515c90d2..1df5f6f5c 100644 --- a/src/graphics/guest_gpu/gpu_defs.h +++ b/src/graphics/guest_gpu/gpu_defs.h @@ -72,6 +72,7 @@ enum class ChannelLayout : uint32_t { k32_32 = 11, k16_16_16_16 = 12, k32_32_32_32 = 14, + k5_6_5 = 16, k5_5_5_1 = 17, k4_4_4_4 = 19, kBc1 = 35, diff --git a/src/graphics/host_gpu/renderer/cache/samplerCache.cpp b/src/graphics/host_gpu/renderer/cache/samplerCache.cpp index a96eadc39..edddcdf60 100644 --- a/src/graphics/host_gpu/renderer/cache/samplerCache.cpp +++ b/src/graphics/host_gpu/renderer/cache/samplerCache.cpp @@ -56,7 +56,10 @@ vk::Sampler SamplerCache::GetSampler(const ShaderSamplerResource& r) { case Prospero::SamplerAnisoRatio::kFour: aniso_ratio = 4.0f; break; case Prospero::SamplerAnisoRatio::kEight: aniso_ratio = 8.0f; break; case Prospero::SamplerAnisoRatio::kSixteen: aniso_ratio = 16.0f; break; - default: EXIT("unknown ratio: %d\n", static_cast(r.MaxAnisoRatio())); + default: + EXIT("unknown ratio: %d dwords=%08x,%08x,%08x,%08x\n", + static_cast(r.MaxAnisoRatio()), r.fields[0], r.fields[1], r.fields[2], + r.fields[3]); } } diff --git a/src/graphics/host_gpu/renderer/image/textureCommon.cpp b/src/graphics/host_gpu/renderer/image/textureCommon.cpp index 2f5c42192..0ca19325e 100644 --- a/src/graphics/host_gpu/renderer/image/textureCommon.cpp +++ b/src/graphics/host_gpu/renderer/image/textureCommon.cpp @@ -70,6 +70,10 @@ constexpr RenderTargetFormatMapping kRenderTargetFormats[] = { Prospero::ChannelType::kFloat, Prospero::ChannelOrder::kStandard, {vk::Format::eB10G11R11UfloatPack32, 4}}, + {Prospero::ChannelLayout::k5_6_5, + Prospero::ChannelType::kUNorm, + Prospero::ChannelOrder::kStandard, + {vk::Format::eB5G6R5UnormPack16, 2}}, {Prospero::ChannelLayout::k16, Prospero::ChannelType::kUNorm, Prospero::ChannelOrder::kStandard, diff --git a/src/graphics/shader/recompiler/ir/ResourceMaterialization.cpp b/src/graphics/shader/recompiler/ir/ResourceMaterialization.cpp index f686c94cb..670f7a41d 100644 --- a/src/graphics/shader/recompiler/ir/ResourceMaterialization.cpp +++ b/src/graphics/shader/recompiler/ir/ResourceMaterialization.cpp @@ -47,8 +47,9 @@ bool NullImageDescriptor(const DescriptorValue& descriptor) { } bool ValidImageDescriptor(const DescriptorValue& descriptor) { - const auto type = static_cast((descriptor.dwords[3] >> 28u) & 0xfu); - if (type < Prospero::ImageType::kColor1D) { + const auto type = static_cast((descriptor.dwords[3] >> 28u) & 0xfu); + const auto format = static_cast((descriptor.dwords[1] >> 20u) & 0x1ffu); + if (type < Prospero::ImageType::kColor1D || format == Prospero::BufferFormat::kInvalid) { return false; } if (type == Prospero::ImageType::kColor2DMsaa || @@ -199,8 +200,12 @@ bool ValidateResourceSpecialization(const Program& program, const ResourceSnapsh if (dimension == Decoder::ImageDimension::Unknown || dimension != image.dimension || DescriptorIsCube(descriptor) != image.cube) { if (error != nullptr) { - *error = - fmt::format("image descriptor {} no longer matches specialized dimension", i); + *error = fmt::format( + "image descriptor {} no longer matches specialized dimension: " + "{:08x},{:08x},{:08x},{:08x},{:08x},{:08x},{:08x},{:08x}", + i, descriptor.dwords[0], descriptor.dwords[1], descriptor.dwords[2], + descriptor.dwords[3], descriptor.dwords[4], descriptor.dwords[5], + descriptor.dwords[6], descriptor.dwords[7]); } return false; } diff --git a/tests/ResourceTrackingTests.cpp b/tests/ResourceTrackingTests.cpp index 5d7c04f9a..87c187f83 100644 --- a/tests/ResourceTrackingTests.cpp +++ b/tests/ResourceTrackingTests.cpp @@ -870,6 +870,7 @@ void TestMaterializationSharesReadConstEvaluation() { for (uint32_t i = 0; i < memory.words.size(); i++) { memory.words[i] = 0x100 + i; } + memory.words[1] |= Prospero::GpuEnumValue(Prospero::BufferFormat::k8UNorm) << 20u; memory.words[3] |= Prospero::GpuEnumValue(Prospero::ImageType::kColor2D) << 28u; std::array user_data {}; user_data[16] = static_cast(memory.base); @@ -910,6 +911,7 @@ void TestInvalidImagesMaterializeAsNull() { std::string error; for (uint32_t type = 0; type < 8; type++) { auto descriptor = stale; + descriptor[1] |= Prospero::GpuEnumValue(Prospero::BufferFormat::k8UNorm) << 20u; descriptor[3] = (descriptor[3] & 0x0fffffffu) | (type << 28u); ResourceSnapshot snapshot; Check(MaterializeResources(sampled, {descriptor}, snapshot, &error) && @@ -966,7 +968,18 @@ void TestInvalidImagesMaterializeAsNull() { } } + std::array invalid_format {}; + invalid_format[0] = 1; + invalid_format[3] = Prospero::GpuEnumValue(Prospero::ImageType::kColor2D) << 28u; + ResourceSnapshot invalid_format_snapshot; + Check(MaterializeResources(sampled, {invalid_format}, invalid_format_snapshot, &error) && + std::all_of(invalid_format_snapshot.images[0].dwords.begin(), + invalid_format_snapshot.images[0].dwords.end(), + [](uint32_t word) { return word == 0; }), + "invalid-format image descriptor was not normalized to null"); + auto valid = stale; + valid[1] |= Prospero::GpuEnumValue(Prospero::BufferFormat::k8UNorm) << 20u; valid[3] = (valid[3] & 0x0fffffffu) | (Prospero::GpuEnumValue(Prospero::ImageType::kColor2D) << 28u); ResourceSnapshot valid_snapshot; diff --git a/tests/ShaderRecompilerComputeTests.cpp b/tests/ShaderRecompilerComputeTests.cpp index 84651d2d1..9b42c0a6e 100644 --- a/tests/ShaderRecompilerComputeTests.cpp +++ b/tests/ShaderRecompilerComputeTests.cpp @@ -14410,6 +14410,12 @@ bool CacheFault(void* opaque, PageFaultAccess access, uint64_t vaddr, uint64_t s #if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS void CheckRenderTargetFormatContract() { + const auto rgb565 = TextureGetRenderTargetFormat(16u, 0u, 0u); + Require("RenderTargetFormat", "RGB565 UNorm", + rgb565.format == vk::Format::eB5G6R5UnormPack16 && + rgb565.bytes_per_element == 2u && rgb565.export_mapping.IsIdentity(), + "RGB565 UNorm render-target tuple was rejected"); + const auto uint_format = TextureGetRenderTargetFormat(12u, 4u, 0u); Require("RenderTargetFormat", "RGBA16 uint", uint_format.format == vk::Format::eR16G16B16A16Uint &&