dusk: abilibity to reference global decl after current decl

This commit is contained in:
Ali Chraghi 2023-03-21 11:08:06 +03:30 committed by Stephen Gutekanst
parent 2025ac8d17
commit 9f58497771
4 changed files with 826 additions and 504 deletions

File diff suppressed because it is too large Load diff

View file

@ -5,8 +5,9 @@ const ErrorMsg = @import("main.zig").ErrorMsg;
const IR = @This();
allocator: std.mem.Allocator,
globals_index: u32,
instructions: []const Inst,
refs: []const Ref,
refs: []const Inst.Ref,
strings: []const u8,
pub fn deinit(self: IR) void {
@ -28,28 +29,65 @@ pub fn generate(allocator: std.mem.Allocator, tree: *const Ast) !AstGenResult {
};
defer astgen.deinit();
if (!try astgen.translationUnit()) {
return .{ .errors = try astgen.errors.toOwnedSlice(allocator) };
}
const globals_index = astgen.genTranslationUnit() catch |err| switch (err) {
error.AnalysisFail => return .{ .errors = try astgen.errors.toOwnedSlice(allocator) },
error.OutOfMemory => return error.OutOfMemory,
};
return .{ .ir = .{
.allocator = allocator,
.globals_index = globals_index,
.instructions = try astgen.instructions.toOwnedSlice(allocator),
.refs = try astgen.refs.toOwnedSlice(allocator),
.strings = try astgen.strings.toOwnedSlice(allocator),
} };
}
pub const Ref = u32;
pub const null_ref: Ref = std.math.maxInt(Ref);
pub fn getStr(self: IR, index: u32) []const u8 {
return std.mem.sliceTo(self.strings[index..], 0);
}
pub const Inst = packed struct {
pub const Inst = struct {
tag: Tag,
data: Data,
pub const Index = u32;
const ref_start_index = @typeInfo(Ref).Enum.fields.len;
pub fn toRef(index: Inst.Index) Ref {
return @intToEnum(Ref, ref_start_index + index);
}
pub const Ref = enum(u32) {
none,
bool_type,
i32_type,
u32_type,
f32_type,
f16_type,
sampler_type,
comparison_sampler_type,
external_sampled_texture_type,
true_literal,
false_literal,
_,
pub fn toIndex(inst: Ref) ?Inst.Index {
const ref_int = @enumToInt(inst);
if (ref_int >= ref_start_index) {
return @intCast(Inst.Index, ref_int - ref_start_index);
} else {
return null;
}
}
};
pub const Tag = enum(u6) {
/// data is global_variable
global_variable,
/// data is global_variable_decl
global_variable_decl,
/// data is struct_decl
struct_decl,
@ -67,16 +105,6 @@ pub const Inst = packed struct {
/// data is attr_interpolate
attr_interpolate,
/// data is none
bool_type,
/// data is none
i32_type,
/// data is none
u32_type,
/// data is none
f32_type,
/// data is none
f16_type,
/// data is vector_type
vector_type,
/// data is matrix_type
@ -87,10 +115,6 @@ pub const Inst = packed struct {
array_type,
/// data is ptr_type
ptr_type,
/// data is none
sampler_type,
/// data is none
comparison_sampler_type,
/// data is sampled_texture_type
sampled_texture_type,
/// data is multisampled_texture_type
@ -99,17 +123,11 @@ pub const Inst = packed struct {
storage_texture_type,
/// data is depth_texture_type
depth_texture_type,
/// data is none
external_sampled_texture_type,
/// data is integer_literal
integer_literal,
/// data is float_literal
float_literal,
/// data is none
true_literal,
/// data is none
false_literal,
/// data is ref
not,
@ -163,134 +181,277 @@ pub const Inst = packed struct {
member_access,
/// data is binary (lhs is expr, rhs is type)
bitcast,
pub fn isDecl(self: Tag) bool {
return switch (self) {
.global_variable_decl, .struct_decl => true,
else => false,
};
}
};
pub const Data = packed union {
/// TODO: https://github.com/ziglang/zig/issues/14980
none: u1,
pub const Data = union {
ref: Ref,
global_variable: packed struct {
/// index to null-terminated string in `strings`
name: u32,
type: Ref,
addr_space: Ast.AddressSpace = .none,
access_mode: Ast.AccessMode = .none,
/// length of attributes
attrs: u4 = 0,
},
struct_decl: packed struct {
/// index to null-terminated string in `strings`
name: u32,
/// length of the member Ref's which comes after this
members: u32,
},
struct_member: packed struct {
/// index to null-terminated string in `strings`
name: u32,
type: Ref,
@"align": u29, // 0 means null
},
global_variable_decl: GlobalVariableDecl,
struct_decl: StructDecl,
struct_member: StructMember,
/// attributes with no argument.
attr_simple: enum {
invariant,
@"const",
vertex,
fragment,
compute,
},
attr_simple: AttrSimple,
/// attributes with an expression argument.
attr_expr: packed struct {
kind: enum {
@"align",
binding,
group,
id,
location,
size,
},
expr: Ref,
},
attr_expr: AttrExpr,
/// @builtin attribute which accepts a BuiltinValue argument.
attr_builtin: Ast.BuiltinValue,
/// @workgroup attribute. accepts at laest 1 argument.
attr_workgroup: packed struct {
expr0: Ref,
expr1: Ref = null_ref,
expr2: Ref = null_ref,
},
attr_workgroup: AttrWorkgroup,
/// @interpolate attribute. accepts 2 arguments.
attr_interpolate: packed struct {
type: Ast.InterpolationType,
sample: Ast.InterpolationSample,
},
vector_type: packed struct {
component_type: Ref,
size: enum { two, three, four },
},
matrix_type: packed struct {
component_type: Ref,
cols: enum { two, three, four },
rows: enum { two, three, four },
},
atomic_type: packed struct { component_type: Ref },
array_type: packed struct {
component_type: Ref,
size: Ref = null_ref,
},
ptr_type: packed struct {
component_type: Ref,
addr_space: Ast.AddressSpace,
access_mode: Ast.AccessMode,
},
sampled_texture_type: packed struct {
kind: enum {
@"1d",
@"2d",
@"2d_array",
@"3d",
cube,
cube_array,
},
component_type: Ref,
},
multisampled_texture_type: packed struct {
kind: enum { @"2d" },
component_type: Ref,
},
storage_texture_type: packed struct {
kind: enum {
@"1d",
@"2d",
@"2d_array",
@"3d",
},
texel_format: Ast.TexelFormat,
access_mode: MultisampledTextureTypeKind,
},
depth_texture_type: enum {
@"2d",
@"2d_array",
cube,
cube_array,
multisampled_2d,
},
attr_interpolate: AttrInterpolate,
vector_type: VectorType,
matrix_type: MatrixType,
atomic_type: AtomicType,
array_type: ArrayType,
ptr_type: PointerType,
sampled_texture_type: SampledTextureType,
multisampled_texture_type: MultisampledTextureType,
storage_texture_type: StorageTextureType,
depth_texture_type: DepthTextureType,
integer_literal: i64,
float_literal: f64,
/// meaning of LHS and RHS depends on the corresponding Tag.
binary: packed struct {
lhs: Ref,
rhs: Ref,
},
member_access: packed struct {
base: Ref,
/// index to null-terminated string in `strings`
name: u32,
},
binary: BinaryExpr,
member_access: MemberAccess,
};
pub const MultisampledTextureTypeKind = enum { write };
pub const GlobalVariableDecl = struct {
/// index to null-terminated string in `strings`
name: u32,
type: Ref,
addr_space: Ast.AddressSpace = .none,
access_mode: Ast.AccessMode = .none,
/// length of attributes
attrs: u4 = 0,
};
pub const StructDecl = struct {
/// index to null-terminated string in `strings`
name: u32,
/// length of the member Ref's which comes after this
members: u32,
};
pub const StructMember = struct {
/// index to null-terminated string in `strings`
name: u32,
type: Ref,
@"align": u29, // 0 means null
};
pub const AttrSimple = enum {
invariant,
@"const",
vertex,
fragment,
compute,
};
pub const AttrExpr = struct {
kind: Kind,
expr: Ref,
pub const Kind = enum {
@"align",
binding,
group,
id,
location,
size,
};
};
pub const AttrWorkgroup = struct {
expr0: Ref,
expr1: Ref = .none,
expr2: Ref = .none,
};
pub const AttrInterpolate = struct {
type: Ast.InterpolationType,
sample: Ast.InterpolationSample,
};
pub const VectorType = struct {
component_type: Ref,
size: Size,
pub const Size = enum { two, three, four };
};
pub const MatrixType = struct {
component_type: Ref,
cols: VectorType.Size,
rows: VectorType.Size,
};
pub const AtomicType = struct { component_type: Ref };
pub const ArrayType = struct {
component_type: Ref,
size: Ref = .none,
};
pub const PointerType = struct {
component_type: Ref,
addr_space: Ast.AddressSpace,
access_mode: Ast.AccessMode,
};
pub const SampledTextureType = struct {
kind: Kind,
component_type: Ref,
pub const Kind = enum {
@"1d",
@"2d",
@"2d_array",
@"3d",
cube,
cube_array,
};
};
pub const MultisampledTextureType = struct {
kind: Kind,
component_type: Ref,
pub const Kind = enum { @"2d" };
};
pub const StorageTextureType = struct {
kind: Kind,
texel_format: Ast.TexelFormat,
access_mode: AccessMode,
pub const Kind = enum {
@"1d",
@"2d",
@"2d_array",
@"3d",
};
pub const AccessMode = enum { write };
};
pub const DepthTextureType = enum {
@"2d",
@"2d_array",
cube,
cube_array,
multisampled_2d,
};
pub const BinaryExpr = struct {
lhs: Ref,
rhs: Ref,
};
pub const MemberAccess = struct {
base: Ref,
/// index to null-terminated string in `strings`
name: u32,
};
comptime {
std.debug.assert(@bitSizeOf(Inst) <= 104); // 13B
std.debug.assert(@sizeOf(Inst) <= 24);
}
};
pub fn print(self: IR, writer: anytype) !void {
const globals = std.mem.sliceTo(self.refs[self.globals_index..], .none);
for (globals) |ref| {
try self.printInst(writer, 0, ref, false);
}
}
pub fn printInst(self: IR, writer: anytype, indention: u16, ref: Inst.Ref, as_ref: bool) !void {
switch (ref) {
.none,
.bool_type,
.i32_type,
.u32_type,
.f32_type,
.f16_type,
.sampler_type,
.comparison_sampler_type,
.external_sampled_texture_type,
.true_literal,
.false_literal,
=> {
try writer.print("{s}()", .{@tagName(ref)});
},
_ => {
const index = ref.toIndex().?;
const inst = self.instructions[index];
if (as_ref and inst.tag.isDecl()) {
try writer.print("%{d}", .{index});
return;
}
try writer.print("%{d} = {s}{{", .{ index, @tagName(inst.tag) });
switch (inst.tag) {
.global_variable_decl => {
try writer.writeByte('\n');
try printIndent(writer, indention + 1);
try writer.writeAll(".type = ");
try self.printInst(writer, indention + 2, inst.data.global_variable_decl.type, true);
try writer.writeAll(",\n");
try printIndent(writer, indention);
try writer.writeAll("},\n");
},
.struct_decl => {
try writer.writeByte('\n');
try printIndent(writer, indention + 1);
try writer.print(".name = \"{s}\",\n", .{self.getStr(inst.data.struct_decl.name)});
const members = std.mem.sliceTo(self.refs[inst.data.struct_decl.members..], .none);
try printIndent(writer, indention + 1);
try writer.writeAll(".members = [\n");
for (members) |member| {
try printIndent(writer, indention + 2);
try self.printInst(writer, indention + 2, member, false);
}
try printIndent(writer, indention + 1);
try writer.writeAll("],\n");
try printIndent(writer, indention);
try writer.writeAll("},\n");
},
.struct_member => {
try writer.writeByte('\n');
try printIndent(writer, indention + 1);
try writer.print(".name = \"{s}\",\n", .{self.getStr(inst.data.struct_member.name)});
try printIndent(writer, indention + 1);
try writer.writeAll(".type = ");
try self.printInst(writer, indention + 2, inst.data.struct_member.type, true);
try writer.writeAll(",\n");
try printIndent(writer, indention);
try writer.writeAll("},\n");
},
else => {
try writer.print("TODO", .{});
try writer.writeAll("}");
},
}
},
}
}
const indention_size = 2;
pub fn printIndent(writer: anytype, indent: u16) !void {
try writer.writeByteNTimes(' ', indent * indention_size);
}

View file

@ -1,5 +1,9 @@
const NUM_PARTICLES: u32 = 1500u;
struct Particles {
particles : array<Particle>
}
struct Particle {
pos : vec2<f32>,
vel : vec2<f32>,
@ -15,10 +19,6 @@ struct SimParams {
rule3Scale : f32,
}
struct Particles {
particles : array<Particle>
}
@group(0) @binding(0) var<uniform> params : SimParams;
@group(0) @binding(1) var<storage> particlesSrc : Particles;
@group(0) @binding(2) var<storage,read_write> particlesDst : Particles;

View file

@ -183,6 +183,7 @@ test "boids" {
const source = @embedFile("boids.wgsl");
var ir = try expectIR(source);
defer ir.deinit();
// try ir.print(std.io.getStdOut().writer());
}
test "gkurve" {