From 29e46633ce29e5325049dd1835c1c0bde0f6d79e Mon Sep 17 00:00:00 2001 From: Ali Cheraghi Date: Sat, 15 Feb 2025 23:03:59 +0330 Subject: spirv: cache more types & merge constructX functions --- src/codegen/spirv.zig | 406 +++++++++++++++++--------------------------------- 1 file changed, 134 insertions(+), 272 deletions(-) (limited to 'src/codegen/spirv.zig') diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index e1baf20156..8c4b0478de 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -159,7 +159,7 @@ pub const Object = struct { uav_link: std.AutoHashMapUnmanaged(struct { InternPool.Index, StorageClass }, SpvModule.Decl.Index) = .empty, /// A map that maps AIR intern pool indices to SPIR-V result-ids. - intern_map: InternMap = .{}, + intern_map: InternMap = .empty, /// This map serves a dual purpose: /// - It keeps track of pointers that are currently being emitted, so that we can tell @@ -314,7 +314,7 @@ const NavGen = struct { next_arg_index: u32 = 0, /// A map keeping track of which instruction generated which result-id. - inst_results: InstMap = .{}, + inst_results: InstMap = .empty, /// A map that maps AIR intern pool indices to SPIR-V result-ids. /// See `Object.intern_map`. @@ -469,7 +469,7 @@ const NavGen = struct { const zcu = self.pt.zcu; const ty = Type.fromInterned(zcu.intern_pool.typeOf(val)); - const decl_ptr_ty_id = try self.ptrType(ty, .Generic); + const decl_ptr_ty_id = try self.ptrType(ty, .Generic, .indirect); const spv_decl_index = blk: { const entry = try self.object.uav_link.getOrPut(self.object.gpa, .{ val, .Function }); @@ -532,7 +532,7 @@ const NavGen = struct { try self.spv.debugNameFmt(initializer_id, "initializer of __anon_{d}", .{@intFromEnum(val)}); - const fn_decl_ptr_ty_id = try self.ptrType(ty, .Function); + const fn_decl_ptr_ty_id = try self.ptrType(ty, .Function, .indirect); try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpExtInst, .{ .id_result_type = fn_decl_ptr_ty_id, .id_result = result_id, @@ -721,36 +721,16 @@ const NavGen = struct { /// Emits a bool constant in a particular representation. fn constBool(self: *NavGen, value: bool, repr: Repr) !IdRef { - // TODO: Cache? - - const section = &self.spv.sections.types_globals_constants; - switch (repr) { - .indirect => { - return try self.constInt(Type.u1, @intFromBool(value), .indirect); - }, - .direct => { - const result_ty_id = try self.resolveType(Type.bool, .direct); - const result_id = self.spv.allocId(); - switch (value) { - inline else => |val_ct| try section.emit( - self.spv.gpa, - if (val_ct) .OpConstantTrue else .OpConstantFalse, - .{ - .id_result_type = result_ty_id, - .id_result = result_id, - }, - ), - } - return result_id; - }, - } + return switch (repr) { + .indirect => self.constInt(Type.u1, @intFromBool(value)), + .direct => self.spv.constBool(value), + }; } /// Emits an integer constant. /// This function, unlike SpvModule.constInt, takes care to bitcast /// the value to an unsigned int first for Kernels. - fn constInt(self: *NavGen, ty: Type, value: anytype, repr: Repr) !IdRef { - // TODO: Cache? + fn constInt(self: *NavGen, ty: Type, value: anytype) !IdRef { const zcu = self.pt.zcu; const scalar_ty = ty.scalarType(zcu); const int_info = scalar_ty.intInfo(zcu); @@ -763,18 +743,18 @@ const NavGen = struct { else => unreachable, }; - const bits: u64 = switch (signedness) { + const value64: u64 = switch (signedness) { .signed => @bitCast(@as(i64, @intCast(value))), .unsigned => @as(u64, @intCast(value)), }; // Manually truncate the value to the right amount of bits. - const truncated_bits = if (backing_bits == 64) - bits + const truncated_value = if (backing_bits == 64) + value64 else - bits & (@as(u64, 1) << @intCast(backing_bits)) - 1; + value64 & (@as(u64, 1) << @intCast(backing_bits)) - 1; - const result_ty_id = try self.resolveType(scalar_ty, repr); + const result_ty_id = try self.resolveType(scalar_ty, .indirect); const result_id = self.spv.allocId(); const section = &self.spv.sections.types_globals_constants; @@ -783,100 +763,42 @@ const NavGen = struct { 1...32 => try section.emit(self.spv.gpa, .OpConstant, .{ .id_result_type = result_ty_id, .id_result = result_id, - .value = .{ .uint32 = @truncate(truncated_bits) }, + .value = .{ .uint32 = @truncate(truncated_value) }, }), 33...64 => try section.emit(self.spv.gpa, .OpConstant, .{ .id_result_type = result_ty_id, .id_result = result_id, - .value = .{ .uint64 = truncated_bits }, + .value = .{ .uint64 = truncated_value }, }), else => unreachable, // TODO: Large integer constants } - if (!ty.isVector(zcu)) { - return result_id; - } - - const n = ty.vectorLen(zcu); - const ids = try self.gpa.alloc(IdRef, n); - defer self.gpa.free(ids); - @memset(ids, result_id); - - const vec_ty_id = try self.resolveType(ty, repr); - const vec_result_id = self.spv.allocId(); - try self.func.body.emit(self.spv.gpa, .OpCompositeConstruct, .{ - .id_result_type = vec_ty_id, - .id_result = vec_result_id, - .constituents = ids, - }); - return vec_result_id; + if (!ty.isVector(zcu)) return result_id; + return self.constructCompositeSplat(ty, result_id); } - /// Construct a struct at runtime. - /// ty must be a struct type. - /// Constituents should be in `indirect` representation (as the elements of a struct should be). - /// Result is in `direct` representation. - fn constructStruct(self: *NavGen, ty: Type, types: []const Type, constituents: []const IdRef) !IdRef { - assert(types.len == constituents.len); - + pub fn constructComposite(self: *NavGen, result_ty_id: IdRef, constituents: []const IdRef) !IdRef { const result_id = self.spv.allocId(); - try self.func.body.emit(self.spv.gpa, .OpCompositeConstruct, .{ - .id_result_type = try self.resolveType(ty, .direct), - .id_result = result_id, - .constituents = constituents, - }); - return result_id; - } - - /// Construct a vector at runtime. - /// ty must be an vector type. - fn constructVector(self: *NavGen, ty: Type, constituents: []const IdRef) !IdRef { - const zcu = self.pt.zcu; - assert(ty.vectorLen(zcu) == constituents.len); - - // Note: older versions of the Khronos SPRIV-LLVM translator crash on this instruction - // because it cannot construct structs which' operands are not constant. - // See https://github.com/KhronosGroup/SPIRV-LLVM-Translator/issues/1349 - // Currently this is the case for Intel OpenCL CPU runtime (2023-WW46), but the - // alternatives dont work properly: - // - using temporaries/pointers doesn't work properly with vectors of bool, causes - // backends that use llvm to crash - // - using OpVectorInsertDynamic doesn't work for non-spirv-vectors of bool. - - const result_id = self.spv.allocId(); - try self.func.body.emit(self.spv.gpa, .OpCompositeConstruct, .{ - .id_result_type = try self.resolveType(ty, .direct), + try self.func.body.emit(self.gpa, .OpCompositeConstruct, .{ + .id_result_type = result_ty_id, .id_result = result_id, .constituents = constituents, }); return result_id; } - /// Construct a vector at runtime with all lanes set to the same value. - /// ty must be an vector type. - fn constructVectorSplat(self: *NavGen, ty: Type, constituent: IdRef) !IdRef { + /// Construct a composite at runtime with all lanes set to the same value. + /// ty must be an aggregate type. + fn constructCompositeSplat(self: *NavGen, ty: Type, constituent: IdRef) !IdRef { const zcu = self.pt.zcu; - const n = ty.vectorLen(zcu); + const n = ty.arrayLen(zcu); const constituents = try self.gpa.alloc(IdRef, n); defer self.gpa.free(constituents); @memset(constituents, constituent); - return try self.constructVector(ty, constituents); - } - - /// Construct an array at runtime. - /// ty must be an array type. - /// Constituents should be in `indirect` representation (as the elements of an array should be). - /// Result is in `direct` representation. - fn constructArray(self: *NavGen, ty: Type, constituents: []const IdRef) !IdRef { - const result_id = self.spv.allocId(); - try self.func.body.emit(self.spv.gpa, .OpCompositeConstruct, .{ - .id_result_type = try self.resolveType(ty, .direct), - .id_result = result_id, - .constituents = constituents, - }); - return result_id; + const result_ty_id = try self.resolveType(ty, .direct); + return self.constructComposite(result_ty_id, constituents); } /// This function generates a load for a constant in direct (ie, non-memory) representation. @@ -947,9 +869,9 @@ const NavGen = struct { }, .int => { if (ty.isSignedInt(zcu)) { - break :cache try self.constInt(ty, val.toSignedInt(zcu), repr); + break :cache try self.constInt(ty, val.toSignedInt(zcu)); } else { - break :cache try self.constInt(ty, val.toUnsignedInt(zcu), repr); + break :cache try self.constInt(ty, val.toUnsignedInt(zcu)); } }, .float => { @@ -970,7 +892,7 @@ const NavGen = struct { }, .err => |err| { const value = try pt.getErrorValue(err.name); - break :cache try self.constInt(ty, value, repr); + break :cache try self.constInt(ty, value); }, .error_union => |error_union| { // TODO: Error unions may be constructed with constant instructions if the payload type @@ -1011,7 +933,8 @@ const NavGen = struct { types = .{ payload_ty, err_ty }; } - return try self.constructStruct(ty, &types, &constituents); + const comp_ty_id = try self.resolveType(ty, .direct); + return try self.constructComposite(comp_ty_id, &constituents); }, .enum_tag => { const int_val = try val.intFromEnum(ty, pt); @@ -1020,14 +943,10 @@ const NavGen = struct { }, .ptr => return self.constantPtr(val), .slice => |slice| { - const ptr_ty = ty.slicePtrFieldType(zcu); const ptr_id = try self.constantPtr(Value.fromInterned(slice.ptr)); const len_id = try self.constant(Type.usize, Value.fromInterned(slice.len), .indirect); - return self.constructStruct( - ty, - &.{ ptr_ty, Type.usize }, - &.{ ptr_id, len_id }, - ); + const comp_ty_id = try self.resolveType(ty, .direct); + return try self.constructComposite(comp_ty_id, &.{ ptr_id, len_id }); }, .opt => { const payload_ty = ty.optionalChild(zcu); @@ -1053,11 +972,8 @@ const NavGen = struct { else try self.spv.constUndef(try self.resolveType(payload_ty, .indirect)); - return try self.constructStruct( - ty, - &.{ payload_ty, Type.bool }, - &.{ payload_id, has_pl_id }, - ); + const comp_ty_id = try self.resolveType(ty, .direct); + return try self.constructComposite(comp_ty_id, &.{ payload_id, has_pl_id }); }, .aggregate => |aggregate| switch (ip.indexToKey(ty.ip_index)) { inline .array_type, .vector_type => |array_type, tag| { @@ -1077,7 +993,7 @@ const NavGen = struct { // TODO: This is really space inefficient, perhaps there is a better // way to do it? for (constituents, bytes.toSlice(constituents.len, ip)) |*constituent, byte| { - constituent.* = try self.constInt(elem_ty, byte, child_repr); + constituent.* = try self.constInt(elem_ty, byte); } }, .elems => |elems| { @@ -1090,11 +1006,8 @@ const NavGen = struct { }, } - switch (tag) { - .array_type => return self.constructArray(ty, constituents), - .vector_type => return self.constructVector(ty, constituents), - else => unreachable, - } + const comp_ty_id = try self.resolveType(ty, .direct); + return self.constructComposite(comp_ty_id, constituents); }, .struct_type => { const struct_type = zcu.typeToStruct(ty).?; @@ -1124,7 +1037,8 @@ const NavGen = struct { try constituents.append(field_id); } - return try self.constructStruct(ty, types.items, constituents.items); + const comp_ty_id = try self.resolveType(ty, .direct); + return try self.constructComposite(comp_ty_id, constituents.items); }, .tuple_type => unreachable, // TODO else => unreachable, @@ -1149,8 +1063,6 @@ const NavGen = struct { } fn constantPtr(self: *NavGen, ptr_val: Value) Error!IdRef { - // TODO: Caching?? - const pt = self.pt; if (ptr_val.isUndef(pt.zcu)) { @@ -1201,7 +1113,7 @@ const NavGen = struct { .elem_ptr => |elem| { const parent_ptr_id = try self.derivePtr(elem.parent.*); const parent_ptr_ty = try elem.parent.ptrType(pt); - const index_id = try self.constInt(Type.usize, elem.elem_idx, .direct); + const index_id = try self.constInt(Type.usize, elem.elem_idx); return self.ptrElemPtr(parent_ptr_ty, parent_ptr_id, index_id); }, .offset_and_cast => |oac| { @@ -1255,7 +1167,7 @@ const NavGen = struct { // Uav refs are always generic. assert(ty.ptrAddressSpace(zcu) == .generic); - const decl_ptr_ty_id = try self.ptrType(uav_ty, .Generic); + const decl_ptr_ty_id = try self.ptrType(uav_ty, .Generic, .indirect); const ptr_id = try self.resolveUav(uav.val); if (decl_ptr_ty_id != ty_id) { @@ -1310,7 +1222,7 @@ const NavGen = struct { const storage_class = self.spvStorageClass(nav.getAddrspace()); try self.addFunctionDep(spv_decl_index, storage_class); - const decl_ptr_ty_id = try self.ptrType(nav_ty, storage_class); + const decl_ptr_ty_id = try self.ptrType(nav_ty, storage_class, .indirect); const ptr_id = switch (storage_class) { .Generic => try self.castToGeneric(decl_ptr_ty_id, decl_id), @@ -1359,23 +1271,11 @@ const NavGen = struct { } fn arrayType(self: *NavGen, len: u32, child_ty: IdRef) !IdRef { - // TODO: Cache?? - const len_id = try self.constInt(Type.u32, len, .direct); - const result_id = self.spv.allocId(); - - try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpTypeArray, .{ - .id_result = result_id, - .element_type = child_ty, - .length = len_id, - }); - return result_id; - } - - fn ptrType(self: *NavGen, child_ty: Type, storage_class: StorageClass) !IdRef { - return try self.ptrType2(child_ty, storage_class, .indirect); + const len_id = try self.constInt(Type.u32, len); + return self.spv.arrayType(len_id, child_ty); } - fn ptrType2(self: *NavGen, child_ty: Type, storage_class: StorageClass, child_repr: Repr) !IdRef { + fn ptrType(self: *NavGen, child_ty: Type, storage_class: StorageClass, child_repr: Repr) !IdRef { const key = .{ child_ty.toIntern(), storage_class, child_repr }; const entry = try self.ptr_types.getOrPut(self.gpa, key); if (entry.found_existing) { @@ -1408,8 +1308,7 @@ const NavGen = struct { } fn functionType(self: *NavGen, return_ty: Type, param_types: []const Type) !IdRef { - // TODO: Cache?? - + const return_ty_id = try self.resolveFnReturnType(return_ty); const param_ids = try self.gpa.alloc(IdRef, param_types.len); defer self.gpa.free(param_ids); @@ -1417,14 +1316,7 @@ const NavGen = struct { param_id.* = try self.resolveType(param_ty, .direct); } - const ty_id = self.spv.allocId(); - try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpTypeFunction, .{ - .id_result = ty_id, - .return_type = try self.resolveFnReturnType(return_ty), - .id_ref_2 = param_ids, - }); - - return ty_id; + return self.spv.functionType(return_ty_id, param_ids); } fn zigScalarOrVectorTypeLike(self: *NavGen, new_ty: Type, base_ty: Type) !Type { @@ -1702,13 +1594,7 @@ const NavGen = struct { const child_ty = Type.fromInterned(ptr_info.child); const storage_class = self.spvStorageClass(ptr_info.flags.address_space); - const ptr_ty_id = try self.ptrType(child_ty, storage_class); - - if (target.os.tag == .vulkan and ptr_info.flags.size == .many) { - try self.spv.decorate(ptr_ty_id, .{ .ArrayStride = .{ - .array_stride = @intCast(child_ty.abiSize(zcu)), - } }); - } + const ptr_ty_id = try self.ptrType(child_ty, storage_class, .indirect); if (ptr_info.flags.size != .slice) { return ptr_ty_id; @@ -1755,10 +1641,6 @@ const NavGen = struct { defer self.gpa.free(type_name); try self.spv.debugName(result_id, type_name); - if (target.os.tag == .vulkan) { - try self.spv.decorate(result_id, .Block); // Decorate all structs as block for now... - } - return result_id; }, .struct_type => ip.loadStructType(ty.toIntern()), @@ -1804,10 +1686,6 @@ const NavGen = struct { defer self.gpa.free(type_name); try self.spv.debugName(result_id, type_name); - if (target.os.tag == .vulkan) { - try self.spv.decorate(result_id, .Block); // Decorate all structs as block for now... - } - return result_id; }, .optional => { @@ -2073,12 +1951,13 @@ const NavGen = struct { .exploded_vector => |range| { assert(self.ty.isVector(zcu)); assert(self.ty.vectorLen(zcu) == range.len); - const consituents = try ng.gpa.alloc(IdRef, range.len); - defer ng.gpa.free(consituents); - for (consituents, 0..range.len) |*id, i| { + const constituents = try ng.gpa.alloc(IdRef, range.len); + defer ng.gpa.free(constituents); + for (constituents, 0..range.len) |*id, i| { id.* = range.at(i); } - return ng.constructVector(self.ty, consituents); + const result_ty_id = try ng.resolveType(self.ty, .direct); + return ng.constructComposite(result_ty_id, constituents); }, } } @@ -2282,7 +2161,7 @@ const NavGen = struct { .child = tmp.ty.toIntern(), }); - const vector = try ng.constructVectorSplat(vector_ty, id); + const vector = try ng.constructCompositeSplat(vector_ty, id); return .{ .ty = vector_ty, .value = .{ .spv_vectorwise = vector }, @@ -3045,7 +2924,7 @@ const NavGen = struct { const spv_err_decl_index = self.object.error_push_constant.?.push_constant_ptr; const push_constant_id = self.spv.declPtr(spv_err_decl_index).result_id; - const zero_id = try self.constInt(Type.u32, 0, .direct); + const zero_id = try self.constInt(Type.u32, 0); // We cannot use OpInBoundsAccessChain to dereference cross-storage class, so we have to use // a load. const tmp = self.spv.allocId(); @@ -3187,7 +3066,7 @@ const NavGen = struct { const storage_class = self.spvStorageClass(nav.getAddrspace()); assert(storage_class != .Generic); // These should be instance globals - const ptr_ty_id = try self.ptrType(ty, storage_class); + const ptr_ty_id = try self.ptrType(ty, storage_class, .indirect); try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpVariable, .{ .id_result_type = ptr_ty_id, @@ -3208,7 +3087,7 @@ const NavGen = struct { try self.spv.declareDeclDeps(spv_decl_index, &.{}); - const ptr_ty_id = try self.ptrType(ty, .Function); + const ptr_ty_id = try self.ptrType(ty, .Function, .indirect); if (maybe_init_val) |init_val| { // TODO: Combine with resolveAnonDecl? @@ -3265,8 +3144,8 @@ const NavGen = struct { } fn intFromBool2(self: *NavGen, value: Temporary, result_ty: Type) !Temporary { - const zero_id = try self.constInt(result_ty, 0, .direct); - const one_id = try self.constInt(result_ty, 1, .direct); + const zero_id = try self.constInt(result_ty, 0); + const one_id = try self.constInt(result_ty, 1); return try self.buildSelect( value, @@ -3648,12 +3527,12 @@ const NavGen = struct { .strange_integer => switch (info.signedness) { .unsigned => { const mask_value = if (info.bits == 64) 0xFFFF_FFFF_FFFF_FFFF else (@as(u64, 1) << @as(u6, @intCast(info.bits))) - 1; - const mask_id = try self.constInt(ty.scalarType(zcu), mask_value, .direct); + const mask_id = try self.constInt(ty.scalarType(zcu), mask_value); return try self.buildBinary(.bit_and, value, Temporary.init(ty.scalarType(zcu), mask_id)); }, .signed => { // Shift left and right so that we can copy the sight bit that way. - const shift_amt_id = try self.constInt(ty.scalarType(zcu), info.backing_bits - info.bits, .direct); + const shift_amt_id = try self.constInt(ty.scalarType(zcu), info.backing_bits - info.bits); const shift_amt = Temporary.init(ty.scalarType(zcu), shift_amt_id); const left = try self.buildBinary(.sll, value, shift_amt); return try self.buildBinary(.sra, left, shift_amt); @@ -3687,7 +3566,7 @@ const NavGen = struct { const div = try self.buildBinary(.s_div, lhs, rhs); const rem = try self.buildBinary(.s_rem, lhs, rhs); - const zero = Temporary.init(lhs.ty, try self.constInt(lhs.ty, 0, .direct)); + const zero = Temporary.init(lhs.ty, try self.constInt(lhs.ty, 0)); const rem_is_not_zero = try self.buildCmp(.i_ne, rem, zero); @@ -3863,7 +3742,7 @@ const NavGen = struct { // = (rhs < 0) == (value < lhs) // = (rhs < 0) == (lhs > value) .signed => blk: { - const zero = Temporary.init(rhs.ty, try self.constInt(rhs.ty, 0, .direct)); + const zero = Temporary.init(rhs.ty, try self.constInt(rhs.ty, 0)); const rhs_lt_zero = try self.buildCmp(.s_lt, rhs, zero); const result_gt_lhs = try self.buildCmp(scmp, lhs, result); break :blk try self.buildCmp(.l_eq, rhs_lt_zero, result_gt_lhs); @@ -3872,11 +3751,8 @@ const NavGen = struct { const ov = try self.intFromBool(overflowed); - return try self.constructStruct( - result_ty, - &.{ result.ty, ov.ty }, - &.{ try result.materialize(self), try ov.materialize(self) }, - ); + const result_ty_id = try self.resolveType(result_ty, .direct); + return try self.constructComposite(result_ty_id, &.{ try result.materialize(self), try ov.materialize(self) }); } fn airMulOverflow(self: *NavGen, inst: Air.Inst.Index) !?IdRef { @@ -3928,11 +3804,11 @@ const NavGen = struct { const result = try self.normalize(low_bits, info); // Shift the result bits away to get the overflow bits. - const shift = Temporary.init(full_result.ty, try self.constInt(full_result.ty, info.bits, .direct)); + const shift = Temporary.init(full_result.ty, try self.constInt(full_result.ty, info.bits)); const overflow = try self.buildBinary(.srl, full_result, shift); // Directly check if its zero in the op_ty without converting first. - const zero = Temporary.init(full_result.ty, try self.constInt(full_result.ty, 0, .direct)); + const zero = Temporary.init(full_result.ty, try self.constInt(full_result.ty, 0)); const overflowed = try self.buildCmp(.i_ne, zero, overflow); break :blk .{ result, overflowed }; @@ -3946,7 +3822,7 @@ const NavGen = struct { // Overflow happened if the high-bits of the result are non-zero OR if the // high bits of the low word of the result (those outside the range of the // int) are nonzero. - const zero = Temporary.init(lhs.ty, try self.constInt(lhs.ty, 0, .direct)); + const zero = Temporary.init(lhs.ty, try self.constInt(lhs.ty, 0)); const high_overflowed = try self.buildCmp(.i_ne, zero, high_bits); // If no overflow bits in low_bits, no extra work needs to be done. @@ -3955,7 +3831,7 @@ const NavGen = struct { } // Shift the result bits away to get the overflow bits. - const shift = Temporary.init(lhs.ty, try self.constInt(lhs.ty, info.bits, .direct)); + const shift = Temporary.init(lhs.ty, try self.constInt(lhs.ty, info.bits)); const low_overflow = try self.buildBinary(.srl, low_bits, shift); const low_overflowed = try self.buildCmp(.i_ne, zero, low_overflow); @@ -3974,7 +3850,7 @@ const NavGen = struct { // overflow should be -1 when // (lhs > 0 && rhs < 0) || (lhs < 0 && rhs > 0) - const zero = Temporary.init(lhs.ty, try self.constInt(lhs.ty, 0, .direct)); + const zero = Temporary.init(lhs.ty, try self.constInt(lhs.ty, 0)); const lhs_negative = try self.buildCmp(.s_lt, lhs, zero); const rhs_negative = try self.buildCmp(.s_lt, rhs, zero); const lhs_positive = try self.buildCmp(.s_gt, lhs, zero); @@ -4003,13 +3879,13 @@ const NavGen = struct { // bit for the expected overflow bits. // To do that, shift out everything bit the sign bit and // then check what remains. - const shift = Temporary.init(full_result.ty, try self.constInt(full_result.ty, info.bits - 1, .direct)); + const shift = Temporary.init(full_result.ty, try self.constInt(full_result.ty, info.bits - 1)); // Use SRA so that any sign bits are duplicated. Now we can just check if ALL bits are set // for negative cases. const overflow = try self.buildBinary(.sra, full_result, shift); - const long_all_set = Temporary.init(full_result.ty, try self.constInt(full_result.ty, -1, .direct)); - const long_zero = Temporary.init(full_result.ty, try self.constInt(full_result.ty, 0, .direct)); + const long_all_set = Temporary.init(full_result.ty, try self.constInt(full_result.ty, -1)); + const long_zero = Temporary.init(full_result.ty, try self.constInt(full_result.ty, 0)); const mask = try self.buildSelect(expected_overflow_bit, long_all_set, long_zero); const overflowed = try self.buildCmp(.i_ne, mask, overflow); @@ -4022,7 +3898,7 @@ const NavGen = struct { // Truncate result if required. const result = try self.normalize(low_bits, info); - const all_set = Temporary.init(lhs.ty, try self.constInt(lhs.ty, -1, .direct)); + const all_set = Temporary.init(lhs.ty, try self.constInt(lhs.ty, -1)); const mask = try self.buildSelect(expected_overflow_bit, all_set, zero); // Like with unsigned, overflow happened if high_bits are not the ones we expect, @@ -4038,7 +3914,7 @@ const NavGen = struct { } // Shift the result bits away to get the overflow bits. - const shift = Temporary.init(lhs.ty, try self.constInt(lhs.ty, info.bits - 1, .direct)); + const shift = Temporary.init(lhs.ty, try self.constInt(lhs.ty, info.bits - 1)); // Use SRA so that any sign bits are duplicated. Now we can just check if ALL bits are set // for negative cases. const low_overflow = try self.buildBinary(.sra, low_bits, shift); @@ -4052,11 +3928,8 @@ const NavGen = struct { const ov = try self.intFromBool(overflowed); - return try self.constructStruct( - result_ty, - &.{ result.ty, ov.ty }, - &.{ try result.materialize(self), try ov.materialize(self) }, - ); + const result_ty_id = try self.resolveType(result_ty, .direct); + return try self.constructComposite(result_ty_id, &.{ try result.materialize(self), try ov.materialize(self) }); } fn airShlOverflow(self: *NavGen, inst: Air.Inst.Index) !?IdRef { @@ -4092,11 +3965,8 @@ const NavGen = struct { const overflowed = try self.buildCmp(.i_ne, base, right); const ov = try self.intFromBool(overflowed); - return try self.constructStruct( - result_ty, - &.{ result.ty, ov.ty }, - &.{ try result.materialize(self), try ov.materialize(self) }, - ); + const result_ty_id = try self.resolveType(result_ty, .direct); + return try self.constructComposite(result_ty_id, &.{ try result.materialize(self), try ov.materialize(self) }); } fn airMulAdd(self: *NavGen, inst: Air.Inst.Index) !?IdRef { @@ -4163,7 +4033,7 @@ const NavGen = struct { const operand_id = try self.resolve(ty_op.operand); const result_ty = self.typeOfIndex(inst); - return try self.constructVectorSplat(result_ty, operand_id); + return try self.constructCompositeSplat(result_ty, operand_id); } fn airReduce(self: *NavGen, inst: Air.Inst.Index) !?IdRef { @@ -4297,10 +4167,10 @@ const NavGen = struct { // Fall back to manually extracting and inserting components. - const components = try self.gpa.alloc(IdRef, result_ty.vectorLen(zcu)); - defer self.gpa.free(components); + const constituents = try self.gpa.alloc(IdRef, result_ty.vectorLen(zcu)); + defer self.gpa.free(constituents); - for (components, 0..) |*id, i| { + for (constituents, 0..) |*id, i| { const elem = try mask.elemValue(pt, i); if (elem.isUndef(zcu)) { id.* = try self.spv.constUndef(scalar_ty_id); @@ -4315,14 +4185,15 @@ const NavGen = struct { } } - return try self.constructVector(result_ty, components); + const result_ty_id = try self.resolveType(result_ty, .direct); + return try self.constructComposite(result_ty_id, constituents); } fn indicesToIds(self: *NavGen, indices: []const u32) ![]IdRef { const ids = try self.gpa.alloc(IdRef, indices.len); errdefer self.gpa.free(ids); for (indices, ids) |index, *id| { - id.* = try self.constInt(Type.u32, index, .direct); + id.* = try self.constInt(Type.u32, index); } return ids; @@ -4676,7 +4547,7 @@ const NavGen = struct { break :blk result_id; } - const dst_ptr_ty_id = try self.ptrType(dst_ty, .Function); + const dst_ptr_ty_id = try self.ptrType(dst_ty, .Function, .indirect); const tmp_id = try self.alloc(src_ty, .{ .storage_class = .Function }); try self.store(src_ty, tmp_id, src_id, .{}); @@ -4851,7 +4722,7 @@ const NavGen = struct { const elem_ptr_ty_id = try self.resolveType(elem_ptr_ty, .direct); const array_ptr_id = try self.resolve(ty_op.operand); - const len_id = try self.constInt(Type.usize, array_ty.arrayLen(zcu), .direct); + const len_id = try self.constInt(Type.usize, array_ty.arrayLen(zcu)); const elem_ptr_id = if (!array_ty.hasRuntimeBitsIgnoreComptime(zcu)) // Note: The pointer is something like *opaque{}, so we need to bitcast it to the element type. @@ -4860,11 +4731,8 @@ const NavGen = struct { // Convert the pointer-to-array to a pointer to the first element. try self.accessChain(elem_ptr_ty_id, array_ptr_id, &.{0}); - return try self.constructStruct( - slice_ty, - &.{ elem_ptr_ty, Type.usize }, - &.{ elem_ptr_id, len_id }, - ); + const slice_ty_id = try self.resolveType(slice_ty, .direct); + return try self.constructComposite(slice_ty_id, &.{ elem_ptr_id, len_id }); } fn airSlice(self: *NavGen, inst: Air.Inst.Index) !?IdRef { @@ -4872,16 +4740,9 @@ const NavGen = struct { const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; const ptr_id = try self.resolve(bin_op.lhs); const len_id = try self.resolve(bin_op.rhs); - const ptr_ty = self.typeOf(bin_op.lhs); const slice_ty = self.typeOfIndex(inst); - - // Note: Types should not need to be converted to direct, these types - // dont need to be converted. - return try self.constructStruct( - slice_ty, - &.{ ptr_ty, Type.usize }, - &.{ ptr_id, len_id }, - ); + const slice_ty_id = try self.resolveType(slice_ty, .direct); + return try self.constructComposite(slice_ty_id, &.{ ptr_id, len_id }); } fn airAggregateInit(self: *NavGen, inst: Air.Inst.Index) !?IdRef { @@ -4936,11 +4797,8 @@ const NavGen = struct { else => unreachable, } - return try self.constructStruct( - result_ty, - types[0..index], - constituents[0..index], - ); + const result_ty_id = try self.resolveType(result_ty, .direct); + return try self.constructComposite(result_ty_id, constituents[0..index]); }, .vector => { const n_elems = result_ty.vectorLen(zcu); @@ -4951,7 +4809,8 @@ const NavGen = struct { elem_ids[i] = try self.resolve(element); } - return try self.constructVector(result_ty, elem_ids); + const result_ty_id = try self.resolveType(result_ty, .direct); + return try self.constructComposite(result_ty_id, elem_ids); }, .array => { const array_info = result_ty.arrayInfo(zcu); @@ -4968,7 +4827,8 @@ const NavGen = struct { elem_ids[n_elems - 1] = try self.constant(array_info.elem_type, sentinel_val, .indirect); } - return try self.constructArray(result_ty, elem_ids); + const result_ty_id = try self.resolveType(result_ty, .direct); + return try self.constructComposite(result_ty_id, elem_ids); }, else => unreachable, } @@ -4984,7 +4844,7 @@ const NavGen = struct { const elem_ty = array_ty.childType(zcu); const abi_size = elem_ty.abiSize(zcu); const size = array_ty.arrayLenIncludingSentinel(zcu) * abi_size; - return try self.constInt(Type.usize, size, .direct); + return try self.constInt(Type.usize, size); }, .many, .c => unreachable, } @@ -5060,7 +4920,7 @@ const NavGen = struct { const zcu = self.pt.zcu; // Construct new pointer type for the resulting pointer const elem_ty = ptr_ty.elemType2(zcu); // use elemType() so that we get T for *[N]T. - const elem_ptr_ty_id = try self.ptrType(elem_ty, self.spvStorageClass(ptr_ty.ptrAddressSpace(zcu))); + const elem_ptr_ty_id = try self.ptrType(elem_ty, self.spvStorageClass(ptr_ty.ptrAddressSpace(zcu)), .indirect); if (ptr_ty.isSinglePointer(zcu)) { // Pointer-to-array. In this case, the resulting pointer is not of the same type // as the ptr_ty (we want a *T, not a *[N]T), and hence we need to use accessChain. @@ -5115,8 +4975,8 @@ const NavGen = struct { const is_vector = array_ty.isVector(zcu); const elem_repr: Repr = if (is_vector) .direct else .indirect; - const ptr_array_ty_id = try self.ptrType2(array_ty, .Function, .direct); - const ptr_elem_ty_id = try self.ptrType2(elem_ty, .Function, elem_repr); + const ptr_array_ty_id = try self.ptrType(array_ty, .Function, .direct); + const ptr_elem_ty_id = try self.ptrType(elem_ty, .Function, elem_repr); const tmp_id = self.spv.allocId(); try self.func.prologue.emit(self.spv.gpa, .OpVariable, .{ @@ -5171,7 +5031,7 @@ const NavGen = struct { const scalar_ty = vector_ty.scalarType(zcu); const storage_class = self.spvStorageClass(vector_ptr_ty.ptrAddressSpace(zcu)); - const scalar_ptr_ty_id = try self.ptrType(scalar_ty, storage_class); + const scalar_ptr_ty_id = try self.ptrType(scalar_ty, storage_class, .indirect); const vector_ptr = try self.resolve(data.vector_ptr); const index = try self.resolve(extra.lhs); @@ -5193,7 +5053,7 @@ const NavGen = struct { if (layout.tag_size == 0) return; const tag_ty = un_ty.unionTagTypeSafety(zcu).?; - const tag_ptr_ty_id = try self.ptrType(tag_ty, self.spvStorageClass(un_ptr_ty.ptrAddressSpace(zcu))); + const tag_ptr_ty_id = try self.ptrType(tag_ty, self.spvStorageClass(un_ptr_ty.ptrAddressSpace(zcu)), .indirect); const union_ptr_id = try self.resolve(bin_op.lhs); const new_tag_id = try self.resolve(bin_op.rhs); @@ -5252,23 +5112,23 @@ const NavGen = struct { } else 0; if (!layout.has_payload) { - return try self.constInt(tag_ty, tag_int, .direct); + return try self.constInt(tag_ty, tag_int); } const tmp_id = try self.alloc(ty, .{ .storage_class = .Function }); if (layout.tag_size != 0) { - const tag_ptr_ty_id = try self.ptrType(tag_ty, .Function); + const tag_ptr_ty_id = try self.ptrType(tag_ty, .Function, .indirect); const ptr_id = try self.accessChain(tag_ptr_ty_id, tmp_id, &.{@as(u32, @intCast(layout.tag_index))}); - const tag_id = try self.constInt(tag_ty, tag_int, .direct); + const tag_id = try self.constInt(tag_ty, tag_int); try self.store(tag_ty, ptr_id, tag_id, .{}); } const payload_ty = Type.fromInterned(union_ty.field_types.get(ip)[active_field]); if (payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { - const pl_ptr_ty_id = try self.ptrType(layout.payload_ty, .Function); + const pl_ptr_ty_id = try self.ptrType(layout.payload_ty, .Function, .indirect); const pl_ptr_id = try self.accessChain(pl_ptr_ty_id, tmp_id, &.{layout.payload_index}); - const active_pl_ptr_ty_id = try self.ptrType(payload_ty, .Function); + const active_pl_ptr_ty_id = try self.ptrType(payload_ty, .Function, .indirect); const active_pl_ptr_id = self.spv.allocId(); try self.func.body.emit(self.spv.gpa, .OpBitcast, .{ .id_result_type = active_pl_ptr_ty_id, @@ -5332,10 +5192,10 @@ const NavGen = struct { const tmp_id = try self.alloc(object_ty, .{ .storage_class = .Function }); try self.store(object_ty, tmp_id, object_id, .{}); - const pl_ptr_ty_id = try self.ptrType(layout.payload_ty, .Function); + const pl_ptr_ty_id = try self.ptrType(layout.payload_ty, .Function, .indirect); const pl_ptr_id = try self.accessChain(pl_ptr_ty_id, tmp_id, &.{layout.payload_index}); - const active_pl_ptr_ty_id = try self.ptrType(field_ty, .Function); + const active_pl_ptr_ty_id = try self.ptrType(field_ty, .Function, .indirect); const active_pl_ptr_id = self.spv.allocId(); try self.func.body.emit(self.spv.gpa, .OpBitcast, .{ .id_result_type = active_pl_ptr_ty_id, @@ -5365,7 +5225,7 @@ const NavGen = struct { const base_ptr_int = base_ptr_int: { if (field_offset == 0) break :base_ptr_int field_ptr_int; - const field_offset_id = try self.constInt(Type.usize, field_offset, .direct); + const field_offset_id = try self.constInt(Type.usize, field_offset); const field_ptr_tmp = Temporary.init(Type.usize, field_ptr_int); const field_offset_tmp = Temporary.init(Type.usize, field_offset_id); const result = try self.buildBinary(.i_sub, field_ptr_tmp, field_offset_tmp); @@ -5415,7 +5275,7 @@ const NavGen = struct { } const storage_class = self.spvStorageClass(object_ptr_ty.ptrAddressSpace(zcu)); - const pl_ptr_ty_id = try self.ptrType(layout.payload_ty, storage_class); + const pl_ptr_ty_id = try self.ptrType(layout.payload_ty, storage_class, .indirect); const pl_ptr_id = try self.accessChain(pl_ptr_ty_id, object_ptr, &.{layout.payload_index}); const active_pl_ptr_id = self.spv.allocId(); @@ -5456,7 +5316,7 @@ const NavGen = struct { ty: Type, options: AllocOptions, ) !IdRef { - const ptr_fn_ty_id = try self.ptrType(ty, .Function); + const ptr_fn_ty_id = try self.ptrType(ty, .Function, .indirect); // SPIR-V requires that OpVariable declarations for locals go into the first block, so we are just going to // directly generate them into func.prologue instead of the body. @@ -5475,7 +5335,7 @@ const NavGen = struct { switch (options.storage_class) { .Generic => { - const ptr_gn_ty_id = try self.ptrType(ty, .Generic); + const ptr_gn_ty_id = try self.ptrType(ty, .Generic, .indirect); // Convert to a generic pointer return self.castToGeneric(ptr_gn_ty_id, var_id); }, @@ -5724,7 +5584,7 @@ const NavGen = struct { assert(cf.block_stack.items.len > 0); // Check if the target of the branch was this current block. - const this_block = try self.constInt(Type.u32, @intFromEnum(inst), .direct); + const this_block = try self.constInt(Type.u32, @intFromEnum(inst)); const jump_to_this_block_id = self.spv.allocId(); const bool_ty_id = try self.resolveType(Type.bool, .direct); try self.func.body.emit(self.spv.gpa, .OpIEqual, .{ @@ -5804,7 +5664,7 @@ const NavGen = struct { try self.store(operand_ty, block_result_var_id, operand_id, .{}); } - const next_block = try self.constInt(Type.u32, @intFromEnum(br.block_inst), .direct); + const next_block = try self.constInt(Type.u32, @intFromEnum(br.block_inst)); try self.structuredBreak(next_block); }, .unstructured => |cf| { @@ -5968,7 +5828,7 @@ const NavGen = struct { // Functions with an empty error set are emitted with an error code // return type and return zero so they can be function pointers coerced // to functions that return anyerror. - const no_err_id = try self.constInt(Type.anyerror, 0, .direct); + const no_err_id = try self.constInt(Type.anyerror, 0); return try self.func.body.emit(self.spv.gpa, .OpReturnValue, .{ .value = no_err_id }); } else { return try self.func.body.emit(self.spv.gpa, .OpReturn, {}); @@ -5992,7 +5852,7 @@ const NavGen = struct { // Functions with an empty error set are emitted with an error code // return type and return zero so they can be function pointers coerced // to functions that return anyerror. - const no_err_id = try self.constInt(Type.anyerror, 0, .direct); + const no_err_id = try self.constInt(Type.anyerror, 0); return try self.func.body.emit(self.spv.gpa, .OpReturnValue, .{ .value = no_err_id }); } else { return try self.func.body.emit(self.spv.gpa, .OpReturn, {}); @@ -6026,7 +5886,7 @@ const NavGen = struct { else err_union_id; - const zero_id = try self.constInt(Type.anyerror, 0, .direct); + const zero_id = try self.constInt(Type.anyerror, 0); const is_err_id = self.spv.allocId(); try self.func.body.emit(self.spv.gpa, .OpINotEqual, .{ .id_result_type = bool_ty_id, @@ -6134,7 +5994,8 @@ const NavGen = struct { types[eu_layout.errorFieldIndex()] = Type.anyerror; types[eu_layout.payloadFieldIndex()] = payload_ty; - return try self.constructStruct(err_union_ty, &types, &members); + const err_union_ty_id = try self.resolveType(err_union_ty, .direct); + return try self.constructComposite(err_union_ty_id, &members); } fn airWrapErrUnionPayload(self: *NavGen, inst: Air.Inst.Index) !?IdRef { @@ -6145,18 +6006,19 @@ const NavGen = struct { const eu_layout = self.errorUnionLayout(payload_ty); if (!eu_layout.payload_has_bits) { - return try self.constInt(Type.anyerror, 0, .direct); + return try self.constInt(Type.anyerror, 0); } var members: [2]IdRef = undefined; - members[eu_layout.errorFieldIndex()] = try self.constInt(Type.anyerror, 0, .direct); + members[eu_layout.errorFieldIndex()] = try self.constInt(Type.anyerror, 0); members[eu_layout.payloadFieldIndex()] = try self.convertToIndirect(payload_ty, operand_id); var types: [2]Type = undefined; types[eu_layout.errorFieldIndex()] = Type.anyerror; types[eu_layout.payloadFieldIndex()] = payload_ty; - return try self.constructStruct(err_union_ty, &types, &members); + const err_union_ty_id = try self.resolveType(err_union_ty, .direct); + return try self.constructComposite(err_union_ty_id, &members); } fn airIsNull(self: *NavGen, inst: Air.Inst.Index, is_pointer: bool, pred: enum { is_null, is_non_null }) !?IdRef { @@ -6204,7 +6066,7 @@ const NavGen = struct { if (is_pointer) { if (payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { const storage_class = self.spvStorageClass(operand_ty.ptrAddressSpace(zcu)); - const bool_ptr_ty_id = try self.ptrType(Type.bool, storage_class); + const bool_ptr_ty_id = try self.ptrType(Type.bool, storage_class, .indirect); const tag_ptr_id = try self.accessChain(bool_ptr_ty_id, operand_id, &.{1}); break :blk try self.load(Type.bool, tag_ptr_id, .{}); } @@ -6267,7 +6129,7 @@ const NavGen = struct { .id_result_type = bool_ty_id, .id_result = result_id, .operand_1 = error_id, - .operand_2 = try self.constInt(Type.anyerror, 0, .direct), + .operand_2 = try self.constInt(Type.anyerror, 0), }, ), } @@ -6335,8 +6197,8 @@ const NavGen = struct { const payload_id = try self.convertToIndirect(payload_ty, operand_id); const members = [_]IdRef{ payload_id, try self.constBool(true, .indirect) }; - const types = [_]Type{ payload_ty, Type.bool }; - return try self.constructStruct(optional_ty, &types, &members); + const optional_ty_id = try self.resolveType(optional_ty, .direct); + return try self.constructComposite(optional_ty_id, &members); } fn airSwitchBr(self: *NavGen, inst: Air.Inst.Index) !void { @@ -6752,13 +6614,13 @@ const NavGen = struct { fn builtin3D(self: *NavGen, result_ty: Type, builtin: spec.BuiltIn, dimension: u32, out_of_range_value: anytype) !IdRef { if (dimension >= 3) { - return try self.constInt(result_ty, out_of_range_value, .direct); + return try self.constInt(result_ty, out_of_range_value); } const vec_ty = try self.pt.vectorType(.{ .len = 3, .child = result_ty.toIntern(), }); - const ptr_ty_id = try self.ptrType(vec_ty, .Input); + const ptr_ty_id = try self.ptrType(vec_ty, .Input, .indirect); const spv_decl_index = try self.spv.builtin(ptr_ty_id, builtin); try self.func.decl_deps.put(self.spv.gpa, spv_decl_index, {}); const ptr = self.spv.declPtr(spv_decl_index).result_id; -- cgit v1.2.3 From 85169bbba24d7e7592a24de5af6743b34bfe5961 Mon Sep 17 00:00:00 2001 From: Ali Cheraghi Date: Fri, 14 Feb 2025 20:28:36 +0330 Subject: spirv: respect cpu features --- src/codegen/spirv.zig | 153 ++++++++++++++++--------------------------- src/codegen/spirv/Module.zig | 40 +++++++---- src/link/SpirV.zig | 92 ++++++++++++++------------ 3 files changed, 132 insertions(+), 153 deletions(-) (limited to 'src/codegen/spirv.zig') diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index 8c4b0478de..58182ead0b 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -176,10 +176,10 @@ pub const Object = struct { push_constant_ptr: SpvModule.Decl.Index, } = null, - pub fn init(gpa: Allocator) Object { + pub fn init(gpa: Allocator, target: std.Target) Object { return .{ .gpa = gpa, - .spv = SpvModule.init(gpa), + .spv = SpvModule.init(gpa, target), }; } @@ -412,11 +412,6 @@ const NavGen = struct { self.func.deinit(self.gpa); } - /// Return the target which we are currently compiling for. - pub fn getTarget(self: *NavGen) std.Target { - return self.pt.zcu.getTarget(); - } - pub fn fail(self: *NavGen, comptime format: []const u8, args: anytype) Error { @branchHint(.cold); const zcu = self.pt.zcu; @@ -431,12 +426,12 @@ const NavGen = struct { } /// This imports the "default" extended instruction set for the target - /// For OpenCL, OpenCL.std.100. For Vulkan, GLSL.std.450. + /// For OpenCL, OpenCL.std.100. For Vulkan and OpenGL, GLSL.std.450. fn importExtendedSet(self: *NavGen) !IdResult { - const target = self.getTarget(); + const target = self.spv.target; return switch (target.os.tag) { .opencl => try self.spv.importInstructionSet(.@"OpenCL.std"), - .vulkan => try self.spv.importInstructionSet(.@"GLSL.std.450"), + .vulkan, .opengl => try self.spv.importInstructionSet(.@"GLSL.std.450"), else => unreachable, }; } @@ -546,14 +541,10 @@ const NavGen = struct { } fn addFunctionDep(self: *NavGen, decl_index: SpvModule.Decl.Index, storage_class: StorageClass) !void { - const target = self.getTarget(); - if (target.os.tag == .vulkan) { - // Shader entry point dependencies must be variables with Input or Output storage class - switch (storage_class) { - .Input, .Output => { - try self.func.decl_deps.put(self.spv.gpa, decl_index, {}); - }, - else => {}, + if (self.spv.version.minor < 4) { + // Before version 1.4, the interface’s storage classes are limited to the Input and Output + if (storage_class == .Input or storage_class == .Output) { + try self.func.decl_deps.put(self.spv.gpa, decl_index, {}); } } else { try self.func.decl_deps.put(self.spv.gpa, decl_index, {}); @@ -561,11 +552,7 @@ const NavGen = struct { } fn castToGeneric(self: *NavGen, type_id: IdRef, ptr_id: IdRef) !IdRef { - const target = self.getTarget(); - - if (target.os.tag == .vulkan) { - return ptr_id; - } else { + if (self.spv.hasFeature(.Kernel)) { const result_id = self.spv.allocId(); try self.func.body.emit(self.spv.gpa, .OpPtrCastToGeneric, .{ .id_result_type = type_id, @@ -574,6 +561,8 @@ const NavGen = struct { }); return result_id; } + + return ptr_id; } /// Start a new SPIR-V block, Emits the label of the new block, and stores which @@ -596,8 +585,6 @@ const NavGen = struct { /// TODO: This probably needs an ABI-version as well (especially in combination with SPV_INTEL_arbitrary_precision_integers). /// TODO: Should the result of this function be cached? fn backingIntBits(self: *NavGen, bits: u16) ?u16 { - const target = self.getTarget(); - // The backend will never be asked to compiler a 0-bit integer, so we won't have to handle those in this function. assert(bits != 0); @@ -611,14 +598,8 @@ const NavGen = struct { }; for (ints) |int| { - const has_feature = if (int.feature) |feature| - Target.spirv.featureSetHas(target.cpu.features, feature) - else - true; - - if (bits <= int.bits and has_feature) { - return int.bits; - } + const has_feature = if (int.feature) |feature| self.spv.hasFeature(feature) else true; + if (bits <= int.bits and has_feature) return int.bits; } return null; @@ -631,11 +612,7 @@ const NavGen = struct { /// is no way of knowing whether those are actually supported. /// TODO: Maybe this should be cached? fn largestSupportedIntBits(self: *NavGen) u16 { - const target = self.getTarget(); - return if (Target.spirv.featureSetHas(target.cpu.features, .Int64)) - 64 - else - 32; + return if (self.spv.hasFeature(.Int64)) 64 else 32; } /// Checks whether the type is "composite int", an integer consisting of multiple native integers. These are represented by @@ -648,7 +625,6 @@ const NavGen = struct { /// Checks whether the type can be directly translated to SPIR-V vectors fn isSpvVector(self: *NavGen, ty: Type) bool { const zcu = self.pt.zcu; - const target = self.getTarget(); if (ty.zigTypeTag(zcu) != .vector) return false; // TODO: This check must be expanded for types that can be represented @@ -664,17 +640,19 @@ const NavGen = struct { } const elem_ty = ty.childType(zcu); - const len = ty.vectorLen(zcu); - const is_scalar = elem_ty.isNumeric(zcu) or elem_ty.toIntern() == .bool_type; - const spirv_len = len > 1 and len <= 4; - const opencl_len = if (target.os.tag == .opencl) (len == 8 or len == 16) else false; - return is_scalar and (spirv_len or opencl_len); + + if (elem_ty.isNumeric(zcu) or elem_ty.toIntern() == .bool_type) { + if (len > 1 and len <= 4) return true; + if (self.spv.hasFeature(.Vector16)) return (len == 8 or len == 16); + } + + return false; } fn arithmeticTypeInfo(self: *NavGen, ty: Type) ArithmeticTypeInfo { const zcu = self.pt.zcu; - const target = self.getTarget(); + const target = self.spv.target; var scalar_ty = ty.scalarType(zcu); if (scalar_ty.zigTypeTag(zcu) == .@"enum") { scalar_ty = scalar_ty.intTagType(zcu); @@ -791,7 +769,7 @@ const NavGen = struct { /// ty must be an aggregate type. fn constructCompositeSplat(self: *NavGen, ty: Type, constituent: IdRef) !IdRef { const zcu = self.pt.zcu; - const n = ty.arrayLen(zcu); + const n: usize = @intCast(ty.arrayLen(zcu)); const constituents = try self.gpa.alloc(IdRef, n); defer self.gpa.free(constituents); @@ -817,7 +795,7 @@ const NavGen = struct { const pt = self.pt; const zcu = pt.zcu; - const target = self.getTarget(); + const target = self.spv.target; const result_ty_id = try self.resolveType(ty, repr); const ip = &zcu.intern_pool; @@ -1263,11 +1241,11 @@ const NavGen = struct { }; // Kernel only supports unsigned ints. - if (self.getTarget().os.tag == .vulkan) { - return self.spv.intType(signedness, backing_bits); + if (self.spv.hasFeature(.Kernel)) { + return self.spv.intType(.unsigned, backing_bits); } - return self.spv.intType(.unsigned, backing_bits); + return self.spv.intType(signedness, backing_bits); } fn arrayType(self: *NavGen, len: u32, child_ty: IdRef) !IdRef { @@ -1436,7 +1414,7 @@ const NavGen = struct { const zcu = pt.zcu; const ip = &zcu.intern_pool; log.debug("resolveType: ty = {}", .{ty.fmt(pt)}); - const target = self.getTarget(); + const target = self.spv.target; const section = &self.spv.sections.types_globals_constants; @@ -1533,7 +1511,7 @@ const NavGen = struct { return try self.arrayType(1, elem_ty_id); } else { const result_id = try self.arrayType(total_len, elem_ty_id); - if (target.os.tag == .vulkan) { + if (self.spv.hasFeature(.Shader)) { try self.spv.decorate(result_id, .{ .ArrayStride = .{ .array_stride = @intCast(elem_ty.abiSize(zcu)), } }); @@ -1667,7 +1645,7 @@ const NavGen = struct { continue; } - if (target.os.tag == .vulkan) { + if (self.spv.hasFeature(.Shader)) { try self.spv.decorateMember(result_id, index, .{ .Offset = .{ .byte_offset = @intCast(ty.structFieldOffset(field_index, zcu)), } }); @@ -1769,20 +1747,11 @@ const NavGen = struct { } fn spvStorageClass(self: *NavGen, as: std.builtin.AddressSpace) StorageClass { - const target = self.getTarget(); return switch (as) { - .generic => switch (target.os.tag) { - .vulkan => .Function, - .opencl => .Generic, - else => unreachable, - }, + .generic => if (self.spv.hasFeature(.GenericPointer)) .Generic else .Function, .shared => .Workgroup, .local => .Function, - .global => switch (target.os.tag) { - .opencl => .CrossWorkgroup, - .vulkan => .PhysicalStorageBuffer, - else => unreachable, - }, + .global => if (self.spv.hasFeature(.Shader)) .PhysicalStorageBuffer else .CrossWorkgroup, .constant => .UniformConstant, .push_constant => .PushConstant, .input => .Input, @@ -2326,7 +2295,7 @@ const NavGen = struct { } fn buildFma(self: *NavGen, a: Temporary, b: Temporary, c: Temporary) !Temporary { - const target = self.getTarget(); + const target = self.spv.target; const v = self.vectorization(.{ a, b, c }); const ops = v.operations(); @@ -2348,7 +2317,7 @@ const NavGen = struct { // NOTE: Vulkan's FMA instruction does *NOT* produce the right values! // its precision guarantees do NOT match zigs and it does NOT match OpenCLs! // it needs to be emulated! - .vulkan => unreachable, // TODO: See above + .vulkan, .opengl => unreachable, // TODO: See above else => unreachable, }; @@ -2485,14 +2454,14 @@ const NavGen = struct { }; fn buildUnary(self: *NavGen, op: UnaryOp, operand: Temporary) !Temporary { - const target = self.getTarget(); + const target = self.spv.target; const v = blk: { const v = self.vectorization(.{operand}); break :blk switch (op) { // TODO: These instructions don't seem to be working // properly for LLVM-based backends on OpenCL for 8- and // 16-component vectors. - .i_abs => if (target.os.tag == .opencl and v.components() >= 8) v.unroll() else v, + .i_abs => if (self.spv.hasFeature(.Vector16) and v.components() >= 8) v.unroll() else v, else => v, }; }; @@ -2545,7 +2514,7 @@ const NavGen = struct { // Note: We'll need to check these for floating point accuracy // Vulkan does not put tight requirements on these, for correction // we might want to emulate them at some point. - .vulkan => switch (op) { + .vulkan, .opengl => switch (op) { .i_abs => 5, // SAbs .f_abs => 4, // FAbs .clz => unreachable, // TODO @@ -2615,7 +2584,7 @@ const NavGen = struct { }; fn buildBinary(self: *NavGen, op: BinaryOp, lhs: Temporary, rhs: Temporary) !Temporary { - const target = self.getTarget(); + const target = self.spv.target; const v = self.vectorization(.{ lhs, rhs }); const ops = v.operations(); @@ -2674,7 +2643,7 @@ const NavGen = struct { .u_min => 159, // u_min else => unreachable, }, - .vulkan => switch (op) { + .vulkan, .opengl => switch (op) { .f_max => 40, // FMax .s_max => 42, // SMax .u_max => 41, // UMax @@ -2713,7 +2682,7 @@ const NavGen = struct { ) !struct { Temporary, Temporary } { const pt = self.pt; const zcu = pt.zcu; - const target = self.getTarget(); + const target = self.spv.target; const ip = &zcu.intern_pool; const v = lhs.vectorization(self).unify(rhs.vectorization(self)); @@ -2756,7 +2725,7 @@ const NavGen = struct { }); } }, - .vulkan => { + .vulkan, .opengl => { // Operations return a struct{T, T} // where T is maybe vectorized. const op_result_ty: Type = .fromInterned(try ip.getTupleType(zcu.gpa, pt.tid, .{ @@ -2843,7 +2812,7 @@ const NavGen = struct { const section = &self.spv.sections.functions; - const target = self.getTarget(); + const target = self.spv.target; const p_error_id = self.spv.allocId(); switch (target.os.tag) { @@ -2866,7 +2835,7 @@ const NavGen = struct { .id_result = self.spv.allocId(), }); }, - .vulkan => { + .vulkan, .opengl => { const ptr_ptr_anyerror_ty_id = self.spv.allocId(); try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpTypePointer, .{ .id_result = ptr_ptr_anyerror_ty_id, @@ -2967,7 +2936,7 @@ const NavGen = struct { defer self.gpa.free(test_name); const execution_mode: spec.ExecutionModel = switch (target.os.tag) { - .vulkan => .GLCompute, + .vulkan, .opengl => .GLCompute, .opencl => .Kernel, else => unreachable, }; @@ -3670,7 +3639,6 @@ const NavGen = struct { } fn abs(self: *NavGen, result_ty: Type, value: Temporary) !Temporary { - const target = self.getTarget(); const operand_info = self.arithmeticTypeInfo(value.ty); switch (operand_info.class) { @@ -3682,7 +3650,7 @@ const NavGen = struct { // depending on the result type. Do that when // bitCast is implemented for vectors. // This is only relevant for Vulkan - assert(target.os.tag != .vulkan); // TODO + assert(self.spv.hasFeature(.Kernel)); // TODO return try self.normalize(abs_value, self.arithmeticTypeInfo(result_ty)); }, @@ -3756,7 +3724,6 @@ const NavGen = struct { } fn airMulOverflow(self: *NavGen, inst: Air.Inst.Index) !?IdRef { - const target = self.getTarget(); const pt = self.pt; const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; @@ -3780,7 +3747,7 @@ const NavGen = struct { // - Additionally, if info.bits != 32, we'll have to check the high bits // of the result too. - const largest_int_bits: u16 = if (Target.spirv.featureSetHas(target.cpu.features, .Int64)) 64 else 32; + const largest_int_bits = self.largestSupportedIntBits(); // If non-null, the number of bits that the multiplication should be performed in. If // null, we have to use wide multiplication. const maybe_op_ty_bits: ?u16 = switch (info.bits) { @@ -3989,7 +3956,6 @@ const NavGen = struct { if (self.liveness.isUnused(inst)) return null; const zcu = self.pt.zcu; - const target = self.getTarget(); const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const operand = try self.temporary(ty_op.operand); @@ -4002,10 +3968,7 @@ const NavGen = struct { .float, .bool => unreachable, } - switch (target.os.tag) { - .vulkan => unreachable, // TODO - else => {}, - } + assert(self.spv.hasFeature(.Kernel)); // TODO const count = try self.buildUnary(op, operand); @@ -4241,23 +4204,22 @@ const NavGen = struct { defer self.gpa.free(ids); const result_id = self.spv.allocId(); - const target = self.getTarget(); - switch (target.os.tag) { - .opencl => try self.func.body.emit(self.spv.gpa, .OpInBoundsPtrAccessChain, .{ + if (self.spv.hasFeature(.Kernel)) { + try self.func.body.emit(self.spv.gpa, .OpInBoundsPtrAccessChain, .{ .id_result_type = result_ty_id, .id_result = result_id, .base = base, .element = element, .indexes = ids, - }), - .vulkan => try self.func.body.emit(self.spv.gpa, .OpPtrAccessChain, .{ + }); + } else { + try self.func.body.emit(self.spv.gpa, .OpPtrAccessChain, .{ .id_result_type = result_ty_id, .id_result = result_id, .base = base, .element = element, .indexes = ids, - }), - else => unreachable, + }); } return result_id; } @@ -5328,10 +5290,7 @@ const NavGen = struct { .initializer = options.initializer, }); - const target = self.getTarget(); - if (target.os.tag == .vulkan) { - return var_id; - } + if (self.spv.hasFeature(.Shader)) return var_id; switch (options.storage_class) { .Generic => { @@ -6204,7 +6163,7 @@ const NavGen = struct { fn airSwitchBr(self: *NavGen, inst: Air.Inst.Index) !void { const pt = self.pt; const zcu = pt.zcu; - const target = self.getTarget(); + const target = self.spv.target; const switch_br = self.air.unwrapSwitch(inst); const cond_ty = self.typeOf(switch_br.operand); const cond = try self.resolve(switch_br.operand); diff --git a/src/codegen/spirv/Module.zig b/src/codegen/spirv/Module.zig index 8e7f5ad4bc..6d5b0afccc 100644 --- a/src/codegen/spirv/Module.zig +++ b/src/codegen/spirv/Module.zig @@ -118,6 +118,12 @@ gpa: Allocator, /// Arena for things that need to live for the length of this program. arena: std.heap.ArenaAllocator, +/// Target info +target: std.Target, + +/// The target SPIR-V version +version: spec.Version, + /// Module layout, according to SPIR-V Spec section 2.4, "Logical Layout of a Module". sections: struct { /// Capability instructions @@ -196,10 +202,23 @@ entry_points: std.ArrayListUnmanaged(EntryPoint) = .empty, /// The list of extended instruction sets that should be imported. extended_instruction_set: std.AutoHashMapUnmanaged(spec.InstructionSet, IdRef) = .empty, -pub fn init(gpa: Allocator) Module { +pub fn init(gpa: Allocator, target: std.Target) Module { + const version_minor: u8 = blk: { + // Prefer higher versions + if (std.Target.spirv.featureSetHas(target.cpu.features, .v1_6)) break :blk 6; + if (std.Target.spirv.featureSetHas(target.cpu.features, .v1_5)) break :blk 5; + if (std.Target.spirv.featureSetHas(target.cpu.features, .v1_4)) break :blk 4; + if (std.Target.spirv.featureSetHas(target.cpu.features, .v1_3)) break :blk 3; + if (std.Target.spirv.featureSetHas(target.cpu.features, .v1_2)) break :blk 2; + if (std.Target.spirv.featureSetHas(target.cpu.features, .v1_1)) break :blk 1; + break :blk 0; + }; + return .{ .gpa = gpa, .arena = std.heap.ArenaAllocator.init(gpa), + .target = target, + .version = .{ .major = 1, .minor = version_minor }, .next_result_id = 1, // 0 is an invalid SPIR-V result id, so start counting at 1. }; } @@ -263,6 +282,10 @@ pub fn idBound(self: Module) Word { return self.next_result_id; } +pub fn hasFeature(self: *Module, feature: std.Target.spirv.Feature) bool { + return std.Target.spirv.featureSetHas(self.target.cpu.features, feature); +} + fn addEntryPointDeps( self: *Module, decl_index: Decl.Index, @@ -315,7 +338,7 @@ fn entryPoints(self: *Module) !Section { return entry_points; } -pub fn finalize(self: *Module, a: Allocator, target: std.Target) ![]Word { +pub fn finalize(self: *Module, a: Allocator) ![]Word { // See SPIR-V Spec section 2.3, "Physical Layout of a SPIR-V Module and Instruction" // TODO: Audit calls to allocId() in this function to make it idempotent. @@ -324,16 +347,7 @@ pub fn finalize(self: *Module, a: Allocator, target: std.Target) ![]Word { const header = [_]Word{ spec.magic_number, - // TODO: From cpu features - spec.Version.toWord(.{ - .major = 1, - .minor = switch (target.os.tag) { - // Emit SPIR-V 1.3 for now. This is the highest version that Vulkan 1.1 supports. - .vulkan => 3, - // Emit SPIR-V 1.4 for now. This is the highest version that Intel's CPU OpenCL supports. - else => 4, - }, - }), + self.version.toWord(), spec.zig_generator_id, self.idBound(), 0, // Schema (currently reserved for future use) @@ -342,7 +356,7 @@ pub fn finalize(self: *Module, a: Allocator, target: std.Target) ![]Word { var source = Section{}; defer source.deinit(self.gpa); try self.sections.debug_strings.emit(self.gpa, .OpSource, .{ - .source_language = .Unknown, + .source_language = .Zig, .version = 0, // We cannot emit these because the Khronos translator does not parse this instruction // correctly. diff --git a/src/link/SpirV.zig b/src/link/SpirV.zig index a5b9615c5e..7e2f2b1114 100644 --- a/src/link/SpirV.zig +++ b/src/link/SpirV.zig @@ -75,7 +75,7 @@ pub fn createEmpty( .disable_lld_caching = options.disable_lld_caching, .build_id = options.build_id, }, - .object = codegen.Object.init(gpa), + .object = codegen.Object.init(gpa, comp.getTarget()), }; errdefer self.deinit(); @@ -172,7 +172,7 @@ pub fn updateExports( const spv_decl_index = try self.object.resolveNav(zcu, nav_index); const cc = Type.fromInterned(nav_ty).fnCallingConvention(zcu); const execution_model: spec.ExecutionModel = switch (target.os.tag) { - .vulkan => switch (cc) { + .vulkan, .opengl => switch (cc) { .spirv_vertex => .Vertex, .spirv_fragment => .Fragment, .spirv_kernel => .GLCompute, @@ -231,10 +231,9 @@ pub fn flushModule( const spv = &self.object.spv; const diags = &comp.link_diags; const gpa = comp.gpa; - const target = comp.getTarget(); - try writeCapabilities(spv, target); - try writeMemoryModel(spv, target); + try writeCapabilities(spv); + try writeMemoryModel(spv); // We need to export the list of error names somewhere so that we can pretty-print them in the // executor. This is not really an important thing though, so we can just dump it in any old @@ -269,7 +268,7 @@ pub fn flushModule( .extension = error_info.items, }); - const module = try spv.finalize(arena, target); + const module = try spv.finalize(arena); errdefer arena.free(module); const linked_module = self.linkModule(arena, module, sub_prog_node) catch |err| switch (err) { @@ -299,56 +298,63 @@ fn linkModule(self: *SpirV, a: Allocator, module: []Word, progress: std.Progress return binary.finalize(a); } -fn writeCapabilities(spv: *SpvModule, target: std.Target) !void { - const gpa = spv.gpa; - // TODO: Integrate with a hypothetical feature system - const caps: []const spec.Capability = switch (target.os.tag) { - .opencl => &.{ .Kernel, .Addresses, .Int8, .Int16, .Int64, .Float64, .Float16, .Vector16, .GenericPointer }, - .vulkan => &.{ .Shader, .PhysicalStorageBufferAddresses, .Int8, .Int16, .Int64, .Float64, .Float16, .VariablePointers, .VariablePointersStorageBuffer }, - else => unreachable, - }; +fn writeCapabilities(spv: *SpvModule) !void { + var caps: std.ArrayList(spec.Capability) = .init(spv.gpa); + var extensions: std.ArrayList([]const u8) = .init(spv.gpa); + defer { + caps.deinit(); + extensions.deinit(); + } - for (caps) |cap| { - try spv.sections.capabilities.emit(gpa, .OpCapability, .{ + // Currently all spirv target features name are mapped to a Capability or an Extension. + // Except for versions which we ignore. + for (std.Target.spirv.all_features, 0..) |_, i| { + if (spv.target.cpu.features.isEnabled(@intCast(i))) { + const feature: std.Target.spirv.Feature = @enumFromInt(i); + const name = @tagName(feature); + if (std.meta.stringToEnum(spec.Capability, name)) |cap| { + try caps.append(cap); + } else if (std.mem.startsWith(u8, name, "SPV_")) { + try extensions.append(name); + } + } + } + + for (caps.items) |cap| { + try spv.sections.capabilities.emit(spv.gpa, .OpCapability, .{ .capability = cap, }); } - switch (target.os.tag) { - .vulkan => { - try spv.sections.extensions.emit(gpa, .OpExtension, .{ - .name = "SPV_KHR_physical_storage_buffer", - }); - }, - else => {}, + for (extensions.items) |ext| { + try spv.sections.extensions.emit(spv.gpa, .OpExtension, .{ .name = ext }); } } -fn writeMemoryModel(spv: *SpvModule, target: std.Target) !void { - const gpa = spv.gpa; +fn writeMemoryModel(spv: *SpvModule) !void { + const addressing_model: spec.AddressingModel = blk: { + if (spv.hasFeature(.Shader)) { + break :blk switch (spv.target.cpu.arch) { + .spirv32 => .Logical, // TODO: I don't think this will ever be implemented. + .spirv64 => .PhysicalStorageBuffer64, + else => unreachable, + }; + } else if (spv.hasFeature(.Kernel)) { + break :blk switch (spv.target.cpu.arch) { + .spirv32 => .Physical32, + .spirv64 => .Physical64, + else => unreachable, + }; + } - const addressing_model: spec.AddressingModel = switch (target.os.tag) { - .opencl => switch (target.cpu.arch) { - .spirv32 => .Physical32, - .spirv64 => .Physical64, - else => unreachable, - }, - .opengl, .vulkan => switch (target.cpu.arch) { - .spirv32 => .Logical, // TODO: I don't think this will ever be implemented. - .spirv64 => .PhysicalStorageBuffer64, - else => unreachable, - }, - else => unreachable, + unreachable; }; - - const memory_model: spec.MemoryModel = switch (target.os.tag) { + const memory_model: spec.MemoryModel = switch (spv.target.os.tag) { .opencl => .OpenCL, - .opengl => .GLSL450, - .vulkan => .GLSL450, + .vulkan, .opengl => .GLSL450, else => unreachable, }; - - try spv.sections.memory_model.emit(gpa, .OpMemoryModel, .{ + try spv.sections.memory_model.emit(spv.gpa, .OpMemoryModel, .{ .addressing_model = addressing_model, .memory_model = memory_model, }); -- cgit v1.2.3 From d5e1cb3ea2cdd85bc2a9ca002d69d121a94f721c Mon Sep 17 00:00:00 2001 From: Ali Cheraghi Date: Sat, 15 Feb 2025 00:08:05 +0330 Subject: spirv: ziggify and remove unknown spirv features `OpCapability` and `OpExtension` now can also be emitted from inline assembly --- lib/std/Target.zig | 2 +- lib/std/Target/spirv.zig | 2803 +-------------------------------------- src/codegen/spirv.zig | 36 +- src/codegen/spirv/Assembler.zig | 10 + src/codegen/spirv/Module.zig | 83 +- src/link/SpirV.zig | 66 - test/standalone/build.zig | 1 - tools/update_cpu_features.zig | 7 - tools/update_spirv_features.zig | 361 ----- 9 files changed, 154 insertions(+), 3215 deletions(-) delete mode 100644 tools/update_spirv_features.zig (limited to 'src/codegen/spirv.zig') diff --git a/lib/std/Target.zig b/lib/std/Target.zig index 402b6a85d3..740949858f 100644 --- a/lib/std/Target.zig +++ b/lib/std/Target.zig @@ -1184,7 +1184,7 @@ pub const Cpu = struct { pub const Set = struct { ints: [usize_count]usize, - pub const needed_bit_count = 398; + pub const needed_bit_count = 288; 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))); diff --git a/lib/std/Target/spirv.zig b/lib/std/Target/spirv.zig index de0370d1ad..73d57060be 100644 --- a/lib/std/Target/spirv.zig +++ b/lib/std/Target/spirv.zig @@ -1,8 +1,3 @@ -//! This file is auto-generated by tools/update_spirv_features.zig. -//! TODO: Dependencies of capabilities on extensions. -//! TODO: Dependencies of extensions on extensions. -//! TODO: Dependencies of extensions on versions. - const std = @import("../std.zig"); const CpuFeature = std.Target.Cpu.Feature; const CpuModel = std.Target.Cpu.Model; @@ -15,397 +10,17 @@ pub const Feature = enum { v1_4, v1_5, v1_6, - SPV_AMDX_shader_enqueue, - SPV_AMD_gcn_shader, - SPV_AMD_gpu_shader_half_float, - SPV_AMD_gpu_shader_half_float_fetch, - SPV_AMD_gpu_shader_int16, - SPV_AMD_shader_ballot, - SPV_AMD_shader_early_and_late_fragment_tests, - SPV_AMD_shader_explicit_vertex_parameter, - SPV_AMD_shader_fragment_mask, - SPV_AMD_shader_image_load_store_lod, - SPV_AMD_shader_trinary_minmax, - SPV_AMD_texture_gather_bias_lod, - SPV_ARM_cooperative_matrix_layouts, - SPV_ARM_core_builtins, - SPV_EXT_arithmetic_fence, - SPV_EXT_demote_to_helper_invocation, - SPV_EXT_descriptor_indexing, - SPV_EXT_fragment_fully_covered, - SPV_EXT_fragment_invocation_density, - SPV_EXT_fragment_shader_interlock, - SPV_EXT_image_raw10_raw12, - SPV_EXT_mesh_shader, - SPV_EXT_opacity_micromap, - SPV_EXT_optnone, - SPV_EXT_physical_storage_buffer, - SPV_EXT_replicated_composites, - SPV_EXT_shader_atomic_float16_add, - SPV_EXT_shader_atomic_float_add, - SPV_EXT_shader_atomic_float_min_max, - SPV_EXT_shader_image_int64, - SPV_EXT_shader_stencil_export, - SPV_EXT_shader_tile_image, - SPV_EXT_shader_viewport_index_layer, - SPV_EXT_ycbcr_attachments, - SPV_GOOGLE_decorate_string, - SPV_GOOGLE_hlsl_functionality1, - SPV_GOOGLE_user_type, - SPV_HUAWEI_cluster_culling_shader, - SPV_HUAWEI_subpass_shading, - SPV_INTEL_arbitrary_precision_fixed_point, - SPV_INTEL_arbitrary_precision_floating_point, - SPV_INTEL_arbitrary_precision_integers, - SPV_INTEL_blocking_pipes, - SPV_INTEL_device_side_avc_motion_estimation, - SPV_INTEL_fpga_argument_interfaces, - SPV_INTEL_fpga_buffer_location, - SPV_INTEL_fpga_cluster_attributes, - SPV_INTEL_fpga_dsp_control, - SPV_INTEL_fpga_invocation_pipelining_attributes, - SPV_INTEL_fpga_latency_control, - SPV_INTEL_fpga_loop_controls, - SPV_INTEL_fpga_memory_accesses, - SPV_INTEL_fpga_memory_attributes, - SPV_INTEL_fpga_reg, - SPV_INTEL_fp_fast_math_mode, - SPV_INTEL_fp_max_error, - SPV_INTEL_global_variable_fpga_decorations, - SPV_INTEL_global_variable_host_access, - SPV_INTEL_io_pipes, - SPV_INTEL_kernel_attributes, - SPV_INTEL_long_composites, - SPV_INTEL_loop_fuse, - SPV_INTEL_maximum_registers, - SPV_INTEL_media_block_io, - SPV_INTEL_runtime_aligned, - SPV_INTEL_shader_integer_functions2, - SPV_INTEL_split_barrier, - SPV_INTEL_subgroups, - SPV_INTEL_subgroup_buffer_prefetch, - SPV_INTEL_task_sequence, - SPV_INTEL_unstructured_loop_controls, - SPV_INTEL_usm_storage_classes, - SPV_KHR_16bit_storage, - SPV_KHR_8bit_storage, - SPV_KHR_bit_instructions, - SPV_KHR_compute_shader_derivatives, - SPV_KHR_cooperative_matrix, - SPV_KHR_device_group, - SPV_KHR_expect_assume, - SPV_KHR_float_controls, - SPV_KHR_float_controls2, - SPV_KHR_fragment_shader_barycentric, - SPV_KHR_fragment_shading_rate, - SPV_KHR_integer_dot_product, - SPV_KHR_linkonce_odr, - SPV_KHR_maximal_reconvergence, - SPV_KHR_multiview, - SPV_KHR_non_semantic_info, - SPV_KHR_no_integer_wrap_decoration, - SPV_KHR_physical_storage_buffer, - SPV_KHR_post_depth_coverage, - SPV_KHR_quad_control, - SPV_KHR_ray_cull_mask, - SPV_KHR_ray_query, - SPV_KHR_ray_tracing, - SPV_KHR_ray_tracing_position_fetch, - SPV_KHR_relaxed_extended_instruction, - SPV_KHR_shader_atomic_counter_ops, - SPV_KHR_shader_ballot, - SPV_KHR_shader_clock, - SPV_KHR_shader_draw_parameters, - SPV_KHR_storage_buffer_storage_class, - SPV_KHR_subgroup_rotate, - SPV_KHR_subgroup_uniform_control_flow, - SPV_KHR_subgroup_vote, - SPV_KHR_terminate_invocation, - SPV_KHR_untyped_pointers, - SPV_KHR_variable_pointers, - SPV_KHR_vulkan_memory_model, - SPV_KHR_workgroup_memory_explicit_layout, - SPV_NVX_multiview_per_view_attributes, - SPV_NV_bindless_texture, - SPV_NV_cluster_acceleration_structure, - SPV_NV_compute_shader_derivatives, - SPV_NV_cooperative_matrix, - SPV_NV_cooperative_matrix2, - SPV_NV_cooperative_vector, - SPV_NV_displacement_micromap, - SPV_NV_fragment_shader_barycentric, - SPV_NV_geometry_shader_passthrough, - SPV_NV_linear_swept_spheres, - SPV_NV_mesh_shader, - SPV_NV_raw_access_chains, - SPV_NV_ray_tracing, - SPV_NV_ray_tracing_motion_blur, - SPV_NV_sample_mask_override_coverage, - SPV_NV_shader_atomic_fp16_vector, - SPV_NV_shader_image_footprint, - SPV_NV_shader_invocation_reorder, - SPV_NV_shader_sm_builtins, - SPV_NV_shader_subgroup_partitioned, - SPV_NV_shading_rate, - SPV_NV_stereo_view_rendering, - SPV_NV_tensor_addressing, - SPV_NV_viewport_array2, - SPV_QCOM_image_processing, - SPV_QCOM_image_processing2, - Matrix, - Shader, - Geometry, - Tessellation, - Addresses, - Linkage, - Kernel, - Vector16, - Float16Buffer, - Float16, - Float64, - Int64, - Int64Atomics, - ImageBasic, - ImageReadWrite, - ImageMipmap, - Pipes, - Groups, - DeviceEnqueue, - LiteralSampler, - AtomicStorage, - Int16, - TessellationPointSize, - GeometryPointSize, - ImageGatherExtended, - StorageImageMultisample, - UniformBufferArrayDynamicIndexing, - SampledImageArrayDynamicIndexing, - StorageBufferArrayDynamicIndexing, - StorageImageArrayDynamicIndexing, - ClipDistance, - CullDistance, - ImageCubeArray, - SampleRateShading, - ImageRect, - SampledRect, - GenericPointer, - Int8, - InputAttachment, - SparseResidency, - MinLod, - Sampled1D, - Image1D, - SampledCubeArray, - SampledBuffer, - ImageBuffer, - ImageMSArray, - StorageImageExtendedFormats, - ImageQuery, - DerivativeControl, - InterpolationFunction, - TransformFeedback, - GeometryStreams, - StorageImageReadWithoutFormat, - StorageImageWriteWithoutFormat, - MultiViewport, - SubgroupDispatch, - NamedBarrier, - PipeStorage, - GroupNonUniform, - GroupNonUniformVote, - GroupNonUniformArithmetic, - GroupNonUniformBallot, - GroupNonUniformShuffle, - GroupNonUniformShuffleRelative, - GroupNonUniformClustered, - GroupNonUniformQuad, - ShaderLayer, - ShaderViewportIndex, - UniformDecoration, - CoreBuiltinsARM, - TileImageColorReadAccessEXT, - TileImageDepthReadAccessEXT, - TileImageStencilReadAccessEXT, - CooperativeMatrixLayoutsARM, - FragmentShadingRateKHR, - SubgroupBallotKHR, - DrawParameters, - WorkgroupMemoryExplicitLayoutKHR, - WorkgroupMemoryExplicitLayout8BitAccessKHR, - WorkgroupMemoryExplicitLayout16BitAccessKHR, - SubgroupVoteKHR, - StorageBuffer16BitAccess, - UniformAndStorageBuffer16BitAccess, - StoragePushConstant16, - StorageInputOutput16, - DeviceGroup, - MultiView, - VariablePointersStorageBuffer, - VariablePointers, - AtomicStorageOps, - SampleMaskPostDepthCoverage, - StorageBuffer8BitAccess, - UniformAndStorageBuffer8BitAccess, - StoragePushConstant8, - DenormPreserve, - DenormFlushToZero, - SignedZeroInfNanPreserve, - RoundingModeRTE, - RoundingModeRTZ, - RayQueryProvisionalKHR, - RayQueryKHR, - UntypedPointersKHR, - RayTraversalPrimitiveCullingKHR, - RayTracingKHR, - TextureSampleWeightedQCOM, - TextureBoxFilterQCOM, - TextureBlockMatchQCOM, - TextureBlockMatch2QCOM, - Float16ImageAMD, - ImageGatherBiasLodAMD, - FragmentMaskAMD, - StencilExportEXT, - ImageReadWriteLodAMD, - Int64ImageEXT, - ShaderClockKHR, - ShaderEnqueueAMDX, - QuadControlKHR, - SampleMaskOverrideCoverageNV, - GeometryShaderPassthroughNV, - ShaderViewportIndexLayerEXT, - ShaderViewportMaskNV, - ShaderStereoViewNV, - PerViewAttributesNV, - FragmentFullyCoveredEXT, - MeshShadingNV, - ImageFootprintNV, - MeshShadingEXT, - FragmentBarycentricKHR, - ComputeDerivativeGroupQuadsKHR, - FragmentDensityEXT, - GroupNonUniformPartitionedNV, - ShaderNonUniform, - RuntimeDescriptorArray, - InputAttachmentArrayDynamicIndexing, - UniformTexelBufferArrayDynamicIndexing, - StorageTexelBufferArrayDynamicIndexing, - UniformBufferArrayNonUniformIndexing, - SampledImageArrayNonUniformIndexing, - StorageBufferArrayNonUniformIndexing, - StorageImageArrayNonUniformIndexing, - InputAttachmentArrayNonUniformIndexing, - UniformTexelBufferArrayNonUniformIndexing, - StorageTexelBufferArrayNonUniformIndexing, - RayTracingPositionFetchKHR, - RayTracingNV, - RayTracingMotionBlurNV, - VulkanMemoryModel, - VulkanMemoryModelDeviceScope, - PhysicalStorageBufferAddresses, - ComputeDerivativeGroupLinearKHR, - RayTracingProvisionalKHR, - CooperativeMatrixNV, - FragmentShaderSampleInterlockEXT, - FragmentShaderShadingRateInterlockEXT, - ShaderSMBuiltinsNV, - FragmentShaderPixelInterlockEXT, - DemoteToHelperInvocation, - DisplacementMicromapNV, - RayTracingOpacityMicromapEXT, - ShaderInvocationReorderNV, - BindlessTextureNV, - RayQueryPositionFetchKHR, - CooperativeVectorNV, - AtomicFloat16VectorNV, - RayTracingDisplacementMicromapNV, - RawAccessChainsNV, - RayTracingSpheresGeometryNV, - RayTracingLinearSweptSpheresGeometryNV, - CooperativeMatrixReductionsNV, - CooperativeMatrixConversionsNV, - CooperativeMatrixPerElementOperationsNV, - CooperativeMatrixTensorAddressingNV, - CooperativeMatrixBlockLoadsNV, - CooperativeVectorTrainingNV, - RayTracingClusterAccelerationStructureNV, - TensorAddressingNV, - SubgroupShuffleINTEL, - SubgroupBufferBlockIOINTEL, - SubgroupImageBlockIOINTEL, - SubgroupImageMediaBlockIOINTEL, - RoundToInfinityINTEL, - FloatingPointModeINTEL, - IntegerFunctions2INTEL, - FunctionPointersINTEL, - IndirectReferencesINTEL, - AsmINTEL, - AtomicFloat32MinMaxEXT, - AtomicFloat64MinMaxEXT, - AtomicFloat16MinMaxEXT, - VectorComputeINTEL, - VectorAnyINTEL, - ExpectAssumeKHR, - SubgroupAvcMotionEstimationINTEL, - SubgroupAvcMotionEstimationIntraINTEL, - SubgroupAvcMotionEstimationChromaINTEL, - VariableLengthArrayINTEL, - FunctionFloatControlINTEL, - FPGAMemoryAttributesINTEL, - FPFastMathModeINTEL, - ArbitraryPrecisionIntegersINTEL, - ArbitraryPrecisionFloatingPointINTEL, - UnstructuredLoopControlsINTEL, - FPGALoopControlsINTEL, - KernelAttributesINTEL, - FPGAKernelAttributesINTEL, - FPGAMemoryAccessesINTEL, - FPGAClusterAttributesINTEL, - LoopFuseINTEL, - FPGADSPControlINTEL, - MemoryAccessAliasingINTEL, - FPGAInvocationPipeliningAttributesINTEL, - FPGABufferLocationINTEL, - ArbitraryPrecisionFixedPointINTEL, - USMStorageClassesINTEL, - RuntimeAlignedAttributeINTEL, - IOPipesINTEL, - BlockingPipesINTEL, - FPGARegINTEL, - DotProductInputAll, - DotProductInput4x8Bit, - DotProductInput4x8BitPacked, - DotProduct, - RayCullMaskKHR, - CooperativeMatrixKHR, - ReplicatedCompositesEXT, - BitInstructions, - GroupNonUniformRotateKHR, - FloatControls2, - AtomicFloat32AddEXT, - AtomicFloat64AddEXT, - LongCompositesINTEL, - OptNoneEXT, - AtomicFloat16AddEXT, - DebugInfoModuleINTEL, - BFloat16ConversionINTEL, - SplitBarrierINTEL, - ArithmeticFenceEXT, - FPGAClusterAttributesV2INTEL, - FPGAKernelAttributesv2INTEL, - FPMaxErrorINTEL, - FPGALatencyControlINTEL, - FPGAArgumentInterfacesINTEL, - GlobalVariableHostAccessINTEL, - GlobalVariableFPGADecorationsINTEL, - SubgroupBufferPrefetchINTEL, - Subgroup2DBlockIOINTEL, - Subgroup2DBlockTransformINTEL, - Subgroup2DBlockTransposeINTEL, - SubgroupMatrixMultiplyAccumulateINTEL, - GroupUniformArithmeticKHR, - MaskedGatherScatterINTEL, - CacheControlsINTEL, - RegisterLimitsINTEL, + int8, + int16, + int64, + float16, + float64, + addresses, + matrix, + kernel, + generic_pointer, + vector16, + shader, }; pub const featureSet = CpuFeature.FeatureSetFns(Feature).featureSet; @@ -426,2391 +41,87 @@ pub const all_features = blk: { result[@intFromEnum(Feature.v1_1)] = .{ .llvm_name = null, .description = "SPIR-V version 1.1", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - }), + .dependencies = featureSet(&[_]Feature{.v1_0}), }; result[@intFromEnum(Feature.v1_2)] = .{ .llvm_name = null, .description = "SPIR-V version 1.2", - .dependencies = featureSet(&[_]Feature{ - .v1_1, - }), + .dependencies = featureSet(&[_]Feature{.v1_1}), }; result[@intFromEnum(Feature.v1_3)] = .{ .llvm_name = null, .description = "SPIR-V version 1.3", - .dependencies = featureSet(&[_]Feature{ - .v1_2, - }), + .dependencies = featureSet(&[_]Feature{.v1_2}), }; result[@intFromEnum(Feature.v1_4)] = .{ .llvm_name = null, .description = "SPIR-V version 1.4", - .dependencies = featureSet(&[_]Feature{ - .v1_3, - }), + .dependencies = featureSet(&[_]Feature{.v1_3}), }; result[@intFromEnum(Feature.v1_5)] = .{ .llvm_name = null, .description = "SPIR-V version 1.5", - .dependencies = featureSet(&[_]Feature{ - .v1_4, - }), + .dependencies = featureSet(&[_]Feature{.v1_4}), }; result[@intFromEnum(Feature.v1_6)] = .{ .llvm_name = null, .description = "SPIR-V version 1.6", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - }), - }; - result[@intFromEnum(Feature.SPV_AMDX_shader_enqueue)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_AMDX_shader_enqueue", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_AMD_gcn_shader)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_AMD_gcn_shader", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_AMD_gpu_shader_half_float)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_AMD_gpu_shader_half_float", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_AMD_gpu_shader_half_float_fetch)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_AMD_gpu_shader_half_float_fetch", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_AMD_gpu_shader_int16)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_AMD_gpu_shader_int16", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_AMD_shader_ballot)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_AMD_shader_ballot", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_AMD_shader_early_and_late_fragment_tests)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_AMD_shader_early_and_late_fragment_tests", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_AMD_shader_explicit_vertex_parameter)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_AMD_shader_explicit_vertex_parameter", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_AMD_shader_fragment_mask)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_AMD_shader_fragment_mask", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_AMD_shader_image_load_store_lod)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_AMD_shader_image_load_store_lod", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_AMD_shader_trinary_minmax)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_AMD_shader_trinary_minmax", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_AMD_texture_gather_bias_lod)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_AMD_texture_gather_bias_lod", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_ARM_cooperative_matrix_layouts)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_ARM_cooperative_matrix_layouts", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_ARM_core_builtins)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_ARM_core_builtins", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_EXT_arithmetic_fence)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_EXT_arithmetic_fence", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_EXT_demote_to_helper_invocation)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_EXT_demote_to_helper_invocation", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_EXT_descriptor_indexing)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_EXT_descriptor_indexing", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_EXT_fragment_fully_covered)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_EXT_fragment_fully_covered", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_EXT_fragment_invocation_density)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_EXT_fragment_invocation_density", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_EXT_fragment_shader_interlock)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_EXT_fragment_shader_interlock", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_EXT_image_raw10_raw12)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_EXT_image_raw10_raw12", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_EXT_mesh_shader)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_EXT_mesh_shader", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_EXT_opacity_micromap)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_EXT_opacity_micromap", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_EXT_optnone)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_EXT_optnone", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_EXT_physical_storage_buffer)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_EXT_physical_storage_buffer", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_EXT_replicated_composites)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_EXT_replicated_composites", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_EXT_shader_atomic_float16_add)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_EXT_shader_atomic_float16_add", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_EXT_shader_atomic_float_add)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_EXT_shader_atomic_float_add", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_EXT_shader_atomic_float_min_max)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_EXT_shader_atomic_float_min_max", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_EXT_shader_image_int64)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_EXT_shader_image_int64", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_EXT_shader_stencil_export)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_EXT_shader_stencil_export", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_EXT_shader_tile_image)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_EXT_shader_tile_image", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_EXT_shader_viewport_index_layer)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_EXT_shader_viewport_index_layer", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_EXT_ycbcr_attachments)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_EXT_ycbcr_attachments", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_GOOGLE_decorate_string)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_GOOGLE_decorate_string", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_GOOGLE_hlsl_functionality1)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_GOOGLE_hlsl_functionality1", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_GOOGLE_user_type)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_GOOGLE_user_type", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_HUAWEI_cluster_culling_shader)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_HUAWEI_cluster_culling_shader", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_HUAWEI_subpass_shading)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_HUAWEI_subpass_shading", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_INTEL_arbitrary_precision_fixed_point)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_INTEL_arbitrary_precision_fixed_point", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_INTEL_arbitrary_precision_floating_point)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_INTEL_arbitrary_precision_floating_point", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_INTEL_arbitrary_precision_integers)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_INTEL_arbitrary_precision_integers", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_INTEL_blocking_pipes)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_INTEL_blocking_pipes", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_INTEL_device_side_avc_motion_estimation)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_INTEL_device_side_avc_motion_estimation", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_INTEL_fpga_argument_interfaces)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_INTEL_fpga_argument_interfaces", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_INTEL_fpga_buffer_location)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_INTEL_fpga_buffer_location", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_INTEL_fpga_cluster_attributes)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_INTEL_fpga_cluster_attributes", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_INTEL_fpga_dsp_control)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_INTEL_fpga_dsp_control", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_INTEL_fpga_invocation_pipelining_attributes)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_INTEL_fpga_invocation_pipelining_attributes", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_INTEL_fpga_latency_control)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_INTEL_fpga_latency_control", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_INTEL_fpga_loop_controls)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_INTEL_fpga_loop_controls", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_INTEL_fpga_memory_accesses)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_INTEL_fpga_memory_accesses", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_INTEL_fpga_memory_attributes)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_INTEL_fpga_memory_attributes", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_INTEL_fpga_reg)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_INTEL_fpga_reg", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_INTEL_fp_fast_math_mode)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_INTEL_fp_fast_math_mode", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_INTEL_fp_max_error)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_INTEL_fp_max_error", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_INTEL_global_variable_fpga_decorations)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_INTEL_global_variable_fpga_decorations", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_INTEL_global_variable_host_access)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_INTEL_global_variable_host_access", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_INTEL_io_pipes)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_INTEL_io_pipes", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_INTEL_kernel_attributes)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_INTEL_kernel_attributes", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_INTEL_long_composites)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_INTEL_long_composites", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_INTEL_loop_fuse)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_INTEL_loop_fuse", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_INTEL_maximum_registers)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_INTEL_maximum_registers", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_INTEL_media_block_io)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_INTEL_media_block_io", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_INTEL_runtime_aligned)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_INTEL_runtime_aligned", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_INTEL_shader_integer_functions2)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_INTEL_shader_integer_functions2", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_INTEL_split_barrier)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_INTEL_split_barrier", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_INTEL_subgroups)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_INTEL_subgroups", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_INTEL_subgroup_buffer_prefetch)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_INTEL_subgroup_buffer_prefetch", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_INTEL_task_sequence)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_INTEL_task_sequence", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_INTEL_unstructured_loop_controls)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_INTEL_unstructured_loop_controls", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_INTEL_usm_storage_classes)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_INTEL_usm_storage_classes", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_KHR_16bit_storage)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_16bit_storage", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_KHR_8bit_storage)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_8bit_storage", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_KHR_bit_instructions)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_bit_instructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_KHR_compute_shader_derivatives)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_compute_shader_derivatives", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_KHR_cooperative_matrix)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_cooperative_matrix", - .dependencies = featureSet(&[_]Feature{}), + .dependencies = featureSet(&[_]Feature{.v1_5}), }; - result[@intFromEnum(Feature.SPV_KHR_device_group)] = .{ + result[@intFromEnum(Feature.int8)] = .{ .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_device_group", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_KHR_expect_assume)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_expect_assume", - .dependencies = featureSet(&[_]Feature{}), + .description = "Enable SPIR-V capability Int8", + .dependencies = featureSet(&[_]Feature{.v1_0}), }; - result[@intFromEnum(Feature.SPV_KHR_float_controls)] = .{ + result[@intFromEnum(Feature.int16)] = .{ .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_float_controls", - .dependencies = featureSet(&[_]Feature{}), + .description = "Enable SPIR-V capability Int16", + .dependencies = featureSet(&[_]Feature{.v1_0}), }; - result[@intFromEnum(Feature.SPV_KHR_float_controls2)] = .{ + result[@intFromEnum(Feature.int64)] = .{ .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_float_controls2", - .dependencies = featureSet(&[_]Feature{}), + .description = "Enable SPIR-V capability Int64", + .dependencies = featureSet(&[_]Feature{.v1_0}), }; - result[@intFromEnum(Feature.SPV_KHR_fragment_shader_barycentric)] = .{ + result[@intFromEnum(Feature.float16)] = .{ .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_fragment_shader_barycentric", - .dependencies = featureSet(&[_]Feature{}), + .description = "Enable SPIR-V capability Float16", + .dependencies = featureSet(&[_]Feature{.v1_0}), }; - result[@intFromEnum(Feature.SPV_KHR_fragment_shading_rate)] = .{ + result[@intFromEnum(Feature.float64)] = .{ .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_fragment_shading_rate", - .dependencies = featureSet(&[_]Feature{}), + .description = "Enable SPIR-V capability Float64", + .dependencies = featureSet(&[_]Feature{.v1_0}), }; - result[@intFromEnum(Feature.SPV_KHR_integer_dot_product)] = .{ + result[@intFromEnum(Feature.addresses)] = .{ .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_integer_dot_product", - .dependencies = featureSet(&[_]Feature{}), + .description = "Enable SPIR-V capability Addresses", + .dependencies = featureSet(&[_]Feature{.v1_0}), }; - result[@intFromEnum(Feature.SPV_KHR_linkonce_odr)] = .{ + result[@intFromEnum(Feature.matrix)] = .{ .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_linkonce_odr", - .dependencies = featureSet(&[_]Feature{}), + .description = "Enable SPIR-V capability Matrix", + .dependencies = featureSet(&[_]Feature{.v1_0}), }; - result[@intFromEnum(Feature.SPV_KHR_maximal_reconvergence)] = .{ + result[@intFromEnum(Feature.kernel)] = .{ .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_maximal_reconvergence", - .dependencies = featureSet(&[_]Feature{}), + .description = "Enable SPIR-V capability Kernel", + .dependencies = featureSet(&[_]Feature{.v1_0}), }; - result[@intFromEnum(Feature.SPV_KHR_multiview)] = .{ + result[@intFromEnum(Feature.generic_pointer)] = .{ .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_multiview", - .dependencies = featureSet(&[_]Feature{}), + .description = "Enable SPIR-V capability GenericPointer", + .dependencies = featureSet(&[_]Feature{ .v1_0, .addresses }), }; - result[@intFromEnum(Feature.SPV_KHR_non_semantic_info)] = .{ + result[@intFromEnum(Feature.vector16)] = .{ .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_non_semantic_info", - .dependencies = featureSet(&[_]Feature{}), + .description = "Enable SPIR-V capability Vector16", + .dependencies = featureSet(&[_]Feature{ .v1_0, .kernel }), }; - result[@intFromEnum(Feature.SPV_KHR_no_integer_wrap_decoration)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_no_integer_wrap_decoration", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_KHR_physical_storage_buffer)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_physical_storage_buffer", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_KHR_post_depth_coverage)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_post_depth_coverage", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_KHR_quad_control)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_quad_control", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_KHR_ray_cull_mask)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_ray_cull_mask", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_KHR_ray_query)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_ray_query", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_KHR_ray_tracing)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_ray_tracing", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_KHR_ray_tracing_position_fetch)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_ray_tracing_position_fetch", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_KHR_relaxed_extended_instruction)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_relaxed_extended_instruction", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_KHR_shader_atomic_counter_ops)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_shader_atomic_counter_ops", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_KHR_shader_ballot)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_shader_ballot", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_KHR_shader_clock)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_shader_clock", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_KHR_shader_draw_parameters)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_shader_draw_parameters", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_KHR_storage_buffer_storage_class)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_storage_buffer_storage_class", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_KHR_subgroup_rotate)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_subgroup_rotate", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_KHR_subgroup_uniform_control_flow)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_subgroup_uniform_control_flow", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_KHR_subgroup_vote)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_subgroup_vote", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_KHR_terminate_invocation)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_terminate_invocation", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_KHR_untyped_pointers)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_untyped_pointers", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_KHR_variable_pointers)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_variable_pointers", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_KHR_vulkan_memory_model)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_vulkan_memory_model", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_KHR_workgroup_memory_explicit_layout)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_KHR_workgroup_memory_explicit_layout", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_NVX_multiview_per_view_attributes)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_NVX_multiview_per_view_attributes", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_NV_bindless_texture)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_NV_bindless_texture", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_NV_cluster_acceleration_structure)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_NV_cluster_acceleration_structure", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_NV_compute_shader_derivatives)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_NV_compute_shader_derivatives", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_NV_cooperative_matrix)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_NV_cooperative_matrix", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_NV_cooperative_matrix2)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_NV_cooperative_matrix2", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_NV_cooperative_vector)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_NV_cooperative_vector", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_NV_displacement_micromap)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_NV_displacement_micromap", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_NV_fragment_shader_barycentric)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_NV_fragment_shader_barycentric", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_NV_geometry_shader_passthrough)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_NV_geometry_shader_passthrough", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_NV_linear_swept_spheres)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_NV_linear_swept_spheres", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_NV_mesh_shader)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_NV_mesh_shader", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_NV_raw_access_chains)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_NV_raw_access_chains", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_NV_ray_tracing)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_NV_ray_tracing", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_NV_ray_tracing_motion_blur)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_NV_ray_tracing_motion_blur", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_NV_sample_mask_override_coverage)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_NV_sample_mask_override_coverage", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_NV_shader_atomic_fp16_vector)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_NV_shader_atomic_fp16_vector", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_NV_shader_image_footprint)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_NV_shader_image_footprint", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_NV_shader_invocation_reorder)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_NV_shader_invocation_reorder", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_NV_shader_sm_builtins)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_NV_shader_sm_builtins", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_NV_shader_subgroup_partitioned)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_NV_shader_subgroup_partitioned", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_NV_shading_rate)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_NV_shading_rate", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_NV_stereo_view_rendering)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_NV_stereo_view_rendering", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_NV_tensor_addressing)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_NV_tensor_addressing", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_NV_viewport_array2)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_NV_viewport_array2", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_QCOM_image_processing)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_QCOM_image_processing", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SPV_QCOM_image_processing2)] = .{ - .llvm_name = null, - .description = "SPIR-V extension SPV_QCOM_image_processing2", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.Matrix)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability Matrix", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - }), - }; - result[@intFromEnum(Feature.Shader)] = .{ + result[@intFromEnum(Feature.shader)] = .{ .llvm_name = null, .description = "Enable SPIR-V capability Shader", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - .Matrix, - }), - }; - result[@intFromEnum(Feature.Geometry)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability Geometry", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - .Shader, - }), - }; - result[@intFromEnum(Feature.Tessellation)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability Tessellation", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - .Shader, - }), - }; - result[@intFromEnum(Feature.Addresses)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability Addresses", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - }), - }; - result[@intFromEnum(Feature.Linkage)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability Linkage", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - }), - }; - result[@intFromEnum(Feature.Kernel)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability Kernel", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - }), - }; - result[@intFromEnum(Feature.Vector16)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability Vector16", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - .Kernel, - }), - }; - result[@intFromEnum(Feature.Float16Buffer)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability Float16Buffer", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - .Kernel, - }), - }; - result[@intFromEnum(Feature.Float16)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability Float16", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - }), - }; - result[@intFromEnum(Feature.Float64)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability Float64", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - }), - }; - result[@intFromEnum(Feature.Int64)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability Int64", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - }), - }; - result[@intFromEnum(Feature.Int64Atomics)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability Int64Atomics", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - .Int64, - }), - }; - result[@intFromEnum(Feature.ImageBasic)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ImageBasic", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - .Kernel, - }), - }; - result[@intFromEnum(Feature.ImageReadWrite)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ImageReadWrite", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - .ImageBasic, - }), - }; - result[@intFromEnum(Feature.ImageMipmap)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ImageMipmap", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - .ImageBasic, - }), - }; - result[@intFromEnum(Feature.Pipes)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability Pipes", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - .Kernel, - }), - }; - result[@intFromEnum(Feature.Groups)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability Groups", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - }), - }; - result[@intFromEnum(Feature.DeviceEnqueue)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability DeviceEnqueue", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - .Kernel, - }), - }; - result[@intFromEnum(Feature.LiteralSampler)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability LiteralSampler", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - .Kernel, - }), - }; - result[@intFromEnum(Feature.AtomicStorage)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability AtomicStorage", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - .Shader, - }), - }; - result[@intFromEnum(Feature.Int16)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability Int16", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - }), - }; - result[@intFromEnum(Feature.TessellationPointSize)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability TessellationPointSize", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - .Tessellation, - }), - }; - result[@intFromEnum(Feature.GeometryPointSize)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability GeometryPointSize", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - .Geometry, - }), - }; - result[@intFromEnum(Feature.ImageGatherExtended)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ImageGatherExtended", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - .Shader, - }), - }; - result[@intFromEnum(Feature.StorageImageMultisample)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability StorageImageMultisample", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - .Shader, - }), - }; - result[@intFromEnum(Feature.UniformBufferArrayDynamicIndexing)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability UniformBufferArrayDynamicIndexing", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - .Shader, - }), - }; - result[@intFromEnum(Feature.SampledImageArrayDynamicIndexing)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability SampledImageArrayDynamicIndexing", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - .Shader, - }), - }; - result[@intFromEnum(Feature.StorageBufferArrayDynamicIndexing)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability StorageBufferArrayDynamicIndexing", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - .Shader, - }), - }; - result[@intFromEnum(Feature.StorageImageArrayDynamicIndexing)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability StorageImageArrayDynamicIndexing", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - .Shader, - }), - }; - result[@intFromEnum(Feature.ClipDistance)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ClipDistance", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - .Shader, - }), - }; - result[@intFromEnum(Feature.CullDistance)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability CullDistance", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - .Shader, - }), - }; - result[@intFromEnum(Feature.ImageCubeArray)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ImageCubeArray", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - .SampledCubeArray, - }), - }; - result[@intFromEnum(Feature.SampleRateShading)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability SampleRateShading", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - .Shader, - }), - }; - result[@intFromEnum(Feature.ImageRect)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ImageRect", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - .SampledRect, - }), - }; - result[@intFromEnum(Feature.SampledRect)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability SampledRect", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - .Shader, - }), - }; - result[@intFromEnum(Feature.GenericPointer)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability GenericPointer", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - .Addresses, - }), - }; - result[@intFromEnum(Feature.Int8)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability Int8", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - }), - }; - result[@intFromEnum(Feature.InputAttachment)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability InputAttachment", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - .Shader, - }), - }; - result[@intFromEnum(Feature.SparseResidency)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability SparseResidency", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - .Shader, - }), - }; - result[@intFromEnum(Feature.MinLod)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability MinLod", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - .Shader, - }), - }; - result[@intFromEnum(Feature.Sampled1D)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability Sampled1D", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - }), - }; - result[@intFromEnum(Feature.Image1D)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability Image1D", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - .Sampled1D, - }), - }; - result[@intFromEnum(Feature.SampledCubeArray)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability SampledCubeArray", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - .Shader, - }), - }; - result[@intFromEnum(Feature.SampledBuffer)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability SampledBuffer", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - }), - }; - result[@intFromEnum(Feature.ImageBuffer)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ImageBuffer", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - .SampledBuffer, - }), - }; - result[@intFromEnum(Feature.ImageMSArray)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ImageMSArray", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - .Shader, - }), - }; - result[@intFromEnum(Feature.StorageImageExtendedFormats)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability StorageImageExtendedFormats", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - .Shader, - }), - }; - result[@intFromEnum(Feature.ImageQuery)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ImageQuery", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - .Shader, - }), - }; - result[@intFromEnum(Feature.DerivativeControl)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability DerivativeControl", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - .Shader, - }), - }; - result[@intFromEnum(Feature.InterpolationFunction)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability InterpolationFunction", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - .Shader, - }), - }; - result[@intFromEnum(Feature.TransformFeedback)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability TransformFeedback", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - .Shader, - }), - }; - result[@intFromEnum(Feature.GeometryStreams)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability GeometryStreams", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - .Geometry, - }), - }; - result[@intFromEnum(Feature.StorageImageReadWithoutFormat)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability StorageImageReadWithoutFormat", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - .Shader, - }), - }; - result[@intFromEnum(Feature.StorageImageWriteWithoutFormat)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability StorageImageWriteWithoutFormat", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - .Shader, - }), - }; - result[@intFromEnum(Feature.MultiViewport)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability MultiViewport", - .dependencies = featureSet(&[_]Feature{ - .v1_0, - .Geometry, - }), - }; - result[@intFromEnum(Feature.SubgroupDispatch)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability SubgroupDispatch", - .dependencies = featureSet(&[_]Feature{ - .v1_1, - .DeviceEnqueue, - }), - }; - result[@intFromEnum(Feature.NamedBarrier)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability NamedBarrier", - .dependencies = featureSet(&[_]Feature{ - .v1_1, - .Kernel, - }), - }; - result[@intFromEnum(Feature.PipeStorage)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability PipeStorage", - .dependencies = featureSet(&[_]Feature{ - .v1_1, - .Pipes, - }), - }; - result[@intFromEnum(Feature.GroupNonUniform)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability GroupNonUniform", - .dependencies = featureSet(&[_]Feature{ - .v1_3, - }), - }; - result[@intFromEnum(Feature.GroupNonUniformVote)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability GroupNonUniformVote", - .dependencies = featureSet(&[_]Feature{ - .v1_3, - .GroupNonUniform, - }), - }; - result[@intFromEnum(Feature.GroupNonUniformArithmetic)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability GroupNonUniformArithmetic", - .dependencies = featureSet(&[_]Feature{ - .v1_3, - .GroupNonUniform, - }), - }; - result[@intFromEnum(Feature.GroupNonUniformBallot)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability GroupNonUniformBallot", - .dependencies = featureSet(&[_]Feature{ - .v1_3, - .GroupNonUniform, - }), - }; - result[@intFromEnum(Feature.GroupNonUniformShuffle)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability GroupNonUniformShuffle", - .dependencies = featureSet(&[_]Feature{ - .v1_3, - .GroupNonUniform, - }), - }; - result[@intFromEnum(Feature.GroupNonUniformShuffleRelative)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability GroupNonUniformShuffleRelative", - .dependencies = featureSet(&[_]Feature{ - .v1_3, - .GroupNonUniform, - }), - }; - result[@intFromEnum(Feature.GroupNonUniformClustered)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability GroupNonUniformClustered", - .dependencies = featureSet(&[_]Feature{ - .v1_3, - .GroupNonUniform, - }), - }; - result[@intFromEnum(Feature.GroupNonUniformQuad)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability GroupNonUniformQuad", - .dependencies = featureSet(&[_]Feature{ - .v1_3, - .GroupNonUniform, - }), - }; - result[@intFromEnum(Feature.ShaderLayer)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ShaderLayer", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - }), - }; - result[@intFromEnum(Feature.ShaderViewportIndex)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ShaderViewportIndex", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - }), - }; - result[@intFromEnum(Feature.UniformDecoration)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability UniformDecoration", - .dependencies = featureSet(&[_]Feature{ - .v1_6, - }), - }; - result[@intFromEnum(Feature.CoreBuiltinsARM)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability CoreBuiltinsARM", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.TileImageColorReadAccessEXT)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability TileImageColorReadAccessEXT", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.TileImageDepthReadAccessEXT)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability TileImageDepthReadAccessEXT", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.TileImageStencilReadAccessEXT)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability TileImageStencilReadAccessEXT", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.CooperativeMatrixLayoutsARM)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability CooperativeMatrixLayoutsARM", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.FragmentShadingRateKHR)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability FragmentShadingRateKHR", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.SubgroupBallotKHR)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability SubgroupBallotKHR", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.DrawParameters)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability DrawParameters", - .dependencies = featureSet(&[_]Feature{ - .v1_3, - .Shader, - }), - }; - result[@intFromEnum(Feature.WorkgroupMemoryExplicitLayoutKHR)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability WorkgroupMemoryExplicitLayoutKHR", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.WorkgroupMemoryExplicitLayout8BitAccessKHR)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability WorkgroupMemoryExplicitLayout8BitAccessKHR", - .dependencies = featureSet(&[_]Feature{ - .WorkgroupMemoryExplicitLayoutKHR, - }), - }; - result[@intFromEnum(Feature.WorkgroupMemoryExplicitLayout16BitAccessKHR)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability WorkgroupMemoryExplicitLayout16BitAccessKHR", - .dependencies = featureSet(&[_]Feature{ - .WorkgroupMemoryExplicitLayoutKHR, - }), - }; - result[@intFromEnum(Feature.SubgroupVoteKHR)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability SubgroupVoteKHR", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.StorageBuffer16BitAccess)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability StorageBuffer16BitAccess", - .dependencies = featureSet(&[_]Feature{ - .v1_3, - }), - }; - result[@intFromEnum(Feature.UniformAndStorageBuffer16BitAccess)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability UniformAndStorageBuffer16BitAccess", - .dependencies = featureSet(&[_]Feature{ - .v1_3, - .StorageBuffer16BitAccess, - }), - }; - result[@intFromEnum(Feature.StoragePushConstant16)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability StoragePushConstant16", - .dependencies = featureSet(&[_]Feature{ - .v1_3, - }), - }; - result[@intFromEnum(Feature.StorageInputOutput16)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability StorageInputOutput16", - .dependencies = featureSet(&[_]Feature{ - .v1_3, - }), - }; - result[@intFromEnum(Feature.DeviceGroup)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability DeviceGroup", - .dependencies = featureSet(&[_]Feature{ - .v1_3, - }), - }; - result[@intFromEnum(Feature.MultiView)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability MultiView", - .dependencies = featureSet(&[_]Feature{ - .v1_3, - .Shader, - }), - }; - result[@intFromEnum(Feature.VariablePointersStorageBuffer)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability VariablePointersStorageBuffer", - .dependencies = featureSet(&[_]Feature{ - .v1_3, - .Shader, - }), - }; - result[@intFromEnum(Feature.VariablePointers)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability VariablePointers", - .dependencies = featureSet(&[_]Feature{ - .v1_3, - .VariablePointersStorageBuffer, - }), - }; - result[@intFromEnum(Feature.AtomicStorageOps)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability AtomicStorageOps", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SampleMaskPostDepthCoverage)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability SampleMaskPostDepthCoverage", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.StorageBuffer8BitAccess)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability StorageBuffer8BitAccess", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - }), - }; - result[@intFromEnum(Feature.UniformAndStorageBuffer8BitAccess)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability UniformAndStorageBuffer8BitAccess", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - .StorageBuffer8BitAccess, - }), - }; - result[@intFromEnum(Feature.StoragePushConstant8)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability StoragePushConstant8", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - }), - }; - result[@intFromEnum(Feature.DenormPreserve)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability DenormPreserve", - .dependencies = featureSet(&[_]Feature{ - .v1_4, - }), - }; - result[@intFromEnum(Feature.DenormFlushToZero)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability DenormFlushToZero", - .dependencies = featureSet(&[_]Feature{ - .v1_4, - }), - }; - result[@intFromEnum(Feature.SignedZeroInfNanPreserve)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability SignedZeroInfNanPreserve", - .dependencies = featureSet(&[_]Feature{ - .v1_4, - }), - }; - result[@intFromEnum(Feature.RoundingModeRTE)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability RoundingModeRTE", - .dependencies = featureSet(&[_]Feature{ - .v1_4, - }), - }; - result[@intFromEnum(Feature.RoundingModeRTZ)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability RoundingModeRTZ", - .dependencies = featureSet(&[_]Feature{ - .v1_4, - }), - }; - result[@intFromEnum(Feature.RayQueryProvisionalKHR)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability RayQueryProvisionalKHR", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.RayQueryKHR)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability RayQueryKHR", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.UntypedPointersKHR)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability UntypedPointersKHR", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.RayTraversalPrimitiveCullingKHR)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability RayTraversalPrimitiveCullingKHR", - .dependencies = featureSet(&[_]Feature{ - .RayQueryKHR, - .RayTracingKHR, - }), - }; - result[@intFromEnum(Feature.RayTracingKHR)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability RayTracingKHR", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.TextureSampleWeightedQCOM)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability TextureSampleWeightedQCOM", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.TextureBoxFilterQCOM)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability TextureBoxFilterQCOM", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.TextureBlockMatchQCOM)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability TextureBlockMatchQCOM", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.TextureBlockMatch2QCOM)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability TextureBlockMatch2QCOM", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.Float16ImageAMD)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability Float16ImageAMD", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.ImageGatherBiasLodAMD)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ImageGatherBiasLodAMD", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.FragmentMaskAMD)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability FragmentMaskAMD", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.StencilExportEXT)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability StencilExportEXT", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.ImageReadWriteLodAMD)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ImageReadWriteLodAMD", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.Int64ImageEXT)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability Int64ImageEXT", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.ShaderClockKHR)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ShaderClockKHR", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ShaderEnqueueAMDX)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ShaderEnqueueAMDX", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.QuadControlKHR)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability QuadControlKHR", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SampleMaskOverrideCoverageNV)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability SampleMaskOverrideCoverageNV", - .dependencies = featureSet(&[_]Feature{ - .SampleRateShading, - }), - }; - result[@intFromEnum(Feature.GeometryShaderPassthroughNV)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability GeometryShaderPassthroughNV", - .dependencies = featureSet(&[_]Feature{ - .Geometry, - }), - }; - result[@intFromEnum(Feature.ShaderViewportIndexLayerEXT)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ShaderViewportIndexLayerEXT", - .dependencies = featureSet(&[_]Feature{ - .MultiViewport, - }), - }; - result[@intFromEnum(Feature.ShaderViewportMaskNV)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ShaderViewportMaskNV", - .dependencies = featureSet(&[_]Feature{ - .ShaderViewportIndexLayerEXT, - }), - }; - result[@intFromEnum(Feature.ShaderStereoViewNV)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ShaderStereoViewNV", - .dependencies = featureSet(&[_]Feature{ - .ShaderViewportMaskNV, - }), - }; - result[@intFromEnum(Feature.PerViewAttributesNV)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability PerViewAttributesNV", - .dependencies = featureSet(&[_]Feature{ - .MultiView, - }), - }; - result[@intFromEnum(Feature.FragmentFullyCoveredEXT)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability FragmentFullyCoveredEXT", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.MeshShadingNV)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability MeshShadingNV", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.ImageFootprintNV)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ImageFootprintNV", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.MeshShadingEXT)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability MeshShadingEXT", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.FragmentBarycentricKHR)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability FragmentBarycentricKHR", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ComputeDerivativeGroupQuadsKHR)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ComputeDerivativeGroupQuadsKHR", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.FragmentDensityEXT)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability FragmentDensityEXT", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.GroupNonUniformPartitionedNV)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability GroupNonUniformPartitionedNV", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ShaderNonUniform)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ShaderNonUniform", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - .Shader, - }), - }; - result[@intFromEnum(Feature.RuntimeDescriptorArray)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability RuntimeDescriptorArray", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - .Shader, - }), - }; - result[@intFromEnum(Feature.InputAttachmentArrayDynamicIndexing)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability InputAttachmentArrayDynamicIndexing", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - .InputAttachment, - }), - }; - result[@intFromEnum(Feature.UniformTexelBufferArrayDynamicIndexing)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability UniformTexelBufferArrayDynamicIndexing", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - .SampledBuffer, - }), - }; - result[@intFromEnum(Feature.StorageTexelBufferArrayDynamicIndexing)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability StorageTexelBufferArrayDynamicIndexing", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - .ImageBuffer, - }), - }; - result[@intFromEnum(Feature.UniformBufferArrayNonUniformIndexing)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability UniformBufferArrayNonUniformIndexing", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - .ShaderNonUniform, - }), - }; - result[@intFromEnum(Feature.SampledImageArrayNonUniformIndexing)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability SampledImageArrayNonUniformIndexing", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - .ShaderNonUniform, - }), - }; - result[@intFromEnum(Feature.StorageBufferArrayNonUniformIndexing)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability StorageBufferArrayNonUniformIndexing", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - .ShaderNonUniform, - }), - }; - result[@intFromEnum(Feature.StorageImageArrayNonUniformIndexing)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability StorageImageArrayNonUniformIndexing", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - .ShaderNonUniform, - }), - }; - result[@intFromEnum(Feature.InputAttachmentArrayNonUniformIndexing)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability InputAttachmentArrayNonUniformIndexing", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - .InputAttachment, - .ShaderNonUniform, - }), - }; - result[@intFromEnum(Feature.UniformTexelBufferArrayNonUniformIndexing)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability UniformTexelBufferArrayNonUniformIndexing", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - .SampledBuffer, - .ShaderNonUniform, - }), - }; - result[@intFromEnum(Feature.StorageTexelBufferArrayNonUniformIndexing)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability StorageTexelBufferArrayNonUniformIndexing", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - .ImageBuffer, - .ShaderNonUniform, - }), - }; - result[@intFromEnum(Feature.RayTracingPositionFetchKHR)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability RayTracingPositionFetchKHR", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.RayTracingNV)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability RayTracingNV", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.RayTracingMotionBlurNV)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability RayTracingMotionBlurNV", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.VulkanMemoryModel)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability VulkanMemoryModel", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - }), - }; - result[@intFromEnum(Feature.VulkanMemoryModelDeviceScope)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability VulkanMemoryModelDeviceScope", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - }), - }; - result[@intFromEnum(Feature.PhysicalStorageBufferAddresses)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability PhysicalStorageBufferAddresses", - .dependencies = featureSet(&[_]Feature{ - .v1_5, - .Shader, - }), - }; - result[@intFromEnum(Feature.ComputeDerivativeGroupLinearKHR)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ComputeDerivativeGroupLinearKHR", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.RayTracingProvisionalKHR)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability RayTracingProvisionalKHR", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.CooperativeMatrixNV)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability CooperativeMatrixNV", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.FragmentShaderSampleInterlockEXT)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability FragmentShaderSampleInterlockEXT", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.FragmentShaderShadingRateInterlockEXT)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability FragmentShaderShadingRateInterlockEXT", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.ShaderSMBuiltinsNV)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ShaderSMBuiltinsNV", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.FragmentShaderPixelInterlockEXT)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability FragmentShaderPixelInterlockEXT", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.DemoteToHelperInvocation)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability DemoteToHelperInvocation", - .dependencies = featureSet(&[_]Feature{ - .v1_6, - .Shader, - }), - }; - result[@intFromEnum(Feature.DisplacementMicromapNV)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability DisplacementMicromapNV", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.RayTracingOpacityMicromapEXT)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability RayTracingOpacityMicromapEXT", - .dependencies = featureSet(&[_]Feature{ - .RayQueryKHR, - .RayTracingKHR, - }), - }; - result[@intFromEnum(Feature.ShaderInvocationReorderNV)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ShaderInvocationReorderNV", - .dependencies = featureSet(&[_]Feature{ - .RayTracingKHR, - }), - }; - result[@intFromEnum(Feature.BindlessTextureNV)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability BindlessTextureNV", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.RayQueryPositionFetchKHR)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability RayQueryPositionFetchKHR", - .dependencies = featureSet(&[_]Feature{ - .Shader, - }), - }; - result[@intFromEnum(Feature.CooperativeVectorNV)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability CooperativeVectorNV", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.AtomicFloat16VectorNV)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability AtomicFloat16VectorNV", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.RayTracingDisplacementMicromapNV)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability RayTracingDisplacementMicromapNV", - .dependencies = featureSet(&[_]Feature{ - .RayTracingKHR, - }), - }; - result[@intFromEnum(Feature.RawAccessChainsNV)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability RawAccessChainsNV", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.RayTracingSpheresGeometryNV)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability RayTracingSpheresGeometryNV", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.RayTracingLinearSweptSpheresGeometryNV)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability RayTracingLinearSweptSpheresGeometryNV", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.CooperativeMatrixReductionsNV)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability CooperativeMatrixReductionsNV", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.CooperativeMatrixConversionsNV)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability CooperativeMatrixConversionsNV", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.CooperativeMatrixPerElementOperationsNV)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability CooperativeMatrixPerElementOperationsNV", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.CooperativeMatrixTensorAddressingNV)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability CooperativeMatrixTensorAddressingNV", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.CooperativeMatrixBlockLoadsNV)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability CooperativeMatrixBlockLoadsNV", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.CooperativeVectorTrainingNV)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability CooperativeVectorTrainingNV", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.RayTracingClusterAccelerationStructureNV)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability RayTracingClusterAccelerationStructureNV", - .dependencies = featureSet(&[_]Feature{ - .RayTracingKHR, - }), - }; - result[@intFromEnum(Feature.TensorAddressingNV)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability TensorAddressingNV", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SubgroupShuffleINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability SubgroupShuffleINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SubgroupBufferBlockIOINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability SubgroupBufferBlockIOINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SubgroupImageBlockIOINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability SubgroupImageBlockIOINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SubgroupImageMediaBlockIOINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability SubgroupImageMediaBlockIOINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.RoundToInfinityINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability RoundToInfinityINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.FloatingPointModeINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability FloatingPointModeINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.IntegerFunctions2INTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability IntegerFunctions2INTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.FunctionPointersINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability FunctionPointersINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.IndirectReferencesINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability IndirectReferencesINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.AsmINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability AsmINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.AtomicFloat32MinMaxEXT)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability AtomicFloat32MinMaxEXT", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.AtomicFloat64MinMaxEXT)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability AtomicFloat64MinMaxEXT", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.AtomicFloat16MinMaxEXT)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability AtomicFloat16MinMaxEXT", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.VectorComputeINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability VectorComputeINTEL", - .dependencies = featureSet(&[_]Feature{ - .VectorAnyINTEL, - }), - }; - result[@intFromEnum(Feature.VectorAnyINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability VectorAnyINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ExpectAssumeKHR)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ExpectAssumeKHR", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SubgroupAvcMotionEstimationINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability SubgroupAvcMotionEstimationINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SubgroupAvcMotionEstimationIntraINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability SubgroupAvcMotionEstimationIntraINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SubgroupAvcMotionEstimationChromaINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability SubgroupAvcMotionEstimationChromaINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.VariableLengthArrayINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability VariableLengthArrayINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.FunctionFloatControlINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability FunctionFloatControlINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.FPGAMemoryAttributesINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability FPGAMemoryAttributesINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.FPFastMathModeINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability FPFastMathModeINTEL", - .dependencies = featureSet(&[_]Feature{ - .Kernel, - }), - }; - result[@intFromEnum(Feature.ArbitraryPrecisionIntegersINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ArbitraryPrecisionIntegersINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ArbitraryPrecisionFloatingPointINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ArbitraryPrecisionFloatingPointINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.UnstructuredLoopControlsINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability UnstructuredLoopControlsINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.FPGALoopControlsINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability FPGALoopControlsINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.KernelAttributesINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability KernelAttributesINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.FPGAKernelAttributesINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability FPGAKernelAttributesINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.FPGAMemoryAccessesINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability FPGAMemoryAccessesINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.FPGAClusterAttributesINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability FPGAClusterAttributesINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.LoopFuseINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability LoopFuseINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.FPGADSPControlINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability FPGADSPControlINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.MemoryAccessAliasingINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability MemoryAccessAliasingINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.FPGAInvocationPipeliningAttributesINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability FPGAInvocationPipeliningAttributesINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.FPGABufferLocationINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability FPGABufferLocationINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ArbitraryPrecisionFixedPointINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ArbitraryPrecisionFixedPointINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.USMStorageClassesINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability USMStorageClassesINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.RuntimeAlignedAttributeINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability RuntimeAlignedAttributeINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.IOPipesINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability IOPipesINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.BlockingPipesINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability BlockingPipesINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.FPGARegINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability FPGARegINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.DotProductInputAll)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability DotProductInputAll", - .dependencies = featureSet(&[_]Feature{ - .v1_6, - }), - }; - result[@intFromEnum(Feature.DotProductInput4x8Bit)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability DotProductInput4x8Bit", - .dependencies = featureSet(&[_]Feature{ - .v1_6, - .Int8, - }), - }; - result[@intFromEnum(Feature.DotProductInput4x8BitPacked)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability DotProductInput4x8BitPacked", - .dependencies = featureSet(&[_]Feature{ - .v1_6, - }), - }; - result[@intFromEnum(Feature.DotProduct)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability DotProduct", - .dependencies = featureSet(&[_]Feature{ - .v1_6, - }), - }; - result[@intFromEnum(Feature.RayCullMaskKHR)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability RayCullMaskKHR", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.CooperativeMatrixKHR)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability CooperativeMatrixKHR", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ReplicatedCompositesEXT)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ReplicatedCompositesEXT", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.BitInstructions)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability BitInstructions", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.GroupNonUniformRotateKHR)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability GroupNonUniformRotateKHR", - .dependencies = featureSet(&[_]Feature{ - .GroupNonUniform, - }), - }; - result[@intFromEnum(Feature.FloatControls2)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability FloatControls2", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.AtomicFloat32AddEXT)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability AtomicFloat32AddEXT", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.AtomicFloat64AddEXT)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability AtomicFloat64AddEXT", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.LongCompositesINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability LongCompositesINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.OptNoneEXT)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability OptNoneEXT", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.AtomicFloat16AddEXT)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability AtomicFloat16AddEXT", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.DebugInfoModuleINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability DebugInfoModuleINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.BFloat16ConversionINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability BFloat16ConversionINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SplitBarrierINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability SplitBarrierINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.ArithmeticFenceEXT)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability ArithmeticFenceEXT", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.FPGAClusterAttributesV2INTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability FPGAClusterAttributesV2INTEL", - .dependencies = featureSet(&[_]Feature{ - .FPGAClusterAttributesINTEL, - }), - }; - result[@intFromEnum(Feature.FPGAKernelAttributesv2INTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability FPGAKernelAttributesv2INTEL", - .dependencies = featureSet(&[_]Feature{ - .FPGAKernelAttributesINTEL, - }), - }; - result[@intFromEnum(Feature.FPMaxErrorINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability FPMaxErrorINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.FPGALatencyControlINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability FPGALatencyControlINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.FPGAArgumentInterfacesINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability FPGAArgumentInterfacesINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.GlobalVariableHostAccessINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability GlobalVariableHostAccessINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.GlobalVariableFPGADecorationsINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability GlobalVariableFPGADecorationsINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.SubgroupBufferPrefetchINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability SubgroupBufferPrefetchINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.Subgroup2DBlockIOINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability Subgroup2DBlockIOINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.Subgroup2DBlockTransformINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability Subgroup2DBlockTransformINTEL", - .dependencies = featureSet(&[_]Feature{ - .Subgroup2DBlockIOINTEL, - }), - }; - result[@intFromEnum(Feature.Subgroup2DBlockTransposeINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability Subgroup2DBlockTransposeINTEL", - .dependencies = featureSet(&[_]Feature{ - .Subgroup2DBlockIOINTEL, - }), - }; - result[@intFromEnum(Feature.SubgroupMatrixMultiplyAccumulateINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability SubgroupMatrixMultiplyAccumulateINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.GroupUniformArithmeticKHR)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability GroupUniformArithmeticKHR", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.MaskedGatherScatterINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability MaskedGatherScatterINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.CacheControlsINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability CacheControlsINTEL", - .dependencies = featureSet(&[_]Feature{}), - }; - result[@intFromEnum(Feature.RegisterLimitsINTEL)] = .{ - .llvm_name = null, - .description = "Enable SPIR-V capability RegisterLimitsINTEL", - .dependencies = featureSet(&[_]Feature{}), + .dependencies = featureSet(&[_]Feature{ .v1_0, .matrix }), }; const ti = @typeInfo(Feature); for (&result, 0..) |*elem, i| { @@ -2830,24 +141,12 @@ pub const cpu = struct { pub const vulkan_v1_2: CpuModel = .{ .name = "vulkan_v1_2", .llvm_name = null, - .features = featureSet(&[_]Feature{ - .v1_5, - .Shader, - .PhysicalStorageBufferAddresses, - .VariablePointers, - .VariablePointersStorageBuffer, - .SPV_KHR_physical_storage_buffer, - }), + .features = featureSet(&[_]Feature{ .v1_5, .shader, .addresses }), }; pub const opencl_v2: CpuModel = .{ .name = "opencl_v2", .llvm_name = null, - .features = featureSet(&[_]Feature{ - .v1_2, - .Kernel, - .Addresses, - .GenericPointer, - }), + .features = featureSet(&[_]Feature{ .v1_2, .kernel, .addresses, .generic_pointer }), }; }; diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index 58182ead0b..d6997c7e6c 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -552,7 +552,7 @@ const NavGen = struct { } fn castToGeneric(self: *NavGen, type_id: IdRef, ptr_id: IdRef) !IdRef { - if (self.spv.hasFeature(.Kernel)) { + if (self.spv.hasFeature(.kernel)) { const result_id = self.spv.allocId(); try self.func.body.emit(self.spv.gpa, .OpPtrCastToGeneric, .{ .id_result_type = type_id, @@ -591,10 +591,10 @@ const NavGen = struct { // 8, 16 and 64-bit integers require the Int8, Int16 and Inr64 capabilities respectively. // 32-bit integers are always supported (see spec, 2.16.1, Data rules). const ints = [_]struct { bits: u16, feature: ?Target.spirv.Feature }{ - .{ .bits = 8, .feature = .Int8 }, - .{ .bits = 16, .feature = .Int16 }, + .{ .bits = 8, .feature = .int8 }, + .{ .bits = 16, .feature = .int16 }, .{ .bits = 32, .feature = null }, - .{ .bits = 64, .feature = .Int64 }, + .{ .bits = 64, .feature = .int64 }, }; for (ints) |int| { @@ -612,7 +612,7 @@ const NavGen = struct { /// is no way of knowing whether those are actually supported. /// TODO: Maybe this should be cached? fn largestSupportedIntBits(self: *NavGen) u16 { - return if (self.spv.hasFeature(.Int64)) 64 else 32; + return if (self.spv.hasFeature(.int64)) 64 else 32; } /// Checks whether the type is "composite int", an integer consisting of multiple native integers. These are represented by @@ -644,7 +644,7 @@ const NavGen = struct { if (elem_ty.isNumeric(zcu) or elem_ty.toIntern() == .bool_type) { if (len > 1 and len <= 4) return true; - if (self.spv.hasFeature(.Vector16)) return (len == 8 or len == 16); + if (self.spv.hasFeature(.vector16)) return (len == 8 or len == 16); } return false; @@ -1241,7 +1241,7 @@ const NavGen = struct { }; // Kernel only supports unsigned ints. - if (self.spv.hasFeature(.Kernel)) { + if (self.spv.hasFeature(.kernel)) { return self.spv.intType(.unsigned, backing_bits); } @@ -1465,10 +1465,10 @@ const NavGen = struct { // so if the float is not supported, just return an error. const bits = ty.floatBits(target); const supported = switch (bits) { - 16 => Target.spirv.featureSetHas(target.cpu.features, .Float16), + 16 => self.spv.hasFeature(.float16), // 32-bit floats are always supported (see spec, 2.16.1, Data rules). 32 => true, - 64 => Target.spirv.featureSetHas(target.cpu.features, .Float64), + 64 => self.spv.hasFeature(.float64), else => false, }; @@ -1511,7 +1511,7 @@ const NavGen = struct { return try self.arrayType(1, elem_ty_id); } else { const result_id = try self.arrayType(total_len, elem_ty_id); - if (self.spv.hasFeature(.Shader)) { + if (self.spv.hasFeature(.shader)) { try self.spv.decorate(result_id, .{ .ArrayStride = .{ .array_stride = @intCast(elem_ty.abiSize(zcu)), } }); @@ -1645,7 +1645,7 @@ const NavGen = struct { continue; } - if (self.spv.hasFeature(.Shader)) { + if (self.spv.hasFeature(.shader)) { try self.spv.decorateMember(result_id, index, .{ .Offset = .{ .byte_offset = @intCast(ty.structFieldOffset(field_index, zcu)), } }); @@ -1748,10 +1748,10 @@ const NavGen = struct { fn spvStorageClass(self: *NavGen, as: std.builtin.AddressSpace) StorageClass { return switch (as) { - .generic => if (self.spv.hasFeature(.GenericPointer)) .Generic else .Function, + .generic => if (self.spv.hasFeature(.generic_pointer)) .Generic else .Function, .shared => .Workgroup, .local => .Function, - .global => if (self.spv.hasFeature(.Shader)) .PhysicalStorageBuffer else .CrossWorkgroup, + .global => if (self.spv.hasFeature(.shader)) .PhysicalStorageBuffer else .CrossWorkgroup, .constant => .UniformConstant, .push_constant => .PushConstant, .input => .Input, @@ -2461,7 +2461,7 @@ const NavGen = struct { // TODO: These instructions don't seem to be working // properly for LLVM-based backends on OpenCL for 8- and // 16-component vectors. - .i_abs => if (self.spv.hasFeature(.Vector16) and v.components() >= 8) v.unroll() else v, + .i_abs => if (self.spv.hasFeature(.vector16) and v.components() >= 8) v.unroll() else v, else => v, }; }; @@ -3650,7 +3650,7 @@ const NavGen = struct { // depending on the result type. Do that when // bitCast is implemented for vectors. // This is only relevant for Vulkan - assert(self.spv.hasFeature(.Kernel)); // TODO + assert(self.spv.hasFeature(.kernel)); // TODO return try self.normalize(abs_value, self.arithmeticTypeInfo(result_ty)); }, @@ -3968,7 +3968,7 @@ const NavGen = struct { .float, .bool => unreachable, } - assert(self.spv.hasFeature(.Kernel)); // TODO + assert(self.spv.hasFeature(.kernel)); // TODO const count = try self.buildUnary(op, operand); @@ -4204,7 +4204,7 @@ const NavGen = struct { defer self.gpa.free(ids); const result_id = self.spv.allocId(); - if (self.spv.hasFeature(.Kernel)) { + if (self.spv.hasFeature(.kernel)) { try self.func.body.emit(self.spv.gpa, .OpInBoundsPtrAccessChain, .{ .id_result_type = result_ty_id, .id_result = result_id, @@ -5290,7 +5290,7 @@ const NavGen = struct { .initializer = options.initializer, }); - if (self.spv.hasFeature(.Shader)) return var_id; + if (self.spv.hasFeature(.shader)) return var_id; switch (options.storage_class) { .Generic => { diff --git a/src/codegen/spirv/Assembler.zig b/src/codegen/spirv/Assembler.zig index 2cfb590273..6bb79a2ebe 100644 --- a/src/codegen/spirv/Assembler.zig +++ b/src/codegen/spirv/Assembler.zig @@ -274,6 +274,16 @@ fn processInstruction(self: *Assembler) !void { .OpEntryPoint => { return self.fail(0, "cannot export entry points via OpEntryPoint, export the kernel using callconv(.Kernel)", .{}); }, + .OpCapability => { + try self.spv.addCapability(@enumFromInt(self.inst.operands.items[0].value)); + return; + }, + .OpExtension => { + const ext_name_offset = self.inst.operands.items[0].string; + const ext_name = std.mem.sliceTo(self.inst.string_bytes.items[ext_name_offset..], 0); + try self.spv.addExtension(ext_name); + return; + }, .OpExtInstImport => blk: { const set_name_offset = self.inst.operands.items[1].string; const set_name = std.mem.sliceTo(self.inst.string_bytes.items[set_name_offset..], 0); diff --git a/src/codegen/spirv/Module.zig b/src/codegen/spirv/Module.zig index 6d5b0afccc..317e32c878 100644 --- a/src/codegen/spirv/Module.zig +++ b/src/codegen/spirv/Module.zig @@ -183,8 +183,11 @@ cache: struct { array_types: std.AutoHashMapUnmanaged(struct { IdRef, IdRef }, IdRef) = .empty, function_types: DeepHashMap(struct { IdRef, []const IdRef }, IdRef) = .empty, - builtins: std.AutoHashMapUnmanaged(struct { IdRef, spec.BuiltIn }, Decl.Index) = .empty, + capabilities: std.AutoHashMapUnmanaged(spec.Capability, void) = .empty, + extensions: std.StringHashMapUnmanaged(void) = .empty, + extended_instruction_set: std.AutoHashMapUnmanaged(spec.InstructionSet, IdRef) = .empty, decorations: std.AutoHashMapUnmanaged(struct { IdRef, spec.Decoration }, void) = .empty, + builtins: std.AutoHashMapUnmanaged(struct { IdRef, spec.BuiltIn }, Decl.Index) = .empty, bool_const: [2]?IdRef = .{ null, null }, } = .{}, @@ -199,9 +202,6 @@ decl_deps: std.ArrayListUnmanaged(Decl.Index) = .empty, /// The list of entry points that should be exported from this module. entry_points: std.ArrayListUnmanaged(EntryPoint) = .empty, -/// The list of extended instruction sets that should be imported. -extended_instruction_set: std.AutoHashMapUnmanaged(spec.InstructionSet, IdRef) = .empty, - pub fn init(gpa: Allocator, target: std.Target) Module { const version_minor: u8 = blk: { // Prefer higher versions @@ -242,15 +242,16 @@ pub fn deinit(self: *Module) void { self.cache.vector_types.deinit(self.gpa); self.cache.array_types.deinit(self.gpa); self.cache.function_types.deinit(self.gpa); - self.cache.builtins.deinit(self.gpa); + self.cache.capabilities.deinit(self.gpa); + self.cache.extensions.deinit(self.gpa); + self.cache.extended_instruction_set.deinit(self.gpa); self.cache.decorations.deinit(self.gpa); + self.cache.builtins.deinit(self.gpa); self.decls.deinit(self.gpa); self.decl_deps.deinit(self.gpa); - self.entry_points.deinit(self.gpa); - self.extended_instruction_set.deinit(self.gpa); self.arena.deinit(); self.* = undefined; @@ -339,9 +340,61 @@ fn entryPoints(self: *Module) !Section { } pub fn finalize(self: *Module, a: Allocator) ![]Word { + // Emit capabilities and extensions + for (std.Target.spirv.all_features) |feature| { + if (self.target.cpu.features.isEnabled(feature.index)) { + const feature_tag: std.Target.spirv.Feature = @enumFromInt(feature.index); + switch (feature_tag) { + .v1_0, .v1_1, .v1_2, .v1_3, .v1_4, .v1_5, .v1_6 => {}, + .int8 => try self.addCapability(.Int8), + .int16 => try self.addCapability(.Int16), + .int64 => try self.addCapability(.Int64), + .float16 => try self.addCapability(.Float16), + .float64 => try self.addCapability(.Float64), + .addresses => if (self.hasFeature(.shader)) { + try self.addCapability(.PhysicalStorageBufferAddresses); + try self.addExtension("SPV_KHR_physical_storage_buffer"); + } else { + try self.addCapability(.Addresses); + }, + .matrix => try self.addCapability(.Matrix), + .kernel => try self.addCapability(.Kernel), + .generic_pointer => try self.addCapability(.GenericPointer), + .vector16 => try self.addCapability(.Vector16), + .shader => try self.addCapability(.Shader), + } + } + } + + // Emit memory model + const addressing_model: spec.AddressingModel = blk: { + if (self.hasFeature(.shader)) { + break :blk switch (self.target.cpu.arch) { + .spirv32 => .Logical, // TODO: I don't think this will ever be implemented. + .spirv64 => .PhysicalStorageBuffer64, + else => unreachable, + }; + } else if (self.hasFeature(.kernel)) { + break :blk switch (self.target.cpu.arch) { + .spirv32 => .Physical32, + .spirv64 => .Physical64, + else => unreachable, + }; + } + + unreachable; + }; + try self.sections.memory_model.emit(self.gpa, .OpMemoryModel, .{ + .addressing_model = addressing_model, + .memory_model = switch (self.target.os.tag) { + .opencl => .OpenCL, + .vulkan, .opengl => .GLSL450, + else => unreachable, + }, + }); + // See SPIR-V Spec section 2.3, "Physical Layout of a SPIR-V Module and Instruction" // TODO: Audit calls to allocId() in this function to make it idempotent. - var entry_points = try self.entryPoints(); defer entry_points.deinit(self.gpa); @@ -405,11 +458,23 @@ pub fn addFunction(self: *Module, decl_index: Decl.Index, func: Fn) !void { try self.declareDeclDeps(decl_index, func.decl_deps.keys()); } +pub fn addCapability(self: *Module, cap: spec.Capability) !void { + const entry = try self.cache.capabilities.getOrPut(self.gpa, cap); + if (entry.found_existing) return; + try self.sections.capabilities.emit(self.gpa, .OpCapability, .{ .capability = cap }); +} + +pub fn addExtension(self: *Module, ext: []const u8) !void { + const entry = try self.cache.extensions.getOrPut(self.gpa, ext); + if (entry.found_existing) return; + try self.sections.extensions.emit(self.gpa, .OpExtension, .{ .name = ext }); +} + /// Imports or returns the existing id of an extended instruction set pub fn importInstructionSet(self: *Module, set: spec.InstructionSet) !IdRef { assert(set != .core); - const gop = try self.extended_instruction_set.getOrPut(self.gpa, set); + const gop = try self.cache.extended_instruction_set.getOrPut(self.gpa, set); if (gop.found_existing) return gop.value_ptr.*; const result_id = self.allocId(); diff --git a/src/link/SpirV.zig b/src/link/SpirV.zig index 7e2f2b1114..0e92967521 100644 --- a/src/link/SpirV.zig +++ b/src/link/SpirV.zig @@ -232,13 +232,9 @@ pub fn flushModule( const diags = &comp.link_diags; const gpa = comp.gpa; - try writeCapabilities(spv); - try writeMemoryModel(spv); - // We need to export the list of error names somewhere so that we can pretty-print them in the // executor. This is not really an important thing though, so we can just dump it in any old // nonsemantic instruction. For now, just put it in OpSourceExtension with a special name. - var error_info = std.ArrayList(u8).init(self.object.gpa); defer error_info.deinit(); @@ -297,65 +293,3 @@ fn linkModule(self: *SpirV, a: Allocator, module: []Word, progress: std.Progress return binary.finalize(a); } - -fn writeCapabilities(spv: *SpvModule) !void { - var caps: std.ArrayList(spec.Capability) = .init(spv.gpa); - var extensions: std.ArrayList([]const u8) = .init(spv.gpa); - defer { - caps.deinit(); - extensions.deinit(); - } - - // Currently all spirv target features name are mapped to a Capability or an Extension. - // Except for versions which we ignore. - for (std.Target.spirv.all_features, 0..) |_, i| { - if (spv.target.cpu.features.isEnabled(@intCast(i))) { - const feature: std.Target.spirv.Feature = @enumFromInt(i); - const name = @tagName(feature); - if (std.meta.stringToEnum(spec.Capability, name)) |cap| { - try caps.append(cap); - } else if (std.mem.startsWith(u8, name, "SPV_")) { - try extensions.append(name); - } - } - } - - for (caps.items) |cap| { - try spv.sections.capabilities.emit(spv.gpa, .OpCapability, .{ - .capability = cap, - }); - } - - for (extensions.items) |ext| { - try spv.sections.extensions.emit(spv.gpa, .OpExtension, .{ .name = ext }); - } -} - -fn writeMemoryModel(spv: *SpvModule) !void { - const addressing_model: spec.AddressingModel = blk: { - if (spv.hasFeature(.Shader)) { - break :blk switch (spv.target.cpu.arch) { - .spirv32 => .Logical, // TODO: I don't think this will ever be implemented. - .spirv64 => .PhysicalStorageBuffer64, - else => unreachable, - }; - } else if (spv.hasFeature(.Kernel)) { - break :blk switch (spv.target.cpu.arch) { - .spirv32 => .Physical32, - .spirv64 => .Physical64, - else => unreachable, - }; - } - - unreachable; - }; - const memory_model: spec.MemoryModel = switch (spv.target.os.tag) { - .opencl => .OpenCL, - .vulkan, .opengl => .GLSL450, - else => unreachable, - }; - try spv.sections.memory_model.emit(spv.gpa, .OpMemoryModel, .{ - .addressing_model = addressing_model, - .memory_model = memory_model, - }); -} diff --git a/test/standalone/build.zig b/test/standalone/build.zig index f89ccd2a18..e2b7a7c387 100644 --- a/test/standalone/build.zig +++ b/test/standalone/build.zig @@ -43,7 +43,6 @@ pub fn build(b: *std.Build) void { "../../tools/update_clang_options.zig", "../../tools/update_cpu_features.zig", "../../tools/update_glibc.zig", - "../../tools/update_spirv_features.zig", }) |tool_src_path| { const tool = b.addTest(.{ .name = std.fs.path.stem(tool_src_path), diff --git a/tools/update_cpu_features.zig b/tools/update_cpu_features.zig index 329c4c1704..e8b3a5431e 100644 --- a/tools/update_cpu_features.zig +++ b/tools/update_cpu_features.zig @@ -1072,13 +1072,6 @@ const targets = [_]ArchTarget{ .td_name = "Sparc", }, }, - // TODO: merge tools/update_spirv_features.zig into this script - //.{ - // .zig_name = "spirv", - // .llvm = .{ - // .name = "SPIRV", - // }, - //}, .{ .zig_name = "s390x", .llvm = .{ diff --git a/tools/update_spirv_features.zig b/tools/update_spirv_features.zig deleted file mode 100644 index 84812c8737..0000000000 --- a/tools/update_spirv_features.zig +++ /dev/null @@ -1,361 +0,0 @@ -//! This tool generates SPIR-V features from the grammar files in the SPIRV-Headers -//! (https://github.com/KhronosGroup/SPIRV-Headers/) and SPIRV-Registry (https://github.com/KhronosGroup/SPIRV-Registry/) -//! repositories. Currently it only generates a basic feature set definition consisting of versions, extensions and capabilities. -//! There is a lot left to be desired, as currently dependencies of extensions and dependencies on extensions aren't generated. -//! This is because there are some peculiarities in the SPIR-V registries: -//! - Capabilities may depend on multiple extensions, which cannot be modelled yet by std.Target. -//! - Extension dependencies are not documented in a machine-readable manner. -//! - Note that the grammar spec also contains definitions from extensions which aren't actually official. Most of these seem to be -//! from an intel project (https://github.com/intel/llvm/, https://github.com/intel/llvm/tree/sycl/sycl/doc/extensions/SPIRV), -//! and so ONLY extensions in the SPIRV-Registry should be included. - -const std = @import("std"); -const fs = std.fs; -const Allocator = std.mem.Allocator; -const g = @import("spirv/grammar.zig"); - -const Version = struct { - major: u32, - minor: u32, - - fn parse(str: []const u8) !Version { - var it = std.mem.splitScalar(u8, str, '.'); - - const major = it.first(); - const minor = it.next() orelse return error.InvalidVersion; - - if (it.next() != null) return error.InvalidVersion; - - return Version{ - .major = std.fmt.parseInt(u32, major, 10) catch return error.InvalidVersion, - .minor = std.fmt.parseInt(u32, minor, 10) catch return error.InvalidVersion, - }; - } - - fn eql(a: Version, b: Version) bool { - return a.major == b.major and a.minor == b.minor; - } - - fn lessThan(ctx: void, a: Version, b: Version) bool { - _ = ctx; - return if (a.major == b.major) - a.minor < b.minor - else - a.major < b.major; - } -}; - -pub fn main() !void { - var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); - defer arena.deinit(); - const allocator = arena.allocator(); - - const args = try std.process.argsAlloc(allocator); - - if (args.len <= 1) { - usageAndExit(std.io.getStdErr(), args[0], 1); - } - if (std.mem.eql(u8, args[1], "--help")) { - usageAndExit(std.io.getStdErr(), args[0], 0); - } - if (args.len != 3) { - usageAndExit(std.io.getStdErr(), args[0], 1); - } - - const spirv_headers_root = args[1]; - const spirv_registry_root = args[2]; - - if (std.mem.startsWith(u8, spirv_headers_root, "-") or std.mem.startsWith(u8, spirv_registry_root, "-")) { - usageAndExit(std.io.getStdErr(), args[0], 1); - } - - // Required for json parsing. - @setEvalBranchQuota(10000); - - const registry_path = try fs.path.join(allocator, &.{ spirv_headers_root, "include", "spirv", "unified1", "spirv.core.grammar.json" }); - const registry_json = try std.fs.cwd().readFileAlloc(allocator, registry_path, std.math.maxInt(usize)); - var scanner = std.json.Scanner.initCompleteInput(allocator, registry_json); - var diagnostics = std.json.Diagnostics{}; - scanner.enableDiagnostics(&diagnostics); - const registry = std.json.parseFromTokenSourceLeaky(g.CoreRegistry, allocator, &scanner, .{ .ignore_unknown_fields = true }) catch |err| { - std.debug.print("line,col: {},{}\n", .{ diagnostics.getLine(), diagnostics.getColumn() }); - return err; - }; - - const capabilities = for (registry.operand_kinds) |opkind| { - if (std.mem.eql(u8, opkind.kind, "Capability")) - break opkind.enumerants orelse return error.InvalidRegistry; - } else return error.InvalidRegistry; - - const extensions = try gather_extensions(allocator, spirv_registry_root); - const versions = try gatherVersions(allocator, registry); - - var bw = std.io.bufferedWriter(std.io.getStdOut().writer()); - const w = bw.writer(); - - try w.writeAll( - \\//! This file is auto-generated by tools/update_spirv_features.zig. - \\//! TODO: Dependencies of capabilities on extensions. - \\//! TODO: Dependencies of extensions on extensions. - \\//! TODO: Dependencies of extensions on versions. - \\ - \\const std = @import("../std.zig"); - \\const CpuFeature = std.Target.Cpu.Feature; - \\const CpuModel = std.Target.Cpu.Model; - \\ - \\pub const Feature = enum { - \\ - ); - - for (versions) |ver| { - try w.print(" v{}_{},\n", .{ ver.major, ver.minor }); - } - - for (extensions) |ext| { - try w.print(" {p},\n", .{std.zig.fmtId(ext)}); - } - - for (capabilities) |cap| { - try w.print(" {p},\n", .{std.zig.fmtId(cap.enumerant)}); - } - - try w.writeAll( - \\}; - \\ - \\pub const featureSet = CpuFeature.FeatureSetFns(Feature).featureSet; - \\pub const featureSetHas = CpuFeature.FeatureSetFns(Feature).featureSetHas; - \\pub const featureSetHasAny = CpuFeature.FeatureSetFns(Feature).featureSetHasAny; - \\pub const featureSetHasAll = CpuFeature.FeatureSetFns(Feature).featureSetHasAll; - \\ - \\pub const all_features = blk: { - \\ @setEvalBranchQuota(2000); - \\ const len = @typeInfo(Feature).@"enum".fields.len; - \\ std.debug.assert(len <= CpuFeature.Set.needed_bit_count); - \\ var result: [len]CpuFeature = undefined; - \\ - ); - - for (versions, 0..) |ver, i| { - try w.print( - \\ result[@intFromEnum(Feature.v{0}_{1})] = .{{ - \\ .llvm_name = null, - \\ .description = "SPIR-V version {0}.{1}", - \\ - , .{ ver.major, ver.minor }); - - if (i == 0) { - try w.writeAll( - \\ .dependencies = featureSet(&[_]Feature{}), - \\ }; - \\ - ); - } else { - try w.print( - \\ .dependencies = featureSet(&[_]Feature{{ - \\ .v{}_{}, - \\ }}), - \\ }}; - \\ - , .{ versions[i - 1].major, versions[i - 1].minor }); - } - } - - // TODO: Extension dependencies. - for (extensions) |ext| { - try w.print( - \\ result[@intFromEnum(Feature.{p_})] = .{{ - \\ .llvm_name = null, - \\ .description = "SPIR-V extension {s}", - \\ .dependencies = featureSet(&[_]Feature{{}}), - \\ }}; - \\ - , .{ - std.zig.fmtId(ext), - ext, - }); - } - - // TODO: Capability extension dependencies. - for (capabilities) |cap| { - try w.print( - \\ result[@intFromEnum(Feature.{p_})] = .{{ - \\ .llvm_name = null, - \\ .description = "Enable SPIR-V capability {s}", - \\ .dependencies = featureSet(&[_]Feature{{ - \\ - , .{ - std.zig.fmtId(cap.enumerant), - cap.enumerant, - }); - - if (cap.version) |ver_str| blk: { - if (std.mem.eql(u8, ver_str, "None")) break :blk; - - const ver = try Version.parse(ver_str); - try w.print(" .v{}_{},\n", .{ ver.major, ver.minor }); - } - - for (cap.capabilities) |cap_dep| { - try w.print(" .{p_},\n", .{std.zig.fmtId(cap_dep)}); - } - - try w.writeAll( - \\ }), - \\ }; - \\ - ); - } - - try w.writeAll( - \\ const ti = @typeInfo(Feature); - \\ for (&result, 0..) |*elem, i| { - \\ elem.index = i; - \\ elem.name = ti.@"enum".fields[i].name; - \\ } - \\ break :blk result; - \\}; - \\ - \\pub const cpu = struct { - \\ pub const generic: CpuModel = .{ - \\ .name = "generic", - \\ .llvm_name = "generic", - \\ .features = featureSet(&[_]Feature{ .v1_0 }), - \\ }; - \\ - \\ pub const vulkan_v1_2: CpuModel = .{ - \\ .name = "vulkan_v1_2", - \\ .llvm_name = null, - \\ .features = featureSet(&[_]Feature{ - \\ .v1_5, - \\ .Shader, - \\ .PhysicalStorageBufferAddresses, - \\ .VariablePointers, - \\ .VariablePointersStorageBuffer, - \\ .SPV_KHR_physical_storage_buffer, - \\ }), - \\ }; - \\ - \\ pub const opencl_v2: CpuModel = .{ - \\ .name = "opencl_v2", - \\ .llvm_name = null, - \\ .features = featureSet(&[_]Feature{ - \\ .v1_2, - \\ .Kernel, - \\ .Addresses, - \\ .GenericPointer, - \\ }), - \\ }; - \\}; - ); - - try bw.flush(); -} - -/// SPIRV-Registry should hold all extensions currently registered for SPIR-V. -/// The *.grammar.json in SPIRV-Headers should have most of these as well, but with this we're sure to get only the actually -/// registered ones. -/// TODO: Unfortunately, neither repository contains a machine-readable list of extension dependencies. -fn gather_extensions(allocator: Allocator, spirv_registry_root: []const u8) ![]const []const u8 { - const extensions_path = try fs.path.join(allocator, &.{ spirv_registry_root, "extensions" }); - var extensions_dir = try fs.cwd().openDir(extensions_path, .{ .iterate = true }); - defer extensions_dir.close(); - - var extensions = std.ArrayList([]const u8).init(allocator); - - var vendor_it = extensions_dir.iterate(); - while (try vendor_it.next()) |vendor_entry| { - std.debug.assert(vendor_entry.kind == .directory); // If this fails, the structure of SPIRV-Registry has changed. - - const vendor_dir = try extensions_dir.openDir(vendor_entry.name, .{ .iterate = true }); - var ext_it = vendor_dir.iterate(); - while (try ext_it.next()) |ext_entry| { - // There is both a HTML and asciidoc version of every spec (as well as some other directories), - // we need just the name, but to avoid duplicates here we will just skip anything thats not asciidoc. - if (!std.mem.endsWith(u8, ext_entry.name, ".asciidoc")) - continue; - - // Unfortunately, some extension filenames are incorrect, so we need to look for the string in the 'Name Strings' section. - // This has the following format: - // ``` - // Name Strings - // ------------ - // - // SPV_EXT_name - // ``` - // OR - // ``` - // == Name Strings - // - // SPV_EXT_name - // ``` - - const ext_spec = try vendor_dir.readFileAlloc(allocator, ext_entry.name, std.math.maxInt(usize)); - const name_strings = "Name Strings"; - - const name_strings_offset = std.mem.indexOf(u8, ext_spec, name_strings) orelse return error.InvalidRegistry; - - // As the specs are inconsistent on this next part, just skip any newlines/minuses - var ext_start = name_strings_offset + name_strings.len + 1; - while (std.ascii.isWhitespace(ext_spec[ext_start]) or ext_spec[ext_start] == '-') { - ext_start += 1; - } - - const ext_end = std.mem.indexOfScalarPos(u8, ext_spec, ext_start, '\n') orelse return error.InvalidRegistry; - const ext = std.mem.trim(u8, ext_spec[ext_start..ext_end], &std.ascii.whitespace); - - // Ignore invalid/incomplete extensions - if (std.mem.eql(u8, ext, "{extension_name}")) continue; - - std.debug.assert(std.mem.startsWith(u8, ext, "SPV_")); // Sanity check, all extensions should have a name like SPV_VENDOR_extension. - - try extensions.append(try allocator.dupe(u8, ext)); - } - } - - return extensions.items; -} - -fn insertVersion(versions: *std.ArrayList(Version), version: ?[]const u8) !void { - const ver_str = version orelse return; - if (std.mem.eql(u8, ver_str, "None")) return; - - const ver = try Version.parse(ver_str); - for (versions.items) |existing_ver| { - if (ver.eql(existing_ver)) return; - } - - try versions.append(ver); -} - -fn gatherVersions(allocator: Allocator, registry: g.CoreRegistry) ![]const Version { - // Expected number of versions is small - var versions = std.ArrayList(Version).init(allocator); - - for (registry.instructions) |inst| { - try insertVersion(&versions, inst.version); - } - - for (registry.operand_kinds) |opkind| { - const enumerants = opkind.enumerants orelse continue; - for (enumerants) |enumerant| { - try insertVersion(&versions, enumerant.version); - } - } - - std.mem.sort(Version, versions.items, {}, Version.lessThan); - - return versions.items; -} - -fn usageAndExit(file: fs.File, arg0: []const u8, code: u8) noreturn { - file.writer().print( - \\Usage: {s} /path/git/SPIRV-Headers /path/git/SPIRV-Registry - \\ - \\Prints to stdout Zig code which can be used to replace the file lib/std/target/spirv.zig. - \\ - \\SPIRV-Headers can be cloned from https://github.com/KhronosGroup/SPIRV-Headers, - \\SPIRV-Registry can be cloned from https://github.com/KhronosGroup/SPIRV-Registry. - \\ - , .{arg0}) catch std.process.exit(1); - std.process.exit(code); -} -- cgit v1.2.3 From 787208293960a02fbaf175a442d911c426a205cd Mon Sep 17 00:00:00 2001 From: Ali Cheraghi Date: Sat, 15 Feb 2025 08:37:22 +0330 Subject: spirv: extend supported `c` constraint values --- src/codegen/spirv.zig | 19 +++++++++++++++---- src/codegen/spirv/Assembler.zig | 26 ++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 4 deletions(-) (limited to 'src/codegen/spirv.zig') diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index d6997c7e6c..ec96c56ae9 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -1254,6 +1254,7 @@ const NavGen = struct { } fn ptrType(self: *NavGen, child_ty: Type, storage_class: StorageClass, child_repr: Repr) !IdRef { + const zcu = self.pt.zcu; const key = .{ child_ty.toIntern(), storage_class, child_repr }; const entry = try self.ptr_types.getOrPut(self.gpa, key); if (entry.found_existing) { @@ -1276,6 +1277,17 @@ const NavGen = struct { const child_ty_id = try self.resolveType(child_ty, child_repr); + if (self.spv.hasFeature(.shader)) { + if (child_ty.zigTypeTag(zcu) == .@"struct") { + switch (storage_class) { + .Uniform, .PushConstant => try self.spv.decorate(child_ty_id, .Block), + else => {}, + } + } + + try self.spv.decorate(result_id, .{ .ArrayStride = .{ .array_stride = @intCast(child_ty.abiSize(zcu)) } }); + } + try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpTypePointer, .{ .id_result = result_id, .storage_class = storage_class, @@ -6426,9 +6438,8 @@ const NavGen = struct { .undef => return self.fail("assembly input with 'c' constraint cannot be undefined", .{}), - .int => { - try as.value_map.put(as.gpa, name, .{ .constant = @intCast(val.toUnsignedInt(zcu)) }); - }, + .int => try as.value_map.put(as.gpa, name, .{ .constant = @intCast(val.toUnsignedInt(zcu)) }), + .enum_literal => |str| try as.value_map.put(as.gpa, name, .{ .string = str.toSlice(ip) }), else => unreachable, // TODO } @@ -6510,7 +6521,7 @@ const NavGen = struct { .just_declared, .unresolved_forward_reference => unreachable, .ty => return self.fail("cannot return spir-v type as value from assembly", .{}), .value => |ref| return ref, - .constant => return self.fail("cannot return constant from assembly", .{}), + .constant, .string => return self.fail("cannot return constant from assembly", .{}), } // TODO: Multiple results diff --git a/src/codegen/spirv/Assembler.zig b/src/codegen/spirv/Assembler.zig index 6bb79a2ebe..0713a63a7e 100644 --- a/src/codegen/spirv/Assembler.zig +++ b/src/codegen/spirv/Assembler.zig @@ -135,6 +135,9 @@ const AsmValue = union(enum) { /// This is a pre-supplied constant integer value. constant: u32, + /// This is a pre-supplied constant string value. + string: []const u8, + /// Retrieve the result-id of this AsmValue. Asserts that this AsmValue /// is of a variant that allows the result to be obtained (not an unresolved /// forward declaration, not in the process of being declared, etc). @@ -144,6 +147,7 @@ const AsmValue = union(enum) { .unresolved_forward_reference, // TODO: Lower this value as constant? .constant, + .string, => unreachable, .value => |result| result, .ty => |result| result, @@ -645,6 +649,28 @@ fn parseBitEnum(self: *Assembler, kind: spec.OperandKind) !void { /// Also handles parsing any required extra operands. fn parseValueEnum(self: *Assembler, kind: spec.OperandKind) !void { const tok = self.currentToken(); + if (self.eatToken(.placeholder)) { + const name = self.tokenText(tok)[1..]; + const value = self.value_map.get(name) orelse { + return self.fail(tok.start, "invalid placeholder '${s}'", .{name}); + }; + switch (value) { + .constant => |literal32| { + try self.inst.operands.append(self.gpa, .{ .value = literal32 }); + }, + .string => |str| { + const enumerant = for (kind.enumerants()) |enumerant| { + if (std.mem.eql(u8, enumerant.name, str)) break enumerant; + } else { + return self.fail(tok.start, "'{s}' is not a valid value for enumeration {s}", .{ str, @tagName(kind) }); + }; + try self.inst.operands.append(self.gpa, .{ .value = enumerant.value }); + }, + else => return self.fail(tok.start, "value '{s}' cannot be used as placeholder", .{name}), + } + return; + } + try self.expectToken(.value); const text = self.tokenText(tok); -- cgit v1.2.3