fix(shader): support multisampled depth image loads

This commit is contained in:
nmzik
2026-07-31 11:30:48 +02:00
parent 167da0abe0
commit 68be13345a
16 changed files with 276 additions and 103 deletions
+3 -3
View File
@@ -5774,7 +5774,7 @@ public:
std::make_shared<ShaderRecompiler::IR::Program>(
*array_runtime.program);
colliding_msaa_program->info.images[0].dimension =
ShaderRecompiler::Decoder::ImageDimension::Dim2D;
ShaderRecompiler::Decoder::ImageDimension::Dim2DMsaa;
auto colliding_msaa_snapshot =
std::make_shared<ShaderRecompiler::IR::ResourceSnapshot>();
colliding_msaa_snapshot->images.push_back(colliding_msaa_descriptor);
@@ -5836,7 +5836,7 @@ public:
auto msaa_program = std::make_shared<ShaderRecompiler::IR::Program>(
*array_runtime.program);
msaa_program->info.images[0].dimension =
ShaderRecompiler::Decoder::ImageDimension::Dim2D;
ShaderRecompiler::Decoder::ImageDimension::Dim2DMsaa;
auto msaa_snapshot =
std::make_shared<ShaderRecompiler::IR::ResourceSnapshot>();
msaa_snapshot->images.push_back(msaa_descriptor);
@@ -5877,7 +5877,7 @@ public:
auto msaa_array_program = std::make_shared<ShaderRecompiler::IR::Program>(
*msaa_runtime.program);
msaa_array_program->info.images[0].dimension =
ShaderRecompiler::Decoder::ImageDimension::Dim2DArray;
ShaderRecompiler::Decoder::ImageDimension::Dim2DMsaaArray;
auto msaa_array_snapshot =
std::make_shared<ShaderRecompiler::IR::ResourceSnapshot>();
msaa_array_snapshot->images.push_back(msaa_array_descriptor);
+47 -3
View File
@@ -221,7 +221,7 @@ uint32_t SpirvExtInstCount(const std::vector<uint32_t>& binary, uint32_t ext_ins
}
bool SpirvContainsTypeImage(const std::vector<uint32_t>& binary, uint32_t dim, uint32_t arrayed,
uint32_t sampled) {
uint32_t sampled, uint32_t multisampled = 0) {
for (size_t i = 5; i < binary.size();) {
const uint32_t word = binary[i];
const uint32_t opcode = word & 0xffffu;
@@ -230,7 +230,7 @@ bool SpirvContainsTypeImage(const std::vector<uint32_t>& binary, uint32_t dim, u
return false;
}
if (opcode == 25u && word_count >= 9u && binary[i + 3] == dim && binary[i + 5] == arrayed &&
binary[i + 7] == sampled) {
binary[i + 6] == multisampled && binary[i + 7] == sampled) {
return true;
}
i += word_count;
@@ -2972,7 +2972,6 @@ void TestNewShaderRecompilerMemoryFamilyLowering() {
Check(SpirvContainsOpcode(result.spirv, 61), "SPIR-V binary does not contain OpLoad");
Check(SpirvContainsOpcode(result.spirv, 62), "SPIR-V binary does not contain OpStore");
Check(SpirvContainsOpcode(result.spirv, 95), "SPIR-V binary does not contain OpImageFetch");
Check(SpirvContainsOpcode(result.spirv, 100), "SPIR-V binary does not contain OpImage");
Check(SpirvContainsOpcode(result.spirv, 103),
"SPIR-V binary does not contain OpImageQuerySizeLod");
Check(SpirvContainsOpcode(result.spirv, 88),
@@ -3766,6 +3765,50 @@ void TestNewShaderRecompilerImageLoadVariants() {
CheckSpirvBinaryValidates(result.spirv);
}
void TestNewShaderRecompilerImageLoad2DMsaa() {
const uint32_t shader[] = {
0xf0000130u, // image_load v3, v[5:7], s[0:7] dmask:x dim:2d_msaa
0x00000305u,
0xbf810000u,
};
auto user_data = ImageTestUserData(Prospero::ImageType::kColor2DMsaa);
user_data[3] |= 2u << 16u;
user_data[5] |= 2u << 4u;
user_data[6] |= 1u << 10u;
ShaderRecompiler::CompileOptions options;
options.stage = ShaderType::Pixel;
options.dump_ir = true;
options.user_data = user_data.data();
ShaderRecompiler::CompileResult result;
std::string error;
Check(ShaderRecompiler::TryRecompile(shader, options, result, &error), error.c_str());
Check(Common::ContainsStr(result.decoded_dump, "image_dim=2d_msaa") &&
Common::ContainsStr(result.ir_dump, "image_dim=2d_msaa") &&
Common::ContainsStr(result.ir_dump, "image_addr=3 image_mip=0"),
"RDNA2 2D-MSAA load did not preserve x, y, and fragment ID");
Check(result.program.info.images.size() == 1 &&
result.program.info.images[0].dimension ==
ShaderRecompiler::Decoder::ImageDimension::Dim2DMsaa,
"2D-MSAA descriptor specialization lost the multisample dimension");
Check(ShaderRecompiler::IR::FindBinding(
result.program.bindings,
ShaderRecompiler::IR::DescriptorBindingKind::Sampled2DMsaa) != nullptr,
"2D-MSAA image did not receive a multisampled descriptor binding");
Check(SpirvContainsTypeImage(result.spirv, 1, 0, 1, 1),
"SPIR-V binary does not contain a multisampled 2D image type");
CheckSpirvBinaryValidates(result.spirv);
const auto source = DisassembleSpirvBinary(result.spirv);
Check(SpirvSourceHasInstructionUsing(source, "OpAccessChain", "sampled_2d_msaa"),
"2D-MSAA load did not access its multisampled descriptor");
Check(SpirvSourceHasInstructionUsing(source, "OpImageFetch", " Sample "),
"2D-MSAA load did not emit the fragment ID as a SPIR-V Sample operand");
Check(!SpirvSourceHasInstructionUsing(source, "OpImageFetch", " Lod "),
"2D-MSAA load incorrectly emitted its fragment ID as a mip level");
}
void TestNewShaderRecompilerImageStoreLowering() {
const uint32_t shader[] = {
EncodeMimg0(0x08, 0xf),
@@ -7018,6 +7061,7 @@ int main() {
TestNewShaderRecompilerImageGatherVariants();
TestNewShaderRecompilerImageLoadA16UintCoords();
TestNewShaderRecompilerImageLoadVariants();
TestNewShaderRecompilerImageLoad2DMsaa();
TestNewShaderRecompilerImageStoreLowering();
TestNewShaderRecompilerStorageImage3DDescriptorVariant();
TestNewShaderRecompilerStorageImage2DDescriptorOverridesMimg3D();