shader: keep unbounded material selectors on bounded GPU heaps

This commit is contained in:
nmzik committed 2026-10-13 21:33:50 +00:00
1 parent 735a229236
commit f57d2c0965
2 files changed
+15 -7

No files matched your search

@@ -2103,7 +2103,7 @@ private:
}
bool MatchScalarMaterialKey(Value key, DescriptorSource::IndirectDescriptor& indirect,
DescriptorSource& material_source) {
DescriptorSource& material_source, bool require_bound) {
DescriptorSource::IndirectDescriptor::SelectorRead selector;
const auto* read = SelectorReadValue(key, Value(true), selector);
if (read == nullptr) return false;
@@ -2160,6 +2160,9 @@ private:
offset = static_cast<uint32_t>(affine.offset % divisor) & ~3u;
}
}
// A bounded image heap already supports GPU selection. Only enumerate a
// narrower proven selector domain instead of scanning unrelated material data.
if (require_bound && count.IsEmpty() && !rows) return false;
if (!MakeRuntimeTableSource(*read, material_source)) return false;
selector.source = InternSource(material_source);
selector.stride = stride;
@@ -2635,7 +2638,8 @@ private:
// only the image handle is projected onto the bounded workgroup key.
plan.retain_reads = true;
} else if (!plan.table_indexed &&
MatchScalarMaterialKey(key, indirect, material_source)) {
MatchScalarMaterialKey(key, indirect, material_source,
table_source.dword_count == 4u)) {
// Keep live descriptor payloads, but project descriptor-only SMEM onto
// the GPU key using the same plan as other indirect image reads.
plan.retain_reads |= table_source.dword_count == 4u;
+9 -5
View File
@@ -278,14 +278,17 @@ MakeIndirectImageFixture(bool malformed, uint32_t table_stride = 32, uint32_t ta
return fixture;
}
void TestInvariantIndirectImageMaterialization() {
auto fixture = MakeIndirectImageFixture(false, 48u, 0u, 16u, true);
void TestInvariantIndirectImageMaterialization(bool nested) {
auto fixture = MakeIndirectImageFixture(false, 48u, 0u, 16u, nested);
fixture->PlanAndTrack();
auto plan = ExtractResourcePlan(fixture->program);
EliminateDeadCode(fixture->program.blocks);
ValidateProgram(fixture->program, true);
const auto &source = *plan.descriptor_sources[plan.info.images[0].source].indirect_descriptor;
Check(!source.selector && fixture->program.info.buffers.size() == 3u,
Check(!source.selector && fixture->program.info.buffers.size() == (nested ? 3u : 2u) &&
std::ranges::any_of(*fixture->block, [](const Inst &inst) {
return inst.GetOpcode() == ValueOpcode::ReadConstBuffer;
}),
"bounded image table retained CPU selector traversal or lost live loads");
std::array<uint32_t, 8> descriptor{};
descriptor[0] = 0x20u;
@@ -293,7 +296,7 @@ void TestInvariantIndirectImageMaterialization() {
descriptor[2] = 3u | (3u << 14u);
descriptor[3] = Libs::Graphics::DstSel(4, 5, 6, 7) |
(static_cast<uint32_t>(Libs::Graphics::Prospero::ImageType::kColor2D) << 28u);
std::array<uint32_t, 16> data{0x3000u, 16u << 16u, 0x200000u, 0u,
std::array<uint32_t, 16> data{0x3000u, 4u << 16u, 0x100000u, 0u,
0x2000u, 48u << 16u, 3u, 0u};
std::copy_n(data.begin(), 4u, data.begin() + 12u);
LinearTestMemory memory;
@@ -5793,7 +5796,8 @@ int main() {
Run("FMASK load specialization", TestFmaskLoadSpecialization);
Run("gather LOD sampler validation", TestGatherLodSamplerValidation);
Run("dynamic storage mips", TestDynamicStorageMipTracking);
Run("invariant indirect images", TestInvariantIndirectImageMaterialization);
Run("invariant indirect images", [] { TestInvariantIndirectImageMaterialization(true); });
Run("unbounded material image keys", [] { TestInvariantIndirectImageMaterialization(false); });
Run("bounded image view eligibility", TestBoundedImageViewEligibility);
Run("waterfall image table", TestWaterfallImageTable);
Run("guarded direct image table", TestGuardedDirectImageTable);