shader: preserve clamped scalar material selector provenance

This commit is contained in:
nmzik
2026-10-13 05:44:07 +02:00
parent 6309ac838d
commit fe6499b86e
4 changed files with 38 additions and 2 deletions
@@ -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 {