mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 06:13:07 +00:00
spirv: error when execution mode is set more than once
This commit is contained in:
parent
9209f4b16a
commit
8fa54eb798
230
lib/std/gpu.zig
230
lib/std/gpu.zig
@ -1,81 +1,24 @@
|
|||||||
const std = @import("std.zig");
|
const std = @import("std.zig");
|
||||||
|
|
||||||
/// Will make `ptr` contain the location of the current invocation within the
|
pub const position_in = @extern(*addrspace(.input) @Vector(4, f32), .{ .name = "position" });
|
||||||
/// global workgroup. Each component is equal to the index of the local workgroup
|
pub const position_out = @extern(*addrspace(.output) @Vector(4, f32), .{ .name = "position" });
|
||||||
/// multiplied by the size of the local workgroup plus `localInvocationId`.
|
pub const point_size_in = @extern(*addrspace(.input) f32, .{ .name = "point_size" });
|
||||||
/// `ptr` must be a reference to variable or struct field.
|
pub const point_size_out = @extern(*addrspace(.output) f32, .{ .name = "point_size" });
|
||||||
pub fn globalInvocationId(comptime ptr: *addrspace(.input) @Vector(3, u32)) void {
|
pub extern const invocation_id: u32 addrspace(.input);
|
||||||
asm volatile (
|
pub extern const frag_coord: @Vector(4, f32) addrspace(.input);
|
||||||
\\OpDecorate %ptr BuiltIn GlobalInvocationId
|
pub extern const point_coord: @Vector(2, f32) addrspace(.input);
|
||||||
:
|
// TODO: direct/indirect values
|
||||||
: [ptr] "" (ptr),
|
// pub extern const front_facing: bool addrspace(.input);
|
||||||
);
|
// TODO: runtime array
|
||||||
}
|
// pub extern const sample_mask;
|
||||||
|
pub extern var frag_depth: f32 addrspace(.output);
|
||||||
/// Will make that variable contain the location of the current cluster
|
pub extern const num_workgroups: @Vector(3, u32) addrspace(.input);
|
||||||
/// culling, task, mesh, or compute shader invocation within the local
|
pub extern const workgroup_size: @Vector(3, u32) addrspace(.input);
|
||||||
/// workgroup. Each component ranges from zero through to the size of the
|
pub extern const workgroup_id: @Vector(3, u32) addrspace(.input);
|
||||||
/// workgroup in that dimension minus one.
|
pub extern const local_invocation_id: @Vector(3, u32) addrspace(.input);
|
||||||
/// `ptr` must be a reference to variable or struct field.
|
pub extern const global_invocation_id: @Vector(3, u32) addrspace(.input);
|
||||||
pub fn localInvocationId(comptime ptr: *addrspace(.input) @Vector(3, u32)) void {
|
pub extern const vertex_index: u32 addrspace(.input);
|
||||||
asm volatile (
|
pub extern const instance_index: u32 addrspace(.input);
|
||||||
\\OpDecorate %ptr BuiltIn LocalInvocationId
|
|
||||||
:
|
|
||||||
: [ptr] "" (ptr),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Output vertex position from a `Vertex` entrypoint
|
|
||||||
/// `ptr` must be a reference to variable or struct field.
|
|
||||||
pub fn position(comptime ptr: *addrspace(.output) @Vector(4, f32)) void {
|
|
||||||
asm volatile (
|
|
||||||
\\OpDecorate %ptr BuiltIn Position
|
|
||||||
:
|
|
||||||
: [ptr] "" (ptr),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Will make `ptr` contain the index of the vertex that is
|
|
||||||
/// being processed by the current vertex shader invocation.
|
|
||||||
/// `ptr` must be a reference to variable or struct field.
|
|
||||||
pub fn vertexIndex(comptime ptr: *addrspace(.input) u32) void {
|
|
||||||
asm volatile (
|
|
||||||
\\OpDecorate %ptr BuiltIn VertexIndex
|
|
||||||
:
|
|
||||||
: [ptr] "" (ptr),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Will make `ptr` contain the index of the instance that is
|
|
||||||
/// being processed by the current vertex shader invocation.
|
|
||||||
/// `ptr` must be a reference to variable or struct field.
|
|
||||||
pub fn instanceIndex(comptime ptr: *addrspace(.input) u32) void {
|
|
||||||
asm volatile (
|
|
||||||
\\OpDecorate %ptr BuiltIn InstanceIndex
|
|
||||||
:
|
|
||||||
: [ptr] "" (ptr),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Output fragment depth from a `Fragment` entrypoint
|
|
||||||
/// `ptr` must be a reference to variable or struct field.
|
|
||||||
pub fn fragmentCoord(comptime ptr: *addrspace(.input) @Vector(4, f32)) void {
|
|
||||||
asm volatile (
|
|
||||||
\\OpDecorate %ptr BuiltIn FragCoord
|
|
||||||
:
|
|
||||||
: [ptr] "" (ptr),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Output fragment depth from a `Fragment` entrypoint
|
|
||||||
/// `ptr` must be a reference to variable or struct field.
|
|
||||||
pub fn fragmentDepth(comptime ptr: *addrspace(.output) f32) void {
|
|
||||||
asm volatile (
|
|
||||||
\\OpDecorate %ptr BuiltIn FragDepth
|
|
||||||
:
|
|
||||||
: [ptr] "" (ptr),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Forms the main linkage for `input` and `output` address spaces.
|
/// Forms the main linkage for `input` and `output` address spaces.
|
||||||
/// `ptr` must be a reference to variable or struct field.
|
/// `ptr` must be a reference to variable or struct field.
|
||||||
@ -101,74 +44,85 @@ pub fn binding(comptime ptr: anytype, comptime set: u32, comptime bind: u32) voi
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const Origin = enum(u32) {
|
pub const ExecutionMode = union(Tag) {
|
||||||
/// Increase toward the right and downward
|
/// Sets origin of the framebuffer to the upper-left corner
|
||||||
upper_left = 7,
|
origin_upper_left,
|
||||||
/// Increase toward the right and upward
|
/// Sets origin of the framebuffer to the lower-left corner
|
||||||
lower_left = 8,
|
origin_lower_left,
|
||||||
};
|
/// Indicates that the fragment shader writes to `frag_depth`,
|
||||||
|
/// replacing the fixed-function depth value.
|
||||||
/// The coordinates appear to originate in the specified `origin`.
|
depth_replacing,
|
||||||
/// Only valid with the `Fragment` calling convention.
|
|
||||||
pub fn fragmentOrigin(comptime entry_point: anytype, comptime origin: Origin) void {
|
|
||||||
asm volatile (
|
|
||||||
\\OpExecutionMode %entry_point $origin
|
|
||||||
:
|
|
||||||
: [entry_point] "" (entry_point),
|
|
||||||
[origin] "c" (@intFromEnum(origin)),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const DepthMode = enum(u32) {
|
|
||||||
/// Declares that this entry point dynamically writes the
|
|
||||||
/// `fragmentDepth` built in-decorated variable.
|
|
||||||
replacing = 12,
|
|
||||||
/// Indicates that per-fragment tests may assume that
|
/// Indicates that per-fragment tests may assume that
|
||||||
/// any `fragmentDepth` built in-decorated value written by the shader is
|
/// any `frag_depth` built in-decorated value written by the shader is
|
||||||
/// greater-than-or-equal to the fragment’s interpolated depth value
|
/// greater-than-or-equal to the fragment’s interpolated depth value
|
||||||
greater = 14,
|
depth_greater,
|
||||||
/// Indicates that per-fragment tests may assume that
|
/// Indicates that per-fragment tests may assume that
|
||||||
/// any `fragmentDepth` built in-decorated value written by the shader is
|
/// any `frag_depth` built in-decorated value written by the shader is
|
||||||
/// less-than-or-equal to the fragment’s interpolated depth value
|
/// less-than-or-equal to the fragment’s interpolated depth value
|
||||||
less = 15,
|
depth_less,
|
||||||
/// Indicates that per-fragment tests may assume that
|
/// Indicates that per-fragment tests may assume that
|
||||||
/// any `fragmentDepth` built in-decorated value written by the shader is
|
/// any `frag_depth` built in-decorated value written by the shader is
|
||||||
/// the same as the fragment’s interpolated depth value
|
/// the same as the fragment’s interpolated depth value
|
||||||
unchanged = 16,
|
depth_unchanged,
|
||||||
|
/// Indicates the workgroup size in the x, y, and z dimensions.
|
||||||
|
local_size: LocalSize,
|
||||||
|
|
||||||
|
pub const Tag = enum(u32) {
|
||||||
|
origin_upper_left = 7,
|
||||||
|
origin_lower_left = 8,
|
||||||
|
depth_replacing = 12,
|
||||||
|
depth_greater = 14,
|
||||||
|
depth_less = 15,
|
||||||
|
depth_unchanged = 16,
|
||||||
|
local_size = 17,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const LocalSize = struct { x: u32, y: u32, z: u32 };
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Only valid with the `Fragment` calling convention.
|
/// Declare the mode entry point executes in.
|
||||||
pub fn depthMode(comptime entry_point: anytype, comptime mode: DepthMode) void {
|
pub fn executionMode(comptime entry_point: anytype, comptime mode: ExecutionMode) void {
|
||||||
asm volatile (
|
const cc = @typeInfo(@TypeOf(entry_point)).@"fn".calling_convention;
|
||||||
\\OpExecutionMode %entry_point $mode
|
switch (mode) {
|
||||||
:
|
.origin_upper_left,
|
||||||
: [entry_point] "" (entry_point),
|
.origin_lower_left,
|
||||||
[mode] "c" (mode),
|
.depth_replacing,
|
||||||
);
|
.depth_greater,
|
||||||
}
|
.depth_less,
|
||||||
|
.depth_unchanged,
|
||||||
/// Indicates the workgroup size in the `x`, `y`, and `z` dimensions.
|
=> {
|
||||||
/// Only valid with the `GLCompute` or `Kernel` calling conventions.
|
if (cc != .spirv_fragment) {
|
||||||
pub fn workgroupSize(comptime entry_point: anytype, comptime size: @Vector(3, u32)) void {
|
@compileError(
|
||||||
asm volatile (
|
\\invalid execution mode '
|
||||||
\\OpExecutionMode %entry_point LocalSize %x %y %z
|
++ @tagName(mode) ++
|
||||||
:
|
\\' for function with '
|
||||||
: [entry_point] "" (entry_point),
|
++ @tagName(cc) ++
|
||||||
[x] "c" (size[0]),
|
\\' calling convention
|
||||||
[y] "c" (size[1]),
|
);
|
||||||
[z] "c" (size[2]),
|
}
|
||||||
);
|
asm volatile (
|
||||||
}
|
\\OpExecutionMode %entry_point $mode
|
||||||
|
:
|
||||||
/// A hint to the client, which indicates the workgroup size in the `x`, `y`, and `z` dimensions.
|
: [entry_point] "" (entry_point),
|
||||||
/// Only valid with the `GLCompute` or `Kernel` calling conventions.
|
[mode] "c" (@intFromEnum(mode)),
|
||||||
pub fn workgroupSizeHint(comptime entry_point: anytype, comptime size: @Vector(3, u32)) void {
|
);
|
||||||
asm volatile (
|
},
|
||||||
\\OpExecutionMode %entry_point LocalSizeHint %x %y %z
|
.local_size => |size| {
|
||||||
:
|
if (cc != .spirv_kernel) {
|
||||||
: [entry_point] "" (entry_point),
|
@compileError(
|
||||||
[x] "c" (size[0]),
|
\\invalid execution mode 'local_size' for function with '
|
||||||
[y] "c" (size[1]),
|
++ @tagName(cc) ++
|
||||||
[z] "c" (size[2]),
|
\\' calling convention
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
asm volatile (
|
||||||
|
\\OpExecutionMode %entry_point LocalSize $x $y $z
|
||||||
|
:
|
||||||
|
: [entry_point] "" (entry_point),
|
||||||
|
[x] "c" (size.x),
|
||||||
|
[y] "c" (size.y),
|
||||||
|
[z] "c" (size.z),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2870,7 +2870,7 @@ const NavGen = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
try self.spv.declareDeclDeps(spv_decl_index, decl_deps.items);
|
try self.spv.declareDeclDeps(spv_decl_index, decl_deps.items);
|
||||||
try self.spv.declareEntryPoint(spv_decl_index, test_name, execution_mode);
|
try self.spv.declareEntryPoint(spv_decl_index, test_name, execution_mode, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn genNav(self: *NavGen, do_codegen: bool) !void {
|
fn genNav(self: *NavGen, do_codegen: bool) !void {
|
||||||
@ -2976,10 +2976,6 @@ const NavGen = struct {
|
|||||||
try self.spv.decorate(result_id, .{ .BuiltIn = .{ .built_in = .Position } });
|
try self.spv.decorate(result_id, .{ .BuiltIn = .{ .built_in = .Position } });
|
||||||
} else if (nav.fqn.eqlSlice("point_size", ip)) {
|
} else if (nav.fqn.eqlSlice("point_size", ip)) {
|
||||||
try self.spv.decorate(result_id, .{ .BuiltIn = .{ .built_in = .PointSize } });
|
try self.spv.decorate(result_id, .{ .BuiltIn = .{ .built_in = .PointSize } });
|
||||||
} else if (nav.fqn.eqlSlice("vertex_id", ip)) {
|
|
||||||
try self.spv.decorate(result_id, .{ .BuiltIn = .{ .built_in = .VertexId } });
|
|
||||||
} else if (nav.fqn.eqlSlice("instance_id", ip)) {
|
|
||||||
try self.spv.decorate(result_id, .{ .BuiltIn = .{ .built_in = .InstanceId } });
|
|
||||||
} else if (nav.fqn.eqlSlice("invocation_id", ip)) {
|
} else if (nav.fqn.eqlSlice("invocation_id", ip)) {
|
||||||
try self.spv.decorate(result_id, .{ .BuiltIn = .{ .built_in = .InvocationId } });
|
try self.spv.decorate(result_id, .{ .BuiltIn = .{ .built_in = .InvocationId } });
|
||||||
} else if (nav.fqn.eqlSlice("frag_coord", ip)) {
|
} else if (nav.fqn.eqlSlice("frag_coord", ip)) {
|
||||||
@ -2990,8 +2986,6 @@ const NavGen = struct {
|
|||||||
try self.spv.decorate(result_id, .{ .BuiltIn = .{ .built_in = .FrontFacing } });
|
try self.spv.decorate(result_id, .{ .BuiltIn = .{ .built_in = .FrontFacing } });
|
||||||
} else if (nav.fqn.eqlSlice("sample_mask", ip)) {
|
} else if (nav.fqn.eqlSlice("sample_mask", ip)) {
|
||||||
try self.spv.decorate(result_id, .{ .BuiltIn = .{ .built_in = .SampleMask } });
|
try self.spv.decorate(result_id, .{ .BuiltIn = .{ .built_in = .SampleMask } });
|
||||||
} else if (nav.fqn.eqlSlice("sample_mask", ip)) {
|
|
||||||
try self.spv.decorate(result_id, .{ .BuiltIn = .{ .built_in = .SampleMask } });
|
|
||||||
} else if (nav.fqn.eqlSlice("frag_depth", ip)) {
|
} else if (nav.fqn.eqlSlice("frag_depth", ip)) {
|
||||||
try self.spv.decorate(result_id, .{ .BuiltIn = .{ .built_in = .FragDepth } });
|
try self.spv.decorate(result_id, .{ .BuiltIn = .{ .built_in = .FragDepth } });
|
||||||
} else if (nav.fqn.eqlSlice("num_workgroups", ip)) {
|
} else if (nav.fqn.eqlSlice("num_workgroups", ip)) {
|
||||||
|
|||||||
@ -296,12 +296,26 @@ fn processInstruction(self: *Assembler) !void {
|
|||||||
};
|
};
|
||||||
break :blk .{ .value = try self.spv.importInstructionSet(set_tag) };
|
break :blk .{ .value = try self.spv.importInstructionSet(set_tag) };
|
||||||
},
|
},
|
||||||
|
.OpExecutionMode, .OpExecutionModeId => {
|
||||||
|
assert(try self.processGenericInstruction() == null);
|
||||||
|
const entry_point_id = try self.resolveRefId(self.inst.operands.items[0].ref_id);
|
||||||
|
const exec_mode: spec.ExecutionMode = @enumFromInt(self.inst.operands.items[1].value);
|
||||||
|
const gop = try self.spv.entry_points.getOrPut(self.gpa, entry_point_id);
|
||||||
|
if (!gop.found_existing) {
|
||||||
|
gop.value_ptr.* = .{};
|
||||||
|
} else if (gop.value_ptr.exec_mode != null) {
|
||||||
|
return self.fail(
|
||||||
|
self.currentToken().start,
|
||||||
|
"cannot set execution mode more than once to any entry point",
|
||||||
|
.{},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
gop.value_ptr.exec_mode = exec_mode;
|
||||||
|
return;
|
||||||
|
},
|
||||||
else => switch (self.inst.opcode.class()) {
|
else => switch (self.inst.opcode.class()) {
|
||||||
.TypeDeclaration => try self.processTypeInstruction(),
|
.TypeDeclaration => try self.processTypeInstruction(),
|
||||||
else => if (try self.processGenericInstruction()) |result|
|
else => (try self.processGenericInstruction()) orelse return,
|
||||||
result
|
|
||||||
else
|
|
||||||
return,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -92,11 +92,12 @@ pub const Decl = struct {
|
|||||||
/// This models a kernel entry point.
|
/// This models a kernel entry point.
|
||||||
pub const EntryPoint = struct {
|
pub const EntryPoint = struct {
|
||||||
/// The declaration that should be exported.
|
/// The declaration that should be exported.
|
||||||
decl_index: Decl.Index,
|
decl_index: ?Decl.Index = null,
|
||||||
/// The name of the kernel to be exported.
|
/// The name of the kernel to be exported.
|
||||||
name: []const u8,
|
name: ?[]const u8 = null,
|
||||||
/// Calling Convention
|
/// Calling Convention
|
||||||
execution_model: spec.ExecutionModel,
|
exec_model: ?spec.ExecutionModel = null,
|
||||||
|
exec_mode: ?spec.ExecutionMode = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A general-purpose allocator which may be used to allocate resources for this module
|
/// A general-purpose allocator which may be used to allocate resources for this module
|
||||||
@ -184,7 +185,7 @@ decls: std.ArrayListUnmanaged(Decl) = .empty,
|
|||||||
decl_deps: std.ArrayListUnmanaged(Decl.Index) = .empty,
|
decl_deps: std.ArrayListUnmanaged(Decl.Index) = .empty,
|
||||||
|
|
||||||
/// The list of entry points that should be exported from this module.
|
/// The list of entry points that should be exported from this module.
|
||||||
entry_points: std.ArrayListUnmanaged(EntryPoint) = .empty,
|
entry_points: std.AutoArrayHashMapUnmanaged(IdRef, EntryPoint) = .empty,
|
||||||
|
|
||||||
pub fn init(gpa: Allocator, target: std.Target) Module {
|
pub fn init(gpa: Allocator, target: std.Target) Module {
|
||||||
const version_minor: u8 = blk: {
|
const version_minor: u8 = blk: {
|
||||||
@ -304,19 +305,30 @@ fn entryPoints(self: *Module) !Section {
|
|||||||
var seen = try std.DynamicBitSetUnmanaged.initEmpty(self.gpa, self.decls.items.len);
|
var seen = try std.DynamicBitSetUnmanaged.initEmpty(self.gpa, self.decls.items.len);
|
||||||
defer seen.deinit(self.gpa);
|
defer seen.deinit(self.gpa);
|
||||||
|
|
||||||
for (self.entry_points.items) |entry_point| {
|
for (self.entry_points.keys(), self.entry_points.values()) |entry_point_id, entry_point| {
|
||||||
interface.items.len = 0;
|
interface.items.len = 0;
|
||||||
seen.setRangeValue(.{ .start = 0, .end = self.decls.items.len }, false);
|
seen.setRangeValue(.{ .start = 0, .end = self.decls.items.len }, false);
|
||||||
|
|
||||||
try self.addEntryPointDeps(entry_point.decl_index, &seen, &interface);
|
try self.addEntryPointDeps(entry_point.decl_index.?, &seen, &interface);
|
||||||
|
|
||||||
const entry_point_id = self.declPtr(entry_point.decl_index).result_id;
|
|
||||||
try entry_points.emit(self.gpa, .OpEntryPoint, .{
|
try entry_points.emit(self.gpa, .OpEntryPoint, .{
|
||||||
.execution_model = entry_point.execution_model,
|
.execution_model = entry_point.exec_model.?,
|
||||||
.entry_point = entry_point_id,
|
.entry_point = entry_point_id,
|
||||||
.name = entry_point.name,
|
.name = entry_point.name.?,
|
||||||
.interface = interface.items,
|
.interface = interface.items,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (entry_point.exec_mode == null and entry_point.exec_model == .Fragment) {
|
||||||
|
switch (self.target.os.tag) {
|
||||||
|
.vulkan, .opengl => |tag| {
|
||||||
|
try self.sections.execution_modes.emit(self.gpa, .OpExecutionMode, .{
|
||||||
|
.entry_point = entry_point_id,
|
||||||
|
.mode = if (tag == .vulkan) .OriginUpperLeft else .OriginLowerLeft,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
.opencl => {},
|
||||||
|
else => unreachable,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return entry_points;
|
return entry_points;
|
||||||
@ -749,13 +761,15 @@ pub fn declareEntryPoint(
|
|||||||
self: *Module,
|
self: *Module,
|
||||||
decl_index: Decl.Index,
|
decl_index: Decl.Index,
|
||||||
name: []const u8,
|
name: []const u8,
|
||||||
execution_model: spec.ExecutionModel,
|
exec_model: spec.ExecutionModel,
|
||||||
|
exec_mode: ?spec.ExecutionMode,
|
||||||
) !void {
|
) !void {
|
||||||
try self.entry_points.append(self.gpa, .{
|
const gop = try self.entry_points.getOrPut(self.gpa, self.declPtr(decl_index).result_id);
|
||||||
.decl_index = decl_index,
|
gop.value_ptr.decl_index = decl_index;
|
||||||
.name = try self.arena.allocator().dupe(u8, name),
|
gop.value_ptr.name = try self.arena.allocator().dupe(u8, name);
|
||||||
.execution_model = execution_model,
|
gop.value_ptr.exec_model = exec_model;
|
||||||
});
|
// Might've been set by assembler
|
||||||
|
if (!gop.found_existing) gop.value_ptr.exec_mode = exec_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn debugName(self: *Module, target: IdResult, name: []const u8) !void {
|
pub fn debugName(self: *Module, target: IdResult, name: []const u8) !void {
|
||||||
|
|||||||
@ -162,7 +162,7 @@ pub fn updateExports(
|
|||||||
if (ip.isFunctionType(nav_ty)) {
|
if (ip.isFunctionType(nav_ty)) {
|
||||||
const spv_decl_index = try self.object.resolveNav(zcu, nav_index);
|
const spv_decl_index = try self.object.resolveNav(zcu, nav_index);
|
||||||
const cc = Type.fromInterned(nav_ty).fnCallingConvention(zcu);
|
const cc = Type.fromInterned(nav_ty).fnCallingConvention(zcu);
|
||||||
const execution_model: spec.ExecutionModel = switch (target.os.tag) {
|
const exec_model: spec.ExecutionModel = switch (target.os.tag) {
|
||||||
.vulkan, .opengl => switch (cc) {
|
.vulkan, .opengl => switch (cc) {
|
||||||
.spirv_vertex => .Vertex,
|
.spirv_vertex => .Vertex,
|
||||||
.spirv_fragment => .Fragment,
|
.spirv_fragment => .Fragment,
|
||||||
@ -185,7 +185,8 @@ pub fn updateExports(
|
|||||||
try self.object.spv.declareEntryPoint(
|
try self.object.spv.declareEntryPoint(
|
||||||
spv_decl_index,
|
spv_decl_index,
|
||||||
exp.opts.name.toSlice(ip),
|
exp.opts.name.toSlice(ip),
|
||||||
execution_model,
|
exec_model,
|
||||||
|
null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user