mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 05:44:20 +00:00
Merge d17fdd4cdd into d0ba6642b5
This commit is contained in:
commit
397e3f43e2
17 changed files with 4967 additions and 302 deletions
20
build.zig
20
build.zig
|
|
@ -66,6 +66,23 @@ pub fn build(b: *std.Build) !void {
|
|||
b.getInstallStep().dependOn(&install_std_docs.step);
|
||||
}
|
||||
|
||||
const update_cpu_features = b.addExecutable(.{
|
||||
.name = "update-cpu-features",
|
||||
.root_module = b.createModule(.{
|
||||
.root_source_file = b.path("tools/update_cpu_features.zig"),
|
||||
.target = b.graph.host,
|
||||
.imports = &.{.{
|
||||
.name = "spirv_spec",
|
||||
.module = b.createModule(.{
|
||||
.root_source_file = b.path("src/codegen/spirv/spec.zig"),
|
||||
.target = b.graph.host,
|
||||
}),
|
||||
}},
|
||||
}),
|
||||
});
|
||||
const run_update_cpu_features = b.addRunArtifact(update_cpu_features);
|
||||
if (b.args) |args| run_update_cpu_features.addArgs(args);
|
||||
|
||||
if (flat) {
|
||||
b.installFile("LICENSE", "LICENSE");
|
||||
b.installFile("README.md", "README.md");
|
||||
|
|
@ -81,6 +98,9 @@ pub fn build(b: *std.Build) !void {
|
|||
docs_step.dependOn(langref_step);
|
||||
docs_step.dependOn(std_docs_step);
|
||||
|
||||
const update_cpu_features_step = b.step("update-cpu-features", "Update CPU Features");
|
||||
update_cpu_features_step.dependOn(&run_update_cpu_features.step);
|
||||
|
||||
const no_matrix = b.option(bool, "no-matrix", "Limit test matrix to exactly one target configuration") orelse false;
|
||||
const skip_debug = b.option(bool, "skip-debug", "Main test suite skips debug builds") orelse false;
|
||||
const skip_release = b.option(bool, "skip-release", "Main test suite skips release builds") orelse no_matrix;
|
||||
|
|
|
|||
|
|
@ -1182,7 +1182,7 @@ pub const Cpu = struct {
|
|||
pub const Set = struct {
|
||||
ints: [usize_count]usize,
|
||||
|
||||
pub const needed_bit_count = 317;
|
||||
pub const needed_bit_count = 421;
|
||||
pub const byte_count = (needed_bit_count + 7) / 8;
|
||||
pub const usize_count = (byte_count + (@sizeOf(usize) - 1)) / @sizeOf(usize);
|
||||
pub const Index = std.math.Log2Int(std.meta.Int(.unsigned, usize_count * @bitSizeOf(usize)));
|
||||
|
|
@ -1924,6 +1924,8 @@ pub const Cpu = struct {
|
|||
.spirv_kernel,
|
||||
.spirv_fragment,
|
||||
.spirv_vertex,
|
||||
.spirv_task,
|
||||
.spirv_mesh,
|
||||
=> &.{ .spirv32, .spirv64 },
|
||||
};
|
||||
}
|
||||
|
|
@ -3291,6 +3293,12 @@ pub fn cTypeBitSize(target: *const Target, c_type: CType) u16 {
|
|||
.longdouble => return 128,
|
||||
},
|
||||
|
||||
// OpenGL has no well defined C ABI, we do this to prevent panic when using floating point types.
|
||||
.opengl => switch (c_type) {
|
||||
.char, .short, .ushort, .int, .uint, .float, .long, .ulong, .longlong, .ulonglong => return 32,
|
||||
.double, .longdouble => return 64,
|
||||
},
|
||||
|
||||
.opencl, .vulkan => switch (c_type) {
|
||||
.char => return 8,
|
||||
.short, .ushort => return 16,
|
||||
|
|
@ -3326,9 +3334,8 @@ pub fn cTypeBitSize(target: *const Target, c_type: CType) u16 {
|
|||
},
|
||||
|
||||
.ps3,
|
||||
.contiki,
|
||||
.managarm,
|
||||
.opengl,
|
||||
.contiki,
|
||||
=> @panic("specify the C integer and float type sizes for this OS"),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -140,7 +140,7 @@ pub const CallingConvention = union(enum(u8)) {
|
|||
pub const kernel: CallingConvention = switch (builtin.target.cpu.arch) {
|
||||
.amdgcn => .amdgcn_kernel,
|
||||
.nvptx, .nvptx64 => .nvptx_kernel,
|
||||
.spirv32, .spirv64 => .spirv_kernel,
|
||||
.spirv32, .spirv64 => .{ .spirv_kernel = .{ .x = 1, .y = 1, .z = 1 } },
|
||||
else => unreachable,
|
||||
};
|
||||
|
||||
|
|
@ -335,11 +335,13 @@ pub const CallingConvention = union(enum(u8)) {
|
|||
nvptx_device,
|
||||
nvptx_kernel,
|
||||
|
||||
// Calling conventions for kernels and shaders on the `spirv`, `spirv32`, and `spirv64` architectures.
|
||||
// Calling conventions for kernels and shaders on the `spirv32`, and `spirv64` architectures.
|
||||
spirv_device,
|
||||
spirv_kernel,
|
||||
spirv_fragment,
|
||||
spirv_kernel: SpirvKernelOptions,
|
||||
spirv_fragment: SpirvFragmentOptions,
|
||||
spirv_vertex,
|
||||
spirv_task: SpirvKernelOptions,
|
||||
spirv_mesh: SpirvMeshOptions,
|
||||
|
||||
/// Options shared across most calling conventions.
|
||||
pub const CommonOptions = struct {
|
||||
|
|
@ -448,6 +450,32 @@ pub const CallingConvention = union(enum(u8)) {
|
|||
};
|
||||
};
|
||||
|
||||
pub const SpirvKernelOptions = struct { x: u32, y: u32, z: u32 };
|
||||
|
||||
pub const SpirvFragmentOptions = struct {
|
||||
const DepthAssumption = enum(u2) {
|
||||
none = 0,
|
||||
greater = 1,
|
||||
less = 2,
|
||||
unchanged = 3,
|
||||
};
|
||||
|
||||
pixel_centered_integer: bool = false,
|
||||
depth_assumption: DepthAssumption = .none,
|
||||
};
|
||||
|
||||
pub const SpirvMeshOptions = struct {
|
||||
const StageOutput = enum(u2) {
|
||||
output_points = 0,
|
||||
output_lines = 1,
|
||||
output_triangles = 2,
|
||||
};
|
||||
|
||||
stage_output: StageOutput = .output_triangles,
|
||||
max_primitives: u32 = 1,
|
||||
max_vertices: u32 = 3,
|
||||
};
|
||||
|
||||
/// Options for the `sh_interrupt` calling convention.
|
||||
pub const ShInterruptOptions = struct {
|
||||
/// The boundary the stack is aligned to when the function is called.
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ pub extern const instance_index: u32 addrspace(.input);
|
|||
|
||||
/// Forms the main linkage for `input` and `output` address spaces.
|
||||
/// `ptr` must be a reference to variable or struct field.
|
||||
pub fn location(comptime ptr: anytype, comptime loc: u32) void {
|
||||
pub inline fn location(comptime ptr: anytype, comptime loc: u32) void {
|
||||
asm volatile (
|
||||
\\OpDecorate %ptr Location $loc
|
||||
:
|
||||
|
|
@ -33,7 +33,7 @@ pub fn location(comptime ptr: anytype, comptime loc: u32) void {
|
|||
|
||||
/// Forms the main linkage for `input` and `output` address spaces.
|
||||
/// `ptr` must be a reference to variable or struct field.
|
||||
pub fn binding(comptime ptr: anytype, comptime set: u32, comptime bind: u32) void {
|
||||
pub inline fn binding(comptime ptr: anytype, comptime set: u32, comptime bind: u32) void {
|
||||
asm volatile (
|
||||
\\OpDecorate %ptr DescriptorSet $set
|
||||
\\OpDecorate %ptr Binding $bind
|
||||
|
|
@ -43,86 +43,3 @@ pub fn binding(comptime ptr: anytype, comptime set: u32, comptime bind: u32) voi
|
|||
[bind] "c" (bind),
|
||||
);
|
||||
}
|
||||
|
||||
pub const ExecutionMode = union(Tag) {
|
||||
/// Sets origin of the framebuffer to the upper-left corner
|
||||
origin_upper_left,
|
||||
/// Sets origin of the framebuffer to the lower-left corner
|
||||
origin_lower_left,
|
||||
/// Indicates that the fragment shader writes to `frag_depth`,
|
||||
/// replacing the fixed-function depth value.
|
||||
depth_replacing,
|
||||
/// Indicates that per-fragment tests may assume that
|
||||
/// any `frag_depth` built in-decorated value written by the shader is
|
||||
/// greater-than-or-equal to the fragment’s interpolated depth value
|
||||
depth_greater,
|
||||
/// Indicates that per-fragment tests may assume that
|
||||
/// any `frag_depth` built in-decorated value written by the shader is
|
||||
/// less-than-or-equal to the fragment’s interpolated depth value
|
||||
depth_less,
|
||||
/// Indicates that per-fragment tests may assume that
|
||||
/// any `frag_depth` built in-decorated value written by the shader is
|
||||
/// the same as the fragment’s interpolated depth value
|
||||
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 };
|
||||
};
|
||||
|
||||
/// Declare the mode entry point executes in.
|
||||
pub fn executionMode(comptime entry_point: anytype, comptime mode: ExecutionMode) void {
|
||||
const cc = @typeInfo(@TypeOf(entry_point)).@"fn".calling_convention;
|
||||
switch (mode) {
|
||||
.origin_upper_left,
|
||||
.origin_lower_left,
|
||||
.depth_replacing,
|
||||
.depth_greater,
|
||||
.depth_less,
|
||||
.depth_unchanged,
|
||||
=> {
|
||||
if (cc != .spirv_fragment) {
|
||||
@compileError(
|
||||
\\invalid execution mode '
|
||||
++ @tagName(mode) ++
|
||||
\\' for function with '
|
||||
++ @tagName(cc) ++
|
||||
\\' calling convention
|
||||
);
|
||||
}
|
||||
asm volatile (
|
||||
\\OpExecutionMode %entry_point $mode
|
||||
:
|
||||
: [entry_point] "" (entry_point),
|
||||
[mode] "c" (@intFromEnum(mode)),
|
||||
);
|
||||
},
|
||||
.local_size => |size| {
|
||||
if (cc != .spirv_kernel) {
|
||||
@compileError(
|
||||
\\invalid execution mode 'local_size' for function with '
|
||||
++ @tagName(cc) ++
|
||||
\\' 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),
|
||||
);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4880,12 +4880,19 @@ pub const Index = enum(u32) {
|
|||
type_function: struct {
|
||||
const @"data.flags.has_comptime_bits" = opaque {};
|
||||
const @"data.flags.has_noalias_bits" = opaque {};
|
||||
const @"data.flags.cc_extra_len" = opaque {};
|
||||
const @"data.params_len" = opaque {};
|
||||
data: *Tag.TypeFunction,
|
||||
@"trailing.comptime_bits.len": *@"data.flags.has_comptime_bits",
|
||||
@"trailing.noalias_bits.len": *@"data.flags.has_noalias_bits",
|
||||
@"trailing.cc_bits.len": *@"data.flags.cc_extra_len",
|
||||
@"trailing.param_types.len": *@"data.params_len",
|
||||
trailing: struct { comptime_bits: []u32, noalias_bits: []u32, param_types: []Index },
|
||||
trailing: struct {
|
||||
comptime_bits: []u32,
|
||||
noalias_bits: []u32,
|
||||
cc_bits: []u32,
|
||||
param_types: []Index,
|
||||
},
|
||||
},
|
||||
|
||||
undef: DataIsIndex,
|
||||
|
|
@ -5861,6 +5868,7 @@ pub const Tag = enum(u8) {
|
|||
.trailing = struct {
|
||||
param_comptime_bits: ?[]u32,
|
||||
param_noalias_bits: ?[]u32,
|
||||
param_cc_bits: ?[]u32,
|
||||
param_type: []Index,
|
||||
},
|
||||
.config = .{
|
||||
|
|
@ -5868,6 +5876,8 @@ pub const Tag = enum(u8) {
|
|||
.@"trailing.param_comptime_bits.?.len" = .@"(payload.params_len + 31) / 32",
|
||||
.@"trailing.param_noalias_bits.?" = .@"payload.flags.has_noalias_bits",
|
||||
.@"trailing.param_noalias_bits.?.len" = .@"(payload.params_len + 31) / 32",
|
||||
.@"trailing.param_cc_bits.?" = .@"payload.flags.cc_extra_len != 0",
|
||||
.@"trailing.param_cc_bits.?.len" = .@"payload.flags.cc_extra_len",
|
||||
.@"trailing.param_type.len" = .@"payload.params_len",
|
||||
},
|
||||
},
|
||||
|
|
@ -6074,7 +6084,11 @@ pub const Tag = enum(u8) {
|
|||
/// Trailing:
|
||||
/// 0. comptime_bits: u32, // if has_comptime_bits
|
||||
/// 1. noalias_bits: u32, // if has_noalias_bits
|
||||
/// 2. param_type: Index for each params_len
|
||||
/// 2. if cc.tag == .spirv_mesh
|
||||
/// cc_bits: [2]u32
|
||||
/// if cc.tag == .spirv_kernel or cc.tag == .spirv_task
|
||||
/// cc_bits: [3]u32
|
||||
/// 3. param_type: Index for each params_len
|
||||
pub const TypeFunction = struct {
|
||||
params_len: u32,
|
||||
return_type: Index,
|
||||
|
|
@ -6086,8 +6100,9 @@ pub const Tag = enum(u8) {
|
|||
is_generic: bool,
|
||||
has_comptime_bits: bool,
|
||||
has_noalias_bits: bool,
|
||||
cc_extra_len: u2,
|
||||
is_noinline: bool,
|
||||
_: u9 = 0,
|
||||
_: u7 = 0,
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -7538,6 +7553,20 @@ fn extraFuncType(tid: Zcu.PerThread.Id, extra: Local.Extra, extra_index: u32) Ke
|
|||
trail_index += 1;
|
||||
break :b x;
|
||||
};
|
||||
var cc = type_function.data.flags.cc.unpack();
|
||||
switch (cc) {
|
||||
.spirv_kernel, .spirv_task => |*kernel| {
|
||||
kernel.x = extra.view().items(.@"0")[trail_index];
|
||||
kernel.y = extra.view().items(.@"0")[trail_index + 1];
|
||||
kernel.z = extra.view().items(.@"0")[trail_index + 2];
|
||||
},
|
||||
.spirv_mesh => |*mesh| {
|
||||
mesh.max_primitives = extra.view().items(.@"0")[trail_index];
|
||||
mesh.max_vertices = extra.view().items(.@"0")[trail_index + 1];
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
trail_index += type_function.data.flags.cc_extra_len;
|
||||
return .{
|
||||
.param_types = .{
|
||||
.tid = tid,
|
||||
|
|
@ -7547,7 +7576,7 @@ fn extraFuncType(tid: Zcu.PerThread.Id, extra: Local.Extra, extra_index: u32) Ke
|
|||
.return_type = type_function.data.return_type,
|
||||
.comptime_bits = comptime_bits,
|
||||
.noalias_bits = noalias_bits,
|
||||
.cc = type_function.data.flags.cc.unpack(),
|
||||
.cc = cc,
|
||||
.is_var_args = type_function.data.flags.is_var_args,
|
||||
.is_noinline = type_function.data.flags.is_noinline,
|
||||
.is_generic = type_function.data.flags.is_generic,
|
||||
|
|
@ -9182,11 +9211,17 @@ pub fn getFuncType(
|
|||
// ask if it already exists, and if so, revert the lengths of the mutated
|
||||
// arrays. This is similar to what `getOrPutTrailingString` does.
|
||||
const prev_extra_len = extra.mutate.len;
|
||||
const cc_extra_len: u2 = if (key.cc) |cc| switch (cc) {
|
||||
.spirv_kernel, .spirv_task => 3,
|
||||
.spirv_mesh => 2,
|
||||
else => 0,
|
||||
} else 0;
|
||||
const params_len: u32 = @intCast(key.param_types.len);
|
||||
|
||||
try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeFunction).@"struct".fields.len +
|
||||
@intFromBool(key.comptime_bits != 0) +
|
||||
@intFromBool(key.noalias_bits != 0) +
|
||||
cc_extra_len +
|
||||
params_len);
|
||||
|
||||
const func_type_extra_index = addExtraAssumeCapacity(extra, Tag.TypeFunction{
|
||||
|
|
@ -9197,6 +9232,7 @@ pub fn getFuncType(
|
|||
.is_var_args = key.is_var_args,
|
||||
.has_comptime_bits = key.comptime_bits != 0,
|
||||
.has_noalias_bits = key.noalias_bits != 0,
|
||||
.cc_extra_len = cc_extra_len,
|
||||
.is_generic = key.is_generic,
|
||||
.is_noinline = key.is_noinline,
|
||||
},
|
||||
|
|
@ -9204,6 +9240,18 @@ pub fn getFuncType(
|
|||
|
||||
if (key.comptime_bits != 0) extra.appendAssumeCapacity(.{key.comptime_bits});
|
||||
if (key.noalias_bits != 0) extra.appendAssumeCapacity(.{key.noalias_bits});
|
||||
if (key.cc) |cc| switch (cc) {
|
||||
.spirv_kernel, .spirv_task => |kernel| extra.appendSliceAssumeCapacity(.{&.{
|
||||
kernel.x,
|
||||
kernel.y,
|
||||
kernel.z,
|
||||
}}),
|
||||
.spirv_mesh => |mesh| extra.appendSliceAssumeCapacity(.{&.{
|
||||
mesh.max_primitives,
|
||||
mesh.max_vertices,
|
||||
}}),
|
||||
else => {},
|
||||
};
|
||||
extra.appendSliceAssumeCapacity(.{@ptrCast(key.param_types)});
|
||||
errdefer extra.mutate.len = prev_extra_len;
|
||||
|
||||
|
|
@ -9458,6 +9506,7 @@ pub fn getFuncDeclIes(
|
|||
.is_var_args = key.is_var_args,
|
||||
.has_comptime_bits = key.comptime_bits != 0,
|
||||
.has_noalias_bits = key.noalias_bits != 0,
|
||||
.cc_extra_len = 0,
|
||||
.is_generic = key.is_generic,
|
||||
.is_noinline = key.is_noinline,
|
||||
},
|
||||
|
|
@ -9754,6 +9803,7 @@ pub fn getFuncInstanceIes(
|
|||
.is_var_args = false,
|
||||
.has_comptime_bits = false,
|
||||
.has_noalias_bits = arg.noalias_bits != 0,
|
||||
.cc_extra_len = 0,
|
||||
.is_generic = false,
|
||||
.is_noinline = arg.is_noinline,
|
||||
},
|
||||
|
|
@ -11225,7 +11275,8 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
|
|||
break :b @sizeOf(Tag.TypeFunction) +
|
||||
(@sizeOf(Index) * info.params_len) +
|
||||
(@as(u32, 4) * @intFromBool(info.flags.has_comptime_bits)) +
|
||||
(@as(u32, 4) * @intFromBool(info.flags.has_noalias_bits));
|
||||
(@as(u32, 4) * @intFromBool(info.flags.has_noalias_bits)) +
|
||||
(@as(u32, 4) * info.flags.cc_extra_len);
|
||||
},
|
||||
|
||||
.undef => 0,
|
||||
|
|
@ -12983,6 +13034,21 @@ const PackedCallingConvention = packed struct(u18) {
|
|||
.incoming_stack_alignment = .fromByteUnits(pl.incoming_stack_alignment orelse 0),
|
||||
.extra = @intFromEnum(pl.mode),
|
||||
},
|
||||
std.builtin.CallingConvention.SpirvKernelOptions => .{
|
||||
.tag = tag,
|
||||
.incoming_stack_alignment = .none, // unused
|
||||
.extra = 0, // unused
|
||||
},
|
||||
std.builtin.CallingConvention.SpirvFragmentOptions => .{
|
||||
.tag = tag,
|
||||
.incoming_stack_alignment = .none, // unused
|
||||
.extra = @as(u4, @intFromEnum(pl.depth_assumption)) << 1 | @intFromBool(pl.pixel_centered_integer),
|
||||
},
|
||||
std.builtin.CallingConvention.SpirvMeshOptions => .{
|
||||
.tag = tag,
|
||||
.incoming_stack_alignment = .none, // unused
|
||||
.extra = @intFromEnum(pl.stage_output),
|
||||
},
|
||||
std.builtin.CallingConvention.ShInterruptOptions => .{
|
||||
.tag = tag,
|
||||
.incoming_stack_alignment = .fromByteUnits(pl.incoming_stack_alignment orelse 0),
|
||||
|
|
@ -13027,6 +13093,20 @@ const PackedCallingConvention = packed struct(u18) {
|
|||
.incoming_stack_alignment = cc.incoming_stack_alignment.toByteUnits(),
|
||||
.mode = @enumFromInt(cc.extra),
|
||||
},
|
||||
std.builtin.CallingConvention.SpirvKernelOptions => .{
|
||||
.x = undefined, // Populated later
|
||||
.y = undefined, // Populated later
|
||||
.z = undefined, // Populated later
|
||||
},
|
||||
std.builtin.CallingConvention.SpirvFragmentOptions => .{
|
||||
.pixel_centered_integer = @bitCast(@as(u1, @truncate(cc.extra))),
|
||||
.depth_assumption = @enumFromInt(@as(u2, @truncate(cc.extra >> 1))),
|
||||
},
|
||||
std.builtin.CallingConvention.SpirvMeshOptions => .{
|
||||
.stage_output = @enumFromInt(cc.extra),
|
||||
.max_primitives = undefined, // Populated later
|
||||
.max_vertices = undefined, // Populated later
|
||||
},
|
||||
std.builtin.CallingConvention.ShInterruptOptions => .{
|
||||
.incoming_stack_alignment = cc.incoming_stack_alignment.toByteUnits(),
|
||||
.save = @enumFromInt(cc.extra),
|
||||
|
|
|
|||
15
src/Sema.zig
15
src/Sema.zig
|
|
@ -9379,6 +9379,8 @@ fn callConvIsCallable(cc: std.builtin.CallingConvention.Tag) bool {
|
|||
.spirv_kernel,
|
||||
.spirv_fragment,
|
||||
.spirv_vertex,
|
||||
.spirv_task,
|
||||
.spirv_mesh,
|
||||
=> false,
|
||||
|
||||
else => true,
|
||||
|
|
@ -30024,14 +30026,23 @@ fn callconvCoerceAllowed(
|
|||
switch (src_cc) {
|
||||
inline else => |src_data, tag| {
|
||||
const dest_data = @field(dest_cc, @tagName(tag));
|
||||
if (@TypeOf(src_data) != void) {
|
||||
if (@TypeOf(src_data) != void and
|
||||
@TypeOf(src_data) != std.builtin.CallingConvention.SpirvKernelOptions and
|
||||
@TypeOf(src_data) != std.builtin.CallingConvention.SpirvMeshOptions and
|
||||
@TypeOf(src_data) != std.builtin.CallingConvention.SpirvFragmentOptions)
|
||||
{
|
||||
const default_stack_align = target.stackAlignment();
|
||||
const src_stack_align = src_data.incoming_stack_alignment orelse default_stack_align;
|
||||
const dest_stack_align = src_data.incoming_stack_alignment orelse default_stack_align;
|
||||
if (dest_stack_align < src_stack_align) return false;
|
||||
}
|
||||
switch (@TypeOf(src_data)) {
|
||||
void, std.builtin.CallingConvention.CommonOptions => {},
|
||||
void,
|
||||
std.builtin.CallingConvention.CommonOptions,
|
||||
std.builtin.CallingConvention.SpirvKernelOptions,
|
||||
std.builtin.CallingConvention.SpirvMeshOptions,
|
||||
std.builtin.CallingConvention.SpirvFragmentOptions,
|
||||
=> {},
|
||||
std.builtin.CallingConvention.X86RegparmOptions => {
|
||||
if (src_data.register_params != dest_data.register_params) return false;
|
||||
},
|
||||
|
|
|
|||
|
|
@ -4563,7 +4563,7 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.builtin.CallingConvention) union(enu
|
|||
},
|
||||
.stage2_spirv => switch (cc) {
|
||||
.spirv_device, .spirv_kernel => true,
|
||||
.spirv_fragment, .spirv_vertex => target.os.tag == .vulkan or target.os.tag == .opengl,
|
||||
.spirv_fragment, .spirv_vertex, .spirv_task, .spirv_mesh => target.os.tag == .vulkan or target.os.tag == .opengl,
|
||||
else => false,
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -11768,7 +11768,11 @@ pub fn toLlvmCallConv(cc: std.builtin.CallingConvention, target: *const std.Targ
|
|||
const llvm_cc = toLlvmCallConvTag(cc, target) orelse return null;
|
||||
const incoming_stack_alignment: ?u64, const register_params: u2 = switch (cc) {
|
||||
inline else => |pl| switch (@TypeOf(pl)) {
|
||||
void => .{ null, 0 },
|
||||
void,
|
||||
std.builtin.CallingConvention.SpirvKernelOptions,
|
||||
std.builtin.CallingConvention.SpirvMeshOptions,
|
||||
std.builtin.CallingConvention.SpirvFragmentOptions,
|
||||
=> .{ null, 0 },
|
||||
std.builtin.CallingConvention.ArcInterruptOptions,
|
||||
std.builtin.CallingConvention.ArmInterruptOptions,
|
||||
std.builtin.CallingConvention.RiscvInterruptOptions,
|
||||
|
|
@ -11917,6 +11921,8 @@ fn toLlvmCallConvTag(cc_tag: std.builtin.CallingConvention.Tag, target: *const s
|
|||
.spirv_kernel,
|
||||
.spirv_fragment,
|
||||
.spirv_vertex,
|
||||
.spirv_task,
|
||||
.spirv_mesh,
|
||||
=> null,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -168,14 +168,10 @@ fn processInstruction(ass: *Assembler) !void {
|
|||
return ass.fail(ass.currentToken().start, "cannot set execution mode in assembly", .{});
|
||||
},
|
||||
.OpCapability => {
|
||||
try module.addCapability(@enumFromInt(ass.inst.operands.items[0].value));
|
||||
return;
|
||||
return ass.fail(ass.currentToken().start, "cannot set capability in assembly", .{});
|
||||
},
|
||||
.OpExtension => {
|
||||
const ext_name_offset = ass.inst.operands.items[0].string;
|
||||
const ext_name = std.mem.sliceTo(ass.inst.string_bytes.items[ext_name_offset..], 0);
|
||||
try module.addExtension(ext_name);
|
||||
return;
|
||||
return ass.fail(ass.currentToken().start, "cannot set extension in assembly", .{});
|
||||
},
|
||||
.OpExtInstImport => blk: {
|
||||
const set_name_offset = ass.inst.operands.items[1].string;
|
||||
|
|
|
|||
|
|
@ -1425,6 +1425,8 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id {
|
|||
.spirv_fragment,
|
||||
.spirv_vertex,
|
||||
.spirv_device,
|
||||
.spirv_task,
|
||||
.spirv_mesh,
|
||||
=> {},
|
||||
else => unreachable,
|
||||
}
|
||||
|
|
@ -2517,13 +2519,11 @@ fn generateTestEntryPoint(
|
|||
// point name is the same as a different OpName.
|
||||
const test_name = try std.fmt.allocPrint(cg.module.arena, "test {s}", .{name});
|
||||
|
||||
const execution_mode: spec.ExecutionModel = switch (target.os.tag) {
|
||||
.vulkan, .opengl => .gl_compute,
|
||||
.opencl, .amdhsa => .kernel,
|
||||
else => unreachable,
|
||||
};
|
||||
|
||||
try cg.module.declareEntryPoint(spv_decl_index, test_name, execution_mode, null);
|
||||
try cg.module.declareEntryPoint(
|
||||
spv_decl_index,
|
||||
test_name,
|
||||
.{ .spirv_kernel = .{ .x = 1, .y = 1, .z = 1 } },
|
||||
);
|
||||
}
|
||||
|
||||
fn intFromBool(cg: *CodeGen, value: Temporary, result_ty: Type) !Temporary {
|
||||
|
|
|
|||
|
|
@ -61,8 +61,8 @@ cache: struct {
|
|||
struct_types: std.ArrayHashMapUnmanaged(StructType, Id, StructType.HashContext, true) = .empty,
|
||||
fn_types: std.ArrayHashMapUnmanaged(FnType, Id, FnType.HashContext, true) = .empty,
|
||||
|
||||
capabilities: std.AutoHashMapUnmanaged(spec.Capability, void) = .empty,
|
||||
extensions: std.StringHashMapUnmanaged(void) = .empty,
|
||||
capabilities: std.EnumSet(spec.Capability) = .initEmpty(),
|
||||
extensions: std.EnumSet(spec.Extension) = .initEmpty(),
|
||||
extended_instruction_set: std.AutoHashMapUnmanaged(spec.InstructionSet, Id) = .empty,
|
||||
decorations: std.AutoHashMapUnmanaged(struct { Id, spec.Decoration }, void) = .empty,
|
||||
builtins: std.AutoHashMapUnmanaged(struct { spec.BuiltIn, spec.StorageClass }, Decl.Index) = .empty,
|
||||
|
|
@ -130,15 +130,10 @@ pub const Decl = struct {
|
|||
end_dep: usize = 0,
|
||||
};
|
||||
|
||||
/// This models a kernel entry point.
|
||||
pub const EntryPoint = struct {
|
||||
/// The declaration that should be exported.
|
||||
decl_index: Decl.Index,
|
||||
/// The name of the kernel to be exported.
|
||||
name: []const u8,
|
||||
/// Calling Convention
|
||||
exec_model: spec.ExecutionModel,
|
||||
exec_mode: ?spec.ExecutionMode = null,
|
||||
cc: std.builtin.CallingConvention,
|
||||
};
|
||||
|
||||
const StructType = struct {
|
||||
|
|
@ -229,8 +224,6 @@ pub fn deinit(module: *Module) void {
|
|||
module.cache.array_types.deinit(module.gpa);
|
||||
module.cache.struct_types.deinit(module.gpa);
|
||||
module.cache.fn_types.deinit(module.gpa);
|
||||
module.cache.capabilities.deinit(module.gpa);
|
||||
module.cache.extensions.deinit(module.gpa);
|
||||
module.cache.extended_instruction_set.deinit(module.gpa);
|
||||
module.cache.decorations.deinit(module.gpa);
|
||||
module.cache.builtins.deinit(module.gpa);
|
||||
|
|
@ -317,25 +310,108 @@ fn entryPoints(module: *Module) !Section {
|
|||
interface.items.len = 0;
|
||||
seen.setRangeValue(.{ .start = 0, .end = module.decls.items.len }, false);
|
||||
|
||||
const exec_model: spec.ExecutionModel = switch (target.os.tag) {
|
||||
.vulkan, .opengl => switch (entry_point.cc) {
|
||||
.spirv_vertex => .vertex,
|
||||
.spirv_fragment => .fragment,
|
||||
.spirv_kernel => .gl_compute,
|
||||
.spirv_task => .task_ext,
|
||||
.spirv_mesh => .mesh_ext,
|
||||
// TODO: We should integrate with the Linkage capability and export this function
|
||||
.spirv_device => continue,
|
||||
else => unreachable,
|
||||
},
|
||||
.opencl => switch (entry_point.cc) {
|
||||
.spirv_kernel => .kernel,
|
||||
// TODO: We should integrate with the Linkage capability and export this function
|
||||
.spirv_device => continue,
|
||||
else => unreachable,
|
||||
},
|
||||
else => unreachable,
|
||||
};
|
||||
try module.addEntryPointDeps(entry_point.decl_index, &seen, &interface);
|
||||
try entry_points.emit(module.gpa, .OpEntryPoint, .{
|
||||
.execution_model = entry_point.exec_model,
|
||||
.execution_model = exec_model,
|
||||
.entry_point = entry_point_id,
|
||||
.name = entry_point.name,
|
||||
.interface = interface.items,
|
||||
});
|
||||
|
||||
if (entry_point.exec_mode == null and entry_point.exec_model == .fragment) {
|
||||
switch (target.os.tag) {
|
||||
.vulkan, .opengl => |tag| {
|
||||
switch (entry_point.cc) {
|
||||
.spirv_kernel, .spirv_task => |kernel| {
|
||||
try module.sections.execution_modes.emit(module.gpa, .OpExecutionMode, .{
|
||||
.entry_point = entry_point_id,
|
||||
.mode = .{ .local_size = .{
|
||||
.x_size = kernel.x,
|
||||
.y_size = kernel.y,
|
||||
.z_size = kernel.z,
|
||||
} },
|
||||
});
|
||||
},
|
||||
.spirv_fragment => |fragment| {
|
||||
if (fragment.pixel_centered_integer and target.os.tag != .vulkan) {
|
||||
try module.sections.execution_modes.emit(module.gpa, .OpExecutionMode, .{
|
||||
.entry_point = entry_point_id,
|
||||
.mode = if (tag == .vulkan) .origin_upper_left else .origin_lower_left,
|
||||
.mode = .pixel_center_integer,
|
||||
});
|
||||
},
|
||||
.opencl => {},
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
try module.sections.execution_modes.emit(module.gpa, .OpExecutionMode, .{
|
||||
.entry_point = entry_point_id,
|
||||
.mode = if (target.os.tag == .vulkan) .origin_upper_left else .origin_lower_left,
|
||||
});
|
||||
switch (fragment.depth_assumption) {
|
||||
.none => {},
|
||||
.greater => {
|
||||
try module.sections.execution_modes.emit(module.gpa, .OpExecutionMode, .{
|
||||
.entry_point = entry_point_id,
|
||||
.mode = .depth_greater,
|
||||
});
|
||||
},
|
||||
.less => {
|
||||
try module.sections.execution_modes.emit(module.gpa, .OpExecutionMode, .{
|
||||
.entry_point = entry_point_id,
|
||||
.mode = .depth_less,
|
||||
});
|
||||
},
|
||||
.unchanged => {
|
||||
try module.sections.execution_modes.emit(module.gpa, .OpExecutionMode, .{
|
||||
.entry_point = entry_point_id,
|
||||
.mode = .depth_unchanged,
|
||||
});
|
||||
},
|
||||
}
|
||||
},
|
||||
.spirv_mesh => |mesh| {
|
||||
try module.sections.execution_modes.emit(module.gpa, .OpExecutionMode, .{
|
||||
.entry_point = entry_point_id,
|
||||
.mode = .{ .output_vertices = .{ .vertex_count = mesh.max_vertices } },
|
||||
});
|
||||
try module.sections.execution_modes.emit(module.gpa, .OpExecutionMode, .{
|
||||
.entry_point = entry_point_id,
|
||||
.mode = .{ .output_primitives_ext = .{ .primitive_count = mesh.max_primitives } },
|
||||
});
|
||||
switch (mesh.stage_output) {
|
||||
.output_points => {
|
||||
try module.sections.execution_modes.emit(module.gpa, .OpExecutionMode, .{
|
||||
.entry_point = entry_point_id,
|
||||
.mode = .output_points,
|
||||
});
|
||||
},
|
||||
.output_lines => {
|
||||
try module.sections.execution_modes.emit(module.gpa, .OpExecutionMode, .{
|
||||
.entry_point = entry_point_id,
|
||||
.mode = .output_lines_ext,
|
||||
});
|
||||
},
|
||||
.output_triangles => {
|
||||
try module.sections.execution_modes.emit(module.gpa, .OpExecutionMode, .{
|
||||
.entry_point = entry_point_id,
|
||||
.mode = .output_triangles_ext,
|
||||
});
|
||||
},
|
||||
}
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -355,7 +431,7 @@ pub fn finalize(module: *Module, gpa: Allocator) ![]Word {
|
|||
try module.addCapability(.shader);
|
||||
try module.addCapability(.matrix);
|
||||
if (target.cpu.arch == .spirv64) {
|
||||
try module.addExtension("SPV_KHR_physical_storage_buffer");
|
||||
try module.addExtension(.SPV_KHR_physical_storage_buffer);
|
||||
try module.addCapability(.physical_storage_buffer_addresses);
|
||||
}
|
||||
},
|
||||
|
|
@ -366,27 +442,24 @@ pub fn finalize(module: *Module, gpa: Allocator) ![]Word {
|
|||
else => unreachable,
|
||||
}
|
||||
if (target.cpu.arch == .spirv64) try module.addCapability(.int64);
|
||||
if (target.cpu.has(.spirv, .int64)) try module.addCapability(.int64);
|
||||
if (target.cpu.has(.spirv, .float16)) {
|
||||
if (target.os.tag == .opencl) try module.addExtension("cl_khr_fp16");
|
||||
try module.addCapability(.float16);
|
||||
inline for (@typeInfo(spec.Capability).@"enum".fields) |field| {
|
||||
if (target.cpu.has(.spirv, std.meta.stringToEnum(std.Target.spirv.Feature, field.name).?)) {
|
||||
try module.addCapability(@enumFromInt(field.value));
|
||||
}
|
||||
}
|
||||
if (target.cpu.has(.spirv, .float64)) try module.addCapability(.float64);
|
||||
if (target.cpu.has(.spirv, .generic_pointer)) try module.addCapability(.generic_pointer);
|
||||
if (target.cpu.has(.spirv, .vector16)) try module.addCapability(.vector16);
|
||||
if (target.cpu.has(.spirv, .storage_push_constant16)) {
|
||||
try module.addExtension("SPV_KHR_16bit_storage");
|
||||
try module.addCapability(.storage_push_constant16);
|
||||
}
|
||||
if (target.cpu.has(.spirv, .arbitrary_precision_integers)) {
|
||||
try module.addExtension("SPV_INTEL_arbitrary_precision_integers");
|
||||
try module.addCapability(.arbitrary_precision_integers_intel);
|
||||
}
|
||||
if (target.cpu.has(.spirv, .variable_pointers)) {
|
||||
try module.addExtension("SPV_KHR_variable_pointers");
|
||||
try module.addCapability(.variable_pointers_storage_buffer);
|
||||
try module.addCapability(.variable_pointers);
|
||||
|
||||
inline for (@typeInfo(spec.Extension).@"enum".fields) |field| {
|
||||
const ext: spec.Extension = @enumFromInt(field.value);
|
||||
switch (ext) {
|
||||
.v1_0, .v1_1, .v1_2, .v1_3, .v1_4, .v1_5, .v1_6 => continue,
|
||||
else => {
|
||||
if (target.cpu.has(.spirv, std.meta.stringToEnum(std.Target.spirv.Feature, field.name).?)) {
|
||||
try module.addExtension(ext);
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// These are well supported
|
||||
try module.addCapability(.int8);
|
||||
try module.addCapability(.int16);
|
||||
|
|
@ -490,15 +563,15 @@ pub fn finalize(module: *Module, gpa: Allocator) ![]Word {
|
|||
}
|
||||
|
||||
pub fn addCapability(module: *Module, cap: spec.Capability) !void {
|
||||
const entry = try module.cache.capabilities.getOrPut(module.gpa, cap);
|
||||
if (entry.found_existing) return;
|
||||
if (module.cache.capabilities.contains(cap)) return;
|
||||
module.cache.capabilities.insert(cap);
|
||||
try module.sections.capabilities.emit(module.gpa, .OpCapability, .{ .capability = cap });
|
||||
}
|
||||
|
||||
pub fn addExtension(module: *Module, ext: []const u8) !void {
|
||||
const entry = try module.cache.extensions.getOrPut(module.gpa, ext);
|
||||
if (entry.found_existing) return;
|
||||
try module.sections.extensions.emit(module.gpa, .OpExtension, .{ .name = ext });
|
||||
pub fn addExtension(module: *Module, ext: spec.Extension) !void {
|
||||
if (module.cache.extensions.contains(ext)) return;
|
||||
module.cache.extensions.insert(ext);
|
||||
try module.sections.extensions.emit(module.gpa, .OpExtension, .{ .name = @tagName(ext) });
|
||||
}
|
||||
|
||||
/// Imports or returns the existing id of an extended instruction set
|
||||
|
|
@ -558,7 +631,7 @@ pub fn backingIntBits(module: *Module, bits: u16) struct { u16, bool } {
|
|||
assert(bits != 0);
|
||||
const target = module.zcu.getTarget();
|
||||
|
||||
if (target.cpu.has(.spirv, .arbitrary_precision_integers) and bits <= 32) {
|
||||
if (target.cpu.has(.spirv, .arbitrary_precision_integers_intel) and bits <= 32) {
|
||||
return .{ bits, false };
|
||||
}
|
||||
|
||||
|
|
@ -871,15 +944,12 @@ pub fn declareEntryPoint(
|
|||
module: *Module,
|
||||
decl_index: Decl.Index,
|
||||
name: []const u8,
|
||||
exec_model: spec.ExecutionModel,
|
||||
exec_mode: ?spec.ExecutionMode,
|
||||
cc: std.builtin.CallingConvention,
|
||||
) !void {
|
||||
const gop = try module.entry_points.getOrPut(module.gpa, module.declPtr(decl_index).result_id);
|
||||
gop.value_ptr.decl_index = decl_index;
|
||||
gop.value_ptr.name = name;
|
||||
gop.value_ptr.exec_model = exec_model;
|
||||
// Might've been set by assembler
|
||||
if (!gop.found_existing) gop.value_ptr.exec_mode = exec_mode;
|
||||
gop.value_ptr.cc = cc;
|
||||
}
|
||||
|
||||
pub fn debugName(module: *Module, target: Id, name: []const u8) !void {
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -189,35 +189,15 @@ pub fn updateExports(
|
|||
},
|
||||
};
|
||||
const nav_ty = ip.getNav(nav_index).typeOf(ip);
|
||||
const target = zcu.getTarget();
|
||||
if (ip.isFunctionType(nav_ty)) {
|
||||
const spv_decl_index = try linker.module.resolveNav(ip, nav_index);
|
||||
const cc = Type.fromInterned(nav_ty).fnCallingConvention(zcu);
|
||||
const exec_model: spec.ExecutionModel = switch (target.os.tag) {
|
||||
.vulkan, .opengl => switch (cc) {
|
||||
.spirv_vertex => .vertex,
|
||||
.spirv_fragment => .fragment,
|
||||
.spirv_kernel => .gl_compute,
|
||||
// TODO: We should integrate with the Linkage capability and export this function
|
||||
.spirv_device => return,
|
||||
else => unreachable,
|
||||
},
|
||||
.opencl => switch (cc) {
|
||||
.spirv_kernel => .kernel,
|
||||
// TODO: We should integrate with the Linkage capability and export this function
|
||||
.spirv_device => return,
|
||||
else => unreachable,
|
||||
},
|
||||
else => unreachable,
|
||||
};
|
||||
|
||||
for (export_indices) |export_idx| {
|
||||
const exp = export_idx.ptr(zcu);
|
||||
try linker.module.declareEntryPoint(
|
||||
spv_decl_index,
|
||||
exp.opts.name.toSlice(ip),
|
||||
exec_model,
|
||||
null,
|
||||
cc,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,10 @@ pub fn build(b: *std.Build) void {
|
|||
const tools_tests_step = b.step("standalone_test_cases.tools", "Test tools");
|
||||
step.dependOn(tools_tests_step);
|
||||
const tools_target = b.resolveTargetQuery(.{});
|
||||
const spirv_spec = b.createModule(.{
|
||||
.root_source_file = b.path("../../src/codegen/spirv/spec.zig"),
|
||||
.target = tools_target,
|
||||
});
|
||||
for ([_][]const u8{
|
||||
// Alphabetically sorted. No need to build `tools/spirv/grammar.zig`.
|
||||
"../../tools/dump-cov.zig",
|
||||
|
|
@ -60,6 +64,9 @@ pub fn build(b: *std.Build) void {
|
|||
.target = tools_target,
|
||||
}),
|
||||
});
|
||||
if (std.mem.endsWith(u8, tool_src_path, "update_cpu_features.zig")) {
|
||||
tool.root_module.addImport("spirv_spec", spirv_spec);
|
||||
}
|
||||
tools_tests_step.dependOn(&tool.step);
|
||||
}
|
||||
for ([_][]const u8{
|
||||
|
|
|
|||
|
|
@ -323,6 +323,38 @@ fn render(
|
|||
|
||||
try renderOperandKinds(writer, all_operand_kinds.values(), extended_structs);
|
||||
try renderInstructionSet(writer, registry, extensions, all_operand_kinds);
|
||||
try renderExtension(writer, all_operand_kinds.values());
|
||||
}
|
||||
|
||||
fn renderExtension(writer: anytype, kinds: []const OperandKind) !void {
|
||||
try writer.writeAll(
|
||||
\\pub const Extension = enum {
|
||||
\\v1_0,
|
||||
\\v1_1,
|
||||
\\v1_2,
|
||||
\\v1_3,
|
||||
\\v1_4,
|
||||
\\v1_5,
|
||||
\\v1_6,
|
||||
\\
|
||||
);
|
||||
|
||||
var seen_extensions = std.StringHashMap(void).init(allocator);
|
||||
defer seen_extensions.deinit();
|
||||
|
||||
for (kinds) |kind| {
|
||||
if (std.mem.eql(u8, "Capability", kind.kind)) {
|
||||
for (kind.enumerants.?) |enumerant| {
|
||||
for (enumerant.extensions) |ext| {
|
||||
if (seen_extensions.contains(ext)) continue;
|
||||
try seen_extensions.put(ext, {});
|
||||
|
||||
try writer.print("{s},\n", .{ext});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
try writer.writeAll("};\n");
|
||||
}
|
||||
|
||||
fn renderInstructionSet(
|
||||
|
|
@ -704,6 +736,39 @@ fn renderValueEnum(
|
|||
});
|
||||
}
|
||||
|
||||
if (std.mem.eql(u8, "Capability", enumeration.kind)) {
|
||||
try writer.writeAll(
|
||||
\\
|
||||
\\pub fn dependencies(self: Capability) []const Extension {
|
||||
\\ return switch (self) {
|
||||
);
|
||||
|
||||
for (enum_indices) |i| {
|
||||
const enumerant = enumerants[i];
|
||||
|
||||
// Convert version to enum.
|
||||
// None is for reserved
|
||||
// Example: "None" -> .v1_0
|
||||
// Example: "1.5" -> .v1_5
|
||||
const enum_version = enumerant.version.?;
|
||||
const version: [4]u8 = .{ 'v', '1', '_', if (enum_version[0] == 'N') '0' else enum_version[2] };
|
||||
|
||||
try writer.print("\n.{f} => &.{{.{s},", .{ formatId(enumerant.enumerant), version });
|
||||
for (enumerant.extensions) |extension| {
|
||||
try writer.print(".{s},", .{extension});
|
||||
}
|
||||
try writer.writeAll("},");
|
||||
}
|
||||
|
||||
try writer.writeAll(
|
||||
\\};
|
||||
\\}
|
||||
\\};
|
||||
\\
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!extended_structs.contains(enumeration.kind)) {
|
||||
try writer.writeAll("};\n");
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const spirv_spec = @import("spirv_spec");
|
||||
const fs = std.fs;
|
||||
const mem = std.mem;
|
||||
const json = std.json;
|
||||
|
|
@ -1367,83 +1368,7 @@ const targets = [_]ArchTarget{
|
|||
.td_name = "SPIRV",
|
||||
},
|
||||
.branch_quota = 2000,
|
||||
.extra_features = &.{
|
||||
.{
|
||||
.zig_name = "v1_0",
|
||||
.desc = "Enable version 1.0",
|
||||
.deps = &.{},
|
||||
},
|
||||
.{
|
||||
.zig_name = "v1_1",
|
||||
.desc = "Enable version 1.1",
|
||||
.deps = &.{"v1_0"},
|
||||
},
|
||||
.{
|
||||
.zig_name = "v1_2",
|
||||
.desc = "Enable version 1.2",
|
||||
.deps = &.{"v1_1"},
|
||||
},
|
||||
.{
|
||||
.zig_name = "v1_3",
|
||||
.desc = "Enable version 1.3",
|
||||
.deps = &.{"v1_2"},
|
||||
},
|
||||
.{
|
||||
.zig_name = "v1_4",
|
||||
.desc = "Enable version 1.4",
|
||||
.deps = &.{"v1_3"},
|
||||
},
|
||||
.{
|
||||
.zig_name = "v1_5",
|
||||
.desc = "Enable version 1.5",
|
||||
.deps = &.{"v1_4"},
|
||||
},
|
||||
.{
|
||||
.zig_name = "v1_6",
|
||||
.desc = "Enable version 1.6",
|
||||
.deps = &.{"v1_5"},
|
||||
},
|
||||
.{
|
||||
.zig_name = "int64",
|
||||
.desc = "Enable Int64 capability",
|
||||
.deps = &.{"v1_0"},
|
||||
},
|
||||
.{
|
||||
.zig_name = "float16",
|
||||
.desc = "Enable Float16 capability",
|
||||
.deps = &.{"v1_0"},
|
||||
},
|
||||
.{
|
||||
.zig_name = "float64",
|
||||
.desc = "Enable Float64 capability",
|
||||
.deps = &.{"v1_0"},
|
||||
},
|
||||
.{
|
||||
.zig_name = "storage_push_constant16",
|
||||
.desc = "Enable SPV_KHR_16bit_storage extension and the StoragePushConstant16 capability",
|
||||
.deps = &.{"v1_3"},
|
||||
},
|
||||
.{
|
||||
.zig_name = "arbitrary_precision_integers",
|
||||
.desc = "Enable SPV_INTEL_arbitrary_precision_integers extension and the ArbitraryPrecisionIntegersINTEL capability",
|
||||
.deps = &.{"v1_5"},
|
||||
},
|
||||
.{
|
||||
.zig_name = "generic_pointer",
|
||||
.desc = "Enable GenericPointer capability",
|
||||
.deps = &.{"v1_0"},
|
||||
},
|
||||
.{
|
||||
.zig_name = "vector16",
|
||||
.desc = "Enable Vector16 capability",
|
||||
.deps = &.{"v1_0"},
|
||||
},
|
||||
.{
|
||||
.zig_name = "variable_pointers",
|
||||
.desc = "Enable SPV_KHR_physical_storage_buffer extension and the PhysicalStorageBufferAddresses capability",
|
||||
.deps = &.{"v1_0"},
|
||||
},
|
||||
},
|
||||
.extra_features = spirvFeatures(),
|
||||
.extra_cpus = &.{
|
||||
.{
|
||||
.llvm_name = null,
|
||||
|
|
@ -2439,6 +2364,41 @@ fn usageAndExit(arg0: []const u8, code: u8) noreturn {
|
|||
std.process.exit(code);
|
||||
}
|
||||
|
||||
fn spirvFeatures() []const Feature {
|
||||
const cap_fields = @typeInfo(spirv_spec.Capability).@"enum".fields;
|
||||
const ext_fields = @typeInfo(spirv_spec.Extension).@"enum".fields;
|
||||
|
||||
var out_feature: [cap_fields.len + ext_fields.len]Feature = undefined;
|
||||
|
||||
@setEvalBranchQuota(2000);
|
||||
for (cap_fields, out_feature[0..cap_fields.len]) |field, *feature| {
|
||||
feature.* = .{
|
||||
.zig_name = field.name,
|
||||
.desc = "Enable " ++ field.name ++ " Capability.",
|
||||
.deps = comptime res: {
|
||||
const extensions = spirv_spec.Capability.dependencies(@enumFromInt(field.value));
|
||||
var out_extensions: [extensions.len][]const u8 = undefined;
|
||||
for (extensions, 0..) |ext, i| {
|
||||
out_extensions[i] = @tagName(ext);
|
||||
}
|
||||
const final_extensions = out_extensions;
|
||||
break :res &final_extensions;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
for (ext_fields, out_feature[cap_fields.len..]) |field, *feature| {
|
||||
feature.* = .{
|
||||
.zig_name = field.name,
|
||||
.desc = "Enable " ++ field.name ++ " Extension.",
|
||||
.deps = &.{},
|
||||
};
|
||||
}
|
||||
|
||||
const final = out_feature;
|
||||
return &final;
|
||||
}
|
||||
|
||||
fn featureLessThan(_: void, a: Feature, b: Feature) bool {
|
||||
return std.ascii.lessThanIgnoreCase(a.zig_name, b.zig_name);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue