mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-11-05 13:20:11 +00:00
fix(shader): fold texel offsets into base-level unnormalized samples
An implicit-LOD or gradient sample with a texel offset through an unnormalized S# was refused at bind time with "unnormalized guest sampler is used by an implicit-LOD sample". PPSA01317 aborts on boot on such a pixel image_sample_o. The base-level path already samples these through OpImageSampleExplicitLod with LOD 0, which Vulkan allows for unnormalized samplers, but it dropped the offset. It now adds the offset to the coordinates in that branch, as the explicit-LOD offset fold does, so a sampler whose uses also include offsets takes the base-level path. A normalized S# keeps the offset operand. AI-assisted: yes
This commit is contained in:
1 parent
f219248f0b
commit
7c19c66def
3 files changed
+22
-2
No files matched your search
@@ -4272,6 +4272,26 @@ void verifyUnnormalizedSamplers() {
|
||||
pixel.context.userData = normalizedPixelData;
|
||||
const auto pixelNormalized = Recompile(pixel);
|
||||
require(proven(pixelNormalized, false) && implicitSamples(pixelNormalized.spirv.Words()) == 1u, "unnormalized samplers: a pixel image_sample through a normalized S# is not an implicit-LOD sample");
|
||||
const std::array<std::uint32_t, 7> pixelOffsetCode{0x7e0202ffu, 0x00000201u, 0xf0c00f08u, 0x00400801u, 0xf800180fu, 0x0b0a0908u, 0xbf810000u};
|
||||
pixel.shader = {ShaderStage::Fragment, 0x50000u, pixelOffsetCode, 0, {}};
|
||||
pixel.context.userData = pixelData;
|
||||
pixel.target.supportedCapabilities = capabilities;
|
||||
pixel.target.nonConstantImageOffsets = true;
|
||||
const auto pixelOffsetUnnormalized = Recompile(pixel);
|
||||
require(proven(pixelOffsetUnnormalized, true), "unnormalized texel offsets: a pixel image_sample_o through an unnormalized S# was not flagged");
|
||||
auditSpirv(pixelOffsetUnnormalized.spirv.Words());
|
||||
require(foldedSamples(pixelOffsetUnnormalized.spirv.Words()), "unnormalized texel offsets: a pixel image_sample_o offset was not added to the base-level coordinates");
|
||||
pixel.context.userData = normalizedPixelData;
|
||||
const auto pixelOffsetNormalized = Recompile(pixel);
|
||||
std::vector<std::uint32_t> implicitMasks;
|
||||
const auto offsetWords = pixelOffsetNormalized.spirv.Words();
|
||||
for (std::size_t cursor = 5; cursor < offsetWords.size();) {
|
||||
const auto count = offsetWords[cursor] >> 16u;
|
||||
require(count != 0 && count <= offsetWords.size() - cursor, "unnormalized texel offsets: truncated SPIR-V instruction");
|
||||
if ((offsetWords[cursor] & 0xffffu) == spv::OpImageSampleImplicitLod && count > 5u) implicitMasks.push_back(offsetWords[cursor + 5]);
|
||||
cursor += count;
|
||||
}
|
||||
require(proven(pixelOffsetNormalized, false) && implicitMasks.size() == 1u && (implicitMasks[0] & (spv::ImageOperandsConstOffsetMask | spv::ImageOperandsOffsetMask)) != 0u, "unnormalized texel offsets: a normalized pixel image_sample_o is not an implicit-LOD sample with its offset");
|
||||
}
|
||||
|
||||
void verifyUnusedUnnormalizedSampler() {
|
||||
|
||||
+1
-1
@@ -140,7 +140,7 @@ inline bool FoldsTexelOffsets(const SamplerResource& sampler) {
|
||||
}
|
||||
|
||||
inline bool SamplesBaseLevelIfUnnormalized(const SamplerResource& sampler) {
|
||||
return (sampler.uses & (SamplerUseImplicitLod | SamplerUseGradient)) != 0u && (sampler.uses & ~static_cast<std::uint32_t>(SamplerUseExplicitLod | SamplerUseImplicitLod | SamplerUseGradient | SamplerUseNonZeroLod)) == 0u && !sampler.depthCompare;
|
||||
return (sampler.uses & (SamplerUseImplicitLod | SamplerUseGradient)) != 0u && (sampler.uses & ~static_cast<std::uint32_t>(SamplerUseExplicitLod | SamplerUseImplicitLod | SamplerUseGradient | SamplerUseNonZeroLod | SamplerUseOffset)) == 0u && !sampler.depthCompare;
|
||||
}
|
||||
|
||||
struct SampledResourcePair {
|
||||
|
||||
@@ -1465,7 +1465,7 @@ void EmitSampleOp(SpirvValueEmitContext& ctx, const ImageEmitAccess& access, con
|
||||
const auto selector = state.module.SpecializationConstant(TypeU32(state), PipelineSpecialization::UnnormalizedBaseLevelBase + mem.sampler, 0u);
|
||||
const auto unnormalized = Binary(state, spv::OpINotEqual, TypeBool(state), selector, ConstantU32(state, 0u));
|
||||
sample = EmitValueIfElse(state, unnormalized, resultType, [&] {
|
||||
return emitSample(setup.coord, spv::ImageOperandsLodMask, {ZeroF32(state)}, spv::OpImageSampleExplicitLod);
|
||||
return emitSample(hasOffset ? FoldedOffsetCoord(ctx, access, setup) : setup.coord, spv::ImageOperandsLodMask, {ZeroF32(state)}, spv::OpImageSampleExplicitLod);
|
||||
}, [&] {
|
||||
return emitSample(setup.coord, operandMask, operands, opcode);
|
||||
});
|
||||
|
||||
Reference in new issue
Block a user