refactor(shader): centralize typed resource metadata

This commit is contained in:
nmzik
2026-08-19 11:33:05 +02:00
parent 87166eed94
commit 85cf965d54
18 changed files with 455 additions and 314 deletions
+75 -1
View File
@@ -597,7 +597,7 @@ void TestImagesSamplersAndAliases() {
const auto storage = fixture.Image(image_words, 16);
MemoryInfo storage_memory;
storage_memory.kind = ResourceKind::StorageImage;
storage_memory.kind = ResourceKind::StorageImageUint;
storage_memory.image_dimension = Decoder::ImageDimension::Dim2D;
fixture.Emit(ValueOpcode::ImageAtomicIAdd32,
{storage, image_address, Value(1u), Value(true)},
@@ -1146,6 +1146,79 @@ void TestResourceLimitIsTransactional() {
"resource-limit failure partially mutated typed resource state");
}
void TestMalformedMemoryKindsRejected() {
{
Fixture fixture;
const auto address = fixture.Address(Value(0u), Value(0u), 4);
MemoryInfo memory;
memory.kind = ResourceKind::Buffer;
fixture.Emit(ValueOpcode::StoreAddressU32,
{address, Value(0u), Value(0u), Value(1u), Value(true)},
fixture.AddMemory(memory, 4));
std::string error;
Check(BuildSrtPlan(fixture.program, &error) &&
!TrackResources(fixture.program, &error) &&
error.find("address operation has invalid resource kind") !=
std::string::npos,
"resource tracking accepted an address opcode with buffer metadata");
}
{
Fixture fixture;
const auto image =
fixture.Image({Value(0u), Value(0u), Value(0u), Value(0u), Value(0u),
Value(0u), Value(0u), Value(0u)},
8);
MemoryInfo memory;
memory.kind = ResourceKind::Flat;
fixture.Emit(ValueOpcode::ImageRead,
{image, fixture.ImageAddress(), Value(true)},
fixture.AddMemory(memory, 8));
std::string error;
Check(BuildSrtPlan(fixture.program, &error) &&
!TrackResources(fixture.program, &error) &&
error.find("image operation has invalid resource kind") !=
std::string::npos,
"resource tracking accepted an image opcode with address metadata");
}
{
Fixture fixture;
const auto image =
fixture.Image({Value(0u), Value(0u), Value(0u), Value(0u), Value(0u),
Value(0u), Value(0u), Value(0u)},
12);
MemoryInfo memory;
memory.kind = ResourceKind::StorageImage;
fixture.Emit(ValueOpcode::ImageRead,
{image, fixture.ImageAddress(), Value(true)},
fixture.AddMemory(memory, 12));
std::string error;
Check(BuildSrtPlan(fixture.program, &error) &&
!TrackResources(fixture.program, &error) &&
error.find("image operation has invalid resource kind") !=
std::string::npos,
"resource tracking accepted a sampled read with storage metadata");
}
{
Fixture fixture;
const auto image =
fixture.Image({Value(0u), Value(0u), Value(0u), Value(0u), Value(0u),
Value(0u), Value(0u), Value(0u)},
16);
MemoryInfo memory;
memory.kind = ResourceKind::StorageImage;
fixture.Emit(ValueOpcode::ImageAtomicIAdd32,
{image, fixture.ImageAddress(), Value(1u), Value(true)},
fixture.AddMemory(memory, 16));
std::string error;
Check(
BuildSrtPlan(fixture.program, &error) &&
!TrackResources(fixture.program, &error) &&
error.find("image operation has invalid resource kind") !=
std::string::npos,
"resource tracking accepted a uint atomic with float storage metadata");
}
}
} // namespace
int main() {
@@ -1173,6 +1246,7 @@ int main() {
Run("buffer swizzle specialization", TestBufferSwizzleSpecialization);
Run("shader info and bindings", TestShaderInfoAndBindingLayout);
Run("resource limit", TestResourceLimitIsTransactional);
Run("malformed memory kinds", TestMalformedMemoryKindsRejected);
} catch (const std::exception &exception) {
std::cerr << "resource tracking test failed: " << exception.what() << '\n';
return 1;
+127 -2
View File
@@ -9118,7 +9118,7 @@ void TestNativeWideValueValidation() {
memory.data_bits = 16;
program.memory_info.push_back(memory);
append_scalar_read(program, ValueOpcode::LoadAddressU32, {});
check_rejected(program, "inconsistent scalar-memory metadata");
check_rejected(program, "inconsistent address-memory metadata");
}
{
auto program = make_program();
@@ -9146,7 +9146,7 @@ void TestNativeWideValueValidation() {
memory.component_index = 4;
program.memory_info.push_back(memory);
append_scalar_read(program, ValueOpcode::LoadAddressU32, {});
check_rejected(program, "inconsistent scalar-memory metadata");
check_rejected(program, "inconsistent address-memory metadata");
}
{
@@ -9248,6 +9248,131 @@ void TestNativeWideValueValidation() {
append_shared(program, ValueOpcode::LoadSharedU32x3, {});
check_rejected(program, "inconsistent shared-memory width");
}
const auto append_address = [](ValueProgram &program, ValueOpcode opcode,
MemoryFlags flags) {
IREmitter ir(program.blocks.front());
const auto resource =
ir.Emit(ValueOpcode::GetAddressResource, {Value(0u), Value(0u)});
if (opcode == ValueOpcode::StoreAddressU32) {
ir.Emit(opcode, {resource, Value(0u), Value(0u), Value(0u), Value(true)},
flags);
} else {
ir.Emit(opcode, {resource, Value(0u), Value(0u), Value(true)}, flags);
}
};
{
auto program = make_program();
append_address(program, ValueOpcode::StoreAddressU32,
MemoryFlags{.index = 1});
check_rejected(program, "invalid memory-info index");
}
{
auto program = make_program();
MemoryInfo memory;
memory.kind = ResourceKind::Buffer;
program.memory_info.push_back(memory);
append_address(program, ValueOpcode::StoreAddressU32, {});
check_rejected(program, "invalid address resource kind");
}
{
auto program = make_program();
MemoryInfo memory;
memory.kind = ResourceKind::Global;
program.memory_info.push_back(memory);
append_address(program, ValueOpcode::LoadAddressU8, {});
check_rejected(program, "inconsistent address-memory metadata");
}
const auto append_image = [](ValueProgram &program, ValueOpcode opcode,
MemoryFlags flags) {
IREmitter ir(program.blocks.front());
const auto image = ir.Emit(ValueOpcode::GetImageResource,
{Value(0u), Value(0u), Value(0u), Value(0u),
Value(0u), Value(0u), Value(0u), Value(0u)});
const auto address =
ir.Emit(ValueOpcode::MakeImageAddress,
{Value(0u), Value(0u), Value(0u), Value(0u), Value(0u),
Value(0u), Value(0u), Value(0u), Value(0u), Value(0u),
Value(0u), Value(0u), Value(0u)});
const auto image_info = ImageOpcodeInfoOf(opcode);
if (opcode == ValueOpcode::ImageWrite) {
const auto data = ir.Emit(ValueOpcode::CompositeConstructU32x4,
{Value(0u), Value(0u), Value(0u), Value(0u)});
ir.Emit(opcode, {image, address, data, Value(true)}, flags);
} else if (image_info.access == ImageAccess::Atomic) {
ir.Emit(opcode, {image, address, Value(0u), Value(true)}, flags);
} else if (image_info.needs_sampler) {
const auto sampler =
ir.Emit(ValueOpcode::GetSamplerResource,
{Value(0u), Value(0u), Value(0u), Value(0u)});
ir.Emit(opcode, {image, sampler, address}, flags);
} else if (opcode == ValueOpcode::ImageQueryDimensions) {
ir.Emit(opcode, {image, address}, flags);
} else {
ir.Emit(opcode, {image, address, Value(true)}, flags);
}
};
{
auto program = make_program();
append_image(program, ValueOpcode::ImageRead, MemoryFlags{.index = 1});
check_rejected(program, "invalid memory-info index");
}
{
auto program = make_program();
MemoryInfo memory;
memory.kind = ResourceKind::Buffer;
program.memory_info.push_back(memory);
append_image(program, ValueOpcode::ImageRead, {});
check_rejected(program, "invalid image-memory metadata");
}
{
auto program = make_program();
MemoryInfo memory;
memory.kind = ResourceKind::StorageImage;
program.memory_info.push_back(memory);
append_image(program, ValueOpcode::ImageRead, {});
check_rejected(program, "invalid image-memory metadata");
}
{
auto program = make_program();
MemoryInfo memory;
memory.kind = ResourceKind::StorageImageUint;
program.memory_info.push_back(memory);
append_image(program, ValueOpcode::ImageQueryDimensions, {});
check_rejected(program, "invalid image-memory metadata");
}
{
auto program = make_program();
MemoryInfo memory;
memory.kind = ResourceKind::Image;
program.memory_info.push_back(memory);
append_image(program, ValueOpcode::ImageWrite, {});
check_rejected(program, "invalid image-memory metadata");
}
{
auto program = make_program();
MemoryInfo memory;
memory.kind = ResourceKind::StorageImage;
program.memory_info.push_back(memory);
append_image(program, ValueOpcode::ImageSampleRaw, {});
check_rejected(program, "invalid image-memory metadata");
}
{
auto program = make_program();
MemoryInfo memory;
memory.kind = ResourceKind::StorageImage;
program.memory_info.push_back(memory);
append_image(program, ValueOpcode::ImageAtomicIAdd32, {});
check_rejected(program, "invalid image-memory metadata");
}
{
auto program = make_program();
IREmitter ir(program.blocks.front());
const auto data = ir.Emit(ValueOpcode::CompositeConstructU32x4,
{Value(0u), Value(0u), Value(0u), Value(0u)});
ir.Emit(ValueOpcode::SetAttribute, {data, Value(true)},
ExportFlags{.index = 1});
check_rejected(program, "invalid export-info index");
}
}
void TestNewShaderRecompilerZeroInitialRegisterState() {