fix(agc): read a 16-bit integer view of a depth plane as its stored values
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
ac70928d86
commit
bbf430e22d
|
|
@ -92,7 +92,7 @@ public:
|
|||
const bool d16 = target.format == VK_FORMAT_D16_UNORM || target.format == VK_FORMAT_D16_UNORM_S8_UINT;
|
||||
const auto expected = stencil ? VK_FORMAT_R8_UINT : d16 ? VK_FORMAT_R16_UNORM : VK_FORMAT_R32_SFLOAT;
|
||||
const auto format = ResolveTextureFormat(resource.format);
|
||||
const bool depthBits = !stencil && !d16 && words.size() >= 4 && ShaderRecompiler::IsDepthBitsTexture(words[1], words[3]);
|
||||
const bool depthBits = !stencil && words.size() >= 4 && ShaderRecompiler::DepthBitsTextureWidth(words[1], words[3]) == (d16 ? 16u : 32u);
|
||||
if ((format != expected && !depthBits) || resource.dimension != TextureDimension::k2D || resource.width != target.extent.width || resource.height != target.extent.height || resource.baseLevel != 0 || resource.lastLevel != 0 || resource.baseArray != 0) {
|
||||
char text[448];
|
||||
std::snprintf(text, sizeof(text), "AGC graphics: sampling the %s plane of depth surface 0x%llx (%ux%u, vk format %d) as a %ux%u texture of guest format %u (vk %d), tile mode %u, dimension %d, levels %u-%u, slice %u is not implemented (T# %08x %08x %08x %08x %08x %08x %08x %08x)",
|
||||
|
|
|
|||
|
|
@ -265,11 +265,18 @@ std::shared_ptr<StorageTexture> sampledStorageSource(const Context& context, con
|
|||
std::shared_ptr<Texture> cachedTexture(const Context& context, std::span<const std::uint32_t> words, const GuestTextureResource& resource, VkComponentMapping components, std::uint64_t guestBytes = 0) {
|
||||
CaptureTrace::Log("sampled-lookup address=%llx width=%u height=%u dcc=%llx", static_cast<unsigned long long>(resource.baseAddress), resource.width, resource.height, static_cast<unsigned long long>(resource.dccAddress));
|
||||
if (auto depth = DepthSurfaceTexture(context, words, resource, components)) return depth;
|
||||
if (words.size() >= 4 && ShaderRecompiler::IsDepthBitsTexture(words[1], words[3])) {
|
||||
const auto depthBitsWidth = words.size() >= 4 ? ShaderRecompiler::DepthBitsTextureWidth(words[1], words[3]) : 0u;
|
||||
if (depthBitsWidth == 32u) {
|
||||
char text[160];
|
||||
std::snprintf(text, sizeof(text), "AGC graphics: 32-bit integer read of the depth-layout texture 0x%llx, which is no depth surface drawn with, is not implemented", static_cast<unsigned long long>(resource.baseAddress));
|
||||
throw std::runtime_error(text);
|
||||
}
|
||||
constexpr auto unorm16 = static_cast<std::uint32_t>(ShaderRecompiler::IrBufferFormat::Format16UNorm);
|
||||
if (depthBitsWidth == 16u && resource.format != unorm16) {
|
||||
auto normalized = resource;
|
||||
normalized.format = unorm16;
|
||||
return cachedTexture(context, words, normalized, components, guestBytes);
|
||||
}
|
||||
static const bool disabled = std::getenv("APS5_NO_TEXTURE_CACHE") != nullptr;
|
||||
const bool profile = LookupOutcomes::Profiled();
|
||||
const auto start = profile ? std::chrono::steady_clock::now() : std::chrono::steady_clock::time_point{};
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ struct ImageResource {
|
|||
bool cube = false;
|
||||
bool r128 = false;
|
||||
bool depthBits = false;
|
||||
bool depthUnorm16 = false;
|
||||
std::uint32_t indirectRoot = NoIndirectImage;
|
||||
std::uint32_t indirectMappingOffset = 0;
|
||||
std::uint32_t indirectSearchIterations = 0;
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ struct ResourceSpecialization {
|
|||
bool cube = false;
|
||||
bool fmask = false;
|
||||
bool depthBits = false;
|
||||
bool depthUnorm16 = false;
|
||||
|
||||
bool operator==(const Image& other) const;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ struct DecodedImage {
|
|||
bool cube = false;
|
||||
bool fmask = false;
|
||||
bool depthBits = false;
|
||||
bool depthUnorm16 = false;
|
||||
};
|
||||
|
||||
ShaderBufferResource decodeBufferDescriptor(const DescriptorValue& value) {
|
||||
|
|
@ -164,6 +165,7 @@ DecodedImage decodeImageDescriptor(const DescriptorValue& descriptor, const Imag
|
|||
decoded.numericClass = SampledTextureNumericClass(format);
|
||||
if (!storage && !base.depthCompare && IsDepthBitsTexture(descriptor.dwords[1], descriptor.dwords[3])) {
|
||||
decoded.depthBits = true;
|
||||
decoded.depthUnorm16 = DepthBitsTextureWidth(descriptor.dwords[1], descriptor.dwords[3]) == 16u;
|
||||
decoded.numericClass = IrTextureNumericClass::Float;
|
||||
decoded.shaderSwizzle = descriptorImageSwizzle(descriptor);
|
||||
}
|
||||
|
|
@ -530,6 +532,7 @@ void buildResourceSpecialization(const IrResourcePlan& plan, ResourceSnapshot& s
|
|||
entry.cube = decoded.cube;
|
||||
entry.fmask = decoded.fmask;
|
||||
entry.depthBits = decoded.depthBits;
|
||||
entry.depthUnorm16 = decoded.depthUnorm16;
|
||||
result.images.push_back(entry);
|
||||
}
|
||||
|
||||
|
|
@ -615,6 +618,7 @@ void ResourceMaterializer::Apply(IrProgram& program, const ResourceSpecializatio
|
|||
image.indirectSearchIterations = source.indirectSearchIterations;
|
||||
image.cube = source.cube;
|
||||
image.depthBits = source.depthBits;
|
||||
image.depthUnorm16 = source.depthUnorm16;
|
||||
image.indirectResources.clear();
|
||||
}
|
||||
for (std::uint32_t index = 0; index < images.size(); index++) {
|
||||
|
|
@ -880,7 +884,7 @@ bool ResourceSpecialization::Buffer::operator==(const Buffer& other) const {
|
|||
}
|
||||
|
||||
bool ResourceSpecialization::Image::operator==(const Image& other) const {
|
||||
return numericClass == other.numericClass && dimension == other.dimension && mipCount == other.mipCount && conversionFormat == other.conversionFormat && shaderSwizzle == other.shaderSwizzle && indirectRoot == other.indirectRoot && indirectMappingOffset == other.indirectMappingOffset && indirectSearchIterations == other.indirectSearchIterations && cube == other.cube && fmask == other.fmask && depthBits == other.depthBits;
|
||||
return numericClass == other.numericClass && dimension == other.dimension && mipCount == other.mipCount && conversionFormat == other.conversionFormat && shaderSwizzle == other.shaderSwizzle && indirectRoot == other.indirectRoot && indirectMappingOffset == other.indirectMappingOffset && indirectSearchIterations == other.indirectSearchIterations && cube == other.cube && fmask == other.fmask && depthBits == other.depthBits && depthUnorm16 == other.depthUnorm16;
|
||||
}
|
||||
|
||||
bool ResourceSpecialization::operator==(const ResourceSpecialization& other) const {
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ enum class ImageType : std::uint32_t {
|
|||
[[nodiscard]] bool IsFmaskTextureFormat(IrBufferFormat format);
|
||||
[[nodiscard]] IrTextureNumericClass SampledTextureNumericClass(IrBufferFormat format);
|
||||
[[nodiscard]] IrBufferFormat RemapTextureFormat(IrBufferFormat format);
|
||||
[[nodiscard]] std::uint32_t DepthBitsTextureWidth(std::uint32_t word1, std::uint32_t word3);
|
||||
[[nodiscard]] bool IsDepthBitsTexture(std::uint32_t word1, std::uint32_t word3);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -121,11 +121,17 @@ IrBufferFormat RemapTextureFormat(IrBufferFormat format) {
|
|||
return format == IrBufferFormat::Format11_11_10UInt ? IrBufferFormat::Format32UInt : format;
|
||||
}
|
||||
|
||||
bool IsDepthBitsTexture(std::uint32_t word1, std::uint32_t word3) {
|
||||
std::uint32_t DepthBitsTextureWidth(std::uint32_t word1, std::uint32_t word3) {
|
||||
const auto format = static_cast<IrBufferFormat>((word1 >> 20u) & 0x1ffu);
|
||||
const auto swizzle = (word3 >> 20u) & 0x1fu;
|
||||
const bool depthLayout = swizzle == 4u || swizzle == 8u || swizzle == 16u || swizzle == 20u || swizzle == 24u;
|
||||
return depthLayout && (format == IrBufferFormat::Format32UInt || format == IrBufferFormat::Format32SInt);
|
||||
if (!depthLayout) return 0u;
|
||||
if (format == IrBufferFormat::Format32UInt || format == IrBufferFormat::Format32SInt) return 32u;
|
||||
return format == IrBufferFormat::Format16UInt ? 16u : 0u;
|
||||
}
|
||||
|
||||
bool IsDepthBitsTexture(std::uint32_t word1, std::uint32_t word3) {
|
||||
return DepthBitsTextureWidth(word1, word3) != 0u;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -396,6 +396,7 @@ void encodeInfo(Writer& writer, const CompiledShaderInfo& compiled) {
|
|||
out.Value(image.cube);
|
||||
out.Value(image.r128);
|
||||
out.Value(image.depthBits);
|
||||
out.Value(image.depthUnorm16);
|
||||
out.Value(image.indirectRoot);
|
||||
out.Value(image.indirectMappingOffset);
|
||||
out.Value(image.indirectSearchIterations);
|
||||
|
|
@ -482,6 +483,7 @@ void decodeInfo(Reader& reader, CompiledShaderInfo& compiled) {
|
|||
in.Value(image.cube);
|
||||
in.Value(image.r128);
|
||||
in.Value(image.depthBits);
|
||||
in.Value(image.depthUnorm16);
|
||||
in.Value(image.indirectRoot);
|
||||
in.Value(image.indirectMappingOffset);
|
||||
in.Value(image.indirectSearchIterations);
|
||||
|
|
@ -793,6 +795,7 @@ void BuildKey(const RecompileRequest& request, std::uint32_t hostSubgroupSize, c
|
|||
out.Value(image.cube);
|
||||
out.Value(image.fmask);
|
||||
out.Value(image.depthBits);
|
||||
out.Value(image.depthUnorm16);
|
||||
});
|
||||
writer.Values(std::span<const std::uint32_t>(specialization.boundDescriptors));
|
||||
const auto& switches = switchKey();
|
||||
|
|
|
|||
|
|
@ -308,6 +308,11 @@ std::uint32_t ResultVector(SpirvValueEmitContext& ctx, const ImageEmitAccess& ac
|
|||
}
|
||||
const auto scalar = state.module.AllocateId();
|
||||
state.module.AddFunction(spv::OpCompositeExtract, ImageScalarType(state, valueClass), scalar, value, index);
|
||||
if (access.image.depthUnorm16) {
|
||||
const auto scaled = Binary(state, spv::OpFMul, TypeF32(state), scalar, ConstantF32Value(state, 65535.0f));
|
||||
component[index] = Unary(state, spv::OpConvertFToU, TypeU32(state), Binary(state, spv::OpFAdd, TypeF32(state), scaled, ConstantF32Value(state, 0.5f)));
|
||||
continue;
|
||||
}
|
||||
component[index] = SampledComponentBits(ctx, scalar, valueClass);
|
||||
}
|
||||
const auto result = state.module.AllocateId();
|
||||
|
|
|
|||
Loading…
Reference in New Issue