Files
VulkanDriver/src/intel/compiler/targets/gen9/compute/resource_lowering.zig
T
kbz_8 04ff263b40
Mirror Gitea refs to GitHub / mirror (push) Successful in 18s
Test / build_and_test (push) Successful in 2m12s
Build / build (push) Successful in 3m21s
[Flint] adding compute resource layout lowering
2026-08-14 20:41:31 +02:00

128 lines
5.3 KiB
Zig

const instruction = @import("../../../ir/instruction.zig");
const program_ir = @import("../../../ir/program.zig");
const validator = @import("../../../ir/validator.zig");
const resource_layout = @import("resource_layout.zig");
pub const Error = error{
InvalidProgram,
InvalidResourceLayout,
};
pub fn run(program: *program_ir.Program, layout: *const resource_layout.Layout) Error!void {
validator.validate(program) catch return Error.InvalidProgram;
if (program.properties.resources_lowered)
return;
if (layout.resource_indices.len != program.storage_buffers.entries.items.len)
return Error.InvalidResourceLayout;
for (program.blocks.entries.items) |block_entry| {
const block = block_entry orelse continue;
for (block.instructions.items) |instruction_id| {
const inst = program.instructions.get(instruction_id) orelse return Error.InvalidProgram;
const reference = bufferReference(inst.operation) orelse continue;
const resource = switch (reference) {
.logical => |value| value,
.binding_table => return Error.InvalidProgram,
};
const binding_table_index = layout.bindingTableIndex(resource) orelse return Error.InvalidResourceLayout;
if (binding_table_index >= layout.bindings.len)
return Error.InvalidResourceLayout;
const buffer = program.storage_buffers.get(resource) orelse return Error.InvalidProgram;
const binding = layout.bindings[binding_table_index];
if (binding.binding_table_index != binding_table_index or binding.set != buffer.set or binding.binding != buffer.binding)
return Error.InvalidResourceLayout;
}
}
for (program.blocks.entries.items) |block_entry| {
const block = block_entry orelse continue;
for (block.instructions.items) |instruction_id| {
const inst = program.instructions.getMut(instruction_id) orelse unreachable;
const reference = bufferReferenceMut(&inst.operation) orelse continue;
const resource = reference.logical;
const binding_table_index = layout.bindingTableIndex(resource).?;
reference.* = .{ .binding_table = binding_table_index };
}
}
program.properties.resources_lowered = true;
validator.validate(program) catch return Error.InvalidProgram;
}
fn bufferReference(operation: instruction.Operation) ?instruction.BufferReference {
return switch (operation) {
.load_buffer => |op| op.buffer,
.store_buffer => |op| op.buffer,
else => null,
};
}
fn bufferReferenceMut(operation: *instruction.Operation) ?*instruction.BufferReference {
return switch (operation.*) {
.load_buffer => |*op| &op.buffer,
.store_buffer => |*op| &op.buffer,
else => null,
};
}
test "[gen9] compute resource lowering: resolve logical buffers" {
const std = @import("std");
const Builder = @import("../../../ir/Builder.zig");
const device = @import("../../../device.zig");
const operand = @import("../../../ir/operand.zig");
const printer = @import("../../../ir/printer.zig");
const device_info: device.DeviceInfo = .{
.generation = .gen9,
.platform = .skylake,
.pci_device_id = 0x1912,
.grf_count = 128,
};
var program = program_ir.Program.init(std.testing.allocator, .{ 1, 1, 1 }, device_info, .simd8);
defer program.deinit();
var builder = Builder.init(&program);
const value = try builder.addVirtualRegister(.{
.size_bytes = 32,
.alignment_bytes = 32,
.element_type = .u32,
.lane_count = 8,
.class = .temporary,
});
const buffer = try builder.addStorageBuffer(.{ .set = 1, .binding = 3, .name = "storage" });
const entry = try builder.addBlock("entry");
const store_id = try builder.appendInstruction(entry, .simd8, null, .{
.store_buffer = .{
.buffer = .{ .logical = buffer },
.byte_offset = .{
.register = .{ .immediate = .{ .u32 = 0 } },
.type = .u32,
.region = operand.Region.broadcast(),
},
.source = .{
.register = .{ .virtual = value },
.type = .u32,
.region = operand.Region.contiguous(.simd8),
},
},
});
try builder.setTerminator(entry, .end_thread);
var layout = try resource_layout.Layout.init(std.testing.allocator, &program);
defer layout.deinit(std.testing.allocator);
layout.bindings[0].binding = 4;
try std.testing.expectError(Error.InvalidResourceLayout, run(&program, &layout));
try std.testing.expect(!program.properties.resources_lowered);
try std.testing.expect(program.instructions.get(store_id).?.operation.store_buffer.buffer == .logical);
layout.bindings[0].binding = 3;
try run(&program, &layout);
try validator.validate(&program);
try std.testing.expect(program.properties.resources_lowered);
try std.testing.expectEqual(@as(u8, 0), program.instructions.get(store_id).?.operation.store_buffer.buffer.binding_table);
const text = try printer.allocPrint(std.testing.allocator, &program);
defer std.testing.allocator.free(text);
try std.testing.expect(std.mem.indexOf(u8, text, "store_buffer bti(0), 0:u32") != null);
}