mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-27 16:02:37 +00:00
shader: preserve clamped scalar material selector provenance
This commit is contained in:
1 parent
6309ac838d
commit
fe6499b86e
4 files changed
+38
-2
No files matched your search
@@ -513,6 +513,7 @@ struct DescriptorSource {
|
||||
uint32_t source = UINT32_MAX;
|
||||
uint32_t stride = 0;
|
||||
uint32_t offset = 0;
|
||||
uint32_t maximum = UINT32_MAX;
|
||||
// Four DWORD bitmap words per record; set-bit ranks subtract from the last key.
|
||||
bool bitset = false;
|
||||
std::optional<CountedRows> rows;
|
||||
|
||||
@@ -538,6 +538,8 @@ bool MaterializeIndirectDescriptor(const ResourcePlan& p
|
||||
if (count < domain_count) keys.push_back(0u); // An out-of-bounds scalar read returns zero.
|
||||
}
|
||||
if (selector != nullptr && selector->byte_ranges.empty()) {
|
||||
if (selector->maximum != UINT32_MAX)
|
||||
for (auto& key: keys) key = std::min(key, selector->maximum);
|
||||
std::ranges::sort(keys);
|
||||
keys.erase(std::unique(keys.begin(), keys.end()), keys.end());
|
||||
}
|
||||
|
||||
@@ -2044,6 +2044,12 @@ private:
|
||||
bool MatchScalarMaterialKey(Value key, DescriptorSource::IndirectDescriptor& indirect,
|
||||
DescriptorSource& material_source) {
|
||||
const auto* read = key.Resolve().TryInstruction();
|
||||
uint32_t maximum = UINT32_MAX;
|
||||
if (read != nullptr && read->GetOpcode() == ValueOpcode::UMin32) {
|
||||
if (ImmediateU32(read->Arg(1), maximum)) read = read->Arg(0).Resolve().TryInstruction();
|
||||
else if (ImmediateU32(read->Arg(0), maximum)) read = read->Arg(1).Resolve().TryInstruction();
|
||||
else return false;
|
||||
}
|
||||
if (read == nullptr) return false;
|
||||
uint32_t memory_index = 0;
|
||||
const auto* memory = ScalarReadMemory(*read, memory_index);
|
||||
@@ -2093,7 +2099,7 @@ private:
|
||||
if (!MakeRuntimeTableSource(*read, material_source)) return false;
|
||||
indirect.selector.emplace(DescriptorSource::IndirectDescriptor::SelectorRead {
|
||||
.source = InternSource(material_source), .stride = stride,
|
||||
.offset = offset + (memory->offset & ~3u)});
|
||||
.offset = offset + (memory->offset & ~3u), .maximum = maximum});
|
||||
indirect.key_count = count;
|
||||
if (rows) indirect.selector->rows.emplace(
|
||||
DescriptorSource::IndirectDescriptor::SelectorRead::CountedRows {
|
||||
|
||||
@@ -1057,6 +1057,7 @@ void TestGuardedDirectImageTable() {
|
||||
|
||||
void TestBoundedComputeImageLoop() {
|
||||
namespace CFG = Libs::Graphics::ShaderRecompiler::CFG;
|
||||
enum class Clamp { None, Right, Left, Dynamic };
|
||||
enum class Variant {
|
||||
Bounded, Plain, Nonzero, TrueEdge, WrongGuard, EntryBypass, ExitBypass, GuardBlock,
|
||||
WrongStep, DivergentBound, DivergentKey, Disjunction, WrongPolarity,
|
||||
@@ -1065,7 +1066,8 @@ void TestBoundedComputeImageLoop() {
|
||||
Masked, MaskedWrongGuard, MaskResurrection, StatusOverwrite,
|
||||
GuardedDiamond, GuardedDiamondBypass
|
||||
};
|
||||
const auto make_plan = [](Variant variant, bool material = false, uint32_t first = 0u) {
|
||||
const auto make_plan = [](Variant variant, bool material = false, uint32_t first = 0u,
|
||||
Clamp clamp = Clamp::None) {
|
||||
const bool diamond = variant >= Variant::GuardedDiamond;
|
||||
Fixture fixture(diamond ? ShaderType::Vertex : ShaderType::Compute);
|
||||
fixture.program.wave_size = 64u;
|
||||
@@ -1300,6 +1302,12 @@ void TestBoundedComputeImageLoop() {
|
||||
image_key = fixture.Emit(ValueOpcode::LoadAddressU32,
|
||||
{table, fixture.Emit(ValueOpcode::IMul32, {key, Value(48u)}), Value(0u), Value(true)},
|
||||
fixture.AddMemory(memory, 0x2ff0));
|
||||
if (clamp != Clamp::None) {
|
||||
const auto maximum = clamp == Clamp::Dynamic ? fixture.UserData(3u) : Value(2u);
|
||||
image_key = fixture.Emit(ValueOpcode::UMin32,
|
||||
clamp == Clamp::Left ? std::initializer_list<Value>{maximum, image_key}
|
||||
: std::initializer_list<Value>{image_key, maximum});
|
||||
}
|
||||
}
|
||||
const auto offset = fixture.Emit(ValueOpcode::IAdd32,
|
||||
{fixture.Emit(ValueOpcode::ShiftLeftLogical32, {image_key, Value(5u)}),
|
||||
@@ -1348,6 +1356,7 @@ void TestBoundedComputeImageLoop() {
|
||||
"nonzero-start image range retained descriptor-only scalar loads");
|
||||
if (material) Check(indirect->selector->stride == 48u &&
|
||||
indirect->selector->offset == 2756u &&
|
||||
indirect->selector->maximum == (clamp == Clamp::None ? UINT32_MAX : 2u) &&
|
||||
fixture.program.descriptor_sources[indirect->selector->source].dword_count == 2u,
|
||||
"bounded scalar selector lost its pointer or record layout");
|
||||
return ExtractResourcePlan(fixture.program);
|
||||
@@ -1502,6 +1511,24 @@ void TestBoundedComputeImageLoop() {
|
||||
memory.words[(first_key - memory.base) / 4u] = UINT32_MAX - 1000u;
|
||||
Check(!MaterializeResources(material, runtime, snapshot, specialization),
|
||||
"raw pointer selector silently discarded an invalid negative key");
|
||||
|
||||
for (const auto clamp : {Clamp::Right, Clamp::Left}) {
|
||||
const auto clamped = make_plan(Variant::Bounded, true, 0u, clamp);
|
||||
memory.words[(table - memory.base) / 4u + 8u + 3u] =
|
||||
static_cast<uint32_t>(Libs::Graphics::Prospero::ImageType::kColor3D) << 28u;
|
||||
memory.words[(first_key - memory.base) / 4u] = 0u;
|
||||
memory.words[(first_key + 48u - memory.base) / 4u] = UINT32_MAX;
|
||||
memory.words[(first_key + 96u - memory.base) / 4u] = 2u;
|
||||
user_data[2] = 3u;
|
||||
memory.fail_address = first_key + 144u;
|
||||
memory.descriptor_reads = 0u;
|
||||
Check(MaterializeResources(clamped, runtime, snapshot, specialization) &&
|
||||
memory.descriptor_reads == 2u && snapshot.images.size() == 2u &&
|
||||
snapshot.images[0].dwords[0] == 0x100u && snapshot.images[1].dwords[0] == 0x102u,
|
||||
"clamped scalar selector read an unreachable image or failed to deduplicate clamped keys");
|
||||
}
|
||||
CheckFatal([&] { make_plan(Variant::Bounded, true, 0u, Clamp::Dynamic); },
|
||||
"not a valid runtime value", "scalar selector accepted an unproved dynamic clamp");
|
||||
}
|
||||
|
||||
void TestDescendingImageRange() {
|
||||
|
||||
Reference in new issue
Block a user