mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-27 21:36:54 +01:00
shader: decode every PS5 image_gather4 encoding
Co-authored-by: shadowbeat070 <70843316+shadowbeat070@users.noreply.github.com>
This commit is contained in:
@@ -1723,7 +1723,7 @@ CompiledShader CompileCase(const TestCase &test, u32 host_subgroup_size = 64) {
|
||||
const auto uses_image =
|
||||
std::any_of(test.opcodes.begin(), test.opcodes.end(), [](auto op) {
|
||||
return op >= ShaderOpcode::IMAGE_GET_RESINFO &&
|
||||
op <= ShaderOpcode::IMAGE_GATHER4H;
|
||||
op <= ShaderOpcode::IMAGE_GATHER4;
|
||||
});
|
||||
if (uses_image && ((user_data[3] >> 28u) & 0xfu) == 0) {
|
||||
user_data[3] = static_cast<uint32_t>(Prospero::ImageType::kColor2D) << 28u;
|
||||
@@ -14132,7 +14132,7 @@ public:
|
||||
test.initial.assign(test.expected.size(), 0xdeadbeefu);
|
||||
test.expected_mip_descriptors = 2u;
|
||||
test.required_spirv = {"OpImageDrefGather", "OpSwitch"};
|
||||
test.decoded_counts = {{"IMAGE_GATHER4_C_L", 6u}};
|
||||
test.decoded_counts = {{"image_gather4_c_l", 6u}};
|
||||
const auto compiled = CompileCase(test, SubgroupSize());
|
||||
Require(test.name, "comparison mip resource", compiled.program.info.images.size() == 1u &&
|
||||
compiled.program.info.images[0].depth_compare,
|
||||
@@ -22771,13 +22771,7 @@ CoverageClass ClassifyOpcode(ShaderOpcode opcode,
|
||||
case Opcode::IMAGE_ATOMIC_FMIN:
|
||||
case Opcode::IMAGE_ATOMIC_FMAX:
|
||||
case Opcode::IMAGE_SAMPLE:
|
||||
case Opcode::IMAGE_GATHER4_LZ:
|
||||
case Opcode::IMAGE_GATHER4_C:
|
||||
case Opcode::IMAGE_GATHER4_C_L:
|
||||
case Opcode::IMAGE_GATHER4_C_LZ:
|
||||
case Opcode::IMAGE_GATHER4_LZ_O:
|
||||
case Opcode::IMAGE_GATHER4_C_O:
|
||||
case Opcode::IMAGE_GATHER4_C_LZ_O:
|
||||
case Opcode::IMAGE_GATHER4:
|
||||
return CoverageClass::NeedsImageCase;
|
||||
|
||||
case Opcode::V_INTERP_P1_F32:
|
||||
@@ -39002,7 +38996,7 @@ TestCase ImageSamplePackedUintConvertsSampleAndGather() {
|
||||
test.code = std::move(code);
|
||||
test.expected = {0x2abu, 0x456u, 0x321u, 0x321u,
|
||||
0x456u, 0x456u, 0x456u, 0x456u};
|
||||
test.opcodes = {O::V_MOV_B32, O::IMAGE_SAMPLE, O::IMAGE_GATHER4_LZ,
|
||||
test.opcodes = {O::V_MOV_B32, O::IMAGE_SAMPLE, O::IMAGE_GATHER4,
|
||||
O::BUFFER_STORE_DWORD, O::S_ENDPGM};
|
||||
test.sampled_image_rgba = std::vector<u32>(16, 0xaae2b321u);
|
||||
test.sampled_image_format = vk::Format::eR32Uint;
|
||||
@@ -39144,7 +39138,7 @@ template <bool rg, bool snorm = false> TestCase ImageSamplePacked8() {
|
||||
for (float value : expected) {
|
||||
test.expected.push_back(std::bit_cast<u32>(value));
|
||||
}
|
||||
test.opcodes = {O::V_MOV_B32, O::IMAGE_SAMPLE, O::IMAGE_GATHER4_LZ,
|
||||
test.opcodes = {O::V_MOV_B32, O::IMAGE_SAMPLE, O::IMAGE_GATHER4,
|
||||
O::BUFFER_STORE_DWORD, O::S_ENDPGM};
|
||||
return test;
|
||||
}
|
||||
@@ -39262,7 +39256,7 @@ TestCase ImageGather2DInstructionWith1DDescriptor() {
|
||||
test.name = "ImageGather2DInstructionWith1DDescriptor";
|
||||
test.code = code;
|
||||
test.expected = {0x40000000u, 0x40400000u, 0x40400000u, 0x40000000u};
|
||||
test.opcodes = {O::V_MOV_B32, O::IMAGE_GATHER4_LZ, O::BUFFER_STORE_DWORD,
|
||||
test.opcodes = {O::V_MOV_B32, O::IMAGE_GATHER4, O::BUFFER_STORE_DWORD,
|
||||
O::S_ENDPGM};
|
||||
test.image_width = 4;
|
||||
test.image_height = 1;
|
||||
@@ -39531,9 +39525,8 @@ TestCase ImageSampleAndGather() {
|
||||
0x3f800000u,
|
||||
0};
|
||||
test.opcodes = {
|
||||
O::V_MOV_B32, O::IMAGE_SAMPLE, O::IMAGE_GET_LOD,
|
||||
O::IMAGE_GATHER4_LZ, O::IMAGE_GATHER4_LZ_O, O::BUFFER_STORE_DWORD,
|
||||
O::S_ENDPGM};
|
||||
O::V_MOV_B32, O::IMAGE_SAMPLE, O::IMAGE_GET_LOD, O::IMAGE_GATHER4,
|
||||
O::BUFFER_STORE_DWORD, O::S_ENDPGM};
|
||||
test.sampled_image_rgba = image;
|
||||
return test;
|
||||
}
|
||||
@@ -39601,7 +39594,7 @@ TestCase ImageGatherExplicitLod() {
|
||||
TestCase test;
|
||||
test.name = "ImageGatherExplicitLod";
|
||||
test.code = std::move(code);
|
||||
test.opcodes = {O::V_MOV_B32, O::IMAGE_GATHER4_L, O::IMAGE_SAMPLE,
|
||||
test.opcodes = {O::V_MOV_B32, O::IMAGE_GATHER4, O::IMAGE_SAMPLE,
|
||||
O::BUFFER_STORE_DWORD, O::S_ENDPGM};
|
||||
// A gather's single-mip descriptors must not replace the ordinary sample's
|
||||
// full mip chain when both instructions use the same guest descriptor.
|
||||
@@ -39726,7 +39719,7 @@ template <u32 mode> TestCase ImageGatherLodPerLane() {
|
||||
}
|
||||
AppendEnd(&code);
|
||||
test.opcodes = {O::V_MOV_B32, O::V_LSHLREV_B32, O::BUFFER_LOAD_DWORD,
|
||||
O::IMAGE_GATHER4_L, O::V_ADD_NC_U32, O::BUFFER_STORE_DWORD,
|
||||
O::IMAGE_GATHER4, O::V_ADD_NC_U32, O::BUFFER_STORE_DWORD,
|
||||
O::S_ENDPGM};
|
||||
test.user_data = MakeSampledTextureData(Prospero::BufferFormat::k32_32_32_32Float);
|
||||
test.user_data[1] |= (3u << 30u) | (mode == 3 ? 768u << 8u : 0u);
|
||||
@@ -39778,7 +39771,7 @@ TestCase ImageD16GatherPacksHalfPairs() {
|
||||
test.name = "ImageD16GatherPacksHalfPairs";
|
||||
test.code = code;
|
||||
test.expected = {0x38003800u, 0x38003800u};
|
||||
test.opcodes = {O::V_MOV_B32, O::IMAGE_GATHER4_LZ, O::BUFFER_STORE_DWORD,
|
||||
test.opcodes = {O::V_MOV_B32, O::IMAGE_GATHER4, O::BUFFER_STORE_DWORD,
|
||||
O::S_ENDPGM};
|
||||
test.sampled_image_rgba = image;
|
||||
test.decoded_counts = {{"d16=1", 1}};
|
||||
@@ -40022,6 +40015,63 @@ TestCase ImageSampleA16CompareBiasRdna2AddressOrder() {
|
||||
return test;
|
||||
}
|
||||
|
||||
TestCase ImageGatherAddressVariants() {
|
||||
using O = ShaderOpcode;
|
||||
struct Gather {
|
||||
u32 opcode;
|
||||
bool offset;
|
||||
bool bias;
|
||||
bool lod_or_clamp;
|
||||
};
|
||||
// Plain, LOD clamp, bias, LOD and offset gathers, with and without gradient adjust.
|
||||
constexpr Gather gathers[] = {
|
||||
{0x40, false, false, false}, {0x41, false, false, true},
|
||||
{0x45, false, true, false}, {0x46, false, true, true},
|
||||
{0x50, true, false, false}, {0x51, true, false, true},
|
||||
{0x54, true, false, true}, {0x55, true, true, false},
|
||||
{0x56, true, true, true}, {0xc0, false, false, false},
|
||||
{0xc1, false, false, true}, {0xc5, false, true, false},
|
||||
{0xc6, false, true, true}, {0xd0, true, false, false},
|
||||
{0xd1, true, false, true}, {0xd5, true, true, false},
|
||||
{0xd6, true, true, true},
|
||||
};
|
||||
const auto texel = [](u32 x, u32 y) { return std::bit_cast<u32>(float(1u + x + y * 4u)); };
|
||||
auto image = MakeRgbaImage(4, 4);
|
||||
for (u32 y = 0; y < 4u; y++) {
|
||||
for (u32 x = 0; x < 4u; x++) {
|
||||
SetRgbaPixel(&image, 4, x, y, texel(x, y), 0, 0, 0);
|
||||
}
|
||||
}
|
||||
TestCase test;
|
||||
test.name = "ImageGatherAddressVariants";
|
||||
for (u32 index = 0; index < std::size(gathers); index++) {
|
||||
const auto &gather = gathers[index];
|
||||
// Zero bias, clamp and LOD keep the base level; a misplaced offset or bias moves the footprint.
|
||||
u32 vaddr = 20;
|
||||
if (gather.offset) AppendVMovU32(&test.code, vaddr++, 0x3fu); // x offset -1
|
||||
if (gather.bias) AppendVMovU32(&test.code, vaddr++, 0);
|
||||
AppendVMovLiteral(&test.code, vaddr++, std::bit_cast<u32>(0.6875f));
|
||||
AppendVMovLiteral(&test.code, vaddr++, std::bit_cast<u32>(0.4375f));
|
||||
if (gather.lod_or_clamp) AppendVMovU32(&test.code, vaddr++, 0);
|
||||
test.code.push_back(EncodeMimg0(gather.opcode, 0x1));
|
||||
test.code.push_back(EncodeMimg1(0, 20));
|
||||
for (u32 component = 0; component < 4u; component++) {
|
||||
AppendStoreVgpr(&test.code, component, index * 4u + component);
|
||||
}
|
||||
// Footprint x 2..3, y 1..2, or x 1..2 with the offset, in (x0, y1), (x1, y1), (x1, y0),
|
||||
// (x0, y0) order.
|
||||
const u32 x0 = gather.offset ? 1u : 2u;
|
||||
for (const auto [x, y] : {std::pair{x0, 2u}, {x0 + 1u, 2u}, {x0 + 1u, 1u}, {x0, 1u}}) {
|
||||
test.expected.push_back(texel(x, y));
|
||||
}
|
||||
}
|
||||
AppendEnd(&test.code);
|
||||
test.opcodes = {O::V_MOV_B32, O::IMAGE_GATHER4, O::BUFFER_STORE_DWORD,
|
||||
O::S_ENDPGM};
|
||||
test.sampled_image_rgba = image;
|
||||
return test;
|
||||
}
|
||||
|
||||
TestCase ImageGatherCompareOpcodes() {
|
||||
using O = ShaderOpcode;
|
||||
|
||||
@@ -40052,15 +40102,21 @@ TestCase ImageGatherCompareOpcodes() {
|
||||
AppendStoreVgpr(&code, 8, 1);
|
||||
AppendStoreVgpr(&code, 0, 2);
|
||||
AppendStoreVgpr(&code, 12, 3);
|
||||
// The other compare gathers.
|
||||
constexpr u32 variants[] = {0x49, 0x4c, 0x4d, 0x4e, 0x59, 0x5c, 0x5d, 0x5e,
|
||||
0xc8, 0xc9, 0xcd, 0xce, 0xd8, 0xd9, 0xdd, 0xde};
|
||||
for (u32 index = 0; index < std::size(variants); index++) {
|
||||
code.push_back(EncodeMimg0(variants[index], 0x1));
|
||||
code.push_back(EncodeMimg1(40, 20));
|
||||
AppendStoreVgpr(&code, 40, 4u + index);
|
||||
}
|
||||
AppendEnd(&code);
|
||||
|
||||
TestCase test;
|
||||
test.name = "ImageGatherCompareOpcodes";
|
||||
test.code = code;
|
||||
test.opcodes = {
|
||||
O::V_MOV_B32, O::IMAGE_GATHER4_C, O::IMAGE_GATHER4_C_LZ,
|
||||
O::IMAGE_GATHER4_C_O, O::IMAGE_GATHER4_C_LZ_O, O::BUFFER_STORE_DWORD,
|
||||
O::S_ENDPGM};
|
||||
test.opcodes = {O::V_MOV_B32, O::IMAGE_GATHER4, O::BUFFER_STORE_DWORD,
|
||||
O::S_ENDPGM};
|
||||
test.required_spirv = {"OpImageDrefGather", "ConstOffset"};
|
||||
test.forbidden_spirv = {"OpBitFieldSExtract"};
|
||||
test.compile_only = true;
|
||||
@@ -45822,6 +45878,7 @@ std::vector<TestCase> MakeCases() {
|
||||
AddCase(ImageGetResinfoDmaskWidthHeight);
|
||||
AddCase(ImageGetResinfoDmaskMipLevels);
|
||||
AddCase(ImageSampleAndGather);
|
||||
AddCase(ImageGatherAddressVariants);
|
||||
AddCase(ImageCubeGradientsPreserveDerivatives);
|
||||
AddCase(ImageGatherExplicitLod);
|
||||
AddCase(ImageSampleLodClamp);
|
||||
@@ -52321,6 +52378,7 @@ int main(int argc, char **argv) {
|
||||
RunCase(&vulkan, ImageSampleA16OffsetKeepsTexelOffset32BitOnGpu<32>());
|
||||
RunCase(&vulkan, ImageSampleA16OffsetKeepsTexelOffset32BitOnGpu<64>());
|
||||
RunCase(&vulkan, ImageSampleAndGather());
|
||||
RunCase(&vulkan, ImageGatherAddressVariants());
|
||||
RunCase(nullptr, ImageGatherCompareOpcodes());
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user