[Flint] centralize compute lowering, adding surface messages with GRF
allocation
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
const std = @import("std");
|
||||
|
||||
pub const message_lowering = @import("message_lowering.zig");
|
||||
pub const resource_layout = @import("resource_layout.zig");
|
||||
pub const resource_lowering = @import("resource_lowering.zig");
|
||||
pub const ResourceLayout = resource_layout.Layout;
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
const instruction = @import("../../../ir/instruction.zig");
|
||||
const operand = @import("../../../ir/operand.zig");
|
||||
const program_ir = @import("../../../ir/program.zig");
|
||||
|
||||
pub const Error = error{
|
||||
ResourcesNotLowered,
|
||||
InvalidProgram,
|
||||
};
|
||||
|
||||
pub fn run(program: *program_ir.Program) Error!void {
|
||||
if (!program.properties.resources_lowered)
|
||||
return error.ResourcesNotLowered;
|
||||
if (program.properties.messages_lowered)
|
||||
return;
|
||||
|
||||
for (program.instructions.entries.items) |*entry| {
|
||||
const inst = if (entry.*) |*value| value else continue;
|
||||
inst.operation = switch (inst.operation) {
|
||||
.load_buffer => |op| .{ .surface_read = .{
|
||||
.destination = op.destination,
|
||||
.binding_table = bindingTableIndex(op.buffer) orelse return error.InvalidProgram,
|
||||
.address = op.byte_offset,
|
||||
.immediate_offset = op.immediate_offset,
|
||||
} },
|
||||
.store_buffer => |op| .{ .surface_write = .{
|
||||
.binding_table = bindingTableIndex(op.buffer) orelse return error.InvalidProgram,
|
||||
.address = op.byte_offset,
|
||||
.immediate_offset = op.immediate_offset,
|
||||
.data = op.source,
|
||||
} },
|
||||
else => inst.operation,
|
||||
};
|
||||
}
|
||||
|
||||
program.properties.messages_lowered = true;
|
||||
}
|
||||
|
||||
fn bindingTableIndex(reference: instruction.BufferReference) ?u8 {
|
||||
return switch (reference) {
|
||||
.binding_table => |index| index,
|
||||
.logical => null,
|
||||
};
|
||||
}
|
||||
|
||||
const std = @import("std");
|
||||
const device = @import("../../../device.zig");
|
||||
|
||||
const test_device: device.DeviceInfo = .{
|
||||
.generation = .gen9,
|
||||
.platform = .skylake,
|
||||
.pci_device_id = 0x1912,
|
||||
.grf_count = 128,
|
||||
};
|
||||
|
||||
fn immediate(value: u32) operand.Source {
|
||||
return .{
|
||||
.register = .{ .immediate = .{ .u32 = value } },
|
||||
.type = .u32,
|
||||
.region = operand.Region.broadcast(),
|
||||
};
|
||||
}
|
||||
|
||||
test "[gen9] compute message lowering: select surface messages" {
|
||||
var program = program_ir.Program.init(std.testing.allocator, .{ 1, 1, 1 }, test_device, .simd8);
|
||||
defer program.deinit();
|
||||
|
||||
const value = try program.addVirtualRegister(.{
|
||||
.size_bytes = 32,
|
||||
.alignment_bytes = 32,
|
||||
.element_type = .u32,
|
||||
.lane_count = 8,
|
||||
.class = .temporary,
|
||||
});
|
||||
const entry = try program.addBlock("entry");
|
||||
const load = try program.appendInstruction(entry, .simd8, null, .{ .load_buffer = .{
|
||||
.destination = .{ .register = .{ .virtual = value }, .type = .u32 },
|
||||
.buffer = .{ .binding_table = 2 },
|
||||
.byte_offset = immediate(16),
|
||||
.immediate_offset = 4,
|
||||
} });
|
||||
const store = try program.appendInstruction(entry, .simd8, null, .{ .store_buffer = .{
|
||||
.buffer = .{ .binding_table = 3 },
|
||||
.byte_offset = immediate(32),
|
||||
.immediate_offset = 8,
|
||||
.source = .{
|
||||
.register = .{ .virtual = value },
|
||||
.type = .u32,
|
||||
.region = operand.Region.contiguous(.simd8),
|
||||
},
|
||||
} });
|
||||
try program.setTerminator(entry, .end_thread);
|
||||
program.properties.resources_lowered = true;
|
||||
|
||||
try run(&program);
|
||||
|
||||
const read = program.instructions.get(load).?.operation.surface_read;
|
||||
try std.testing.expectEqual(@as(u8, 2), read.binding_table);
|
||||
try std.testing.expectEqual(@as(u32, 4), read.immediate_offset);
|
||||
const write = program.instructions.get(store).?.operation.surface_write;
|
||||
try std.testing.expectEqual(@as(u8, 3), write.binding_table);
|
||||
try std.testing.expectEqual(@as(u32, 8), write.immediate_offset);
|
||||
try std.testing.expect(program.properties.messages_lowered);
|
||||
}
|
||||
|
||||
test "[gen9] compute message lowering: reject unresolved resources" {
|
||||
var program = program_ir.Program.init(std.testing.allocator, .{ 1, 1, 1 }, test_device, .simd8);
|
||||
defer program.deinit();
|
||||
|
||||
try std.testing.expectError(error.ResourcesNotLowered, run(&program));
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
const std = @import("std");
|
||||
const shader_ir = @import("shader_ir").ir;
|
||||
|
||||
const device = @import("../../../device.zig");
|
||||
const program_ir = @import("../../../ir/program.zig");
|
||||
const common_ir = @import("../../../lower/common_ir.zig");
|
||||
const block_arguments = @import("../../../lower/block_arguments.zig");
|
||||
const parallel_copies = @import("../../../lower/parallel_copies.zig");
|
||||
const flag_allocation = @import("../flag_allocation.zig");
|
||||
const register_allocation = @import("../register_allocation.zig");
|
||||
|
||||
const compute = @import("compute.zig");
|
||||
const message_lowering = @import("message_lowering.zig");
|
||||
const resource_layout = @import("resource_layout.zig");
|
||||
const resource_lowering = @import("resource_lowering.zig");
|
||||
|
||||
pub const Error = common_ir.Error || block_arguments.Error || parallel_copies.Error ||
|
||||
message_lowering.Error || resource_layout.Error || resource_lowering.Error || flag_allocation.Error || register_allocation.Error || compute.Error || error{
|
||||
UnsupportedGeneration,
|
||||
UnsupportedStage,
|
||||
UnsupportedDispatchWidth,
|
||||
UnsupportedGrfSize,
|
||||
};
|
||||
|
||||
pub const Artifact = struct {
|
||||
program: program_ir.Program,
|
||||
resources: resource_layout.Layout,
|
||||
|
||||
pub fn deinit(self: *Artifact, allocator: std.mem.Allocator) void {
|
||||
self.resources.deinit(allocator);
|
||||
self.program.deinit();
|
||||
self.* = undefined;
|
||||
}
|
||||
};
|
||||
|
||||
pub fn compile(allocator: std.mem.Allocator, module: *shader_ir.module.Module, device_info: device.DeviceInfo, options: common_ir.Options) Error!Artifact {
|
||||
if (device_info.generation != .gen9)
|
||||
return Error.UnsupportedGeneration;
|
||||
if (module.stage != .compute)
|
||||
return Error.UnsupportedStage;
|
||||
if (options.dispatch_width != .simd8 or !device_info.supportsDispatch(.simd8))
|
||||
return Error.UnsupportedDispatchWidth;
|
||||
if (device_info.grf_size_bytes != 32)
|
||||
return Error.UnsupportedGrfSize;
|
||||
if (module.execution_modes.workgroup_size) |workgroup_size|
|
||||
try compute.validateWorkgroupSize(workgroup_size);
|
||||
|
||||
var program = try common_ir.lower(
|
||||
allocator,
|
||||
module,
|
||||
device_info,
|
||||
options,
|
||||
);
|
||||
errdefer program.deinit();
|
||||
|
||||
try block_arguments.run(allocator, &program);
|
||||
try parallel_copies.run(allocator, &program);
|
||||
|
||||
var resources = try resource_layout.Layout.init(
|
||||
allocator,
|
||||
&program,
|
||||
);
|
||||
errdefer resources.deinit(allocator);
|
||||
|
||||
try resource_lowering.run(&program, &resources);
|
||||
try message_lowering.run(&program);
|
||||
try flag_allocation.run(allocator, &program);
|
||||
try register_allocation.run(allocator, &program);
|
||||
|
||||
return .{
|
||||
.program = program,
|
||||
.resources = resources,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user