mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 02:47:02 +02:00
shader: share bounded material-key scans across scalar and vector loads
This commit is contained in:
@@ -35604,9 +35604,9 @@ void CheckImageSamplerSpecialization() {
|
||||
"a shared float/unsigned/signed sampler lost its border or filtering "
|
||||
"class in the compiled bindings, instruction or descriptor snapshot");
|
||||
|
||||
{
|
||||
for (const bool scalar : {false, true}) {
|
||||
using namespace ShaderRecompiler::IR;
|
||||
constexpr const char *name = "GpuMaterialImageDomain";
|
||||
const char *name = scalar ? "ScalarMaterialImageDomain" : "GpuMaterialImageDomain";
|
||||
constexpr u32 count = 70, table_base = 0x1000, material_base = 0x2000;
|
||||
std::vector<u32> memory(4096);
|
||||
for (u32 i = 0; i < count; ++i) {
|
||||
@@ -35628,29 +35628,44 @@ void CheckImageSamplerSpecialization() {
|
||||
std::copy_n(output.begin(), 4, user_data.begin() + 48);
|
||||
user_data[48] = 0x3000u;
|
||||
std::vector<u32> code{EncodeVopc(0xc5, InlineU32(0), 0),
|
||||
EncodeSop1(0x24, 24, 106), EncodeSopp(0x08, 0),
|
||||
EncodeSop1(0x04, 26, 126), EncodeVop1(0x01, 16, InlineU32(1))};
|
||||
// An earlier descriptor waterfall separates the EXECZ witness from this material load.
|
||||
const auto previous_loop = code.size();
|
||||
code.insert(code.end(), {EncodeSop1(0x04, 28, 126),
|
||||
EncodeVop1(0x02, 22, Vgpr(0)), EncodeVopc(0xd2, 22, 0),
|
||||
EncodeVop1(0x01, 16, InlineU32(0)),
|
||||
EncodeSop1(0x04, 126, 28), EncodeVopc(0xd5, InlineU32(0), 16)});
|
||||
code.push_back(EncodeSopp(0x09, static_cast<int16_t>(previous_loop - code.size() - 1u)));
|
||||
code.insert(code.end(), {EncodeSop1(0x04, 126, 26),
|
||||
EncodeMubuf0(0x0c, 0, true, false), EncodeMubuf1(15, 1, 0),
|
||||
EncodeVop2(0x16, 15, InlineU32(4), 15),
|
||||
EncodeVop1(0x01, 16, InlineU32(1))});
|
||||
EncodeSop1(0x24, 24, 106), EncodeSopp(0x08, 0)};
|
||||
size_t scalar_shift = 0;
|
||||
if (scalar) {
|
||||
code.insert(code.end(), {EncodeVop1(0x02, 20, Vgpr(0)),
|
||||
EncodeSop2(0x00, 20, 20, 21),
|
||||
EncodeSop2(0x26, 20, 20, InlineU32(3)),
|
||||
EncodeSop2(0x1e, 20, 20, InlineU32(2)),
|
||||
EncodeSop2(0x00, 20, 20, InlineU32(8)),
|
||||
EncodeSmem0(0x08, 20, 2), EncodeSmem1(0, 20)});
|
||||
scalar_shift = code.size();
|
||||
code.push_back(EncodeSop2(0x20, 20, 20, InlineU32(4)));
|
||||
} else {
|
||||
code.insert(code.end(), {EncodeSop1(0x04, 26, 126), EncodeVop1(0x01, 16, InlineU32(1))});
|
||||
// An earlier descriptor waterfall separates the EXECZ witness from the material load.
|
||||
const auto previous_loop = code.size();
|
||||
code.insert(code.end(), {EncodeSop1(0x04, 28, 126),
|
||||
EncodeVop1(0x02, 22, Vgpr(0)), EncodeVopc(0xd2, 22, 0),
|
||||
EncodeVop1(0x01, 16, InlineU32(0)),
|
||||
EncodeSop1(0x04, 126, 28), EncodeVopc(0xd5, InlineU32(0), 16)});
|
||||
code.push_back(EncodeSopp(0x09, static_cast<int16_t>(previous_loop - code.size() - 1u)));
|
||||
code.insert(code.end(), {EncodeSop1(0x04, 126, 26),
|
||||
EncodeMubuf0(0x0c, 0, true, false), EncodeMubuf1(15, 1, 0),
|
||||
EncodeVop2(0x16, 15, InlineU32(4), 15),
|
||||
EncodeVop1(0x01, 16, InlineU32(1))});
|
||||
}
|
||||
const auto image_loop = code.size();
|
||||
code.insert(code.end(), {EncodeSop1(0x04, 28, 126),
|
||||
EncodeVop1(0x02, 20, Vgpr(15)), EncodeVopc(0xd2, 20, 15),
|
||||
EncodeSop2(0x1e, 20, 20, InlineU32(5)),
|
||||
if (!scalar)
|
||||
code.insert(code.end(), {EncodeSop1(0x04, 28, 126),
|
||||
EncodeVop1(0x02, 20, Vgpr(15)), EncodeVopc(0xd2, 20, 15)});
|
||||
code.insert(code.end(), {EncodeSop2(0x1e, 20, 20, InlineU32(5)),
|
||||
EncodeSmem0(0x0b, 12), EncodeSmem1(0, 20),
|
||||
EncodeMimg0(0x24, 1), EncodeMimg1(4, 0, 3, 2)});
|
||||
AppendBufferStoreDword(&code, 4, 0);
|
||||
code.insert(code.end(), {EncodeVop1(0x01, 16, InlineU32(0)),
|
||||
EncodeSop1(0x04, 126, 28), EncodeVopc(0xd5, InlineU32(0), 16)});
|
||||
code.push_back(EncodeSopp(0x09, static_cast<int16_t>(image_loop - code.size() - 1u)));
|
||||
if (!scalar) {
|
||||
code.insert(code.end(), {EncodeVop1(0x01, 16, InlineU32(0)),
|
||||
EncodeSop1(0x04, 126, 28), EncodeVopc(0xd5, InlineU32(0), 16)});
|
||||
code.push_back(EncodeSopp(0x09, static_cast<int16_t>(image_loop - code.size() - 1u)));
|
||||
}
|
||||
code[2] = EncodeSopp(0x08, static_cast<int16_t>(code.size() - 3u));
|
||||
AppendEnd(&code);
|
||||
ShaderComputeInputInfo compute{};
|
||||
@@ -35695,21 +35710,34 @@ void CheckImageSamplerSpecialization() {
|
||||
"descriptor addresses were frozen or entered the shader specialization");
|
||||
auto compiled = ShaderRecompiler::CompileProgram(std::move(translated), options, specialization);
|
||||
ValidateSpirv(name, compiled.spirv);
|
||||
user_data[4] += 1u;
|
||||
Require(name, "misaligned material rejection",
|
||||
!MaterializeResources(plan, runtime, snapshot, specialization),
|
||||
"unaligned raw buffer base was treated as separately aligned scalar memory");
|
||||
user_data[4] -= 1u;
|
||||
if (!scalar) {
|
||||
user_data[4] += 1u;
|
||||
Require(name, "misaligned material rejection",
|
||||
!MaterializeResources(plan, runtime, snapshot, specialization),
|
||||
"unaligned raw buffer base was treated as separately aligned scalar memory");
|
||||
user_data[4] -= 1u;
|
||||
}
|
||||
auto dirty = runtime;
|
||||
dirty.read_specialization_memory = +[](void*, uint64_t, std::span<u32>) { return false; };
|
||||
Require(name, "dirty material rejection",
|
||||
!MaterializeResources(plan, dirty, snapshot, specialization),
|
||||
"GPU-selected texture materialization bypassed strict read provenance");
|
||||
#if KYTY_PLATFORM != KYTY_PLATFORM_WINDOWS
|
||||
ExpectFatal("MaterialImageWithoutEntryWitness", [&] {
|
||||
code[2] = EncodeSopp(0x00, 0); // S_NOP removes the original nonempty-EXEC witness.
|
||||
(void)ShaderRecompiler::TranslateProgram(code, options);
|
||||
});
|
||||
if (scalar) {
|
||||
ExpectFatal("ScalarMaterialNumericConsumer", [&] {
|
||||
code.insert(code.begin() + scalar_shift, EncodeVop1(0x01, 17, 20));
|
||||
code.pop_back();
|
||||
AppendBufferStoreDword(&code, 17, 0);
|
||||
code[2] = EncodeSopp(0x08, static_cast<int16_t>(code.size() - 3u));
|
||||
AppendEnd(&code);
|
||||
(void)ShaderRecompiler::TranslateProgram(code, options);
|
||||
});
|
||||
} else {
|
||||
ExpectFatal("MaterialImageWithoutEntryWitness", [&] {
|
||||
code[2] = EncodeSopp(0x00, 0); // S_NOP removes the original nonempty-EXEC witness.
|
||||
(void)ShaderRecompiler::TranslateProgram(code, options);
|
||||
});
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user