dusk: abilibity to reference global decl after current decl
This commit is contained in:
parent
2025ac8d17
commit
9f58497771
4 changed files with 826 additions and 504 deletions
File diff suppressed because it is too large
Load diff
|
|
@ -5,8 +5,9 @@ const ErrorMsg = @import("main.zig").ErrorMsg;
|
||||||
const IR = @This();
|
const IR = @This();
|
||||||
|
|
||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
|
globals_index: u32,
|
||||||
instructions: []const Inst,
|
instructions: []const Inst,
|
||||||
refs: []const Ref,
|
refs: []const Inst.Ref,
|
||||||
strings: []const u8,
|
strings: []const u8,
|
||||||
|
|
||||||
pub fn deinit(self: IR) void {
|
pub fn deinit(self: IR) void {
|
||||||
|
|
@ -28,28 +29,65 @@ pub fn generate(allocator: std.mem.Allocator, tree: *const Ast) !AstGenResult {
|
||||||
};
|
};
|
||||||
defer astgen.deinit();
|
defer astgen.deinit();
|
||||||
|
|
||||||
if (!try astgen.translationUnit()) {
|
const globals_index = astgen.genTranslationUnit() catch |err| switch (err) {
|
||||||
return .{ .errors = try astgen.errors.toOwnedSlice(allocator) };
|
error.AnalysisFail => return .{ .errors = try astgen.errors.toOwnedSlice(allocator) },
|
||||||
}
|
error.OutOfMemory => return error.OutOfMemory,
|
||||||
|
};
|
||||||
|
|
||||||
return .{ .ir = .{
|
return .{ .ir = .{
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
|
.globals_index = globals_index,
|
||||||
.instructions = try astgen.instructions.toOwnedSlice(allocator),
|
.instructions = try astgen.instructions.toOwnedSlice(allocator),
|
||||||
.refs = try astgen.refs.toOwnedSlice(allocator),
|
.refs = try astgen.refs.toOwnedSlice(allocator),
|
||||||
.strings = try astgen.strings.toOwnedSlice(allocator),
|
.strings = try astgen.strings.toOwnedSlice(allocator),
|
||||||
} };
|
} };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const Ref = u32;
|
pub fn getStr(self: IR, index: u32) []const u8 {
|
||||||
pub const null_ref: Ref = std.math.maxInt(Ref);
|
return std.mem.sliceTo(self.strings[index..], 0);
|
||||||
|
}
|
||||||
|
|
||||||
pub const Inst = packed struct {
|
pub const Inst = struct {
|
||||||
tag: Tag,
|
tag: Tag,
|
||||||
data: Data,
|
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) {
|
pub const Tag = enum(u6) {
|
||||||
/// data is global_variable
|
/// data is global_variable_decl
|
||||||
global_variable,
|
global_variable_decl,
|
||||||
|
|
||||||
/// data is struct_decl
|
/// data is struct_decl
|
||||||
struct_decl,
|
struct_decl,
|
||||||
|
|
@ -67,16 +105,6 @@ pub const Inst = packed struct {
|
||||||
/// data is attr_interpolate
|
/// data is attr_interpolate
|
||||||
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
|
/// data is vector_type
|
||||||
vector_type,
|
vector_type,
|
||||||
/// data is matrix_type
|
/// data is matrix_type
|
||||||
|
|
@ -87,10 +115,6 @@ pub const Inst = packed struct {
|
||||||
array_type,
|
array_type,
|
||||||
/// data is ptr_type
|
/// data is ptr_type
|
||||||
ptr_type,
|
ptr_type,
|
||||||
/// data is none
|
|
||||||
sampler_type,
|
|
||||||
/// data is none
|
|
||||||
comparison_sampler_type,
|
|
||||||
/// data is sampled_texture_type
|
/// data is sampled_texture_type
|
||||||
sampled_texture_type,
|
sampled_texture_type,
|
||||||
/// data is multisampled_texture_type
|
/// data is multisampled_texture_type
|
||||||
|
|
@ -99,17 +123,11 @@ pub const Inst = packed struct {
|
||||||
storage_texture_type,
|
storage_texture_type,
|
||||||
/// data is depth_texture_type
|
/// data is depth_texture_type
|
||||||
depth_texture_type,
|
depth_texture_type,
|
||||||
/// data is none
|
|
||||||
external_sampled_texture_type,
|
|
||||||
|
|
||||||
/// data is integer_literal
|
/// data is integer_literal
|
||||||
integer_literal,
|
integer_literal,
|
||||||
/// data is float_literal
|
/// data is float_literal
|
||||||
float_literal,
|
float_literal,
|
||||||
/// data is none
|
|
||||||
true_literal,
|
|
||||||
/// data is none
|
|
||||||
false_literal,
|
|
||||||
|
|
||||||
/// data is ref
|
/// data is ref
|
||||||
not,
|
not,
|
||||||
|
|
@ -163,134 +181,277 @@ pub const Inst = packed struct {
|
||||||
member_access,
|
member_access,
|
||||||
/// data is binary (lhs is expr, rhs is type)
|
/// data is binary (lhs is expr, rhs is type)
|
||||||
bitcast,
|
bitcast,
|
||||||
|
|
||||||
|
pub fn isDecl(self: Tag) bool {
|
||||||
|
return switch (self) {
|
||||||
|
.global_variable_decl, .struct_decl => true,
|
||||||
|
else => false,
|
||||||
|
};
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Data = packed union {
|
pub const Data = union {
|
||||||
/// TODO: https://github.com/ziglang/zig/issues/14980
|
|
||||||
none: u1,
|
|
||||||
ref: Ref,
|
ref: Ref,
|
||||||
global_variable: packed struct {
|
global_variable_decl: GlobalVariableDecl,
|
||||||
/// index to null-terminated string in `strings`
|
struct_decl: StructDecl,
|
||||||
name: u32,
|
struct_member: StructMember,
|
||||||
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
|
|
||||||
},
|
|
||||||
/// attributes with no argument.
|
/// attributes with no argument.
|
||||||
attr_simple: enum {
|
attr_simple: AttrSimple,
|
||||||
invariant,
|
|
||||||
@"const",
|
|
||||||
vertex,
|
|
||||||
fragment,
|
|
||||||
compute,
|
|
||||||
},
|
|
||||||
/// attributes with an expression argument.
|
/// attributes with an expression argument.
|
||||||
attr_expr: packed struct {
|
attr_expr: AttrExpr,
|
||||||
kind: enum {
|
|
||||||
@"align",
|
|
||||||
binding,
|
|
||||||
group,
|
|
||||||
id,
|
|
||||||
location,
|
|
||||||
size,
|
|
||||||
},
|
|
||||||
expr: Ref,
|
|
||||||
},
|
|
||||||
/// @builtin attribute which accepts a BuiltinValue argument.
|
/// @builtin attribute which accepts a BuiltinValue argument.
|
||||||
attr_builtin: Ast.BuiltinValue,
|
attr_builtin: Ast.BuiltinValue,
|
||||||
/// @workgroup attribute. accepts at laest 1 argument.
|
/// @workgroup attribute. accepts at laest 1 argument.
|
||||||
attr_workgroup: packed struct {
|
attr_workgroup: AttrWorkgroup,
|
||||||
expr0: Ref,
|
|
||||||
expr1: Ref = null_ref,
|
|
||||||
expr2: Ref = null_ref,
|
|
||||||
},
|
|
||||||
/// @interpolate attribute. accepts 2 arguments.
|
/// @interpolate attribute. accepts 2 arguments.
|
||||||
attr_interpolate: packed struct {
|
attr_interpolate: AttrInterpolate,
|
||||||
type: Ast.InterpolationType,
|
vector_type: VectorType,
|
||||||
sample: Ast.InterpolationSample,
|
matrix_type: MatrixType,
|
||||||
},
|
atomic_type: AtomicType,
|
||||||
vector_type: packed struct {
|
array_type: ArrayType,
|
||||||
component_type: Ref,
|
ptr_type: PointerType,
|
||||||
size: enum { two, three, four },
|
sampled_texture_type: SampledTextureType,
|
||||||
},
|
multisampled_texture_type: MultisampledTextureType,
|
||||||
matrix_type: packed struct {
|
storage_texture_type: StorageTextureType,
|
||||||
component_type: Ref,
|
depth_texture_type: DepthTextureType,
|
||||||
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,
|
|
||||||
},
|
|
||||||
integer_literal: i64,
|
integer_literal: i64,
|
||||||
float_literal: f64,
|
float_literal: f64,
|
||||||
/// meaning of LHS and RHS depends on the corresponding Tag.
|
/// meaning of LHS and RHS depends on the corresponding Tag.
|
||||||
binary: packed struct {
|
binary: BinaryExpr,
|
||||||
lhs: Ref,
|
member_access: MemberAccess,
|
||||||
rhs: Ref,
|
};
|
||||||
},
|
|
||||||
member_access: packed struct {
|
|
||||||
base: Ref,
|
|
||||||
/// index to null-terminated string in `strings`
|
|
||||||
name: u32,
|
|
||||||
},
|
|
||||||
|
|
||||||
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 {
|
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);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,9 @@
|
||||||
const NUM_PARTICLES: u32 = 1500u;
|
const NUM_PARTICLES: u32 = 1500u;
|
||||||
|
|
||||||
|
struct Particles {
|
||||||
|
particles : array<Particle>
|
||||||
|
}
|
||||||
|
|
||||||
struct Particle {
|
struct Particle {
|
||||||
pos : vec2<f32>,
|
pos : vec2<f32>,
|
||||||
vel : vec2<f32>,
|
vel : vec2<f32>,
|
||||||
|
|
@ -15,10 +19,6 @@ struct SimParams {
|
||||||
rule3Scale : f32,
|
rule3Scale : f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Particles {
|
|
||||||
particles : array<Particle>
|
|
||||||
}
|
|
||||||
|
|
||||||
@group(0) @binding(0) var<uniform> params : SimParams;
|
@group(0) @binding(0) var<uniform> params : SimParams;
|
||||||
@group(0) @binding(1) var<storage> particlesSrc : Particles;
|
@group(0) @binding(1) var<storage> particlesSrc : Particles;
|
||||||
@group(0) @binding(2) var<storage,read_write> particlesDst : Particles;
|
@group(0) @binding(2) var<storage,read_write> particlesDst : Particles;
|
||||||
|
|
|
||||||
|
|
@ -183,6 +183,7 @@ test "boids" {
|
||||||
const source = @embedFile("boids.wgsl");
|
const source = @embedFile("boids.wgsl");
|
||||||
var ir = try expectIR(source);
|
var ir = try expectIR(source);
|
||||||
defer ir.deinit();
|
defer ir.deinit();
|
||||||
|
// try ir.print(std.io.getStdOut().writer());
|
||||||
}
|
}
|
||||||
|
|
||||||
test "gkurve" {
|
test "gkurve" {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue