mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 02:47:02 +02:00
shader: preserve native types in indirect image tables
This commit is contained in:
@@ -974,6 +974,63 @@ void TestMixedSamplerVariantsShareRuntimeDescriptor() {
|
||||
"sampler variants retained stale or duplicated descriptors after refresh");
|
||||
}
|
||||
|
||||
void TestIndirectImageSamplerClasses(bool mixed) {
|
||||
using namespace Libs::Graphics::ShaderRecompiler::IR;
|
||||
using Libs::Graphics::Prospero::BufferFormat;
|
||||
using Libs::Graphics::Prospero::TextureNumericClass;
|
||||
auto program = MixedSamplerProgram();
|
||||
auto &first = program.descriptor_sources[0];
|
||||
first.dwords[0] = Value(0x100u);
|
||||
first.dwords[1] = Value(static_cast<uint32_t>(BufferFormat::k8UNorm) << 20u);
|
||||
first.dwords[3] = program.descriptor_sources[1].dwords[3];
|
||||
program.descriptor_sources[1].dwords[1] = Value(static_cast<uint32_t>(
|
||||
mixed ? BufferFormat::k8UInt : BufferFormat::k8UNorm) << 20u);
|
||||
DescriptorSource root;
|
||||
root.dword_count = 8;
|
||||
root.dwords.fill(Value(0u));
|
||||
root.indirect_descriptor.emplace().sources = {0, 1, 0};
|
||||
program.info.images.resize(1);
|
||||
program.info.images[0].source = static_cast<uint32_t>(program.descriptor_sources.size());
|
||||
program.descriptor_sources.push_back(root);
|
||||
program.info.samplers.resize(1);
|
||||
program.info.sampled_pairs.resize(1);
|
||||
auto plan = ExtractResourcePlan(program);
|
||||
std::array<uint32_t, 1> user_data{0x11111111u};
|
||||
uint32_t reads = 0;
|
||||
const SrtRuntime runtime{.user_data = user_data, .userdata = &reads,
|
||||
.read_specialization_memory = RejectSpecializationRead};
|
||||
ResourceSnapshot snapshot;
|
||||
ResourceSpecialization specialization;
|
||||
Check(MaterializeResources(plan, runtime, snapshot, specialization) && reads == 0 &&
|
||||
snapshot.images.size() == 2 && snapshot.images[0].dwords[0] == 0x100u &&
|
||||
snapshot.images[1].dwords[0] == 1u &&
|
||||
specialization.images[0].numeric_class == TextureNumericClass::Float &&
|
||||
specialization.images[1].numeric_class ==
|
||||
(mixed ? TextureNumericClass::Uint : TextureNumericClass::Float),
|
||||
"indirect image materialization rejected or changed a typed candidate");
|
||||
const auto offset = specialization.images[0].indirect_mapping_offset;
|
||||
Check(snapshot.flattened_srt[offset] == 3u &&
|
||||
snapshot.flattened_srt[offset + 2u] == 0u &&
|
||||
snapshot.flattened_srt[offset + 4u] == 1u &&
|
||||
snapshot.flattened_srt[offset + 6u] == 0u,
|
||||
"mixed image classes changed selector ordinals or duplicated candidates");
|
||||
ApplyResourceSpecialization(program, specialization);
|
||||
Check(program.info.images[0].indirect_resources == std::vector<uint32_t>({0, 1}) &&
|
||||
snapshot.samplers.size() == 1 && program.info.samplers.size() == (mixed ? 2u : 1u),
|
||||
"indirect images lost candidates or created unnecessary sampler variants");
|
||||
user_data[0] = 0x33333333u;
|
||||
Check(MaterializeResources(plan, runtime, snapshot, specialization),
|
||||
"mixed image sampler refresh failed");
|
||||
for (uint32_t index = 0; index < program.info.samplers.size(); ++index) {
|
||||
const auto &sampler = program.info.samplers[index];
|
||||
Check(sampler.snapshot_index == 0u && sampler.source == plan.info.samplers[0].source &&
|
||||
sampler.force_point_filtering == (index != 0u) &&
|
||||
sampler.integer_border == (index != 0u) &&
|
||||
snapshot.samplers[sampler.snapshot_index].dwords[0] == user_data[0],
|
||||
"typed sampler variants lost filtering, border class, or shared live descriptor");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace Common {
|
||||
@@ -1007,6 +1064,7 @@ int main() {
|
||||
TestEmptyTraversalSkipsUnmappedDescriptor(independent_mask);
|
||||
TestCyclicControlPredicatesRemainUnknown();
|
||||
TestMixedSamplerVariantsShareRuntimeDescriptor();
|
||||
for (const bool mixed : {false, true}) TestIndirectImageSamplerClasses(mixed);
|
||||
std::puts("ResourceMaterializationTests: all cases passed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -37279,6 +37279,46 @@ void CheckIndirectImageKeySwitch(VulkanHarness &vulkan) {
|
||||
const auto actual = vulkan.ReadBuffer(test.name, buffer, test.expected.size());
|
||||
vulkan.DestroyBuffer(&buffer);
|
||||
CompareWords(test, "root, native slots, array runs and mapping bounds", test.expected, actual);
|
||||
if (wave_size == 32u && !homogeneous) {
|
||||
// A single integer candidate must keep raw register bits across the
|
||||
// same descriptor runs used by samples, gathers, and image fetches.
|
||||
const auto coordinate_conversions = CountText(text, "OpConvertUToF");
|
||||
auto &typed = compiled.program.info.images[3];
|
||||
typed.numeric_class = Prospero::TextureNumericClass::Uint;
|
||||
if (!fetch) {
|
||||
auto integer_sampler = compiled.program.info.samplers[0];
|
||||
integer_sampler.force_point_filtering = true;
|
||||
integer_sampler.integer_border = true;
|
||||
compiled.program.info.samplers.push_back(integer_sampler);
|
||||
}
|
||||
compiled.program.shader_info_complete = false;
|
||||
CollectShaderInfo(compiled.program, {.compute = &compute});
|
||||
const auto mixed_spirv = ShaderRecompiler::Spirv::EmitProgram(
|
||||
compiled.program, {.compute = &compute});
|
||||
ValidateSpirv("IndirectImageMixedNumeric", mixed_spirv);
|
||||
u32 unsigned_type = 0u, raw_vector = 0u;
|
||||
bool raw_join = false;
|
||||
for (size_t offset = 5; offset < mixed_spirv.size();) {
|
||||
const auto words = std::span<const u32>(mixed_spirv).subspan(
|
||||
offset, mixed_spirv[offset] >> 16u);
|
||||
const auto opcode = static_cast<spv::Op>(words[0] & 0xffffu);
|
||||
if (opcode == spv::OpTypeInt && words[2] == 32u && words[3] == 0u)
|
||||
unsigned_type = words[1];
|
||||
if (opcode == spv::OpTypeVector && words[2] == unsigned_type && words[3] == 4u)
|
||||
raw_vector = words[1];
|
||||
if (opcode == spv::OpPhi && words[1] == raw_vector) raw_join = true;
|
||||
offset += words.size();
|
||||
}
|
||||
Require(test.name, "mixed numeric image result", raw_join &&
|
||||
tools.Disassemble(mixed_spirv, &text) &&
|
||||
CountText(text, image_opcode) == 4u * halves &&
|
||||
CountText(text, "OpConvertUToF") == coordinate_conversions,
|
||||
"mixed image classes lost raw result bits or expanded per image");
|
||||
typed.numeric_class = Prospero::TextureNumericClass::Float;
|
||||
if (!fetch) compiled.program.info.samplers.pop_back();
|
||||
compiled.program.shader_info_complete = false;
|
||||
CollectShaderInfo(compiled.program, {.compute = &compute});
|
||||
}
|
||||
}
|
||||
std::printf("[compute] %-32s ok\n", test.name);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user