shader: bound workgroup selector prefixes from runtime starting indices

This commit is contained in:
nmzik
2026-10-14 20:39:25 +02:00
parent ceccd746d8
commit 5313181ecf
4 changed files with 252 additions and 114 deletions
@@ -577,8 +577,9 @@ bool MaterializeIndirectDescriptor(const ResourcePlan& p
(material.Type() != 0u || material.SwizzleEnabled() || material.AddTid() ||
material.OutOfBounds() != 0u || uint64_t {selector->offset} + 4u > step ||
uint64_t {first} + count > material.NumRecords())) return false;
const auto end = count != 0u
? (uint64_t {first} + count - 1u) * step + selector->offset + 4u : 0u;
const auto last = count != 0u ? uint64_t {first} + count - 1u : 0u;
if (last > UINT32_MAX) return false;
const auto end = count != 0u ? last * step + selector->offset + 4u : 0u;
if (end > uint64_t {UINT32_MAX} + 1u ||
(indirect.workgroup_axis == UINT32_MAX && end > size))
return false;
@@ -2204,6 +2204,7 @@ private:
const auto* memory = ScalarReadMemory(*read, memory_index);
Value index;
Value count;
Value first(0u);
uint32_t workgroup_axis = UINT32_MAX;
DescriptorSource count_source;
uint32_t row_stride = 0;
@@ -2214,6 +2215,20 @@ private:
((offset | stride | memory->offset) & 3u) == 0u &&
uint64_t {offset} + memory->offset <= UINT32_MAX) {
workgroup_axis = WorkgroupAxis(index);
if (workgroup_axis == UINT32_MAX) {
const auto* sum = index.Resolve().TryInstruction();
if (sum != nullptr && sum->GetOpcode() == ValueOpcode::IAdd32) {
for (uint32_t arm = 0; arm < 2u; ++arm) {
const auto axis = WorkgroupAxis(sum->Arg(arm));
const auto base = sum->Arg(arm ^ 1u);
if (axis == UINT32_MAX ||
!ValidateRuntimeValue(m_program, base, RuntimeValueType::Integer)) continue;
workgroup_axis = axis;
first = base;
break;
}
}
}
const auto* bound = BoundedLoop(index, read->Parent());
if (bound != nullptr && bound->GetOpcode() == ValueOpcode::ULessThan32) {
count = bound->Arg(1);
@@ -2269,7 +2284,7 @@ private:
if (rows) indirect.selector->rows.emplace(
DescriptorSource::IndirectDescriptor::SelectorRead::CountedRows {
.source = InternSource(count_source), .stride = row_stride});
if (!count.IsEmpty() || workgroup_axis != UINT32_MAX) indirect.selector_first = Value(0u);
if (!count.IsEmpty() || workgroup_axis != UINT32_MAX) indirect.selector_first = first;
return true;
}