90 lines
3.3 KiB
Zig
90 lines
3.3 KiB
Zig
//! Flint-specific shader IR for Intel Gen hardware.
|
|
//! This is the mutable, non-SSA layer between the common shader IR and machine code.
|
|
|
|
pub const device = @import("device.zig");
|
|
pub const ir = @import("ir/ir.zig");
|
|
pub const lower = @import("lower/lower.zig");
|
|
pub const targets = @import("targets/targets.zig");
|
|
|
|
pub const Builder = ir.Builder;
|
|
pub const id = ir.id;
|
|
pub const instruction = ir.instruction;
|
|
pub const operand = ir.operand;
|
|
pub const printer = ir.printer;
|
|
pub const program = ir.program;
|
|
pub const pseudo = ir.pseudo;
|
|
pub const validator = ir.validator;
|
|
|
|
pub const Program = ir.Program;
|
|
|
|
const std = @import("std");
|
|
|
|
test "[ir] basic compute shader" {
|
|
const device_info: device.DeviceInfo = .{
|
|
.generation = .gen9,
|
|
.platform = .skylake,
|
|
.pci_device_id = 0x1912,
|
|
.grf_count = 128,
|
|
};
|
|
|
|
var shader = Program.init(std.testing.allocator, .{ 1, 1, 1 }, device_info, .simd8);
|
|
defer shader.deinit();
|
|
var builder = Builder.init(&shader);
|
|
|
|
const value = try builder.addVirtualRegister(.{
|
|
.size_bytes = 32,
|
|
.alignment_bytes = 32,
|
|
.element_type = .u32,
|
|
.lane_count = 8,
|
|
.class = .temporary,
|
|
.name = "value",
|
|
});
|
|
const storage = try builder.addStorageBuffer(.{ .set = 0, .binding = 1, .name = "storage" });
|
|
const entry = try builder.addBlock("entry");
|
|
try builder.setEntryBlock(entry);
|
|
|
|
_ = try builder.appendInstruction(entry, .simd8, null, .{
|
|
.load_global_invocation_id = .{
|
|
.destination = .{ .register = .{ .virtual = value }, .type = .u32 },
|
|
.component = 0,
|
|
},
|
|
});
|
|
_ = try builder.appendInstruction(entry, .simd8, null, .{
|
|
.store_buffer = .{
|
|
.buffer = .{ .logical = storage },
|
|
.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);
|
|
try validator.validate(&shader);
|
|
|
|
const text = try printer.allocPrint(std.testing.allocator, &shader);
|
|
defer std.testing.allocator.free(text);
|
|
try std.testing.expect(std.mem.indexOf(u8, text, "Flint compute program") != null);
|
|
try std.testing.expect(std.mem.indexOf(u8, text, "@storage = storage_buffer[set(0), binding(1)]") != null);
|
|
try std.testing.expect(std.mem.indexOf(u8, text, "load_global_invocation_id %value:u32, component(0)") != null);
|
|
try std.testing.expect(std.mem.indexOf(u8, text, "store_buffer @storage, 0:u32, %value:u32") != null);
|
|
}
|
|
|
|
test "[ir] ID stability after removal" {
|
|
var store: id.Store(id.VirtualFlagId, operand.VirtualFlag) = .{};
|
|
defer store.entries.deinit(std.testing.allocator);
|
|
|
|
const first = try store.add(std.testing.allocator, .{ .name = "first" });
|
|
try std.testing.expect(store.remove(first));
|
|
const second = try store.add(std.testing.allocator, .{ .name = "second" });
|
|
|
|
try std.testing.expect(first != second);
|
|
try std.testing.expect(store.get(first) == null);
|
|
try std.testing.expectEqualStrings("second", store.get(second).?.name.?);
|
|
}
|