authorgravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2025-02-18 21:14:02+01:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2025-02-18 21:14:02+01:00
log4720a79477e7f0faf30bcce3ea4bfd3056469a79
tree917bd1ad111065e548971ffec88e2b6b5ac2f6c6
parent0779e847f79851419dfeb39595b1817ce72ea9fa
parent787208293960a02fbaf175a442d911c426a205cd
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #22889 from alichraghi/ali_spv

spirv: miscellaneous stuff

11 files changed, 530 insertions(+), 2850 deletions(-)

lib/std/Target/spirv.zig+79-2018
......@@ -1,297 +1,26 @@
1//! This file is auto-generated by tools/update_spirv_features.zig.
2//! TODO: Dependencies of capabilities on extensions.
3//! TODO: Dependencies of extensions on extensions.
4//! TODO: Dependencies of extensions on versions.
5
61const std = @import("../std.zig");
72const CpuFeature = std.Target.Cpu.Feature;
83const CpuModel = std.Target.Cpu.Model;
94
105pub const Feature = enum {
6 v1_0,
117 v1_1,
128 v1_2,
139 v1_3,
1410 v1_4,
1511 v1_5,
16 SPV_AMD_shader_fragment_mask,
17 SPV_AMD_gpu_shader_int16,
18 SPV_AMD_gpu_shader_half_float,
19 SPV_AMD_texture_gather_bias_lod,
20 SPV_AMD_shader_ballot,
21 SPV_AMD_gcn_shader,
22 SPV_AMD_shader_image_load_store_lod,
23 SPV_AMD_shader_explicit_vertex_parameter,
24 SPV_AMD_shader_trinary_minmax,
25 SPV_AMD_gpu_shader_half_float_fetch,
26 SPV_GOOGLE_hlsl_functionality1,
27 SPV_GOOGLE_user_type,
28 SPV_GOOGLE_decorate_string,
29 SPV_EXT_demote_to_helper_invocation,
30 SPV_EXT_descriptor_indexing,
31 SPV_EXT_fragment_fully_covered,
32 SPV_EXT_shader_stencil_export,
33 SPV_EXT_physical_storage_buffer,
34 SPV_EXT_shader_atomic_float_add,
35 SPV_EXT_shader_atomic_float_min_max,
36 SPV_EXT_shader_image_int64,
37 SPV_EXT_fragment_shader_interlock,
38 SPV_EXT_fragment_invocation_density,
39 SPV_EXT_shader_viewport_index_layer,
40 SPV_INTEL_loop_fuse,
41 SPV_INTEL_fpga_dsp_control,
42 SPV_INTEL_fpga_reg,
43 SPV_INTEL_fpga_memory_accesses,
44 SPV_INTEL_fpga_loop_controls,
45 SPV_INTEL_io_pipes,
46 SPV_INTEL_unstructured_loop_controls,
47 SPV_INTEL_blocking_pipes,
48 SPV_INTEL_device_side_avc_motion_estimation,
49 SPV_INTEL_fpga_memory_attributes,
50 SPV_INTEL_fp_fast_math_mode,
51 SPV_INTEL_media_block_io,
52 SPV_INTEL_shader_integer_functions2,
53 SPV_INTEL_subgroups,
54 SPV_INTEL_fpga_cluster_attributes,
55 SPV_INTEL_kernel_attributes,
56 SPV_INTEL_arbitrary_precision_integers,
57 SPV_KHR_8bit_storage,
58 SPV_KHR_shader_clock,
59 SPV_KHR_device_group,
60 SPV_KHR_16bit_storage,
61 SPV_KHR_variable_pointers,
62 SPV_KHR_no_integer_wrap_decoration,
63 SPV_KHR_subgroup_vote,
64 SPV_KHR_multiview,
65 SPV_KHR_shader_ballot,
66 SPV_KHR_vulkan_memory_model,
67 SPV_KHR_physical_storage_buffer,
68 SPV_KHR_workgroup_memory_explicit_layout,
69 SPV_KHR_fragment_shading_rate,
70 SPV_KHR_shader_atomic_counter_ops,
71 SPV_KHR_shader_draw_parameters,
72 SPV_KHR_storage_buffer_storage_class,
73 SPV_KHR_linkonce_odr,
74 SPV_KHR_terminate_invocation,
75 SPV_KHR_non_semantic_info,
76 SPV_KHR_post_depth_coverage,
77 SPV_KHR_expect_assume,
78 SPV_KHR_ray_tracing,
79 SPV_KHR_ray_query,
80 SPV_KHR_float_controls,
81 SPV_NV_viewport_array2,
82 SPV_NV_shader_subgroup_partitioned,
83 SPV_NVX_multiview_per_view_attributes,
84 SPV_NV_ray_tracing,
85 SPV_NV_shader_image_footprint,
86 SPV_NV_shading_rate,
87 SPV_NV_stereo_view_rendering,
88 SPV_NV_compute_shader_derivatives,
89 SPV_NV_shader_sm_builtins,
90 SPV_NV_mesh_shader,
91 SPV_NV_geometry_shader_passthrough,
92 SPV_NV_fragment_shader_barycentric,
93 SPV_NV_cooperative_matrix,
94 SPV_NV_sample_mask_override_coverage,
95 Matrix,
96 Shader,
97 Geometry,
98 Tessellation,
99 Addresses,
100 Linkage,
101 Kernel,
102 Vector16,
103 Float16Buffer,
104 Float16,
105 Float64,
106 Int64,
107 Int64Atomics,
108 ImageBasic,
109 ImageReadWrite,
110 ImageMipmap,
111 Pipes,
112 Groups,
113 DeviceEnqueue,
114 LiteralSampler,
115 AtomicStorage,
116 Int16,
117 TessellationPointSize,
118 GeometryPointSize,
119 ImageGatherExtended,
120 StorageImageMultisample,
121 UniformBufferArrayDynamicIndexing,
122 SampledImageArrayDynamicIndexing,
123 StorageBufferArrayDynamicIndexing,
124 StorageImageArrayDynamicIndexing,
125 ClipDistance,
126 CullDistance,
127 ImageCubeArray,
128 SampleRateShading,
129 ImageRect,
130 SampledRect,
131 GenericPointer,
132 Int8,
133 InputAttachment,
134 SparseResidency,
135 MinLod,
136 Sampled1D,
137 Image1D,
138 SampledCubeArray,
139 SampledBuffer,
140 ImageBuffer,
141 ImageMSArray,
142 StorageImageExtendedFormats,
143 ImageQuery,
144 DerivativeControl,
145 InterpolationFunction,
146 TransformFeedback,
147 GeometryStreams,
148 StorageImageReadWithoutFormat,
149 StorageImageWriteWithoutFormat,
150 MultiViewport,
151 SubgroupDispatch,
152 NamedBarrier,
153 PipeStorage,
154 GroupNonUniform,
155 GroupNonUniformVote,
156 GroupNonUniformArithmetic,
157 GroupNonUniformBallot,
158 GroupNonUniformShuffle,
159 GroupNonUniformShuffleRelative,
160 GroupNonUniformClustered,
161 GroupNonUniformQuad,
162 ShaderLayer,
163 ShaderViewportIndex,
164 FragmentShadingRateKHR,
165 SubgroupBallotKHR,
166 DrawParameters,
167 WorkgroupMemoryExplicitLayoutKHR,
168 WorkgroupMemoryExplicitLayout8BitAccessKHR,
169 WorkgroupMemoryExplicitLayout16BitAccessKHR,
170 SubgroupVoteKHR,
171 StorageBuffer16BitAccess,
172 StorageUniformBufferBlock16,
173 UniformAndStorageBuffer16BitAccess,
174 StorageUniform16,
175 StoragePushConstant16,
176 StorageInputOutput16,
177 DeviceGroup,
178 MultiView,
179 VariablePointersStorageBuffer,
180 VariablePointers,
181 AtomicStorageOps,
182 SampleMaskPostDepthCoverage,
183 StorageBuffer8BitAccess,
184 UniformAndStorageBuffer8BitAccess,
185 StoragePushConstant8,
186 DenormPreserve,
187 DenormFlushToZero,
188 SignedZeroInfNanPreserve,
189 RoundingModeRTE,
190 RoundingModeRTZ,
191 RayQueryProvisionalKHR,
192 RayQueryKHR,
193 RayTraversalPrimitiveCullingKHR,
194 RayTracingKHR,
195 Float16ImageAMD,
196 ImageGatherBiasLodAMD,
197 FragmentMaskAMD,
198 StencilExportEXT,
199 ImageReadWriteLodAMD,
200 Int64ImageEXT,
201 ShaderClockKHR,
202 SampleMaskOverrideCoverageNV,
203 GeometryShaderPassthroughNV,
204 ShaderViewportIndexLayerEXT,
205 ShaderViewportIndexLayerNV,
206 ShaderViewportMaskNV,
207 ShaderStereoViewNV,
208 PerViewAttributesNV,
209 FragmentFullyCoveredEXT,
210 MeshShadingNV,
211 ImageFootprintNV,
212 FragmentBarycentricNV,
213 ComputeDerivativeGroupQuadsNV,
214 FragmentDensityEXT,
215 ShadingRateNV,
216 GroupNonUniformPartitionedNV,
217 ShaderNonUniform,
218 ShaderNonUniformEXT,
219 RuntimeDescriptorArray,
220 RuntimeDescriptorArrayEXT,
221 InputAttachmentArrayDynamicIndexing,
222 InputAttachmentArrayDynamicIndexingEXT,
223 UniformTexelBufferArrayDynamicIndexing,
224 UniformTexelBufferArrayDynamicIndexingEXT,
225 StorageTexelBufferArrayDynamicIndexing,
226 StorageTexelBufferArrayDynamicIndexingEXT,
227 UniformBufferArrayNonUniformIndexing,
228 UniformBufferArrayNonUniformIndexingEXT,
229 SampledImageArrayNonUniformIndexing,
230 SampledImageArrayNonUniformIndexingEXT,
231 StorageBufferArrayNonUniformIndexing,
232 StorageBufferArrayNonUniformIndexingEXT,
233 StorageImageArrayNonUniformIndexing,
234 StorageImageArrayNonUniformIndexingEXT,
235 InputAttachmentArrayNonUniformIndexing,
236 InputAttachmentArrayNonUniformIndexingEXT,
237 UniformTexelBufferArrayNonUniformIndexing,
238 UniformTexelBufferArrayNonUniformIndexingEXT,
239 StorageTexelBufferArrayNonUniformIndexing,
240 StorageTexelBufferArrayNonUniformIndexingEXT,
241 RayTracingNV,
242 VulkanMemoryModel,
243 VulkanMemoryModelKHR,
244 VulkanMemoryModelDeviceScope,
245 VulkanMemoryModelDeviceScopeKHR,
246 PhysicalStorageBufferAddresses,
247 PhysicalStorageBufferAddressesEXT,
248 ComputeDerivativeGroupLinearNV,
249 RayTracingProvisionalKHR,
250 CooperativeMatrixNV,
251 FragmentShaderSampleInterlockEXT,
252 FragmentShaderShadingRateInterlockEXT,
253 ShaderSMBuiltinsNV,
254 FragmentShaderPixelInterlockEXT,
255 DemoteToHelperInvocationEXT,
256 SubgroupShuffleINTEL,
257 SubgroupBufferBlockIOINTEL,
258 SubgroupImageBlockIOINTEL,
259 SubgroupImageMediaBlockIOINTEL,
260 RoundToInfinityINTEL,
261 FloatingPointModeINTEL,
262 IntegerFunctions2INTEL,
263 FunctionPointersINTEL,
264 IndirectReferencesINTEL,
265 AsmINTEL,
266 AtomicFloat32MinMaxEXT,
267 AtomicFloat64MinMaxEXT,
268 AtomicFloat16MinMaxEXT,
269 VectorComputeINTEL,
270 VectorAnyINTEL,
271 ExpectAssumeKHR,
272 SubgroupAvcMotionEstimationINTEL,
273 SubgroupAvcMotionEstimationIntraINTEL,
274 SubgroupAvcMotionEstimationChromaINTEL,
275 VariableLengthArrayINTEL,
276 FunctionFloatControlINTEL,
277 FPGAMemoryAttributesINTEL,
278 FPFastMathModeINTEL,
279 ArbitraryPrecisionIntegersINTEL,
280 UnstructuredLoopControlsINTEL,
281 FPGALoopControlsINTEL,
282 KernelAttributesINTEL,
283 FPGAKernelAttributesINTEL,
284 FPGAMemoryAccessesINTEL,
285 FPGAClusterAttributesINTEL,
286 LoopFuseINTEL,
287 FPGABufferLocationINTEL,
288 USMStorageClassesINTEL,
289 IOPipesINTEL,
290 BlockingPipesINTEL,
291 FPGARegINTEL,
292 AtomicFloat32AddEXT,
293 AtomicFloat64AddEXT,
294 LongConstantCompositeINTEL,
12 v1_6,
13 int8,
14 int16,
15 int64,
16 float16,
17 float64,
18 addresses,
19 matrix,
20 kernel,
21 generic_pointer,
22 vector16,
23 shader,
29524};
29625
29726pub const featureSet = CpuFeature.FeatureSetFns(Feature).featureSet;
......@@ -304,1788 +33,120 @@ pub const all_features = blk: {
30433 const len = @typeInfo(Feature).@"enum".fields.len;
30534 std.debug.assert(len <= CpuFeature.Set.needed_bit_count);
30635 var result: [len]CpuFeature = undefined;
36 result[@intFromEnum(Feature.v1_0)] = .{
37 .llvm_name = null,
38 .description = "SPIR-V version 1.0",
39 .dependencies = featureSet(&[_]Feature{}),
40 };
30741 result[@intFromEnum(Feature.v1_1)] = .{
30842 .llvm_name = null,
30943 .description = "SPIR-V version 1.1",
310 .dependencies = featureSet(&[_]Feature{}),
44 .dependencies = featureSet(&[_]Feature{.v1_0}),
31145 };
31246 result[@intFromEnum(Feature.v1_2)] = .{
31347 .llvm_name = null,
31448 .description = "SPIR-V version 1.2",
315 .dependencies = featureSet(&[_]Feature{
316 .v1_1,
317 }),
49 .dependencies = featureSet(&[_]Feature{.v1_1}),
31850 };
31951 result[@intFromEnum(Feature.v1_3)] = .{
32052 .llvm_name = null,
32153 .description = "SPIR-V version 1.3",
322 .dependencies = featureSet(&[_]Feature{
323 .v1_2,
324 }),
54 .dependencies = featureSet(&[_]Feature{.v1_2}),
32555 };
32656 result[@intFromEnum(Feature.v1_4)] = .{
32757 .llvm_name = null,
32858 .description = "SPIR-V version 1.4",
329 .dependencies = featureSet(&[_]Feature{
330 .v1_3,
331 }),
59 .dependencies = featureSet(&[_]Feature{.v1_3}),
33260 };
33361 result[@intFromEnum(Feature.v1_5)] = .{
33462 .llvm_name = null,
33563 .description = "SPIR-V version 1.5",
336 .dependencies = featureSet(&[_]Feature{
337 .v1_4,
338 }),
339 };
340 result[@intFromEnum(Feature.SPV_AMD_shader_fragment_mask)] = .{
341 .llvm_name = null,
342 .description = "SPIR-V extension SPV_AMD_shader_fragment_mask",
343 .dependencies = featureSet(&[_]Feature{}),
344 };
345 result[@intFromEnum(Feature.SPV_AMD_gpu_shader_int16)] = .{
346 .llvm_name = null,
347 .description = "SPIR-V extension SPV_AMD_gpu_shader_int16",
348 .dependencies = featureSet(&[_]Feature{}),
349 };
350 result[@intFromEnum(Feature.SPV_AMD_gpu_shader_half_float)] = .{
351 .llvm_name = null,
352 .description = "SPIR-V extension SPV_AMD_gpu_shader_half_float",
353 .dependencies = featureSet(&[_]Feature{}),
354 };
355 result[@intFromEnum(Feature.SPV_AMD_texture_gather_bias_lod)] = .{
356 .llvm_name = null,
357 .description = "SPIR-V extension SPV_AMD_texture_gather_bias_lod",
358 .dependencies = featureSet(&[_]Feature{}),
359 };
360 result[@intFromEnum(Feature.SPV_AMD_shader_ballot)] = .{
361 .llvm_name = null,
362 .description = "SPIR-V extension SPV_AMD_shader_ballot",
363 .dependencies = featureSet(&[_]Feature{}),
364 };
365 result[@intFromEnum(Feature.SPV_AMD_gcn_shader)] = .{
366 .llvm_name = null,
367 .description = "SPIR-V extension SPV_AMD_gcn_shader",
368 .dependencies = featureSet(&[_]Feature{}),
369 };
370 result[@intFromEnum(Feature.SPV_AMD_shader_image_load_store_lod)] = .{
371 .llvm_name = null,
372 .description = "SPIR-V extension SPV_AMD_shader_image_load_store_lod",
373 .dependencies = featureSet(&[_]Feature{}),
374 };
375 result[@intFromEnum(Feature.SPV_AMD_shader_explicit_vertex_parameter)] = .{
376 .llvm_name = null,
377 .description = "SPIR-V extension SPV_AMD_shader_explicit_vertex_parameter",
378 .dependencies = featureSet(&[_]Feature{}),
379 };
380 result[@intFromEnum(Feature.SPV_AMD_shader_trinary_minmax)] = .{
381 .llvm_name = null,
382 .description = "SPIR-V extension SPV_AMD_shader_trinary_minmax",
383 .dependencies = featureSet(&[_]Feature{}),
384 };
385 result[@intFromEnum(Feature.SPV_AMD_gpu_shader_half_float_fetch)] = .{
386 .llvm_name = null,
387 .description = "SPIR-V extension SPV_AMD_gpu_shader_half_float_fetch",
388 .dependencies = featureSet(&[_]Feature{}),
389 };
390 result[@intFromEnum(Feature.SPV_GOOGLE_hlsl_functionality1)] = .{
391 .llvm_name = null,
392 .description = "SPIR-V extension SPV_GOOGLE_hlsl_functionality1",
393 .dependencies = featureSet(&[_]Feature{}),
394 };
395 result[@intFromEnum(Feature.SPV_GOOGLE_user_type)] = .{
396 .llvm_name = null,
397 .description = "SPIR-V extension SPV_GOOGLE_user_type",
398 .dependencies = featureSet(&[_]Feature{}),
399 };
400 result[@intFromEnum(Feature.SPV_GOOGLE_decorate_string)] = .{
401 .llvm_name = null,
402 .description = "SPIR-V extension SPV_GOOGLE_decorate_string",
403 .dependencies = featureSet(&[_]Feature{}),
404 };
405 result[@intFromEnum(Feature.SPV_EXT_demote_to_helper_invocation)] = .{
406 .llvm_name = null,
407 .description = "SPIR-V extension SPV_EXT_demote_to_helper_invocation",
408 .dependencies = featureSet(&[_]Feature{}),
409 };
410 result[@intFromEnum(Feature.SPV_EXT_descriptor_indexing)] = .{
411 .llvm_name = null,
412 .description = "SPIR-V extension SPV_EXT_descriptor_indexing",
413 .dependencies = featureSet(&[_]Feature{}),
414 };
415 result[@intFromEnum(Feature.SPV_EXT_fragment_fully_covered)] = .{
416 .llvm_name = null,
417 .description = "SPIR-V extension SPV_EXT_fragment_fully_covered",
418 .dependencies = featureSet(&[_]Feature{}),
419 };
420 result[@intFromEnum(Feature.SPV_EXT_shader_stencil_export)] = .{
421 .llvm_name = null,
422 .description = "SPIR-V extension SPV_EXT_shader_stencil_export",
423 .dependencies = featureSet(&[_]Feature{}),
424 };
425 result[@intFromEnum(Feature.SPV_EXT_physical_storage_buffer)] = .{
426 .llvm_name = null,
427 .description = "SPIR-V extension SPV_EXT_physical_storage_buffer",
428 .dependencies = featureSet(&[_]Feature{}),
429 };
430 result[@intFromEnum(Feature.SPV_EXT_shader_atomic_float_add)] = .{
431 .llvm_name = null,
432 .description = "SPIR-V extension SPV_EXT_shader_atomic_float_add",
433 .dependencies = featureSet(&[_]Feature{}),
434 };
435 result[@intFromEnum(Feature.SPV_EXT_shader_atomic_float_min_max)] = .{
436 .llvm_name = null,
437 .description = "SPIR-V extension SPV_EXT_shader_atomic_float_min_max",
438 .dependencies = featureSet(&[_]Feature{}),
439 };
440 result[@intFromEnum(Feature.SPV_EXT_shader_image_int64)] = .{
441 .llvm_name = null,
442 .description = "SPIR-V extension SPV_EXT_shader_image_int64",
443 .dependencies = featureSet(&[_]Feature{}),
444 };
445 result[@intFromEnum(Feature.SPV_EXT_fragment_shader_interlock)] = .{
446 .llvm_name = null,
447 .description = "SPIR-V extension SPV_EXT_fragment_shader_interlock",
448 .dependencies = featureSet(&[_]Feature{}),
449 };
450 result[@intFromEnum(Feature.SPV_EXT_fragment_invocation_density)] = .{
451 .llvm_name = null,
452 .description = "SPIR-V extension SPV_EXT_fragment_invocation_density",
453 .dependencies = featureSet(&[_]Feature{}),
454 };
455 result[@intFromEnum(Feature.SPV_EXT_shader_viewport_index_layer)] = .{
456 .llvm_name = null,
457 .description = "SPIR-V extension SPV_EXT_shader_viewport_index_layer",
458 .dependencies = featureSet(&[_]Feature{}),
459 };
460 result[@intFromEnum(Feature.SPV_INTEL_loop_fuse)] = .{
461 .llvm_name = null,
462 .description = "SPIR-V extension SPV_INTEL_loop_fuse",
463 .dependencies = featureSet(&[_]Feature{}),
464 };
465 result[@intFromEnum(Feature.SPV_INTEL_fpga_dsp_control)] = .{
466 .llvm_name = null,
467 .description = "SPIR-V extension SPV_INTEL_fpga_dsp_control",
468 .dependencies = featureSet(&[_]Feature{}),
469 };
470 result[@intFromEnum(Feature.SPV_INTEL_fpga_reg)] = .{
471 .llvm_name = null,
472 .description = "SPIR-V extension SPV_INTEL_fpga_reg",
473 .dependencies = featureSet(&[_]Feature{}),
474 };
475 result[@intFromEnum(Feature.SPV_INTEL_fpga_memory_accesses)] = .{
476 .llvm_name = null,
477 .description = "SPIR-V extension SPV_INTEL_fpga_memory_accesses",
478 .dependencies = featureSet(&[_]Feature{}),
479 };
480 result[@intFromEnum(Feature.SPV_INTEL_fpga_loop_controls)] = .{
481 .llvm_name = null,
482 .description = "SPIR-V extension SPV_INTEL_fpga_loop_controls",
483 .dependencies = featureSet(&[_]Feature{}),
484 };
485 result[@intFromEnum(Feature.SPV_INTEL_io_pipes)] = .{
486 .llvm_name = null,
487 .description = "SPIR-V extension SPV_INTEL_io_pipes",
488 .dependencies = featureSet(&[_]Feature{}),
489 };
490 result[@intFromEnum(Feature.SPV_INTEL_unstructured_loop_controls)] = .{
491 .llvm_name = null,
492 .description = "SPIR-V extension SPV_INTEL_unstructured_loop_controls",
493 .dependencies = featureSet(&[_]Feature{}),
494 };
495 result[@intFromEnum(Feature.SPV_INTEL_blocking_pipes)] = .{
496 .llvm_name = null,
497 .description = "SPIR-V extension SPV_INTEL_blocking_pipes",
498 .dependencies = featureSet(&[_]Feature{}),
499 };
500 result[@intFromEnum(Feature.SPV_INTEL_device_side_avc_motion_estimation)] = .{
501 .llvm_name = null,
502 .description = "SPIR-V extension SPV_INTEL_device_side_avc_motion_estimation",
503 .dependencies = featureSet(&[_]Feature{}),
504 };
505 result[@intFromEnum(Feature.SPV_INTEL_fpga_memory_attributes)] = .{
506 .llvm_name = null,
507 .description = "SPIR-V extension SPV_INTEL_fpga_memory_attributes",
508 .dependencies = featureSet(&[_]Feature{}),
509 };
510 result[@intFromEnum(Feature.SPV_INTEL_fp_fast_math_mode)] = .{
511 .llvm_name = null,
512 .description = "SPIR-V extension SPV_INTEL_fp_fast_math_mode",
513 .dependencies = featureSet(&[_]Feature{}),
514 };
515 result[@intFromEnum(Feature.SPV_INTEL_media_block_io)] = .{
516 .llvm_name = null,
517 .description = "SPIR-V extension SPV_INTEL_media_block_io",
518 .dependencies = featureSet(&[_]Feature{}),
519 };
520 result[@intFromEnum(Feature.SPV_INTEL_shader_integer_functions2)] = .{
521 .llvm_name = null,
522 .description = "SPIR-V extension SPV_INTEL_shader_integer_functions2",
523 .dependencies = featureSet(&[_]Feature{}),
524 };
525 result[@intFromEnum(Feature.SPV_INTEL_subgroups)] = .{
526 .llvm_name = null,
527 .description = "SPIR-V extension SPV_INTEL_subgroups",
528 .dependencies = featureSet(&[_]Feature{}),
529 };
530 result[@intFromEnum(Feature.SPV_INTEL_fpga_cluster_attributes)] = .{
531 .llvm_name = null,
532 .description = "SPIR-V extension SPV_INTEL_fpga_cluster_attributes",
533 .dependencies = featureSet(&[_]Feature{}),
534 };
535 result[@intFromEnum(Feature.SPV_INTEL_kernel_attributes)] = .{
536 .llvm_name = null,
537 .description = "SPIR-V extension SPV_INTEL_kernel_attributes",
538 .dependencies = featureSet(&[_]Feature{}),
539 };
540 result[@intFromEnum(Feature.SPV_INTEL_arbitrary_precision_integers)] = .{
541 .llvm_name = null,
542 .description = "SPIR-V extension SPV_INTEL_arbitrary_precision_integers",
543 .dependencies = featureSet(&[_]Feature{}),
64 .dependencies = featureSet(&[_]Feature{.v1_4}),
54465 };
545 result[@intFromEnum(Feature.SPV_KHR_8bit_storage)] = .{
66 result[@intFromEnum(Feature.v1_6)] = .{
54667 .llvm_name = null,
547 .description = "SPIR-V extension SPV_KHR_8bit_storage",
548 .dependencies = featureSet(&[_]Feature{}),
549 };
550 result[@intFromEnum(Feature.SPV_KHR_shader_clock)] = .{
551 .llvm_name = null,
552 .description = "SPIR-V extension SPV_KHR_shader_clock",
553 .dependencies = featureSet(&[_]Feature{}),
554 };
555 result[@intFromEnum(Feature.SPV_KHR_device_group)] = .{
556 .llvm_name = null,
557 .description = "SPIR-V extension SPV_KHR_device_group",
558 .dependencies = featureSet(&[_]Feature{}),
559 };
560 result[@intFromEnum(Feature.SPV_KHR_16bit_storage)] = .{
561 .llvm_name = null,
562 .description = "SPIR-V extension SPV_KHR_16bit_storage",
563 .dependencies = featureSet(&[_]Feature{}),
564 };
565 result[@intFromEnum(Feature.SPV_KHR_variable_pointers)] = .{
566 .llvm_name = null,
567 .description = "SPIR-V extension SPV_KHR_variable_pointers",
568 .dependencies = featureSet(&[_]Feature{}),
569 };
570 result[@intFromEnum(Feature.SPV_KHR_no_integer_wrap_decoration)] = .{
571 .llvm_name = null,
572 .description = "SPIR-V extension SPV_KHR_no_integer_wrap_decoration",
573 .dependencies = featureSet(&[_]Feature{}),
574 };
575 result[@intFromEnum(Feature.SPV_KHR_subgroup_vote)] = .{
576 .llvm_name = null,
577 .description = "SPIR-V extension SPV_KHR_subgroup_vote",
578 .dependencies = featureSet(&[_]Feature{}),
579 };
580 result[@intFromEnum(Feature.SPV_KHR_multiview)] = .{
581 .llvm_name = null,
582 .description = "SPIR-V extension SPV_KHR_multiview",
583 .dependencies = featureSet(&[_]Feature{}),
584 };
585 result[@intFromEnum(Feature.SPV_KHR_shader_ballot)] = .{
586 .llvm_name = null,
587 .description = "SPIR-V extension SPV_KHR_shader_ballot",
588 .dependencies = featureSet(&[_]Feature{}),
589 };
590 result[@intFromEnum(Feature.SPV_KHR_vulkan_memory_model)] = .{
591 .llvm_name = null,
592 .description = "SPIR-V extension SPV_KHR_vulkan_memory_model",
593 .dependencies = featureSet(&[_]Feature{}),
594 };
595 result[@intFromEnum(Feature.SPV_KHR_physical_storage_buffer)] = .{
596 .llvm_name = null,
597 .description = "SPIR-V extension SPV_KHR_physical_storage_buffer",
598 .dependencies = featureSet(&[_]Feature{}),
599 };
600 result[@intFromEnum(Feature.SPV_KHR_workgroup_memory_explicit_layout)] = .{
601 .llvm_name = null,
602 .description = "SPIR-V extension SPV_KHR_workgroup_memory_explicit_layout",
603 .dependencies = featureSet(&[_]Feature{}),
604 };
605 result[@intFromEnum(Feature.SPV_KHR_fragment_shading_rate)] = .{
606 .llvm_name = null,
607 .description = "SPIR-V extension SPV_KHR_fragment_shading_rate",
608 .dependencies = featureSet(&[_]Feature{}),
609 };
610 result[@intFromEnum(Feature.SPV_KHR_shader_atomic_counter_ops)] = .{
611 .llvm_name = null,
612 .description = "SPIR-V extension SPV_KHR_shader_atomic_counter_ops",
613 .dependencies = featureSet(&[_]Feature{}),
614 };
615 result[@intFromEnum(Feature.SPV_KHR_shader_draw_parameters)] = .{
616 .llvm_name = null,
617 .description = "SPIR-V extension SPV_KHR_shader_draw_parameters",
618 .dependencies = featureSet(&[_]Feature{}),
619 };
620 result[@intFromEnum(Feature.SPV_KHR_storage_buffer_storage_class)] = .{
621 .llvm_name = null,
622 .description = "SPIR-V extension SPV_KHR_storage_buffer_storage_class",
623 .dependencies = featureSet(&[_]Feature{}),
624 };
625 result[@intFromEnum(Feature.SPV_KHR_linkonce_odr)] = .{
626 .llvm_name = null,
627 .description = "SPIR-V extension SPV_KHR_linkonce_odr",
628 .dependencies = featureSet(&[_]Feature{}),
629 };
630 result[@intFromEnum(Feature.SPV_KHR_terminate_invocation)] = .{
631 .llvm_name = null,
632 .description = "SPIR-V extension SPV_KHR_terminate_invocation",
633 .dependencies = featureSet(&[_]Feature{}),
634 };
635 result[@intFromEnum(Feature.SPV_KHR_non_semantic_info)] = .{
636 .llvm_name = null,
637 .description = "SPIR-V extension SPV_KHR_non_semantic_info",
638 .dependencies = featureSet(&[_]Feature{}),
639 };
640 result[@intFromEnum(Feature.SPV_KHR_post_depth_coverage)] = .{
641 .llvm_name = null,
642 .description = "SPIR-V extension SPV_KHR_post_depth_coverage",
643 .dependencies = featureSet(&[_]Feature{}),
644 };
645 result[@intFromEnum(Feature.SPV_KHR_expect_assume)] = .{
646 .llvm_name = null,
647 .description = "SPIR-V extension SPV_KHR_expect_assume",
648 .dependencies = featureSet(&[_]Feature{}),
649 };
650 result[@intFromEnum(Feature.SPV_KHR_ray_tracing)] = .{
651 .llvm_name = null,
652 .description = "SPIR-V extension SPV_KHR_ray_tracing",
653 .dependencies = featureSet(&[_]Feature{}),
68 .description = "SPIR-V version 1.6",
69 .dependencies = featureSet(&[_]Feature{.v1_5}),
65470 };
655 result[@intFromEnum(Feature.SPV_KHR_ray_query)] = .{
71 result[@intFromEnum(Feature.int8)] = .{
65672 .llvm_name = null,
657 .description = "SPIR-V extension SPV_KHR_ray_query",
658 .dependencies = featureSet(&[_]Feature{}),
659 };
660 result[@intFromEnum(Feature.SPV_KHR_float_controls)] = .{
661 .llvm_name = null,
662 .description = "SPIR-V extension SPV_KHR_float_controls",
663 .dependencies = featureSet(&[_]Feature{}),
664 };
665 result[@intFromEnum(Feature.SPV_NV_viewport_array2)] = .{
666 .llvm_name = null,
667 .description = "SPIR-V extension SPV_NV_viewport_array2",
668 .dependencies = featureSet(&[_]Feature{}),
669 };
670 result[@intFromEnum(Feature.SPV_NV_shader_subgroup_partitioned)] = .{
671 .llvm_name = null,
672 .description = "SPIR-V extension SPV_NV_shader_subgroup_partitioned",
673 .dependencies = featureSet(&[_]Feature{}),
674 };
675 result[@intFromEnum(Feature.SPV_NVX_multiview_per_view_attributes)] = .{
676 .llvm_name = null,
677 .description = "SPIR-V extension SPV_NVX_multiview_per_view_attributes",
678 .dependencies = featureSet(&[_]Feature{}),
679 };
680 result[@intFromEnum(Feature.SPV_NV_ray_tracing)] = .{
681 .llvm_name = null,
682 .description = "SPIR-V extension SPV_NV_ray_tracing",
683 .dependencies = featureSet(&[_]Feature{}),
684 };
685 result[@intFromEnum(Feature.SPV_NV_shader_image_footprint)] = .{
686 .llvm_name = null,
687 .description = "SPIR-V extension SPV_NV_shader_image_footprint",
688 .dependencies = featureSet(&[_]Feature{}),
689 };
690 result[@intFromEnum(Feature.SPV_NV_shading_rate)] = .{
691 .llvm_name = null,
692 .description = "SPIR-V extension SPV_NV_shading_rate",
693 .dependencies = featureSet(&[_]Feature{}),
73 .description = "Enable SPIR-V capability Int8",
74 .dependencies = featureSet(&[_]Feature{.v1_0}),
69475 };
695 result[@intFromEnum(Feature.SPV_NV_stereo_view_rendering)] = .{
76 result[@intFromEnum(Feature.int16)] = .{
69677 .llvm_name = null,
697 .description = "SPIR-V extension SPV_NV_stereo_view_rendering",
698 .dependencies = featureSet(&[_]Feature{}),
78 .description = "Enable SPIR-V capability Int16",
79 .dependencies = featureSet(&[_]Feature{.v1_0}),
69980 };
700 result[@intFromEnum(Feature.SPV_NV_compute_shader_derivatives)] = .{
81 result[@intFromEnum(Feature.int64)] = .{
70182 .llvm_name = null,
702 .description = "SPIR-V extension SPV_NV_compute_shader_derivatives",
703 .dependencies = featureSet(&[_]Feature{}),
83 .description = "Enable SPIR-V capability Int64",
84 .dependencies = featureSet(&[_]Feature{.v1_0}),
70485 };
705 result[@intFromEnum(Feature.SPV_NV_shader_sm_builtins)] = .{
86 result[@intFromEnum(Feature.float16)] = .{
70687 .llvm_name = null,
707 .description = "SPIR-V extension SPV_NV_shader_sm_builtins",
708 .dependencies = featureSet(&[_]Feature{}),
88 .description = "Enable SPIR-V capability Float16",
89 .dependencies = featureSet(&[_]Feature{.v1_0}),
70990 };
710 result[@intFromEnum(Feature.SPV_NV_mesh_shader)] = .{
91 result[@intFromEnum(Feature.float64)] = .{
71192 .llvm_name = null,
712 .description = "SPIR-V extension SPV_NV_mesh_shader",
713 .dependencies = featureSet(&[_]Feature{}),
93 .description = "Enable SPIR-V capability Float64",
94 .dependencies = featureSet(&[_]Feature{.v1_0}),
71495 };
715 result[@intFromEnum(Feature.SPV_NV_geometry_shader_passthrough)] = .{
96 result[@intFromEnum(Feature.addresses)] = .{
71697 .llvm_name = null,
717 .description = "SPIR-V extension SPV_NV_geometry_shader_passthrough",
718 .dependencies = featureSet(&[_]Feature{}),
98 .description = "Enable SPIR-V capability Addresses",
99 .dependencies = featureSet(&[_]Feature{.v1_0}),
719100 };
720 result[@intFromEnum(Feature.SPV_NV_fragment_shader_barycentric)] = .{
101 result[@intFromEnum(Feature.matrix)] = .{
721102 .llvm_name = null,
722 .description = "SPIR-V extension SPV_NV_fragment_shader_barycentric",
723 .dependencies = featureSet(&[_]Feature{}),
103 .description = "Enable SPIR-V capability Matrix",
104 .dependencies = featureSet(&[_]Feature{.v1_0}),
724105 };
725 result[@intFromEnum(Feature.SPV_NV_cooperative_matrix)] = .{
106 result[@intFromEnum(Feature.kernel)] = .{
726107 .llvm_name = null,
727 .description = "SPIR-V extension SPV_NV_cooperative_matrix",
728 .dependencies = featureSet(&[_]Feature{}),
108 .description = "Enable SPIR-V capability Kernel",
109 .dependencies = featureSet(&[_]Feature{.v1_0}),
729110 };
730 result[@intFromEnum(Feature.SPV_NV_sample_mask_override_coverage)] = .{
111 result[@intFromEnum(Feature.generic_pointer)] = .{
731112 .llvm_name = null,
732 .description = "SPIR-V extension SPV_NV_sample_mask_override_coverage",
733 .dependencies = featureSet(&[_]Feature{}),
113 .description = "Enable SPIR-V capability GenericPointer",
114 .dependencies = featureSet(&[_]Feature{ .v1_0, .addresses }),
734115 };
735 result[@intFromEnum(Feature.Matrix)] = .{
116 result[@intFromEnum(Feature.vector16)] = .{
736117 .llvm_name = null,
737 .description = "Enable SPIR-V capability Matrix",
738 .dependencies = featureSet(&[_]Feature{}),
118 .description = "Enable SPIR-V capability Vector16",
119 .dependencies = featureSet(&[_]Feature{ .v1_0, .kernel }),
739120 };
740 result[@intFromEnum(Feature.Shader)] = .{
121 result[@intFromEnum(Feature.shader)] = .{
741122 .llvm_name = null,
742123 .description = "Enable SPIR-V capability Shader",
743 .dependencies = featureSet(&[_]Feature{
744 .Matrix,
745 }),
746 };
747 result[@intFromEnum(Feature.Geometry)] = .{
748 .llvm_name = null,
749 .description = "Enable SPIR-V capability Geometry",
750 .dependencies = featureSet(&[_]Feature{
751 .Shader,
752 }),
124 .dependencies = featureSet(&[_]Feature{ .v1_0, .matrix }),
753125 };
754 result[@intFromEnum(Feature.Tessellation)] = .{
755 .llvm_name = null,
756 .description = "Enable SPIR-V capability Tessellation",
757 .dependencies = featureSet(&[_]Feature{
758 .Shader,
759 }),
760 };
761 result[@intFromEnum(Feature.Addresses)] = .{
762 .llvm_name = null,
763 .description = "Enable SPIR-V capability Addresses",
764 .dependencies = featureSet(&[_]Feature{}),
126 const ti = @typeInfo(Feature);
127 for (&result, 0..) |*elem, i| {
128 elem.index = i;
129 elem.name = ti.@"enum".fields[i].name;
130 }
131 break :blk result;
132};
133
134pub const cpu = struct {
135 pub const generic: CpuModel = .{
136 .name = "generic",
137 .llvm_name = "generic",
138 .features = featureSet(&[_]Feature{.v1_0}),
765139 };
766 result[@intFromEnum(Feature.Linkage)] = .{
140
141 pub const vulkan_v1_2: CpuModel = .{
142 .name = "vulkan_v1_2",
767143 .llvm_name = null,
768 .description = "Enable SPIR-V capability Linkage",
769 .dependencies = featureSet(&[_]Feature{}),
144 .features = featureSet(&[_]Feature{ .v1_5, .shader, .addresses }),
770145 };
771 result[@intFromEnum(Feature.Kernel)] = .{
146
147 pub const opencl_v2: CpuModel = .{
148 .name = "opencl_v2",
772149 .llvm_name = null,
773 .description = "Enable SPIR-V capability Kernel",
774 .dependencies = featureSet(&[_]Feature{}),
775 };
776 result[@intFromEnum(Feature.Vector16)] = .{
777 .llvm_name = null,
778 .description = "Enable SPIR-V capability Vector16",
779 .dependencies = featureSet(&[_]Feature{
780 .Kernel,
781 }),
782 };
783 result[@intFromEnum(Feature.Float16Buffer)] = .{
784 .llvm_name = null,
785 .description = "Enable SPIR-V capability Float16Buffer",
786 .dependencies = featureSet(&[_]Feature{
787 .Kernel,
788 }),
789 };
790 result[@intFromEnum(Feature.Float16)] = .{
791 .llvm_name = null,
792 .description = "Enable SPIR-V capability Float16",
793 .dependencies = featureSet(&[_]Feature{}),
794 };
795 result[@intFromEnum(Feature.Float64)] = .{
796 .llvm_name = null,
797 .description = "Enable SPIR-V capability Float64",
798 .dependencies = featureSet(&[_]Feature{}),
799 };
800 result[@intFromEnum(Feature.Int64)] = .{
801 .llvm_name = null,
802 .description = "Enable SPIR-V capability Int64",
803 .dependencies = featureSet(&[_]Feature{}),
804 };
805 result[@intFromEnum(Feature.Int64Atomics)] = .{
806 .llvm_name = null,
807 .description = "Enable SPIR-V capability Int64Atomics",
808 .dependencies = featureSet(&[_]Feature{
809 .Int64,
810 }),
811 };
812 result[@intFromEnum(Feature.ImageBasic)] = .{
813 .llvm_name = null,
814 .description = "Enable SPIR-V capability ImageBasic",
815 .dependencies = featureSet(&[_]Feature{
816 .Kernel,
817 }),
818 };
819 result[@intFromEnum(Feature.ImageReadWrite)] = .{
820 .llvm_name = null,
821 .description = "Enable SPIR-V capability ImageReadWrite",
822 .dependencies = featureSet(&[_]Feature{
823 .ImageBasic,
824 }),
825 };
826 result[@intFromEnum(Feature.ImageMipmap)] = .{
827 .llvm_name = null,
828 .description = "Enable SPIR-V capability ImageMipmap",
829 .dependencies = featureSet(&[_]Feature{
830 .ImageBasic,
831 }),
832 };
833 result[@intFromEnum(Feature.Pipes)] = .{
834 .llvm_name = null,
835 .description = "Enable SPIR-V capability Pipes",
836 .dependencies = featureSet(&[_]Feature{
837 .Kernel,
838 }),
839 };
840 result[@intFromEnum(Feature.Groups)] = .{
841 .llvm_name = null,
842 .description = "Enable SPIR-V capability Groups",
843 .dependencies = featureSet(&[_]Feature{}),
844 };
845 result[@intFromEnum(Feature.DeviceEnqueue)] = .{
846 .llvm_name = null,
847 .description = "Enable SPIR-V capability DeviceEnqueue",
848 .dependencies = featureSet(&[_]Feature{
849 .Kernel,
850 }),
851 };
852 result[@intFromEnum(Feature.LiteralSampler)] = .{
853 .llvm_name = null,
854 .description = "Enable SPIR-V capability LiteralSampler",
855 .dependencies = featureSet(&[_]Feature{
856 .Kernel,
857 }),
858 };
859 result[@intFromEnum(Feature.AtomicStorage)] = .{
860 .llvm_name = null,
861 .description = "Enable SPIR-V capability AtomicStorage",
862 .dependencies = featureSet(&[_]Feature{
863 .Shader,
864 }),
865 };
866 result[@intFromEnum(Feature.Int16)] = .{
867 .llvm_name = null,
868 .description = "Enable SPIR-V capability Int16",
869 .dependencies = featureSet(&[_]Feature{}),
870 };
871 result[@intFromEnum(Feature.TessellationPointSize)] = .{
872 .llvm_name = null,
873 .description = "Enable SPIR-V capability TessellationPointSize",
874 .dependencies = featureSet(&[_]Feature{
875 .Tessellation,
876 }),
877 };
878 result[@intFromEnum(Feature.GeometryPointSize)] = .{
879 .llvm_name = null,
880 .description = "Enable SPIR-V capability GeometryPointSize",
881 .dependencies = featureSet(&[_]Feature{
882 .Geometry,
883 }),
884 };
885 result[@intFromEnum(Feature.ImageGatherExtended)] = .{
886 .llvm_name = null,
887 .description = "Enable SPIR-V capability ImageGatherExtended",
888 .dependencies = featureSet(&[_]Feature{
889 .Shader,
890 }),
891 };
892 result[@intFromEnum(Feature.StorageImageMultisample)] = .{
893 .llvm_name = null,
894 .description = "Enable SPIR-V capability StorageImageMultisample",
895 .dependencies = featureSet(&[_]Feature{
896 .Shader,
897 }),
898 };
899 result[@intFromEnum(Feature.UniformBufferArrayDynamicIndexing)] = .{
900 .llvm_name = null,
901 .description = "Enable SPIR-V capability UniformBufferArrayDynamicIndexing",
902 .dependencies = featureSet(&[_]Feature{
903 .Shader,
904 }),
905 };
906 result[@intFromEnum(Feature.SampledImageArrayDynamicIndexing)] = .{
907 .llvm_name = null,
908 .description = "Enable SPIR-V capability SampledImageArrayDynamicIndexing",
909 .dependencies = featureSet(&[_]Feature{
910 .Shader,
911 }),
912 };
913 result[@intFromEnum(Feature.StorageBufferArrayDynamicIndexing)] = .{
914 .llvm_name = null,
915 .description = "Enable SPIR-V capability StorageBufferArrayDynamicIndexing",
916 .dependencies = featureSet(&[_]Feature{
917 .Shader,
918 }),
919 };
920 result[@intFromEnum(Feature.StorageImageArrayDynamicIndexing)] = .{
921 .llvm_name = null,
922 .description = "Enable SPIR-V capability StorageImageArrayDynamicIndexing",
923 .dependencies = featureSet(&[_]Feature{
924 .Shader,
925 }),
926 };
927 result[@intFromEnum(Feature.ClipDistance)] = .{
928 .llvm_name = null,
929 .description = "Enable SPIR-V capability ClipDistance",
930 .dependencies = featureSet(&[_]Feature{
931 .Shader,
932 }),
933 };
934 result[@intFromEnum(Feature.CullDistance)] = .{
935 .llvm_name = null,
936 .description = "Enable SPIR-V capability CullDistance",
937 .dependencies = featureSet(&[_]Feature{
938 .Shader,
939 }),
940 };
941 result[@intFromEnum(Feature.ImageCubeArray)] = .{
942 .llvm_name = null,
943 .description = "Enable SPIR-V capability ImageCubeArray",
944 .dependencies = featureSet(&[_]Feature{
945 .SampledCubeArray,
946 }),
947 };
948 result[@intFromEnum(Feature.SampleRateShading)] = .{
949 .llvm_name = null,
950 .description = "Enable SPIR-V capability SampleRateShading",
951 .dependencies = featureSet(&[_]Feature{
952 .Shader,
953 }),
954 };
955 result[@intFromEnum(Feature.ImageRect)] = .{
956 .llvm_name = null,
957 .description = "Enable SPIR-V capability ImageRect",
958 .dependencies = featureSet(&[_]Feature{
959 .SampledRect,
960 }),
961 };
962 result[@intFromEnum(Feature.SampledRect)] = .{
963 .llvm_name = null,
964 .description = "Enable SPIR-V capability SampledRect",
965 .dependencies = featureSet(&[_]Feature{
966 .Shader,
967 }),
968 };
969 result[@intFromEnum(Feature.GenericPointer)] = .{
970 .llvm_name = null,
971 .description = "Enable SPIR-V capability GenericPointer",
972 .dependencies = featureSet(&[_]Feature{
973 .Addresses,
974 }),
975 };
976 result[@intFromEnum(Feature.Int8)] = .{
977 .llvm_name = null,
978 .description = "Enable SPIR-V capability Int8",
979 .dependencies = featureSet(&[_]Feature{}),
980 };
981 result[@intFromEnum(Feature.InputAttachment)] = .{
982 .llvm_name = null,
983 .description = "Enable SPIR-V capability InputAttachment",
984 .dependencies = featureSet(&[_]Feature{
985 .Shader,
986 }),
987 };
988 result[@intFromEnum(Feature.SparseResidency)] = .{
989 .llvm_name = null,
990 .description = "Enable SPIR-V capability SparseResidency",
991 .dependencies = featureSet(&[_]Feature{
992 .Shader,
993 }),
994 };
995 result[@intFromEnum(Feature.MinLod)] = .{
996 .llvm_name = null,
997 .description = "Enable SPIR-V capability MinLod",
998 .dependencies = featureSet(&[_]Feature{
999 .Shader,
1000 }),
1001 };
1002 result[@intFromEnum(Feature.Sampled1D)] = .{
1003 .llvm_name = null,
1004 .description = "Enable SPIR-V capability Sampled1D",
1005 .dependencies = featureSet(&[_]Feature{}),
1006 };
1007 result[@intFromEnum(Feature.Image1D)] = .{
1008 .llvm_name = null,
1009 .description = "Enable SPIR-V capability Image1D",
1010 .dependencies = featureSet(&[_]Feature{
1011 .Sampled1D,
1012 }),
1013 };
1014 result[@intFromEnum(Feature.SampledCubeArray)] = .{
1015 .llvm_name = null,
1016 .description = "Enable SPIR-V capability SampledCubeArray",
1017 .dependencies = featureSet(&[_]Feature{
1018 .Shader,
1019 }),
1020 };
1021 result[@intFromEnum(Feature.SampledBuffer)] = .{
1022 .llvm_name = null,
1023 .description = "Enable SPIR-V capability SampledBuffer",
1024 .dependencies = featureSet(&[_]Feature{}),
1025 };
1026 result[@intFromEnum(Feature.ImageBuffer)] = .{
1027 .llvm_name = null,
1028 .description = "Enable SPIR-V capability ImageBuffer",
1029 .dependencies = featureSet(&[_]Feature{
1030 .SampledBuffer,
1031 }),
1032 };
1033 result[@intFromEnum(Feature.ImageMSArray)] = .{
1034 .llvm_name = null,
1035 .description = "Enable SPIR-V capability ImageMSArray",
1036 .dependencies = featureSet(&[_]Feature{
1037 .Shader,
1038 }),
1039 };
1040 result[@intFromEnum(Feature.StorageImageExtendedFormats)] = .{
1041 .llvm_name = null,
1042 .description = "Enable SPIR-V capability StorageImageExtendedFormats",
1043 .dependencies = featureSet(&[_]Feature{
1044 .Shader,
1045 }),
1046 };
1047 result[@intFromEnum(Feature.ImageQuery)] = .{
1048 .llvm_name = null,
1049 .description = "Enable SPIR-V capability ImageQuery",
1050 .dependencies = featureSet(&[_]Feature{
1051 .Shader,
1052 }),
1053 };
1054 result[@intFromEnum(Feature.DerivativeControl)] = .{
1055 .llvm_name = null,
1056 .description = "Enable SPIR-V capability DerivativeControl",
1057 .dependencies = featureSet(&[_]Feature{
1058 .Shader,
1059 }),
1060 };
1061 result[@intFromEnum(Feature.InterpolationFunction)] = .{
1062 .llvm_name = null,
1063 .description = "Enable SPIR-V capability InterpolationFunction",
1064 .dependencies = featureSet(&[_]Feature{
1065 .Shader,
1066 }),
1067 };
1068 result[@intFromEnum(Feature.TransformFeedback)] = .{
1069 .llvm_name = null,
1070 .description = "Enable SPIR-V capability TransformFeedback",
1071 .dependencies = featureSet(&[_]Feature{
1072 .Shader,
1073 }),
1074 };
1075 result[@intFromEnum(Feature.GeometryStreams)] = .{
1076 .llvm_name = null,
1077 .description = "Enable SPIR-V capability GeometryStreams",
1078 .dependencies = featureSet(&[_]Feature{
1079 .Geometry,
1080 }),
1081 };
1082 result[@intFromEnum(Feature.StorageImageReadWithoutFormat)] = .{
1083 .llvm_name = null,
1084 .description = "Enable SPIR-V capability StorageImageReadWithoutFormat",
1085 .dependencies = featureSet(&[_]Feature{
1086 .Shader,
1087 }),
1088 };
1089 result[@intFromEnum(Feature.StorageImageWriteWithoutFormat)] = .{
1090 .llvm_name = null,
1091 .description = "Enable SPIR-V capability StorageImageWriteWithoutFormat",
1092 .dependencies = featureSet(&[_]Feature{
1093 .Shader,
1094 }),
1095 };
1096 result[@intFromEnum(Feature.MultiViewport)] = .{
1097 .llvm_name = null,
1098 .description = "Enable SPIR-V capability MultiViewport",
1099 .dependencies = featureSet(&[_]Feature{
1100 .Geometry,
1101 }),
1102 };
1103 result[@intFromEnum(Feature.SubgroupDispatch)] = .{
1104 .llvm_name = null,
1105 .description = "Enable SPIR-V capability SubgroupDispatch",
1106 .dependencies = featureSet(&[_]Feature{
1107 .v1_1,
1108 .DeviceEnqueue,
1109 }),
1110 };
1111 result[@intFromEnum(Feature.NamedBarrier)] = .{
1112 .llvm_name = null,
1113 .description = "Enable SPIR-V capability NamedBarrier",
1114 .dependencies = featureSet(&[_]Feature{
1115 .v1_1,
1116 .Kernel,
1117 }),
1118 };
1119 result[@intFromEnum(Feature.PipeStorage)] = .{
1120 .llvm_name = null,
1121 .description = "Enable SPIR-V capability PipeStorage",
1122 .dependencies = featureSet(&[_]Feature{
1123 .v1_1,
1124 .Pipes,
1125 }),
1126 };
1127 result[@intFromEnum(Feature.GroupNonUniform)] = .{
1128 .llvm_name = null,
1129 .description = "Enable SPIR-V capability GroupNonUniform",
1130 .dependencies = featureSet(&[_]Feature{
1131 .v1_3,
1132 }),
1133 };
1134 result[@intFromEnum(Feature.GroupNonUniformVote)] = .{
1135 .llvm_name = null,
1136 .description = "Enable SPIR-V capability GroupNonUniformVote",
1137 .dependencies = featureSet(&[_]Feature{
1138 .v1_3,
1139 .GroupNonUniform,
1140 }),
1141 };
1142 result[@intFromEnum(Feature.GroupNonUniformArithmetic)] = .{
1143 .llvm_name = null,
1144 .description = "Enable SPIR-V capability GroupNonUniformArithmetic",
1145 .dependencies = featureSet(&[_]Feature{
1146 .v1_3,
1147 .GroupNonUniform,
1148 }),
1149 };
1150 result[@intFromEnum(Feature.GroupNonUniformBallot)] = .{
1151 .llvm_name = null,
1152 .description = "Enable SPIR-V capability GroupNonUniformBallot",
1153 .dependencies = featureSet(&[_]Feature{
1154 .v1_3,
1155 .GroupNonUniform,
1156 }),
1157 };
1158 result[@intFromEnum(Feature.GroupNonUniformShuffle)] = .{
1159 .llvm_name = null,
1160 .description = "Enable SPIR-V capability GroupNonUniformShuffle",
1161 .dependencies = featureSet(&[_]Feature{
1162 .v1_3,
1163 .GroupNonUniform,
1164 }),
1165 };
1166 result[@intFromEnum(Feature.GroupNonUniformShuffleRelative)] = .{
1167 .llvm_name = null,
1168 .description = "Enable SPIR-V capability GroupNonUniformShuffleRelative",
1169 .dependencies = featureSet(&[_]Feature{
1170 .v1_3,
1171 .GroupNonUniform,
1172 }),
1173 };
1174 result[@intFromEnum(Feature.GroupNonUniformClustered)] = .{
1175 .llvm_name = null,
1176 .description = "Enable SPIR-V capability GroupNonUniformClustered",
1177 .dependencies = featureSet(&[_]Feature{
1178 .v1_3,
1179 .GroupNonUniform,
1180 }),
1181 };
1182 result[@intFromEnum(Feature.GroupNonUniformQuad)] = .{
1183 .llvm_name = null,
1184 .description = "Enable SPIR-V capability GroupNonUniformQuad",
1185 .dependencies = featureSet(&[_]Feature{
1186 .v1_3,
1187 .GroupNonUniform,
1188 }),
1189 };
1190 result[@intFromEnum(Feature.ShaderLayer)] = .{
1191 .llvm_name = null,
1192 .description = "Enable SPIR-V capability ShaderLayer",
1193 .dependencies = featureSet(&[_]Feature{
1194 .v1_5,
1195 }),
1196 };
1197 result[@intFromEnum(Feature.ShaderViewportIndex)] = .{
1198 .llvm_name = null,
1199 .description = "Enable SPIR-V capability ShaderViewportIndex",
1200 .dependencies = featureSet(&[_]Feature{
1201 .v1_5,
1202 }),
1203 };
1204 result[@intFromEnum(Feature.FragmentShadingRateKHR)] = .{
1205 .llvm_name = null,
1206 .description = "Enable SPIR-V capability FragmentShadingRateKHR",
1207 .dependencies = featureSet(&[_]Feature{
1208 .Shader,
1209 }),
1210 };
1211 result[@intFromEnum(Feature.SubgroupBallotKHR)] = .{
1212 .llvm_name = null,
1213 .description = "Enable SPIR-V capability SubgroupBallotKHR",
1214 .dependencies = featureSet(&[_]Feature{}),
1215 };
1216 result[@intFromEnum(Feature.DrawParameters)] = .{
1217 .llvm_name = null,
1218 .description = "Enable SPIR-V capability DrawParameters",
1219 .dependencies = featureSet(&[_]Feature{
1220 .v1_3,
1221 .Shader,
1222 }),
1223 };
1224 result[@intFromEnum(Feature.WorkgroupMemoryExplicitLayoutKHR)] = .{
1225 .llvm_name = null,
1226 .description = "Enable SPIR-V capability WorkgroupMemoryExplicitLayoutKHR",
1227 .dependencies = featureSet(&[_]Feature{
1228 .Shader,
1229 }),
1230 };
1231 result[@intFromEnum(Feature.WorkgroupMemoryExplicitLayout8BitAccessKHR)] = .{
1232 .llvm_name = null,
1233 .description = "Enable SPIR-V capability WorkgroupMemoryExplicitLayout8BitAccessKHR",
1234 .dependencies = featureSet(&[_]Feature{
1235 .WorkgroupMemoryExplicitLayoutKHR,
1236 }),
1237 };
1238 result[@intFromEnum(Feature.WorkgroupMemoryExplicitLayout16BitAccessKHR)] = .{
1239 .llvm_name = null,
1240 .description = "Enable SPIR-V capability WorkgroupMemoryExplicitLayout16BitAccessKHR",
1241 .dependencies = featureSet(&[_]Feature{
1242 .Shader,
1243 }),
1244 };
1245 result[@intFromEnum(Feature.SubgroupVoteKHR)] = .{
1246 .llvm_name = null,
1247 .description = "Enable SPIR-V capability SubgroupVoteKHR",
1248 .dependencies = featureSet(&[_]Feature{}),
1249 };
1250 result[@intFromEnum(Feature.StorageBuffer16BitAccess)] = .{
1251 .llvm_name = null,
1252 .description = "Enable SPIR-V capability StorageBuffer16BitAccess",
1253 .dependencies = featureSet(&[_]Feature{
1254 .v1_3,
1255 }),
1256 };
1257 result[@intFromEnum(Feature.StorageUniformBufferBlock16)] = .{
1258 .llvm_name = null,
1259 .description = "Enable SPIR-V capability StorageUniformBufferBlock16",
1260 .dependencies = featureSet(&[_]Feature{
1261 .v1_3,
1262 }),
1263 };
1264 result[@intFromEnum(Feature.UniformAndStorageBuffer16BitAccess)] = .{
1265 .llvm_name = null,
1266 .description = "Enable SPIR-V capability UniformAndStorageBuffer16BitAccess",
1267 .dependencies = featureSet(&[_]Feature{
1268 .v1_3,
1269 .StorageBuffer16BitAccess,
1270 .StorageUniformBufferBlock16,
1271 }),
1272 };
1273 result[@intFromEnum(Feature.StorageUniform16)] = .{
1274 .llvm_name = null,
1275 .description = "Enable SPIR-V capability StorageUniform16",
1276 .dependencies = featureSet(&[_]Feature{
1277 .v1_3,
1278 .StorageBuffer16BitAccess,
1279 .StorageUniformBufferBlock16,
1280 }),
1281 };
1282 result[@intFromEnum(Feature.StoragePushConstant16)] = .{
1283 .llvm_name = null,
1284 .description = "Enable SPIR-V capability StoragePushConstant16",
1285 .dependencies = featureSet(&[_]Feature{
1286 .v1_3,
1287 }),
1288 };
1289 result[@intFromEnum(Feature.StorageInputOutput16)] = .{
1290 .llvm_name = null,
1291 .description = "Enable SPIR-V capability StorageInputOutput16",
1292 .dependencies = featureSet(&[_]Feature{
1293 .v1_3,
1294 }),
1295 };
1296 result[@intFromEnum(Feature.DeviceGroup)] = .{
1297 .llvm_name = null,
1298 .description = "Enable SPIR-V capability DeviceGroup",
1299 .dependencies = featureSet(&[_]Feature{
1300 .v1_3,
1301 }),
1302 };
1303 result[@intFromEnum(Feature.MultiView)] = .{
1304 .llvm_name = null,
1305 .description = "Enable SPIR-V capability MultiView",
1306 .dependencies = featureSet(&[_]Feature{
1307 .v1_3,
1308 .Shader,
1309 }),
1310 };
1311 result[@intFromEnum(Feature.VariablePointersStorageBuffer)] = .{
1312 .llvm_name = null,
1313 .description = "Enable SPIR-V capability VariablePointersStorageBuffer",
1314 .dependencies = featureSet(&[_]Feature{
1315 .v1_3,
1316 .Shader,
1317 }),
1318 };
1319 result[@intFromEnum(Feature.VariablePointers)] = .{
1320 .llvm_name = null,
1321 .description = "Enable SPIR-V capability VariablePointers",
1322 .dependencies = featureSet(&[_]Feature{
1323 .v1_3,
1324 .VariablePointersStorageBuffer,
1325 }),
1326 };
1327 result[@intFromEnum(Feature.AtomicStorageOps)] = .{
1328 .llvm_name = null,
1329 .description = "Enable SPIR-V capability AtomicStorageOps",
1330 .dependencies = featureSet(&[_]Feature{}),
1331 };
1332 result[@intFromEnum(Feature.SampleMaskPostDepthCoverage)] = .{
1333 .llvm_name = null,
1334 .description = "Enable SPIR-V capability SampleMaskPostDepthCoverage",
1335 .dependencies = featureSet(&[_]Feature{}),
1336 };
1337 result[@intFromEnum(Feature.StorageBuffer8BitAccess)] = .{
1338 .llvm_name = null,
1339 .description = "Enable SPIR-V capability StorageBuffer8BitAccess",
1340 .dependencies = featureSet(&[_]Feature{
1341 .v1_5,
1342 }),
1343 };
1344 result[@intFromEnum(Feature.UniformAndStorageBuffer8BitAccess)] = .{
1345 .llvm_name = null,
1346 .description = "Enable SPIR-V capability UniformAndStorageBuffer8BitAccess",
1347 .dependencies = featureSet(&[_]Feature{
1348 .v1_5,
1349 .StorageBuffer8BitAccess,
1350 }),
1351 };
1352 result[@intFromEnum(Feature.StoragePushConstant8)] = .{
1353 .llvm_name = null,
1354 .description = "Enable SPIR-V capability StoragePushConstant8",
1355 .dependencies = featureSet(&[_]Feature{
1356 .v1_5,
1357 }),
1358 };
1359 result[@intFromEnum(Feature.DenormPreserve)] = .{
1360 .llvm_name = null,
1361 .description = "Enable SPIR-V capability DenormPreserve",
1362 .dependencies = featureSet(&[_]Feature{
1363 .v1_4,
1364 }),
1365 };
1366 result[@intFromEnum(Feature.DenormFlushToZero)] = .{
1367 .llvm_name = null,
1368 .description = "Enable SPIR-V capability DenormFlushToZero",
1369 .dependencies = featureSet(&[_]Feature{
1370 .v1_4,
1371 }),
1372 };
1373 result[@intFromEnum(Feature.SignedZeroInfNanPreserve)] = .{
1374 .llvm_name = null,
1375 .description = "Enable SPIR-V capability SignedZeroInfNanPreserve",
1376 .dependencies = featureSet(&[_]Feature{
1377 .v1_4,
1378 }),
1379 };
1380 result[@intFromEnum(Feature.RoundingModeRTE)] = .{
1381 .llvm_name = null,
1382 .description = "Enable SPIR-V capability RoundingModeRTE",
1383 .dependencies = featureSet(&[_]Feature{
1384 .v1_4,
1385 }),
1386 };
1387 result[@intFromEnum(Feature.RoundingModeRTZ)] = .{
1388 .llvm_name = null,
1389 .description = "Enable SPIR-V capability RoundingModeRTZ",
1390 .dependencies = featureSet(&[_]Feature{
1391 .v1_4,
1392 }),
1393 };
1394 result[@intFromEnum(Feature.RayQueryProvisionalKHR)] = .{
1395 .llvm_name = null,
1396 .description = "Enable SPIR-V capability RayQueryProvisionalKHR",
1397 .dependencies = featureSet(&[_]Feature{
1398 .Shader,
1399 }),
1400 };
1401 result[@intFromEnum(Feature.RayQueryKHR)] = .{
1402 .llvm_name = null,
1403 .description = "Enable SPIR-V capability RayQueryKHR",
1404 .dependencies = featureSet(&[_]Feature{
1405 .Shader,
1406 }),
1407 };
1408 result[@intFromEnum(Feature.RayTraversalPrimitiveCullingKHR)] = .{
1409 .llvm_name = null,
1410 .description = "Enable SPIR-V capability RayTraversalPrimitiveCullingKHR",
1411 .dependencies = featureSet(&[_]Feature{
1412 .RayQueryKHR,
1413 .RayTracingKHR,
1414 }),
1415 };
1416 result[@intFromEnum(Feature.RayTracingKHR)] = .{
1417 .llvm_name = null,
1418 .description = "Enable SPIR-V capability RayTracingKHR",
1419 .dependencies = featureSet(&[_]Feature{
1420 .Shader,
1421 }),
1422 };
1423 result[@intFromEnum(Feature.Float16ImageAMD)] = .{
1424 .llvm_name = null,
1425 .description = "Enable SPIR-V capability Float16ImageAMD",
1426 .dependencies = featureSet(&[_]Feature{
1427 .Shader,
1428 }),
1429 };
1430 result[@intFromEnum(Feature.ImageGatherBiasLodAMD)] = .{
1431 .llvm_name = null,
1432 .description = "Enable SPIR-V capability ImageGatherBiasLodAMD",
1433 .dependencies = featureSet(&[_]Feature{
1434 .Shader,
1435 }),
1436 };
1437 result[@intFromEnum(Feature.FragmentMaskAMD)] = .{
1438 .llvm_name = null,
1439 .description = "Enable SPIR-V capability FragmentMaskAMD",
1440 .dependencies = featureSet(&[_]Feature{
1441 .Shader,
1442 }),
1443 };
1444 result[@intFromEnum(Feature.StencilExportEXT)] = .{
1445 .llvm_name = null,
1446 .description = "Enable SPIR-V capability StencilExportEXT",
1447 .dependencies = featureSet(&[_]Feature{
1448 .Shader,
1449 }),
1450 };
1451 result[@intFromEnum(Feature.ImageReadWriteLodAMD)] = .{
1452 .llvm_name = null,
1453 .description = "Enable SPIR-V capability ImageReadWriteLodAMD",
1454 .dependencies = featureSet(&[_]Feature{
1455 .Shader,
1456 }),
1457 };
1458 result[@intFromEnum(Feature.Int64ImageEXT)] = .{
1459 .llvm_name = null,
1460 .description = "Enable SPIR-V capability Int64ImageEXT",
1461 .dependencies = featureSet(&[_]Feature{
1462 .Shader,
1463 }),
1464 };
1465 result[@intFromEnum(Feature.ShaderClockKHR)] = .{
1466 .llvm_name = null,
1467 .description = "Enable SPIR-V capability ShaderClockKHR",
1468 .dependencies = featureSet(&[_]Feature{
1469 .Shader,
1470 }),
1471 };
1472 result[@intFromEnum(Feature.SampleMaskOverrideCoverageNV)] = .{
1473 .llvm_name = null,
1474 .description = "Enable SPIR-V capability SampleMaskOverrideCoverageNV",
1475 .dependencies = featureSet(&[_]Feature{
1476 .SampleRateShading,
1477 }),
1478 };
1479 result[@intFromEnum(Feature.GeometryShaderPassthroughNV)] = .{
1480 .llvm_name = null,
1481 .description = "Enable SPIR-V capability GeometryShaderPassthroughNV",
1482 .dependencies = featureSet(&[_]Feature{
1483 .Geometry,
1484 }),
1485 };
1486 result[@intFromEnum(Feature.ShaderViewportIndexLayerEXT)] = .{
1487 .llvm_name = null,
1488 .description = "Enable SPIR-V capability ShaderViewportIndexLayerEXT",
1489 .dependencies = featureSet(&[_]Feature{
1490 .MultiViewport,
1491 }),
1492 };
1493 result[@intFromEnum(Feature.ShaderViewportIndexLayerNV)] = .{
1494 .llvm_name = null,
1495 .description = "Enable SPIR-V capability ShaderViewportIndexLayerNV",
1496 .dependencies = featureSet(&[_]Feature{
1497 .MultiViewport,
1498 }),
1499 };
1500 result[@intFromEnum(Feature.ShaderViewportMaskNV)] = .{
1501 .llvm_name = null,
1502 .description = "Enable SPIR-V capability ShaderViewportMaskNV",
1503 .dependencies = featureSet(&[_]Feature{
1504 .ShaderViewportIndexLayerNV,
1505 }),
1506 };
1507 result[@intFromEnum(Feature.ShaderStereoViewNV)] = .{
1508 .llvm_name = null,
1509 .description = "Enable SPIR-V capability ShaderStereoViewNV",
1510 .dependencies = featureSet(&[_]Feature{
1511 .ShaderViewportMaskNV,
1512 }),
1513 };
1514 result[@intFromEnum(Feature.PerViewAttributesNV)] = .{
1515 .llvm_name = null,
1516 .description = "Enable SPIR-V capability PerViewAttributesNV",
1517 .dependencies = featureSet(&[_]Feature{
1518 .MultiView,
1519 }),
1520 };
1521 result[@intFromEnum(Feature.FragmentFullyCoveredEXT)] = .{
1522 .llvm_name = null,
1523 .description = "Enable SPIR-V capability FragmentFullyCoveredEXT",
1524 .dependencies = featureSet(&[_]Feature{
1525 .Shader,
1526 }),
1527 };
1528 result[@intFromEnum(Feature.MeshShadingNV)] = .{
1529 .llvm_name = null,
1530 .description = "Enable SPIR-V capability MeshShadingNV",
1531 .dependencies = featureSet(&[_]Feature{
1532 .Shader,
1533 }),
1534 };
1535 result[@intFromEnum(Feature.ImageFootprintNV)] = .{
1536 .llvm_name = null,
1537 .description = "Enable SPIR-V capability ImageFootprintNV",
1538 .dependencies = featureSet(&[_]Feature{}),
1539 };
1540 result[@intFromEnum(Feature.FragmentBarycentricNV)] = .{
1541 .llvm_name = null,
1542 .description = "Enable SPIR-V capability FragmentBarycentricNV",
1543 .dependencies = featureSet(&[_]Feature{}),
1544 };
1545 result[@intFromEnum(Feature.ComputeDerivativeGroupQuadsNV)] = .{
1546 .llvm_name = null,
1547 .description = "Enable SPIR-V capability ComputeDerivativeGroupQuadsNV",
1548 .dependencies = featureSet(&[_]Feature{}),
1549 };
1550 result[@intFromEnum(Feature.FragmentDensityEXT)] = .{
1551 .llvm_name = null,
1552 .description = "Enable SPIR-V capability FragmentDensityEXT",
1553 .dependencies = featureSet(&[_]Feature{
1554 .Shader,
1555 }),
1556 };
1557 result[@intFromEnum(Feature.ShadingRateNV)] = .{
1558 .llvm_name = null,
1559 .description = "Enable SPIR-V capability ShadingRateNV",
1560 .dependencies = featureSet(&[_]Feature{
1561 .Shader,
1562 }),
1563 };
1564 result[@intFromEnum(Feature.GroupNonUniformPartitionedNV)] = .{
1565 .llvm_name = null,
1566 .description = "Enable SPIR-V capability GroupNonUniformPartitionedNV",
1567 .dependencies = featureSet(&[_]Feature{}),
1568 };
1569 result[@intFromEnum(Feature.ShaderNonUniform)] = .{
1570 .llvm_name = null,
1571 .description = "Enable SPIR-V capability ShaderNonUniform",
1572 .dependencies = featureSet(&[_]Feature{
1573 .v1_5,
1574 .Shader,
1575 }),
1576 };
1577 result[@intFromEnum(Feature.ShaderNonUniformEXT)] = .{
1578 .llvm_name = null,
1579 .description = "Enable SPIR-V capability ShaderNonUniformEXT",
1580 .dependencies = featureSet(&[_]Feature{
1581 .v1_5,
1582 .Shader,
1583 }),
1584 };
1585 result[@intFromEnum(Feature.RuntimeDescriptorArray)] = .{
1586 .llvm_name = null,
1587 .description = "Enable SPIR-V capability RuntimeDescriptorArray",
1588 .dependencies = featureSet(&[_]Feature{
1589 .v1_5,
1590 .Shader,
1591 }),
1592 };
1593 result[@intFromEnum(Feature.RuntimeDescriptorArrayEXT)] = .{
1594 .llvm_name = null,
1595 .description = "Enable SPIR-V capability RuntimeDescriptorArrayEXT",
1596 .dependencies = featureSet(&[_]Feature{
1597 .v1_5,
1598 .Shader,
1599 }),
1600 };
1601 result[@intFromEnum(Feature.InputAttachmentArrayDynamicIndexing)] = .{
1602 .llvm_name = null,
1603 .description = "Enable SPIR-V capability InputAttachmentArrayDynamicIndexing",
1604 .dependencies = featureSet(&[_]Feature{
1605 .v1_5,
1606 .InputAttachment,
1607 }),
1608 };
1609 result[@intFromEnum(Feature.InputAttachmentArrayDynamicIndexingEXT)] = .{
1610 .llvm_name = null,
1611 .description = "Enable SPIR-V capability InputAttachmentArrayDynamicIndexingEXT",
1612 .dependencies = featureSet(&[_]Feature{
1613 .v1_5,
1614 .InputAttachment,
1615 }),
1616 };
1617 result[@intFromEnum(Feature.UniformTexelBufferArrayDynamicIndexing)] = .{
1618 .llvm_name = null,
1619 .description = "Enable SPIR-V capability UniformTexelBufferArrayDynamicIndexing",
1620 .dependencies = featureSet(&[_]Feature{
1621 .v1_5,
1622 .SampledBuffer,
1623 }),
1624 };
1625 result[@intFromEnum(Feature.UniformTexelBufferArrayDynamicIndexingEXT)] = .{
1626 .llvm_name = null,
1627 .description = "Enable SPIR-V capability UniformTexelBufferArrayDynamicIndexingEXT",
1628 .dependencies = featureSet(&[_]Feature{
1629 .v1_5,
1630 .SampledBuffer,
1631 }),
1632 };
1633 result[@intFromEnum(Feature.StorageTexelBufferArrayDynamicIndexing)] = .{
1634 .llvm_name = null,
1635 .description = "Enable SPIR-V capability StorageTexelBufferArrayDynamicIndexing",
1636 .dependencies = featureSet(&[_]Feature{
1637 .v1_5,
1638 .ImageBuffer,
1639 }),
1640 };
1641 result[@intFromEnum(Feature.StorageTexelBufferArrayDynamicIndexingEXT)] = .{
1642 .llvm_name = null,
1643 .description = "Enable SPIR-V capability StorageTexelBufferArrayDynamicIndexingEXT",
1644 .dependencies = featureSet(&[_]Feature{
1645 .v1_5,
1646 .ImageBuffer,
1647 }),
1648 };
1649 result[@intFromEnum(Feature.UniformBufferArrayNonUniformIndexing)] = .{
1650 .llvm_name = null,
1651 .description = "Enable SPIR-V capability UniformBufferArrayNonUniformIndexing",
1652 .dependencies = featureSet(&[_]Feature{
1653 .v1_5,
1654 .ShaderNonUniform,
1655 }),
1656 };
1657 result[@intFromEnum(Feature.UniformBufferArrayNonUniformIndexingEXT)] = .{
1658 .llvm_name = null,
1659 .description = "Enable SPIR-V capability UniformBufferArrayNonUniformIndexingEXT",
1660 .dependencies = featureSet(&[_]Feature{
1661 .v1_5,
1662 .ShaderNonUniform,
1663 }),
1664 };
1665 result[@intFromEnum(Feature.SampledImageArrayNonUniformIndexing)] = .{
1666 .llvm_name = null,
1667 .description = "Enable SPIR-V capability SampledImageArrayNonUniformIndexing",
1668 .dependencies = featureSet(&[_]Feature{
1669 .v1_5,
1670 .ShaderNonUniform,
1671 }),
1672 };
1673 result[@intFromEnum(Feature.SampledImageArrayNonUniformIndexingEXT)] = .{
1674 .llvm_name = null,
1675 .description = "Enable SPIR-V capability SampledImageArrayNonUniformIndexingEXT",
1676 .dependencies = featureSet(&[_]Feature{
1677 .v1_5,
1678 .ShaderNonUniform,
1679 }),
1680 };
1681 result[@intFromEnum(Feature.StorageBufferArrayNonUniformIndexing)] = .{
1682 .llvm_name = null,
1683 .description = "Enable SPIR-V capability StorageBufferArrayNonUniformIndexing",
1684 .dependencies = featureSet(&[_]Feature{
1685 .v1_5,
1686 .ShaderNonUniform,
1687 }),
1688 };
1689 result[@intFromEnum(Feature.StorageBufferArrayNonUniformIndexingEXT)] = .{
1690 .llvm_name = null,
1691 .description = "Enable SPIR-V capability StorageBufferArrayNonUniformIndexingEXT",
1692 .dependencies = featureSet(&[_]Feature{
1693 .v1_5,
1694 .ShaderNonUniform,
1695 }),
1696 };
1697 result[@intFromEnum(Feature.StorageImageArrayNonUniformIndexing)] = .{
1698 .llvm_name = null,
1699 .description = "Enable SPIR-V capability StorageImageArrayNonUniformIndexing",
1700 .dependencies = featureSet(&[_]Feature{
1701 .v1_5,
1702 .ShaderNonUniform,
1703 }),
1704 };
1705 result[@intFromEnum(Feature.StorageImageArrayNonUniformIndexingEXT)] = .{
1706 .llvm_name = null,
1707 .description = "Enable SPIR-V capability StorageImageArrayNonUniformIndexingEXT",
1708 .dependencies = featureSet(&[_]Feature{
1709 .v1_5,
1710 .ShaderNonUniform,
1711 }),
1712 };
1713 result[@intFromEnum(Feature.InputAttachmentArrayNonUniformIndexing)] = .{
1714 .llvm_name = null,
1715 .description = "Enable SPIR-V capability InputAttachmentArrayNonUniformIndexing",
1716 .dependencies = featureSet(&[_]Feature{
1717 .v1_5,
1718 .InputAttachment,
1719 .ShaderNonUniform,
1720 }),
1721 };
1722 result[@intFromEnum(Feature.InputAttachmentArrayNonUniformIndexingEXT)] = .{
1723 .llvm_name = null,
1724 .description = "Enable SPIR-V capability InputAttachmentArrayNonUniformIndexingEXT",
1725 .dependencies = featureSet(&[_]Feature{
1726 .v1_5,
1727 .InputAttachment,
1728 .ShaderNonUniform,
1729 }),
1730 };
1731 result[@intFromEnum(Feature.UniformTexelBufferArrayNonUniformIndexing)] = .{
1732 .llvm_name = null,
1733 .description = "Enable SPIR-V capability UniformTexelBufferArrayNonUniformIndexing",
1734 .dependencies = featureSet(&[_]Feature{
1735 .v1_5,
1736 .SampledBuffer,
1737 .ShaderNonUniform,
1738 }),
1739 };
1740 result[@intFromEnum(Feature.UniformTexelBufferArrayNonUniformIndexingEXT)] = .{
1741 .llvm_name = null,
1742 .description = "Enable SPIR-V capability UniformTexelBufferArrayNonUniformIndexingEXT",
1743 .dependencies = featureSet(&[_]Feature{
1744 .v1_5,
1745 .SampledBuffer,
1746 .ShaderNonUniform,
1747 }),
1748 };
1749 result[@intFromEnum(Feature.StorageTexelBufferArrayNonUniformIndexing)] = .{
1750 .llvm_name = null,
1751 .description = "Enable SPIR-V capability StorageTexelBufferArrayNonUniformIndexing",
1752 .dependencies = featureSet(&[_]Feature{
1753 .v1_5,
1754 .ImageBuffer,
1755 .ShaderNonUniform,
1756 }),
1757 };
1758 result[@intFromEnum(Feature.StorageTexelBufferArrayNonUniformIndexingEXT)] = .{
1759 .llvm_name = null,
1760 .description = "Enable SPIR-V capability StorageTexelBufferArrayNonUniformIndexingEXT",
1761 .dependencies = featureSet(&[_]Feature{
1762 .v1_5,
1763 .ImageBuffer,
1764 .ShaderNonUniform,
1765 }),
1766 };
1767 result[@intFromEnum(Feature.RayTracingNV)] = .{
1768 .llvm_name = null,
1769 .description = "Enable SPIR-V capability RayTracingNV",
1770 .dependencies = featureSet(&[_]Feature{
1771 .Shader,
1772 }),
1773 };
1774 result[@intFromEnum(Feature.VulkanMemoryModel)] = .{
1775 .llvm_name = null,
1776 .description = "Enable SPIR-V capability VulkanMemoryModel",
1777 .dependencies = featureSet(&[_]Feature{
1778 .v1_5,
1779 }),
1780 };
1781 result[@intFromEnum(Feature.VulkanMemoryModelKHR)] = .{
1782 .llvm_name = null,
1783 .description = "Enable SPIR-V capability VulkanMemoryModelKHR",
1784 .dependencies = featureSet(&[_]Feature{
1785 .v1_5,
1786 }),
1787 };
1788 result[@intFromEnum(Feature.VulkanMemoryModelDeviceScope)] = .{
1789 .llvm_name = null,
1790 .description = "Enable SPIR-V capability VulkanMemoryModelDeviceScope",
1791 .dependencies = featureSet(&[_]Feature{
1792 .v1_5,
1793 }),
1794 };
1795 result[@intFromEnum(Feature.VulkanMemoryModelDeviceScopeKHR)] = .{
1796 .llvm_name = null,
1797 .description = "Enable SPIR-V capability VulkanMemoryModelDeviceScopeKHR",
1798 .dependencies = featureSet(&[_]Feature{
1799 .v1_5,
1800 }),
1801 };
1802 result[@intFromEnum(Feature.PhysicalStorageBufferAddresses)] = .{
1803 .llvm_name = null,
1804 .description = "Enable SPIR-V capability PhysicalStorageBufferAddresses",
1805 .dependencies = featureSet(&[_]Feature{
1806 .v1_5,
1807 .Shader,
1808 }),
1809 };
1810 result[@intFromEnum(Feature.PhysicalStorageBufferAddressesEXT)] = .{
1811 .llvm_name = null,
1812 .description = "Enable SPIR-V capability PhysicalStorageBufferAddressesEXT",
1813 .dependencies = featureSet(&[_]Feature{
1814 .v1_5,
1815 .Shader,
1816 }),
1817 };
1818 result[@intFromEnum(Feature.ComputeDerivativeGroupLinearNV)] = .{
1819 .llvm_name = null,
1820 .description = "Enable SPIR-V capability ComputeDerivativeGroupLinearNV",
1821 .dependencies = featureSet(&[_]Feature{}),
1822 };
1823 result[@intFromEnum(Feature.RayTracingProvisionalKHR)] = .{
1824 .llvm_name = null,
1825 .description = "Enable SPIR-V capability RayTracingProvisionalKHR",
1826 .dependencies = featureSet(&[_]Feature{
1827 .Shader,
1828 }),
1829 };
1830 result[@intFromEnum(Feature.CooperativeMatrixNV)] = .{
1831 .llvm_name = null,
1832 .description = "Enable SPIR-V capability CooperativeMatrixNV",
1833 .dependencies = featureSet(&[_]Feature{
1834 .Shader,
1835 }),
1836 };
1837 result[@intFromEnum(Feature.FragmentShaderSampleInterlockEXT)] = .{
1838 .llvm_name = null,
1839 .description = "Enable SPIR-V capability FragmentShaderSampleInterlockEXT",
1840 .dependencies = featureSet(&[_]Feature{
1841 .Shader,
1842 }),
1843 };
1844 result[@intFromEnum(Feature.FragmentShaderShadingRateInterlockEXT)] = .{
1845 .llvm_name = null,
1846 .description = "Enable SPIR-V capability FragmentShaderShadingRateInterlockEXT",
1847 .dependencies = featureSet(&[_]Feature{
1848 .Shader,
1849 }),
1850 };
1851 result[@intFromEnum(Feature.ShaderSMBuiltinsNV)] = .{
1852 .llvm_name = null,
1853 .description = "Enable SPIR-V capability ShaderSMBuiltinsNV",
1854 .dependencies = featureSet(&[_]Feature{
1855 .Shader,
1856 }),
1857 };
1858 result[@intFromEnum(Feature.FragmentShaderPixelInterlockEXT)] = .{
1859 .llvm_name = null,
1860 .description = "Enable SPIR-V capability FragmentShaderPixelInterlockEXT",
1861 .dependencies = featureSet(&[_]Feature{
1862 .Shader,
1863 }),
1864 };
1865 result[@intFromEnum(Feature.DemoteToHelperInvocationEXT)] = .{
1866 .llvm_name = null,
1867 .description = "Enable SPIR-V capability DemoteToHelperInvocationEXT",
1868 .dependencies = featureSet(&[_]Feature{
1869 .Shader,
1870 }),
1871 };
1872 result[@intFromEnum(Feature.SubgroupShuffleINTEL)] = .{
1873 .llvm_name = null,
1874 .description = "Enable SPIR-V capability SubgroupShuffleINTEL",
1875 .dependencies = featureSet(&[_]Feature{}),
1876 };
1877 result[@intFromEnum(Feature.SubgroupBufferBlockIOINTEL)] = .{
1878 .llvm_name = null,
1879 .description = "Enable SPIR-V capability SubgroupBufferBlockIOINTEL",
1880 .dependencies = featureSet(&[_]Feature{}),
1881 };
1882 result[@intFromEnum(Feature.SubgroupImageBlockIOINTEL)] = .{
1883 .llvm_name = null,
1884 .description = "Enable SPIR-V capability SubgroupImageBlockIOINTEL",
1885 .dependencies = featureSet(&[_]Feature{}),
1886 };
1887 result[@intFromEnum(Feature.SubgroupImageMediaBlockIOINTEL)] = .{
1888 .llvm_name = null,
1889 .description = "Enable SPIR-V capability SubgroupImageMediaBlockIOINTEL",
1890 .dependencies = featureSet(&[_]Feature{}),
1891 };
1892 result[@intFromEnum(Feature.RoundToInfinityINTEL)] = .{
1893 .llvm_name = null,
1894 .description = "Enable SPIR-V capability RoundToInfinityINTEL",
1895 .dependencies = featureSet(&[_]Feature{}),
1896 };
1897 result[@intFromEnum(Feature.FloatingPointModeINTEL)] = .{
1898 .llvm_name = null,
1899 .description = "Enable SPIR-V capability FloatingPointModeINTEL",
1900 .dependencies = featureSet(&[_]Feature{}),
1901 };
1902 result[@intFromEnum(Feature.IntegerFunctions2INTEL)] = .{
1903 .llvm_name = null,
1904 .description = "Enable SPIR-V capability IntegerFunctions2INTEL",
1905 .dependencies = featureSet(&[_]Feature{
1906 .Shader,
1907 }),
1908 };
1909 result[@intFromEnum(Feature.FunctionPointersINTEL)] = .{
1910 .llvm_name = null,
1911 .description = "Enable SPIR-V capability FunctionPointersINTEL",
1912 .dependencies = featureSet(&[_]Feature{}),
1913 };
1914 result[@intFromEnum(Feature.IndirectReferencesINTEL)] = .{
1915 .llvm_name = null,
1916 .description = "Enable SPIR-V capability IndirectReferencesINTEL",
1917 .dependencies = featureSet(&[_]Feature{}),
1918 };
1919 result[@intFromEnum(Feature.AsmINTEL)] = .{
1920 .llvm_name = null,
1921 .description = "Enable SPIR-V capability AsmINTEL",
1922 .dependencies = featureSet(&[_]Feature{}),
1923 };
1924 result[@intFromEnum(Feature.AtomicFloat32MinMaxEXT)] = .{
1925 .llvm_name = null,
1926 .description = "Enable SPIR-V capability AtomicFloat32MinMaxEXT",
1927 .dependencies = featureSet(&[_]Feature{}),
1928 };
1929 result[@intFromEnum(Feature.AtomicFloat64MinMaxEXT)] = .{
1930 .llvm_name = null,
1931 .description = "Enable SPIR-V capability AtomicFloat64MinMaxEXT",
1932 .dependencies = featureSet(&[_]Feature{}),
1933 };
1934 result[@intFromEnum(Feature.AtomicFloat16MinMaxEXT)] = .{
1935 .llvm_name = null,
1936 .description = "Enable SPIR-V capability AtomicFloat16MinMaxEXT",
1937 .dependencies = featureSet(&[_]Feature{}),
1938 };
1939 result[@intFromEnum(Feature.VectorComputeINTEL)] = .{
1940 .llvm_name = null,
1941 .description = "Enable SPIR-V capability VectorComputeINTEL",
1942 .dependencies = featureSet(&[_]Feature{
1943 .VectorAnyINTEL,
1944 }),
1945 };
1946 result[@intFromEnum(Feature.VectorAnyINTEL)] = .{
1947 .llvm_name = null,
1948 .description = "Enable SPIR-V capability VectorAnyINTEL",
1949 .dependencies = featureSet(&[_]Feature{}),
1950 };
1951 result[@intFromEnum(Feature.ExpectAssumeKHR)] = .{
1952 .llvm_name = null,
1953 .description = "Enable SPIR-V capability ExpectAssumeKHR",
1954 .dependencies = featureSet(&[_]Feature{}),
1955 };
1956 result[@intFromEnum(Feature.SubgroupAvcMotionEstimationINTEL)] = .{
1957 .llvm_name = null,
1958 .description = "Enable SPIR-V capability SubgroupAvcMotionEstimationINTEL",
1959 .dependencies = featureSet(&[_]Feature{}),
1960 };
1961 result[@intFromEnum(Feature.SubgroupAvcMotionEstimationIntraINTEL)] = .{
1962 .llvm_name = null,
1963 .description = "Enable SPIR-V capability SubgroupAvcMotionEstimationIntraINTEL",
1964 .dependencies = featureSet(&[_]Feature{}),
1965 };
1966 result[@intFromEnum(Feature.SubgroupAvcMotionEstimationChromaINTEL)] = .{
1967 .llvm_name = null,
1968 .description = "Enable SPIR-V capability SubgroupAvcMotionEstimationChromaINTEL",
1969 .dependencies = featureSet(&[_]Feature{}),
1970 };
1971 result[@intFromEnum(Feature.VariableLengthArrayINTEL)] = .{
1972 .llvm_name = null,
1973 .description = "Enable SPIR-V capability VariableLengthArrayINTEL",
1974 .dependencies = featureSet(&[_]Feature{}),
1975 };
1976 result[@intFromEnum(Feature.FunctionFloatControlINTEL)] = .{
1977 .llvm_name = null,
1978 .description = "Enable SPIR-V capability FunctionFloatControlINTEL",
1979 .dependencies = featureSet(&[_]Feature{}),
1980 };
1981 result[@intFromEnum(Feature.FPGAMemoryAttributesINTEL)] = .{
1982 .llvm_name = null,
1983 .description = "Enable SPIR-V capability FPGAMemoryAttributesINTEL",
1984 .dependencies = featureSet(&[_]Feature{}),
1985 };
1986 result[@intFromEnum(Feature.FPFastMathModeINTEL)] = .{
1987 .llvm_name = null,
1988 .description = "Enable SPIR-V capability FPFastMathModeINTEL",
1989 .dependencies = featureSet(&[_]Feature{
1990 .Kernel,
1991 }),
1992 };
1993 result[@intFromEnum(Feature.ArbitraryPrecisionIntegersINTEL)] = .{
1994 .llvm_name = null,
1995 .description = "Enable SPIR-V capability ArbitraryPrecisionIntegersINTEL",
1996 .dependencies = featureSet(&[_]Feature{}),
1997 };
1998 result[@intFromEnum(Feature.UnstructuredLoopControlsINTEL)] = .{
1999 .llvm_name = null,
2000 .description = "Enable SPIR-V capability UnstructuredLoopControlsINTEL",
2001 .dependencies = featureSet(&[_]Feature{}),
2002 };
2003 result[@intFromEnum(Feature.FPGALoopControlsINTEL)] = .{
2004 .llvm_name = null,
2005 .description = "Enable SPIR-V capability FPGALoopControlsINTEL",
2006 .dependencies = featureSet(&[_]Feature{}),
2007 };
2008 result[@intFromEnum(Feature.KernelAttributesINTEL)] = .{
2009 .llvm_name = null,
2010 .description = "Enable SPIR-V capability KernelAttributesINTEL",
2011 .dependencies = featureSet(&[_]Feature{}),
2012 };
2013 result[@intFromEnum(Feature.FPGAKernelAttributesINTEL)] = .{
2014 .llvm_name = null,
2015 .description = "Enable SPIR-V capability FPGAKernelAttributesINTEL",
2016 .dependencies = featureSet(&[_]Feature{}),
2017 };
2018 result[@intFromEnum(Feature.FPGAMemoryAccessesINTEL)] = .{
2019 .llvm_name = null,
2020 .description = "Enable SPIR-V capability FPGAMemoryAccessesINTEL",
2021 .dependencies = featureSet(&[_]Feature{}),
2022 };
2023 result[@intFromEnum(Feature.FPGAClusterAttributesINTEL)] = .{
2024 .llvm_name = null,
2025 .description = "Enable SPIR-V capability FPGAClusterAttributesINTEL",
2026 .dependencies = featureSet(&[_]Feature{}),
2027 };
2028 result[@intFromEnum(Feature.LoopFuseINTEL)] = .{
2029 .llvm_name = null,
2030 .description = "Enable SPIR-V capability LoopFuseINTEL",
2031 .dependencies = featureSet(&[_]Feature{}),
2032 };
2033 result[@intFromEnum(Feature.FPGABufferLocationINTEL)] = .{
2034 .llvm_name = null,
2035 .description = "Enable SPIR-V capability FPGABufferLocationINTEL",
2036 .dependencies = featureSet(&[_]Feature{}),
2037 };
2038 result[@intFromEnum(Feature.USMStorageClassesINTEL)] = .{
2039 .llvm_name = null,
2040 .description = "Enable SPIR-V capability USMStorageClassesINTEL",
2041 .dependencies = featureSet(&[_]Feature{}),
2042 };
2043 result[@intFromEnum(Feature.IOPipesINTEL)] = .{
2044 .llvm_name = null,
2045 .description = "Enable SPIR-V capability IOPipesINTEL",
2046 .dependencies = featureSet(&[_]Feature{}),
2047 };
2048 result[@intFromEnum(Feature.BlockingPipesINTEL)] = .{
2049 .llvm_name = null,
2050 .description = "Enable SPIR-V capability BlockingPipesINTEL",
2051 .dependencies = featureSet(&[_]Feature{}),
2052 };
2053 result[@intFromEnum(Feature.FPGARegINTEL)] = .{
2054 .llvm_name = null,
2055 .description = "Enable SPIR-V capability FPGARegINTEL",
2056 .dependencies = featureSet(&[_]Feature{}),
2057 };
2058 result[@intFromEnum(Feature.AtomicFloat32AddEXT)] = .{
2059 .llvm_name = null,
2060 .description = "Enable SPIR-V capability AtomicFloat32AddEXT",
2061 .dependencies = featureSet(&[_]Feature{
2062 .Shader,
2063 }),
2064 };
2065 result[@intFromEnum(Feature.AtomicFloat64AddEXT)] = .{
2066 .llvm_name = null,
2067 .description = "Enable SPIR-V capability AtomicFloat64AddEXT",
2068 .dependencies = featureSet(&[_]Feature{
2069 .Shader,
2070 }),
2071 };
2072 result[@intFromEnum(Feature.LongConstantCompositeINTEL)] = .{
2073 .llvm_name = null,
2074 .description = "Enable SPIR-V capability LongConstantCompositeINTEL",
2075 .dependencies = featureSet(&[_]Feature{}),
2076 };
2077 const ti = @typeInfo(Feature);
2078 for (&result, 0..) |*elem, i| {
2079 elem.index = i;
2080 elem.name = ti.@"enum".fields[i].name;
2081 }
2082 break :blk result;
2083};
2084
2085pub const cpu = struct {
2086 pub const generic = CpuModel{
2087 .name = "generic",
2088 .llvm_name = "generic",
2089 .features = featureSet(&[_]Feature{}),
150 .features = featureSet(&[_]Feature{ .v1_2, .kernel, .addresses, .generic_pointer }),
2090151 };
2091152};
lib/std/gpu.zig+20-28
......@@ -1,5 +1,4 @@
11const std = @import("std.zig");
2const comptimePrint = std.fmt.comptimePrint;
32
43/// Will make `ptr` contain the location of the current invocation within the
54/// global workgroup. Each component is equal to the index of the local workgroup
......@@ -81,23 +80,23 @@ pub fn fragmentDepth(comptime ptr: *addrspace(.output) f32) void {
8180/// Forms the main linkage for `input` and `output` address spaces.
8281/// `ptr` must be a reference to variable or struct field.
8382pub fn location(comptime ptr: anytype, comptime loc: u32) void {
84 const code = comptimePrint("OpDecorate %ptr Location {}", .{loc});
85 asm volatile (code
83 asm volatile ("OpDecorate %ptr Location $loc"
8684 :
8785 : [ptr] "" (ptr),
86 [loc] "c" (loc),
8887 );
8988}
9089
9190/// Forms the main linkage for `input` and `output` address spaces.
9291/// `ptr` must be a reference to variable or struct field.
93pub fn binding(comptime ptr: anytype, comptime group: u32, comptime bind: u32) void {
94 const code = comptimePrint(
95 \\OpDecorate %ptr DescriptorSet {}
96 \\OpDecorate %ptr Binding {}
97 , .{ group, bind });
98 asm volatile (code
92pub fn binding(comptime ptr: anytype, comptime set: u32, comptime bind: u32) void {
93 asm volatile (
94 \\OpDecorate %ptr DescriptorSet $set
95 \\OpDecorate %ptr Binding $bind
9996 :
10097 : [ptr] "" (ptr),
98 [set] "c" (set),
99 [bind] "c" (bind),
101100 );
102101}
103102
......@@ -111,13 +110,10 @@ pub const Origin = enum(u32) {
111110/// The coordinates appear to originate in the specified `origin`.
112111/// Only valid with the `Fragment` calling convention.
113112pub fn fragmentOrigin(comptime entry_point: anytype, comptime origin: Origin) void {
114 const origin_enum = switch (origin) {
115 .upper_left => .OriginUpperLeft,
116 .lower_left => .OriginLowerLeft,
117 };
118 asm volatile ("OpExecutionMode %entry_point " ++ @tagName(origin_enum)
113 asm volatile ("OpExecutionMode %entry_point $origin"
119114 :
120115 : [entry_point] "" (entry_point),
116 [origin] "c" (@intFromEnum(origin)),
121117 );
122118}
123119
......@@ -141,37 +137,33 @@ pub const DepthMode = enum(u32) {
141137
142138/// Only valid with the `Fragment` calling convention.
143139pub fn depthMode(comptime entry_point: anytype, comptime mode: DepthMode) void {
144 const code = comptimePrint("OpExecutionMode %entry_point {}", .{@intFromEnum(mode)});
145 asm volatile (code
140 asm volatile ("OpExecutionMode %entry_point $mode"
146141 :
147142 : [entry_point] "" (entry_point),
143 [mode] "c" (mode),
148144 );
149145}
150146
151147/// Indicates the workgroup size in the `x`, `y`, and `z` dimensions.
152148/// Only valid with the `GLCompute` or `Kernel` calling conventions.
153149pub fn workgroupSize(comptime entry_point: anytype, comptime size: @Vector(3, u32)) void {
154 const code = comptimePrint("OpExecutionMode %entry_point LocalSize {} {} {}", .{
155 size[0],
156 size[1],
157 size[2],
158 });
159 asm volatile (code
150 asm volatile ("OpExecutionMode %entry_point LocalSize %x %y %z"
160151 :
161152 : [entry_point] "" (entry_point),
153 [x] "c" (size[0]),
154 [y] "c" (size[1]),
155 [z] "c" (size[2]),
162156 );
163157}
164158
165159/// A hint to the client, which indicates the workgroup size in the `x`, `y`, and `z` dimensions.
166160/// Only valid with the `GLCompute` or `Kernel` calling conventions.
167161pub fn workgroupSizeHint(comptime entry_point: anytype, comptime size: @Vector(3, u32)) void {
168 const code = comptimePrint("OpExecutionMode %entry_point LocalSizeHint {} {} {}", .{
169 size[0],
170 size[1],
171 size[2],
172 });
173 asm volatile (code
162 asm volatile ("OpExecutionMode %entry_point LocalSizeHint %x %y %z"
174163 :
175164 : [entry_point] "" (entry_point),
165 [x] "c" (size[0]),
166 [y] "c" (size[1]),
167 [z] "c" (size[2]),
176168 );
177169}
src/codegen/spirv.zig+209-377
......@@ -159,7 +159,7 @@ pub const Object = struct {
159159 uav_link: std.AutoHashMapUnmanaged(struct { InternPool.Index, StorageClass }, SpvModule.Decl.Index) = .empty,
160160
161161 /// A map that maps AIR intern pool indices to SPIR-V result-ids.
162 intern_map: InternMap = .{},
162 intern_map: InternMap = .empty,
163163
164164 /// This map serves a dual purpose:
165165 /// - It keeps track of pointers that are currently being emitted, so that we can tell
......@@ -176,10 +176,10 @@ pub const Object = struct {
176176 push_constant_ptr: SpvModule.Decl.Index,
177177 } = null,
178178
179 pub fn init(gpa: Allocator) Object {
179 pub fn init(gpa: Allocator, target: std.Target) Object {
180180 return .{
181181 .gpa = gpa,
182 .spv = SpvModule.init(gpa),
182 .spv = SpvModule.init(gpa, target),
183183 };
184184 }
185185
......@@ -314,7 +314,7 @@ const NavGen = struct {
314314 next_arg_index: u32 = 0,
315315
316316 /// A map keeping track of which instruction generated which result-id.
317 inst_results: InstMap = .{},
317 inst_results: InstMap = .empty,
318318
319319 /// A map that maps AIR intern pool indices to SPIR-V result-ids.
320320 /// See `Object.intern_map`.
......@@ -412,11 +412,6 @@ const NavGen = struct {
412412 self.func.deinit(self.gpa);
413413 }
414414
415 /// Return the target which we are currently compiling for.
416 pub fn getTarget(self: *NavGen) std.Target {
417 return self.pt.zcu.getTarget();
418 }
419
420415 pub fn fail(self: *NavGen, comptime format: []const u8, args: anytype) Error {
421416 @branchHint(.cold);
422417 const zcu = self.pt.zcu;
......@@ -431,12 +426,12 @@ const NavGen = struct {
431426 }
432427
433428 /// This imports the "default" extended instruction set for the target
434 /// For OpenCL, OpenCL.std.100. For Vulkan, GLSL.std.450.
429 /// For OpenCL, OpenCL.std.100. For Vulkan and OpenGL, GLSL.std.450.
435430 fn importExtendedSet(self: *NavGen) !IdResult {
436 const target = self.getTarget();
431 const target = self.spv.target;
437432 return switch (target.os.tag) {
438433 .opencl => try self.spv.importInstructionSet(.@"OpenCL.std"),
439 .vulkan => try self.spv.importInstructionSet(.@"GLSL.std.450"),
434 .vulkan, .opengl => try self.spv.importInstructionSet(.@"GLSL.std.450"),
440435 else => unreachable,
441436 };
442437 }
......@@ -469,7 +464,7 @@ const NavGen = struct {
469464
470465 const zcu = self.pt.zcu;
471466 const ty = Type.fromInterned(zcu.intern_pool.typeOf(val));
472 const decl_ptr_ty_id = try self.ptrType(ty, .Generic);
467 const decl_ptr_ty_id = try self.ptrType(ty, .Generic, .indirect);
473468
474469 const spv_decl_index = blk: {
475470 const entry = try self.object.uav_link.getOrPut(self.object.gpa, .{ val, .Function });
......@@ -532,7 +527,7 @@ const NavGen = struct {
532527
533528 try self.spv.debugNameFmt(initializer_id, "initializer of __anon_{d}", .{@intFromEnum(val)});
534529
535 const fn_decl_ptr_ty_id = try self.ptrType(ty, .Function);
530 const fn_decl_ptr_ty_id = try self.ptrType(ty, .Function, .indirect);
536531 try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpExtInst, .{
537532 .id_result_type = fn_decl_ptr_ty_id,
538533 .id_result = result_id,
......@@ -546,14 +541,10 @@ const NavGen = struct {
546541 }
547542
548543 fn addFunctionDep(self: *NavGen, decl_index: SpvModule.Decl.Index, storage_class: StorageClass) !void {
549 const target = self.getTarget();
550 if (target.os.tag == .vulkan) {
551 // Shader entry point dependencies must be variables with Input or Output storage class
552 switch (storage_class) {
553 .Input, .Output => {
554 try self.func.decl_deps.put(self.spv.gpa, decl_index, {});
555 },
556 else => {},
544 if (self.spv.version.minor < 4) {
545 // Before version 1.4, the interface’s storage classes are limited to the Input and Output
546 if (storage_class == .Input or storage_class == .Output) {
547 try self.func.decl_deps.put(self.spv.gpa, decl_index, {});
557548 }
558549 } else {
559550 try self.func.decl_deps.put(self.spv.gpa, decl_index, {});
......@@ -561,11 +552,7 @@ const NavGen = struct {
561552 }
562553
563554 fn castToGeneric(self: *NavGen, type_id: IdRef, ptr_id: IdRef) !IdRef {
564 const target = self.getTarget();
565
566 if (target.os.tag == .vulkan) {
567 return ptr_id;
568 } else {
555 if (self.spv.hasFeature(.kernel)) {
569556 const result_id = self.spv.allocId();
570557 try self.func.body.emit(self.spv.gpa, .OpPtrCastToGeneric, .{
571558 .id_result_type = type_id,
......@@ -574,6 +561,8 @@ const NavGen = struct {
574561 });
575562 return result_id;
576563 }
564
565 return ptr_id;
577566 }
578567
579568 /// Start a new SPIR-V block, Emits the label of the new block, and stores which
......@@ -596,29 +585,21 @@ const NavGen = struct {
596585 /// TODO: This probably needs an ABI-version as well (especially in combination with SPV_INTEL_arbitrary_precision_integers).
597586 /// TODO: Should the result of this function be cached?
598587 fn backingIntBits(self: *NavGen, bits: u16) ?u16 {
599 const target = self.getTarget();
600
601588 // The backend will never be asked to compiler a 0-bit integer, so we won't have to handle those in this function.
602589 assert(bits != 0);
603590
604591 // 8, 16 and 64-bit integers require the Int8, Int16 and Inr64 capabilities respectively.
605592 // 32-bit integers are always supported (see spec, 2.16.1, Data rules).
606593 const ints = [_]struct { bits: u16, feature: ?Target.spirv.Feature }{
607 .{ .bits = 8, .feature = .Int8 },
608 .{ .bits = 16, .feature = .Int16 },
594 .{ .bits = 8, .feature = .int8 },
595 .{ .bits = 16, .feature = .int16 },
609596 .{ .bits = 32, .feature = null },
610 .{ .bits = 64, .feature = .Int64 },
597 .{ .bits = 64, .feature = .int64 },
611598 };
612599
613600 for (ints) |int| {
614 const has_feature = if (int.feature) |feature|
615 Target.spirv.featureSetHas(target.cpu.features, feature)
616 else
617 true;
618
619 if (bits <= int.bits and has_feature) {
620 return int.bits;
621 }
601 const has_feature = if (int.feature) |feature| self.spv.hasFeature(feature) else true;
602 if (bits <= int.bits and has_feature) return int.bits;
622603 }
623604
624605 return null;
......@@ -631,11 +612,7 @@ const NavGen = struct {
631612 /// is no way of knowing whether those are actually supported.
632613 /// TODO: Maybe this should be cached?
633614 fn largestSupportedIntBits(self: *NavGen) u16 {
634 const target = self.getTarget();
635 return if (Target.spirv.featureSetHas(target.cpu.features, .Int64))
636 64
637 else
638 32;
615 return if (self.spv.hasFeature(.int64)) 64 else 32;
639616 }
640617
641618 /// 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 {
648625 /// Checks whether the type can be directly translated to SPIR-V vectors
649626 fn isSpvVector(self: *NavGen, ty: Type) bool {
650627 const zcu = self.pt.zcu;
651 const target = self.getTarget();
652628 if (ty.zigTypeTag(zcu) != .vector) return false;
653629
654630 // TODO: This check must be expanded for types that can be represented
......@@ -664,17 +640,19 @@ const NavGen = struct {
664640 }
665641
666642 const elem_ty = ty.childType(zcu);
667
668643 const len = ty.vectorLen(zcu);
669 const is_scalar = elem_ty.isNumeric(zcu) or elem_ty.toIntern() == .bool_type;
670 const spirv_len = len > 1 and len <= 4;
671 const opencl_len = if (target.os.tag == .opencl) (len == 8 or len == 16) else false;
672 return is_scalar and (spirv_len or opencl_len);
644
645 if (elem_ty.isNumeric(zcu) or elem_ty.toIntern() == .bool_type) {
646 if (len > 1 and len <= 4) return true;
647 if (self.spv.hasFeature(.vector16)) return (len == 8 or len == 16);
648 }
649
650 return false;
673651 }
674652
675653 fn arithmeticTypeInfo(self: *NavGen, ty: Type) ArithmeticTypeInfo {
676654 const zcu = self.pt.zcu;
677 const target = self.getTarget();
655 const target = self.spv.target;
678656 var scalar_ty = ty.scalarType(zcu);
679657 if (scalar_ty.zigTypeTag(zcu) == .@"enum") {
680658 scalar_ty = scalar_ty.intTagType(zcu);
......@@ -721,36 +699,16 @@ const NavGen = struct {
721699
722700 /// Emits a bool constant in a particular representation.
723701 fn constBool(self: *NavGen, value: bool, repr: Repr) !IdRef {
724 // TODO: Cache?
725
726 const section = &self.spv.sections.types_globals_constants;
727 switch (repr) {
728 .indirect => {
729 return try self.constInt(Type.u1, @intFromBool(value), .indirect);
730 },
731 .direct => {
732 const result_ty_id = try self.resolveType(Type.bool, .direct);
733 const result_id = self.spv.allocId();
734 switch (value) {
735 inline else => |val_ct| try section.emit(
736 self.spv.gpa,
737 if (val_ct) .OpConstantTrue else .OpConstantFalse,
738 .{
739 .id_result_type = result_ty_id,
740 .id_result = result_id,
741 },
742 ),
743 }
744 return result_id;
745 },
746 }
702 return switch (repr) {
703 .indirect => self.constInt(Type.u1, @intFromBool(value)),
704 .direct => self.spv.constBool(value),
705 };
747706 }
748707
749708 /// Emits an integer constant.
750709 /// This function, unlike SpvModule.constInt, takes care to bitcast
751710 /// the value to an unsigned int first for Kernels.
752 fn constInt(self: *NavGen, ty: Type, value: anytype, repr: Repr) !IdRef {
753 // TODO: Cache?
711 fn constInt(self: *NavGen, ty: Type, value: anytype) !IdRef {
754712 const zcu = self.pt.zcu;
755713 const scalar_ty = ty.scalarType(zcu);
756714 const int_info = scalar_ty.intInfo(zcu);
......@@ -763,18 +721,18 @@ const NavGen = struct {
763721 else => unreachable,
764722 };
765723
766 const bits: u64 = switch (signedness) {
724 const value64: u64 = switch (signedness) {
767725 .signed => @bitCast(@as(i64, @intCast(value))),
768726 .unsigned => @as(u64, @intCast(value)),
769727 };
770728
771729 // Manually truncate the value to the right amount of bits.
772 const truncated_bits = if (backing_bits == 64)
773 bits
730 const truncated_value = if (backing_bits == 64)
731 value64
774732 else
775 bits & (@as(u64, 1) << @intCast(backing_bits)) - 1;
733 value64 & (@as(u64, 1) << @intCast(backing_bits)) - 1;
776734
777 const result_ty_id = try self.resolveType(scalar_ty, repr);
735 const result_ty_id = try self.resolveType(scalar_ty, .indirect);
778736 const result_id = self.spv.allocId();
779737
780738 const section = &self.spv.sections.types_globals_constants;
......@@ -783,100 +741,42 @@ const NavGen = struct {
783741 1...32 => try section.emit(self.spv.gpa, .OpConstant, .{
784742 .id_result_type = result_ty_id,
785743 .id_result = result_id,
786 .value = .{ .uint32 = @truncate(truncated_bits) },
744 .value = .{ .uint32 = @truncate(truncated_value) },
787745 }),
788746 33...64 => try section.emit(self.spv.gpa, .OpConstant, .{
789747 .id_result_type = result_ty_id,
790748 .id_result = result_id,
791 .value = .{ .uint64 = truncated_bits },
749 .value = .{ .uint64 = truncated_value },
792750 }),
793751 else => unreachable, // TODO: Large integer constants
794752 }
795753
796 if (!ty.isVector(zcu)) {
797 return result_id;
798 }
799
800 const n = ty.vectorLen(zcu);
801 const ids = try self.gpa.alloc(IdRef, n);
802 defer self.gpa.free(ids);
803 @memset(ids, result_id);
804
805 const vec_ty_id = try self.resolveType(ty, repr);
806 const vec_result_id = self.spv.allocId();
807 try self.func.body.emit(self.spv.gpa, .OpCompositeConstruct, .{
808 .id_result_type = vec_ty_id,
809 .id_result = vec_result_id,
810 .constituents = ids,
811 });
812 return vec_result_id;
754 if (!ty.isVector(zcu)) return result_id;
755 return self.constructCompositeSplat(ty, result_id);
813756 }
814757
815 /// Construct a struct at runtime.
816 /// ty must be a struct type.
817 /// Constituents should be in `indirect` representation (as the elements of a struct should be).
818 /// Result is in `direct` representation.
819 fn constructStruct(self: *NavGen, ty: Type, types: []const Type, constituents: []const IdRef) !IdRef {
820 assert(types.len == constituents.len);
821
758 pub fn constructComposite(self: *NavGen, result_ty_id: IdRef, constituents: []const IdRef) !IdRef {
822759 const result_id = self.spv.allocId();
823 try self.func.body.emit(self.spv.gpa, .OpCompositeConstruct, .{
824 .id_result_type = try self.resolveType(ty, .direct),
825 .id_result = result_id,
826 .constituents = constituents,
827 });
828 return result_id;
829 }
830
831 /// Construct a vector at runtime.
832 /// ty must be an vector type.
833 fn constructVector(self: *NavGen, ty: Type, constituents: []const IdRef) !IdRef {
834 const zcu = self.pt.zcu;
835 assert(ty.vectorLen(zcu) == constituents.len);
836
837 // Note: older versions of the Khronos SPRIV-LLVM translator crash on this instruction
838 // because it cannot construct structs which' operands are not constant.
839 // See https://github.com/KhronosGroup/SPIRV-LLVM-Translator/issues/1349
840 // Currently this is the case for Intel OpenCL CPU runtime (2023-WW46), but the
841 // alternatives dont work properly:
842 // - using temporaries/pointers doesn't work properly with vectors of bool, causes
843 // backends that use llvm to crash
844 // - using OpVectorInsertDynamic doesn't work for non-spirv-vectors of bool.
845
846 const result_id = self.spv.allocId();
847 try self.func.body.emit(self.spv.gpa, .OpCompositeConstruct, .{
848 .id_result_type = try self.resolveType(ty, .direct),
760 try self.func.body.emit(self.gpa, .OpCompositeConstruct, .{
761 .id_result_type = result_ty_id,
849762 .id_result = result_id,
850763 .constituents = constituents,
851764 });
852765 return result_id;
853766 }
854767
855 /// Construct a vector at runtime with all lanes set to the same value.
856 /// ty must be an vector type.
857 fn constructVectorSplat(self: *NavGen, ty: Type, constituent: IdRef) !IdRef {
768 /// Construct a composite at runtime with all lanes set to the same value.
769 /// ty must be an aggregate type.
770 fn constructCompositeSplat(self: *NavGen, ty: Type, constituent: IdRef) !IdRef {
858771 const zcu = self.pt.zcu;
859 const n = ty.vectorLen(zcu);
772 const n: usize = @intCast(ty.arrayLen(zcu));
860773
861774 const constituents = try self.gpa.alloc(IdRef, n);
862775 defer self.gpa.free(constituents);
863776 @memset(constituents, constituent);
864777
865 return try self.constructVector(ty, constituents);
866 }
867
868 /// Construct an array at runtime.
869 /// ty must be an array type.
870 /// Constituents should be in `indirect` representation (as the elements of an array should be).
871 /// Result is in `direct` representation.
872 fn constructArray(self: *NavGen, ty: Type, constituents: []const IdRef) !IdRef {
873 const result_id = self.spv.allocId();
874 try self.func.body.emit(self.spv.gpa, .OpCompositeConstruct, .{
875 .id_result_type = try self.resolveType(ty, .direct),
876 .id_result = result_id,
877 .constituents = constituents,
878 });
879 return result_id;
778 const result_ty_id = try self.resolveType(ty, .direct);
779 return self.constructComposite(result_ty_id, constituents);
880780 }
881781
882782 /// This function generates a load for a constant in direct (ie, non-memory) representation.
......@@ -895,7 +795,7 @@ const NavGen = struct {
895795
896796 const pt = self.pt;
897797 const zcu = pt.zcu;
898 const target = self.getTarget();
798 const target = self.spv.target;
899799 const result_ty_id = try self.resolveType(ty, repr);
900800 const ip = &zcu.intern_pool;
901801
......@@ -947,9 +847,9 @@ const NavGen = struct {
947847 },
948848 .int => {
949849 if (ty.isSignedInt(zcu)) {
950 break :cache try self.constInt(ty, val.toSignedInt(zcu), repr);
850 break :cache try self.constInt(ty, val.toSignedInt(zcu));
951851 } else {
952 break :cache try self.constInt(ty, val.toUnsignedInt(zcu), repr);
852 break :cache try self.constInt(ty, val.toUnsignedInt(zcu));
953853 }
954854 },
955855 .float => {
......@@ -970,7 +870,7 @@ const NavGen = struct {
970870 },
971871 .err => |err| {
972872 const value = try pt.getErrorValue(err.name);
973 break :cache try self.constInt(ty, value, repr);
873 break :cache try self.constInt(ty, value);
974874 },
975875 .error_union => |error_union| {
976876 // TODO: Error unions may be constructed with constant instructions if the payload type
......@@ -1011,7 +911,8 @@ const NavGen = struct {
1011911 types = .{ payload_ty, err_ty };
1012912 }
1013913
1014 return try self.constructStruct(ty, &types, &constituents);
914 const comp_ty_id = try self.resolveType(ty, .direct);
915 return try self.constructComposite(comp_ty_id, &constituents);
1015916 },
1016917 .enum_tag => {
1017918 const int_val = try val.intFromEnum(ty, pt);
......@@ -1020,14 +921,10 @@ const NavGen = struct {
1020921 },
1021922 .ptr => return self.constantPtr(val),
1022923 .slice => |slice| {
1023 const ptr_ty = ty.slicePtrFieldType(zcu);
1024924 const ptr_id = try self.constantPtr(Value.fromInterned(slice.ptr));
1025925 const len_id = try self.constant(Type.usize, Value.fromInterned(slice.len), .indirect);
1026 return self.constructStruct(
1027 ty,
1028 &.{ ptr_ty, Type.usize },
1029 &.{ ptr_id, len_id },
1030 );
926 const comp_ty_id = try self.resolveType(ty, .direct);
927 return try self.constructComposite(comp_ty_id, &.{ ptr_id, len_id });
1031928 },
1032929 .opt => {
1033930 const payload_ty = ty.optionalChild(zcu);
......@@ -1053,11 +950,8 @@ const NavGen = struct {
1053950 else
1054951 try self.spv.constUndef(try self.resolveType(payload_ty, .indirect));
1055952
1056 return try self.constructStruct(
1057 ty,
1058 &.{ payload_ty, Type.bool },
1059 &.{ payload_id, has_pl_id },
1060 );
953 const comp_ty_id = try self.resolveType(ty, .direct);
954 return try self.constructComposite(comp_ty_id, &.{ payload_id, has_pl_id });
1061955 },
1062956 .aggregate => |aggregate| switch (ip.indexToKey(ty.ip_index)) {
1063957 inline .array_type, .vector_type => |array_type, tag| {
......@@ -1077,7 +971,7 @@ const NavGen = struct {
1077971 // TODO: This is really space inefficient, perhaps there is a better
1078972 // way to do it?
1079973 for (constituents, bytes.toSlice(constituents.len, ip)) |*constituent, byte| {
1080 constituent.* = try self.constInt(elem_ty, byte, child_repr);
974 constituent.* = try self.constInt(elem_ty, byte);
1081975 }
1082976 },
1083977 .elems => |elems| {
......@@ -1090,11 +984,8 @@ const NavGen = struct {
1090984 },
1091985 }
1092986
1093 switch (tag) {
1094 .array_type => return self.constructArray(ty, constituents),
1095 .vector_type => return self.constructVector(ty, constituents),
1096 else => unreachable,
1097 }
987 const comp_ty_id = try self.resolveType(ty, .direct);
988 return self.constructComposite(comp_ty_id, constituents);
1098989 },
1099990 .struct_type => {
1100991 const struct_type = zcu.typeToStruct(ty).?;
......@@ -1124,7 +1015,8 @@ const NavGen = struct {
11241015 try constituents.append(field_id);
11251016 }
11261017
1127 return try self.constructStruct(ty, types.items, constituents.items);
1018 const comp_ty_id = try self.resolveType(ty, .direct);
1019 return try self.constructComposite(comp_ty_id, constituents.items);
11281020 },
11291021 .tuple_type => unreachable, // TODO
11301022 else => unreachable,
......@@ -1149,8 +1041,6 @@ const NavGen = struct {
11491041 }
11501042
11511043 fn constantPtr(self: *NavGen, ptr_val: Value) Error!IdRef {
1152 // TODO: Caching??
1153
11541044 const pt = self.pt;
11551045
11561046 if (ptr_val.isUndef(pt.zcu)) {
......@@ -1201,7 +1091,7 @@ const NavGen = struct {
12011091 .elem_ptr => |elem| {
12021092 const parent_ptr_id = try self.derivePtr(elem.parent.*);
12031093 const parent_ptr_ty = try elem.parent.ptrType(pt);
1204 const index_id = try self.constInt(Type.usize, elem.elem_idx, .direct);
1094 const index_id = try self.constInt(Type.usize, elem.elem_idx);
12051095 return self.ptrElemPtr(parent_ptr_ty, parent_ptr_id, index_id);
12061096 },
12071097 .offset_and_cast => |oac| {
......@@ -1255,7 +1145,7 @@ const NavGen = struct {
12551145
12561146 // Uav refs are always generic.
12571147 assert(ty.ptrAddressSpace(zcu) == .generic);
1258 const decl_ptr_ty_id = try self.ptrType(uav_ty, .Generic);
1148 const decl_ptr_ty_id = try self.ptrType(uav_ty, .Generic, .indirect);
12591149 const ptr_id = try self.resolveUav(uav.val);
12601150
12611151 if (decl_ptr_ty_id != ty_id) {
......@@ -1310,7 +1200,7 @@ const NavGen = struct {
13101200 const storage_class = self.spvStorageClass(nav.getAddrspace());
13111201 try self.addFunctionDep(spv_decl_index, storage_class);
13121202
1313 const decl_ptr_ty_id = try self.ptrType(nav_ty, storage_class);
1203 const decl_ptr_ty_id = try self.ptrType(nav_ty, storage_class, .indirect);
13141204
13151205 const ptr_id = switch (storage_class) {
13161206 .Generic => try self.castToGeneric(decl_ptr_ty_id, decl_id),
......@@ -1351,31 +1241,20 @@ const NavGen = struct {
13511241 };
13521242
13531243 // Kernel only supports unsigned ints.
1354 if (self.getTarget().os.tag == .vulkan) {
1355 return self.spv.intType(signedness, backing_bits);
1244 if (self.spv.hasFeature(.kernel)) {
1245 return self.spv.intType(.unsigned, backing_bits);
13561246 }
13571247
1358 return self.spv.intType(.unsigned, backing_bits);
1248 return self.spv.intType(signedness, backing_bits);
13591249 }
13601250
13611251 fn arrayType(self: *NavGen, len: u32, child_ty: IdRef) !IdRef {
1362 // TODO: Cache??
1363 const len_id = try self.constInt(Type.u32, len, .direct);
1364 const result_id = self.spv.allocId();
1365
1366 try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpTypeArray, .{
1367 .id_result = result_id,
1368 .element_type = child_ty,
1369 .length = len_id,
1370 });
1371 return result_id;
1372 }
1373
1374 fn ptrType(self: *NavGen, child_ty: Type, storage_class: StorageClass) !IdRef {
1375 return try self.ptrType2(child_ty, storage_class, .indirect);
1252 const len_id = try self.constInt(Type.u32, len);
1253 return self.spv.arrayType(len_id, child_ty);
13761254 }
13771255
1378 fn ptrType2(self: *NavGen, child_ty: Type, storage_class: StorageClass, child_repr: Repr) !IdRef {
1256 fn ptrType(self: *NavGen, child_ty: Type, storage_class: StorageClass, child_repr: Repr) !IdRef {
1257 const zcu = self.pt.zcu;
13791258 const key = .{ child_ty.toIntern(), storage_class, child_repr };
13801259 const entry = try self.ptr_types.getOrPut(self.gpa, key);
13811260 if (entry.found_existing) {
......@@ -1398,6 +1277,17 @@ const NavGen = struct {
13981277
13991278 const child_ty_id = try self.resolveType(child_ty, child_repr);
14001279
1280 if (self.spv.hasFeature(.shader)) {
1281 if (child_ty.zigTypeTag(zcu) == .@"struct") {
1282 switch (storage_class) {
1283 .Uniform, .PushConstant => try self.spv.decorate(child_ty_id, .Block),
1284 else => {},
1285 }
1286 }
1287
1288 try self.spv.decorate(result_id, .{ .ArrayStride = .{ .array_stride = @intCast(child_ty.abiSize(zcu)) } });
1289 }
1290
14011291 try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpTypePointer, .{
14021292 .id_result = result_id,
14031293 .storage_class = storage_class,
......@@ -1408,8 +1298,7 @@ const NavGen = struct {
14081298 }
14091299
14101300 fn functionType(self: *NavGen, return_ty: Type, param_types: []const Type) !IdRef {
1411 // TODO: Cache??
1412
1301 const return_ty_id = try self.resolveFnReturnType(return_ty);
14131302 const param_ids = try self.gpa.alloc(IdRef, param_types.len);
14141303 defer self.gpa.free(param_ids);
14151304
......@@ -1417,14 +1306,7 @@ const NavGen = struct {
14171306 param_id.* = try self.resolveType(param_ty, .direct);
14181307 }
14191308
1420 const ty_id = self.spv.allocId();
1421 try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpTypeFunction, .{
1422 .id_result = ty_id,
1423 .return_type = try self.resolveFnReturnType(return_ty),
1424 .id_ref_2 = param_ids,
1425 });
1426
1427 return ty_id;
1309 return self.spv.functionType(return_ty_id, param_ids);
14281310 }
14291311
14301312 fn zigScalarOrVectorTypeLike(self: *NavGen, new_ty: Type, base_ty: Type) !Type {
......@@ -1544,7 +1426,7 @@ const NavGen = struct {
15441426 const zcu = pt.zcu;
15451427 const ip = &zcu.intern_pool;
15461428 log.debug("resolveType: ty = {}", .{ty.fmt(pt)});
1547 const target = self.getTarget();
1429 const target = self.spv.target;
15481430
15491431 const section = &self.spv.sections.types_globals_constants;
15501432
......@@ -1595,10 +1477,10 @@ const NavGen = struct {
15951477 // so if the float is not supported, just return an error.
15961478 const bits = ty.floatBits(target);
15971479 const supported = switch (bits) {
1598 16 => Target.spirv.featureSetHas(target.cpu.features, .Float16),
1480 16 => self.spv.hasFeature(.float16),
15991481 // 32-bit floats are always supported (see spec, 2.16.1, Data rules).
16001482 32 => true,
1601 64 => Target.spirv.featureSetHas(target.cpu.features, .Float64),
1483 64 => self.spv.hasFeature(.float64),
16021484 else => false,
16031485 };
16041486
......@@ -1641,7 +1523,7 @@ const NavGen = struct {
16411523 return try self.arrayType(1, elem_ty_id);
16421524 } else {
16431525 const result_id = try self.arrayType(total_len, elem_ty_id);
1644 if (target.os.tag == .vulkan) {
1526 if (self.spv.hasFeature(.shader)) {
16451527 try self.spv.decorate(result_id, .{ .ArrayStride = .{
16461528 .array_stride = @intCast(elem_ty.abiSize(zcu)),
16471529 } });
......@@ -1702,13 +1584,7 @@ const NavGen = struct {
17021584
17031585 const child_ty = Type.fromInterned(ptr_info.child);
17041586 const storage_class = self.spvStorageClass(ptr_info.flags.address_space);
1705 const ptr_ty_id = try self.ptrType(child_ty, storage_class);
1706
1707 if (target.os.tag == .vulkan and ptr_info.flags.size == .many) {
1708 try self.spv.decorate(ptr_ty_id, .{ .ArrayStride = .{
1709 .array_stride = @intCast(child_ty.abiSize(zcu)),
1710 } });
1711 }
1587 const ptr_ty_id = try self.ptrType(child_ty, storage_class, .indirect);
17121588
17131589 if (ptr_info.flags.size != .slice) {
17141590 return ptr_ty_id;
......@@ -1755,10 +1631,6 @@ const NavGen = struct {
17551631 defer self.gpa.free(type_name);
17561632 try self.spv.debugName(result_id, type_name);
17571633
1758 if (target.os.tag == .vulkan) {
1759 try self.spv.decorate(result_id, .Block); // Decorate all structs as block for now...
1760 }
1761
17621634 return result_id;
17631635 },
17641636 .struct_type => ip.loadStructType(ty.toIntern()),
......@@ -1785,7 +1657,7 @@ const NavGen = struct {
17851657 continue;
17861658 }
17871659
1788 if (target.os.tag == .vulkan) {
1660 if (self.spv.hasFeature(.shader)) {
17891661 try self.spv.decorateMember(result_id, index, .{ .Offset = .{
17901662 .byte_offset = @intCast(ty.structFieldOffset(field_index, zcu)),
17911663 } });
......@@ -1804,10 +1676,6 @@ const NavGen = struct {
18041676 defer self.gpa.free(type_name);
18051677 try self.spv.debugName(result_id, type_name);
18061678
1807 if (target.os.tag == .vulkan) {
1808 try self.spv.decorate(result_id, .Block); // Decorate all structs as block for now...
1809 }
1810
18111679 return result_id;
18121680 },
18131681 .optional => {
......@@ -1891,20 +1759,11 @@ const NavGen = struct {
18911759 }
18921760
18931761 fn spvStorageClass(self: *NavGen, as: std.builtin.AddressSpace) StorageClass {
1894 const target = self.getTarget();
18951762 return switch (as) {
1896 .generic => switch (target.os.tag) {
1897 .vulkan => .Function,
1898 .opencl => .Generic,
1899 else => unreachable,
1900 },
1763 .generic => if (self.spv.hasFeature(.generic_pointer)) .Generic else .Function,
19011764 .shared => .Workgroup,
19021765 .local => .Function,
1903 .global => switch (target.os.tag) {
1904 .opencl => .CrossWorkgroup,
1905 .vulkan => .PhysicalStorageBuffer,
1906 else => unreachable,
1907 },
1766 .global => if (self.spv.hasFeature(.shader)) .PhysicalStorageBuffer else .CrossWorkgroup,
19081767 .constant => .UniformConstant,
19091768 .push_constant => .PushConstant,
19101769 .input => .Input,
......@@ -2073,12 +1932,13 @@ const NavGen = struct {
20731932 .exploded_vector => |range| {
20741933 assert(self.ty.isVector(zcu));
20751934 assert(self.ty.vectorLen(zcu) == range.len);
2076 const consituents = try ng.gpa.alloc(IdRef, range.len);
2077 defer ng.gpa.free(consituents);
2078 for (consituents, 0..range.len) |*id, i| {
1935 const constituents = try ng.gpa.alloc(IdRef, range.len);
1936 defer ng.gpa.free(constituents);
1937 for (constituents, 0..range.len) |*id, i| {
20791938 id.* = range.at(i);
20801939 }
2081 return ng.constructVector(self.ty, consituents);
1940 const result_ty_id = try ng.resolveType(self.ty, .direct);
1941 return ng.constructComposite(result_ty_id, constituents);
20821942 },
20831943 }
20841944 }
......@@ -2282,7 +2142,7 @@ const NavGen = struct {
22822142 .child = tmp.ty.toIntern(),
22832143 });
22842144
2285 const vector = try ng.constructVectorSplat(vector_ty, id);
2145 const vector = try ng.constructCompositeSplat(vector_ty, id);
22862146 return .{
22872147 .ty = vector_ty,
22882148 .value = .{ .spv_vectorwise = vector },
......@@ -2447,7 +2307,7 @@ const NavGen = struct {
24472307 }
24482308
24492309 fn buildFma(self: *NavGen, a: Temporary, b: Temporary, c: Temporary) !Temporary {
2450 const target = self.getTarget();
2310 const target = self.spv.target;
24512311
24522312 const v = self.vectorization(.{ a, b, c });
24532313 const ops = v.operations();
......@@ -2469,7 +2329,7 @@ const NavGen = struct {
24692329 // NOTE: Vulkan's FMA instruction does *NOT* produce the right values!
24702330 // its precision guarantees do NOT match zigs and it does NOT match OpenCLs!
24712331 // it needs to be emulated!
2472 .vulkan => unreachable, // TODO: See above
2332 .vulkan, .opengl => unreachable, // TODO: See above
24732333 else => unreachable,
24742334 };
24752335
......@@ -2606,14 +2466,14 @@ const NavGen = struct {
26062466 };
26072467
26082468 fn buildUnary(self: *NavGen, op: UnaryOp, operand: Temporary) !Temporary {
2609 const target = self.getTarget();
2469 const target = self.spv.target;
26102470 const v = blk: {
26112471 const v = self.vectorization(.{operand});
26122472 break :blk switch (op) {
26132473 // TODO: These instructions don't seem to be working
26142474 // properly for LLVM-based backends on OpenCL for 8- and
26152475 // 16-component vectors.
2616 .i_abs => if (target.os.tag == .opencl and v.components() >= 8) v.unroll() else v,
2476 .i_abs => if (self.spv.hasFeature(.vector16) and v.components() >= 8) v.unroll() else v,
26172477 else => v,
26182478 };
26192479 };
......@@ -2666,7 +2526,7 @@ const NavGen = struct {
26662526 // Note: We'll need to check these for floating point accuracy
26672527 // Vulkan does not put tight requirements on these, for correction
26682528 // we might want to emulate them at some point.
2669 .vulkan => switch (op) {
2529 .vulkan, .opengl => switch (op) {
26702530 .i_abs => 5, // SAbs
26712531 .f_abs => 4, // FAbs
26722532 .clz => unreachable, // TODO
......@@ -2736,7 +2596,7 @@ const NavGen = struct {
27362596 };
27372597
27382598 fn buildBinary(self: *NavGen, op: BinaryOp, lhs: Temporary, rhs: Temporary) !Temporary {
2739 const target = self.getTarget();
2599 const target = self.spv.target;
27402600
27412601 const v = self.vectorization(.{ lhs, rhs });
27422602 const ops = v.operations();
......@@ -2795,7 +2655,7 @@ const NavGen = struct {
27952655 .u_min => 159, // u_min
27962656 else => unreachable,
27972657 },
2798 .vulkan => switch (op) {
2658 .vulkan, .opengl => switch (op) {
27992659 .f_max => 40, // FMax
28002660 .s_max => 42, // SMax
28012661 .u_max => 41, // UMax
......@@ -2834,7 +2694,7 @@ const NavGen = struct {
28342694 ) !struct { Temporary, Temporary } {
28352695 const pt = self.pt;
28362696 const zcu = pt.zcu;
2837 const target = self.getTarget();
2697 const target = self.spv.target;
28382698 const ip = &zcu.intern_pool;
28392699
28402700 const v = lhs.vectorization(self).unify(rhs.vectorization(self));
......@@ -2877,7 +2737,7 @@ const NavGen = struct {
28772737 });
28782738 }
28792739 },
2880 .vulkan => {
2740 .vulkan, .opengl => {
28812741 // Operations return a struct{T, T}
28822742 // where T is maybe vectorized.
28832743 const op_result_ty: Type = .fromInterned(try ip.getTupleType(zcu.gpa, pt.tid, .{
......@@ -2964,7 +2824,7 @@ const NavGen = struct {
29642824
29652825 const section = &self.spv.sections.functions;
29662826
2967 const target = self.getTarget();
2827 const target = self.spv.target;
29682828
29692829 const p_error_id = self.spv.allocId();
29702830 switch (target.os.tag) {
......@@ -2987,7 +2847,7 @@ const NavGen = struct {
29872847 .id_result = self.spv.allocId(),
29882848 });
29892849 },
2990 .vulkan => {
2850 .vulkan, .opengl => {
29912851 const ptr_ptr_anyerror_ty_id = self.spv.allocId();
29922852 try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpTypePointer, .{
29932853 .id_result = ptr_ptr_anyerror_ty_id,
......@@ -3045,7 +2905,7 @@ const NavGen = struct {
30452905 const spv_err_decl_index = self.object.error_push_constant.?.push_constant_ptr;
30462906 const push_constant_id = self.spv.declPtr(spv_err_decl_index).result_id;
30472907
3048 const zero_id = try self.constInt(Type.u32, 0, .direct);
2908 const zero_id = try self.constInt(Type.u32, 0);
30492909 // We cannot use OpInBoundsAccessChain to dereference cross-storage class, so we have to use
30502910 // a load.
30512911 const tmp = self.spv.allocId();
......@@ -3088,7 +2948,7 @@ const NavGen = struct {
30882948 defer self.gpa.free(test_name);
30892949
30902950 const execution_mode: spec.ExecutionModel = switch (target.os.tag) {
3091 .vulkan => .GLCompute,
2951 .vulkan, .opengl => .GLCompute,
30922952 .opencl => .Kernel,
30932953 else => unreachable,
30942954 };
......@@ -3187,7 +3047,7 @@ const NavGen = struct {
31873047 const storage_class = self.spvStorageClass(nav.getAddrspace());
31883048 assert(storage_class != .Generic); // These should be instance globals
31893049
3190 const ptr_ty_id = try self.ptrType(ty, storage_class);
3050 const ptr_ty_id = try self.ptrType(ty, storage_class, .indirect);
31913051
31923052 try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpVariable, .{
31933053 .id_result_type = ptr_ty_id,
......@@ -3208,7 +3068,7 @@ const NavGen = struct {
32083068
32093069 try self.spv.declareDeclDeps(spv_decl_index, &.{});
32103070
3211 const ptr_ty_id = try self.ptrType(ty, .Function);
3071 const ptr_ty_id = try self.ptrType(ty, .Function, .indirect);
32123072
32133073 if (maybe_init_val) |init_val| {
32143074 // TODO: Combine with resolveAnonDecl?
......@@ -3265,8 +3125,8 @@ const NavGen = struct {
32653125 }
32663126
32673127 fn intFromBool2(self: *NavGen, value: Temporary, result_ty: Type) !Temporary {
3268 const zero_id = try self.constInt(result_ty, 0, .direct);
3269 const one_id = try self.constInt(result_ty, 1, .direct);
3128 const zero_id = try self.constInt(result_ty, 0);
3129 const one_id = try self.constInt(result_ty, 1);
32703130
32713131 return try self.buildSelect(
32723132 value,
......@@ -3648,12 +3508,12 @@ const NavGen = struct {
36483508 .strange_integer => switch (info.signedness) {
36493509 .unsigned => {
36503510 const mask_value = if (info.bits == 64) 0xFFFF_FFFF_FFFF_FFFF else (@as(u64, 1) << @as(u6, @intCast(info.bits))) - 1;
3651 const mask_id = try self.constInt(ty.scalarType(zcu), mask_value, .direct);
3511 const mask_id = try self.constInt(ty.scalarType(zcu), mask_value);
36523512 return try self.buildBinary(.bit_and, value, Temporary.init(ty.scalarType(zcu), mask_id));
36533513 },
36543514 .signed => {
36553515 // Shift left and right so that we can copy the sight bit that way.
3656 const shift_amt_id = try self.constInt(ty.scalarType(zcu), info.backing_bits - info.bits, .direct);
3516 const shift_amt_id = try self.constInt(ty.scalarType(zcu), info.backing_bits - info.bits);
36573517 const shift_amt = Temporary.init(ty.scalarType(zcu), shift_amt_id);
36583518 const left = try self.buildBinary(.sll, value, shift_amt);
36593519 return try self.buildBinary(.sra, left, shift_amt);
......@@ -3687,7 +3547,7 @@ const NavGen = struct {
36873547 const div = try self.buildBinary(.s_div, lhs, rhs);
36883548 const rem = try self.buildBinary(.s_rem, lhs, rhs);
36893549
3690 const zero = Temporary.init(lhs.ty, try self.constInt(lhs.ty, 0, .direct));
3550 const zero = Temporary.init(lhs.ty, try self.constInt(lhs.ty, 0));
36913551
36923552 const rem_is_not_zero = try self.buildCmp(.i_ne, rem, zero);
36933553
......@@ -3791,7 +3651,6 @@ const NavGen = struct {
37913651 }
37923652
37933653 fn abs(self: *NavGen, result_ty: Type, value: Temporary) !Temporary {
3794 const target = self.getTarget();
37953654 const operand_info = self.arithmeticTypeInfo(value.ty);
37963655
37973656 switch (operand_info.class) {
......@@ -3803,7 +3662,7 @@ const NavGen = struct {
38033662 // depending on the result type. Do that when
38043663 // bitCast is implemented for vectors.
38053664 // This is only relevant for Vulkan
3806 assert(target.os.tag != .vulkan); // TODO
3665 assert(self.spv.hasFeature(.kernel)); // TODO
38073666
38083667 return try self.normalize(abs_value, self.arithmeticTypeInfo(result_ty));
38093668 },
......@@ -3863,7 +3722,7 @@ const NavGen = struct {
38633722 // = (rhs < 0) == (value < lhs)
38643723 // = (rhs < 0) == (lhs > value)
38653724 .signed => blk: {
3866 const zero = Temporary.init(rhs.ty, try self.constInt(rhs.ty, 0, .direct));
3725 const zero = Temporary.init(rhs.ty, try self.constInt(rhs.ty, 0));
38673726 const rhs_lt_zero = try self.buildCmp(.s_lt, rhs, zero);
38683727 const result_gt_lhs = try self.buildCmp(scmp, lhs, result);
38693728 break :blk try self.buildCmp(.l_eq, rhs_lt_zero, result_gt_lhs);
......@@ -3872,15 +3731,11 @@ const NavGen = struct {
38723731
38733732 const ov = try self.intFromBool(overflowed);
38743733
3875 return try self.constructStruct(
3876 result_ty,
3877 &.{ result.ty, ov.ty },
3878 &.{ try result.materialize(self), try ov.materialize(self) },
3879 );
3734 const result_ty_id = try self.resolveType(result_ty, .direct);
3735 return try self.constructComposite(result_ty_id, &.{ try result.materialize(self), try ov.materialize(self) });
38803736 }
38813737
38823738 fn airMulOverflow(self: *NavGen, inst: Air.Inst.Index) !?IdRef {
3883 const target = self.getTarget();
38843739 const pt = self.pt;
38853740
38863741 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
......@@ -3904,7 +3759,7 @@ const NavGen = struct {
39043759 // - Additionally, if info.bits != 32, we'll have to check the high bits
39053760 // of the result too.
39063761
3907 const largest_int_bits: u16 = if (Target.spirv.featureSetHas(target.cpu.features, .Int64)) 64 else 32;
3762 const largest_int_bits = self.largestSupportedIntBits();
39083763 // If non-null, the number of bits that the multiplication should be performed in. If
39093764 // null, we have to use wide multiplication.
39103765 const maybe_op_ty_bits: ?u16 = switch (info.bits) {
......@@ -3928,11 +3783,11 @@ const NavGen = struct {
39283783 const result = try self.normalize(low_bits, info);
39293784
39303785 // Shift the result bits away to get the overflow bits.
3931 const shift = Temporary.init(full_result.ty, try self.constInt(full_result.ty, info.bits, .direct));
3786 const shift = Temporary.init(full_result.ty, try self.constInt(full_result.ty, info.bits));
39323787 const overflow = try self.buildBinary(.srl, full_result, shift);
39333788
39343789 // Directly check if its zero in the op_ty without converting first.
3935 const zero = Temporary.init(full_result.ty, try self.constInt(full_result.ty, 0, .direct));
3790 const zero = Temporary.init(full_result.ty, try self.constInt(full_result.ty, 0));
39363791 const overflowed = try self.buildCmp(.i_ne, zero, overflow);
39373792
39383793 break :blk .{ result, overflowed };
......@@ -3946,7 +3801,7 @@ const NavGen = struct {
39463801 // Overflow happened if the high-bits of the result are non-zero OR if the
39473802 // high bits of the low word of the result (those outside the range of the
39483803 // int) are nonzero.
3949 const zero = Temporary.init(lhs.ty, try self.constInt(lhs.ty, 0, .direct));
3804 const zero = Temporary.init(lhs.ty, try self.constInt(lhs.ty, 0));
39503805 const high_overflowed = try self.buildCmp(.i_ne, zero, high_bits);
39513806
39523807 // If no overflow bits in low_bits, no extra work needs to be done.
......@@ -3955,7 +3810,7 @@ const NavGen = struct {
39553810 }
39563811
39573812 // Shift the result bits away to get the overflow bits.
3958 const shift = Temporary.init(lhs.ty, try self.constInt(lhs.ty, info.bits, .direct));
3813 const shift = Temporary.init(lhs.ty, try self.constInt(lhs.ty, info.bits));
39593814 const low_overflow = try self.buildBinary(.srl, low_bits, shift);
39603815 const low_overflowed = try self.buildCmp(.i_ne, zero, low_overflow);
39613816
......@@ -3974,7 +3829,7 @@ const NavGen = struct {
39743829 // overflow should be -1 when
39753830 // (lhs > 0 && rhs < 0) || (lhs < 0 && rhs > 0)
39763831
3977 const zero = Temporary.init(lhs.ty, try self.constInt(lhs.ty, 0, .direct));
3832 const zero = Temporary.init(lhs.ty, try self.constInt(lhs.ty, 0));
39783833 const lhs_negative = try self.buildCmp(.s_lt, lhs, zero);
39793834 const rhs_negative = try self.buildCmp(.s_lt, rhs, zero);
39803835 const lhs_positive = try self.buildCmp(.s_gt, lhs, zero);
......@@ -4003,13 +3858,13 @@ const NavGen = struct {
40033858 // bit for the expected overflow bits.
40043859 // To do that, shift out everything bit the sign bit and
40053860 // then check what remains.
4006 const shift = Temporary.init(full_result.ty, try self.constInt(full_result.ty, info.bits - 1, .direct));
3861 const shift = Temporary.init(full_result.ty, try self.constInt(full_result.ty, info.bits - 1));
40073862 // Use SRA so that any sign bits are duplicated. Now we can just check if ALL bits are set
40083863 // for negative cases.
40093864 const overflow = try self.buildBinary(.sra, full_result, shift);
40103865
4011 const long_all_set = Temporary.init(full_result.ty, try self.constInt(full_result.ty, -1, .direct));
4012 const long_zero = Temporary.init(full_result.ty, try self.constInt(full_result.ty, 0, .direct));
3866 const long_all_set = Temporary.init(full_result.ty, try self.constInt(full_result.ty, -1));
3867 const long_zero = Temporary.init(full_result.ty, try self.constInt(full_result.ty, 0));
40133868 const mask = try self.buildSelect(expected_overflow_bit, long_all_set, long_zero);
40143869
40153870 const overflowed = try self.buildCmp(.i_ne, mask, overflow);
......@@ -4022,7 +3877,7 @@ const NavGen = struct {
40223877 // Truncate result if required.
40233878 const result = try self.normalize(low_bits, info);
40243879
4025 const all_set = Temporary.init(lhs.ty, try self.constInt(lhs.ty, -1, .direct));
3880 const all_set = Temporary.init(lhs.ty, try self.constInt(lhs.ty, -1));
40263881 const mask = try self.buildSelect(expected_overflow_bit, all_set, zero);
40273882
40283883 // Like with unsigned, overflow happened if high_bits are not the ones we expect,
......@@ -4038,7 +3893,7 @@ const NavGen = struct {
40383893 }
40393894
40403895 // Shift the result bits away to get the overflow bits.
4041 const shift = Temporary.init(lhs.ty, try self.constInt(lhs.ty, info.bits - 1, .direct));
3896 const shift = Temporary.init(lhs.ty, try self.constInt(lhs.ty, info.bits - 1));
40423897 // Use SRA so that any sign bits are duplicated. Now we can just check if ALL bits are set
40433898 // for negative cases.
40443899 const low_overflow = try self.buildBinary(.sra, low_bits, shift);
......@@ -4052,11 +3907,8 @@ const NavGen = struct {
40523907
40533908 const ov = try self.intFromBool(overflowed);
40543909
4055 return try self.constructStruct(
4056 result_ty,
4057 &.{ result.ty, ov.ty },
4058 &.{ try result.materialize(self), try ov.materialize(self) },
4059 );
3910 const result_ty_id = try self.resolveType(result_ty, .direct);
3911 return try self.constructComposite(result_ty_id, &.{ try result.materialize(self), try ov.materialize(self) });
40603912 }
40613913
40623914 fn airShlOverflow(self: *NavGen, inst: Air.Inst.Index) !?IdRef {
......@@ -4092,11 +3944,8 @@ const NavGen = struct {
40923944 const overflowed = try self.buildCmp(.i_ne, base, right);
40933945 const ov = try self.intFromBool(overflowed);
40943946
4095 return try self.constructStruct(
4096 result_ty,
4097 &.{ result.ty, ov.ty },
4098 &.{ try result.materialize(self), try ov.materialize(self) },
4099 );
3947 const result_ty_id = try self.resolveType(result_ty, .direct);
3948 return try self.constructComposite(result_ty_id, &.{ try result.materialize(self), try ov.materialize(self) });
41003949 }
41013950
41023951 fn airMulAdd(self: *NavGen, inst: Air.Inst.Index) !?IdRef {
......@@ -4119,7 +3968,6 @@ const NavGen = struct {
41193968 if (self.liveness.isUnused(inst)) return null;
41203969
41213970 const zcu = self.pt.zcu;
4122 const target = self.getTarget();
41233971 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
41243972 const operand = try self.temporary(ty_op.operand);
41253973
......@@ -4132,10 +3980,7 @@ const NavGen = struct {
41323980 .float, .bool => unreachable,
41333981 }
41343982
4135 switch (target.os.tag) {
4136 .vulkan => unreachable, // TODO
4137 else => {},
4138 }
3983 assert(self.spv.hasFeature(.kernel)); // TODO
41393984
41403985 const count = try self.buildUnary(op, operand);
41413986
......@@ -4163,7 +4008,7 @@ const NavGen = struct {
41634008 const operand_id = try self.resolve(ty_op.operand);
41644009 const result_ty = self.typeOfIndex(inst);
41654010
4166 return try self.constructVectorSplat(result_ty, operand_id);
4011 return try self.constructCompositeSplat(result_ty, operand_id);
41674012 }
41684013
41694014 fn airReduce(self: *NavGen, inst: Air.Inst.Index) !?IdRef {
......@@ -4297,10 +4142,10 @@ const NavGen = struct {
42974142
42984143 // Fall back to manually extracting and inserting components.
42994144
4300 const components = try self.gpa.alloc(IdRef, result_ty.vectorLen(zcu));
4301 defer self.gpa.free(components);
4145 const constituents = try self.gpa.alloc(IdRef, result_ty.vectorLen(zcu));
4146 defer self.gpa.free(constituents);
43024147
4303 for (components, 0..) |*id, i| {
4148 for (constituents, 0..) |*id, i| {
43044149 const elem = try mask.elemValue(pt, i);
43054150 if (elem.isUndef(zcu)) {
43064151 id.* = try self.spv.constUndef(scalar_ty_id);
......@@ -4315,14 +4160,15 @@ const NavGen = struct {
43154160 }
43164161 }
43174162
4318 return try self.constructVector(result_ty, components);
4163 const result_ty_id = try self.resolveType(result_ty, .direct);
4164 return try self.constructComposite(result_ty_id, constituents);
43194165 }
43204166
43214167 fn indicesToIds(self: *NavGen, indices: []const u32) ![]IdRef {
43224168 const ids = try self.gpa.alloc(IdRef, indices.len);
43234169 errdefer self.gpa.free(ids);
43244170 for (indices, ids) |index, *id| {
4325 id.* = try self.constInt(Type.u32, index, .direct);
4171 id.* = try self.constInt(Type.u32, index);
43264172 }
43274173
43284174 return ids;
......@@ -4370,23 +4216,22 @@ const NavGen = struct {
43704216 defer self.gpa.free(ids);
43714217
43724218 const result_id = self.spv.allocId();
4373 const target = self.getTarget();
4374 switch (target.os.tag) {
4375 .opencl => try self.func.body.emit(self.spv.gpa, .OpInBoundsPtrAccessChain, .{
4219 if (self.spv.hasFeature(.kernel)) {
4220 try self.func.body.emit(self.spv.gpa, .OpInBoundsPtrAccessChain, .{
43764221 .id_result_type = result_ty_id,
43774222 .id_result = result_id,
43784223 .base = base,
43794224 .element = element,
43804225 .indexes = ids,
4381 }),
4382 .vulkan => try self.func.body.emit(self.spv.gpa, .OpPtrAccessChain, .{
4226 });
4227 } else {
4228 try self.func.body.emit(self.spv.gpa, .OpPtrAccessChain, .{
43834229 .id_result_type = result_ty_id,
43844230 .id_result = result_id,
43854231 .base = base,
43864232 .element = element,
43874233 .indexes = ids,
4388 }),
4389 else => unreachable,
4234 });
43904235 }
43914236 return result_id;
43924237 }
......@@ -4676,7 +4521,7 @@ const NavGen = struct {
46764521 break :blk result_id;
46774522 }
46784523
4679 const dst_ptr_ty_id = try self.ptrType(dst_ty, .Function);
4524 const dst_ptr_ty_id = try self.ptrType(dst_ty, .Function, .indirect);
46804525
46814526 const tmp_id = try self.alloc(src_ty, .{ .storage_class = .Function });
46824527 try self.store(src_ty, tmp_id, src_id, .{});
......@@ -4851,7 +4696,7 @@ const NavGen = struct {
48514696 const elem_ptr_ty_id = try self.resolveType(elem_ptr_ty, .direct);
48524697
48534698 const array_ptr_id = try self.resolve(ty_op.operand);
4854 const len_id = try self.constInt(Type.usize, array_ty.arrayLen(zcu), .direct);
4699 const len_id = try self.constInt(Type.usize, array_ty.arrayLen(zcu));
48554700
48564701 const elem_ptr_id = if (!array_ty.hasRuntimeBitsIgnoreComptime(zcu))
48574702 // Note: The pointer is something like *opaque{}, so we need to bitcast it to the element type.
......@@ -4860,11 +4705,8 @@ const NavGen = struct {
48604705 // Convert the pointer-to-array to a pointer to the first element.
48614706 try self.accessChain(elem_ptr_ty_id, array_ptr_id, &.{0});
48624707
4863 return try self.constructStruct(
4864 slice_ty,
4865 &.{ elem_ptr_ty, Type.usize },
4866 &.{ elem_ptr_id, len_id },
4867 );
4708 const slice_ty_id = try self.resolveType(slice_ty, .direct);
4709 return try self.constructComposite(slice_ty_id, &.{ elem_ptr_id, len_id });
48684710 }
48694711
48704712 fn airSlice(self: *NavGen, inst: Air.Inst.Index) !?IdRef {
......@@ -4872,16 +4714,9 @@ const NavGen = struct {
48724714 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
48734715 const ptr_id = try self.resolve(bin_op.lhs);
48744716 const len_id = try self.resolve(bin_op.rhs);
4875 const ptr_ty = self.typeOf(bin_op.lhs);
48764717 const slice_ty = self.typeOfIndex(inst);
4877
4878 // Note: Types should not need to be converted to direct, these types
4879 // dont need to be converted.
4880 return try self.constructStruct(
4881 slice_ty,
4882 &.{ ptr_ty, Type.usize },
4883 &.{ ptr_id, len_id },
4884 );
4718 const slice_ty_id = try self.resolveType(slice_ty, .direct);
4719 return try self.constructComposite(slice_ty_id, &.{ ptr_id, len_id });
48854720 }
48864721
48874722 fn airAggregateInit(self: *NavGen, inst: Air.Inst.Index) !?IdRef {
......@@ -4936,11 +4771,8 @@ const NavGen = struct {
49364771 else => unreachable,
49374772 }
49384773
4939 return try self.constructStruct(
4940 result_ty,
4941 types[0..index],
4942 constituents[0..index],
4943 );
4774 const result_ty_id = try self.resolveType(result_ty, .direct);
4775 return try self.constructComposite(result_ty_id, constituents[0..index]);
49444776 },
49454777 .vector => {
49464778 const n_elems = result_ty.vectorLen(zcu);
......@@ -4951,7 +4783,8 @@ const NavGen = struct {
49514783 elem_ids[i] = try self.resolve(element);
49524784 }
49534785
4954 return try self.constructVector(result_ty, elem_ids);
4786 const result_ty_id = try self.resolveType(result_ty, .direct);
4787 return try self.constructComposite(result_ty_id, elem_ids);
49554788 },
49564789 .array => {
49574790 const array_info = result_ty.arrayInfo(zcu);
......@@ -4968,7 +4801,8 @@ const NavGen = struct {
49684801 elem_ids[n_elems - 1] = try self.constant(array_info.elem_type, sentinel_val, .indirect);
49694802 }
49704803
4971 return try self.constructArray(result_ty, elem_ids);
4804 const result_ty_id = try self.resolveType(result_ty, .direct);
4805 return try self.constructComposite(result_ty_id, elem_ids);
49724806 },
49734807 else => unreachable,
49744808 }
......@@ -4984,7 +4818,7 @@ const NavGen = struct {
49844818 const elem_ty = array_ty.childType(zcu);
49854819 const abi_size = elem_ty.abiSize(zcu);
49864820 const size = array_ty.arrayLenIncludingSentinel(zcu) * abi_size;
4987 return try self.constInt(Type.usize, size, .direct);
4821 return try self.constInt(Type.usize, size);
49884822 },
49894823 .many, .c => unreachable,
49904824 }
......@@ -5060,7 +4894,7 @@ const NavGen = struct {
50604894 const zcu = self.pt.zcu;
50614895 // Construct new pointer type for the resulting pointer
50624896 const elem_ty = ptr_ty.elemType2(zcu); // use elemType() so that we get T for *[N]T.
5063 const elem_ptr_ty_id = try self.ptrType(elem_ty, self.spvStorageClass(ptr_ty.ptrAddressSpace(zcu)));
4897 const elem_ptr_ty_id = try self.ptrType(elem_ty, self.spvStorageClass(ptr_ty.ptrAddressSpace(zcu)), .indirect);
50644898 if (ptr_ty.isSinglePointer(zcu)) {
50654899 // Pointer-to-array. In this case, the resulting pointer is not of the same type
50664900 // as the ptr_ty (we want a *T, not a *[N]T), and hence we need to use accessChain.
......@@ -5115,8 +4949,8 @@ const NavGen = struct {
51154949 const is_vector = array_ty.isVector(zcu);
51164950
51174951 const elem_repr: Repr = if (is_vector) .direct else .indirect;
5118 const ptr_array_ty_id = try self.ptrType2(array_ty, .Function, .direct);
5119 const ptr_elem_ty_id = try self.ptrType2(elem_ty, .Function, elem_repr);
4952 const ptr_array_ty_id = try self.ptrType(array_ty, .Function, .direct);
4953 const ptr_elem_ty_id = try self.ptrType(elem_ty, .Function, elem_repr);
51204954
51214955 const tmp_id = self.spv.allocId();
51224956 try self.func.prologue.emit(self.spv.gpa, .OpVariable, .{
......@@ -5171,7 +5005,7 @@ const NavGen = struct {
51715005 const scalar_ty = vector_ty.scalarType(zcu);
51725006
51735007 const storage_class = self.spvStorageClass(vector_ptr_ty.ptrAddressSpace(zcu));
5174 const scalar_ptr_ty_id = try self.ptrType(scalar_ty, storage_class);
5008 const scalar_ptr_ty_id = try self.ptrType(scalar_ty, storage_class, .indirect);
51755009
51765010 const vector_ptr = try self.resolve(data.vector_ptr);
51775011 const index = try self.resolve(extra.lhs);
......@@ -5193,7 +5027,7 @@ const NavGen = struct {
51935027 if (layout.tag_size == 0) return;
51945028
51955029 const tag_ty = un_ty.unionTagTypeSafety(zcu).?;
5196 const tag_ptr_ty_id = try self.ptrType(tag_ty, self.spvStorageClass(un_ptr_ty.ptrAddressSpace(zcu)));
5030 const tag_ptr_ty_id = try self.ptrType(tag_ty, self.spvStorageClass(un_ptr_ty.ptrAddressSpace(zcu)), .indirect);
51975031
51985032 const union_ptr_id = try self.resolve(bin_op.lhs);
51995033 const new_tag_id = try self.resolve(bin_op.rhs);
......@@ -5252,23 +5086,23 @@ const NavGen = struct {
52525086 } else 0;
52535087
52545088 if (!layout.has_payload) {
5255 return try self.constInt(tag_ty, tag_int, .direct);
5089 return try self.constInt(tag_ty, tag_int);
52565090 }
52575091
52585092 const tmp_id = try self.alloc(ty, .{ .storage_class = .Function });
52595093
52605094 if (layout.tag_size != 0) {
5261 const tag_ptr_ty_id = try self.ptrType(tag_ty, .Function);
5095 const tag_ptr_ty_id = try self.ptrType(tag_ty, .Function, .indirect);
52625096 const ptr_id = try self.accessChain(tag_ptr_ty_id, tmp_id, &.{@as(u32, @intCast(layout.tag_index))});
5263 const tag_id = try self.constInt(tag_ty, tag_int, .direct);
5097 const tag_id = try self.constInt(tag_ty, tag_int);
52645098 try self.store(tag_ty, ptr_id, tag_id, .{});
52655099 }
52665100
52675101 const payload_ty = Type.fromInterned(union_ty.field_types.get(ip)[active_field]);
52685102 if (payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
5269 const pl_ptr_ty_id = try self.ptrType(layout.payload_ty, .Function);
5103 const pl_ptr_ty_id = try self.ptrType(layout.payload_ty, .Function, .indirect);
52705104 const pl_ptr_id = try self.accessChain(pl_ptr_ty_id, tmp_id, &.{layout.payload_index});
5271 const active_pl_ptr_ty_id = try self.ptrType(payload_ty, .Function);
5105 const active_pl_ptr_ty_id = try self.ptrType(payload_ty, .Function, .indirect);
52725106 const active_pl_ptr_id = self.spv.allocId();
52735107 try self.func.body.emit(self.spv.gpa, .OpBitcast, .{
52745108 .id_result_type = active_pl_ptr_ty_id,
......@@ -5332,10 +5166,10 @@ const NavGen = struct {
53325166 const tmp_id = try self.alloc(object_ty, .{ .storage_class = .Function });
53335167 try self.store(object_ty, tmp_id, object_id, .{});
53345168
5335 const pl_ptr_ty_id = try self.ptrType(layout.payload_ty, .Function);
5169 const pl_ptr_ty_id = try self.ptrType(layout.payload_ty, .Function, .indirect);
53365170 const pl_ptr_id = try self.accessChain(pl_ptr_ty_id, tmp_id, &.{layout.payload_index});
53375171
5338 const active_pl_ptr_ty_id = try self.ptrType(field_ty, .Function);
5172 const active_pl_ptr_ty_id = try self.ptrType(field_ty, .Function, .indirect);
53395173 const active_pl_ptr_id = self.spv.allocId();
53405174 try self.func.body.emit(self.spv.gpa, .OpBitcast, .{
53415175 .id_result_type = active_pl_ptr_ty_id,
......@@ -5365,7 +5199,7 @@ const NavGen = struct {
53655199 const base_ptr_int = base_ptr_int: {
53665200 if (field_offset == 0) break :base_ptr_int field_ptr_int;
53675201
5368 const field_offset_id = try self.constInt(Type.usize, field_offset, .direct);
5202 const field_offset_id = try self.constInt(Type.usize, field_offset);
53695203 const field_ptr_tmp = Temporary.init(Type.usize, field_ptr_int);
53705204 const field_offset_tmp = Temporary.init(Type.usize, field_offset_id);
53715205 const result = try self.buildBinary(.i_sub, field_ptr_tmp, field_offset_tmp);
......@@ -5415,7 +5249,7 @@ const NavGen = struct {
54155249 }
54165250
54175251 const storage_class = self.spvStorageClass(object_ptr_ty.ptrAddressSpace(zcu));
5418 const pl_ptr_ty_id = try self.ptrType(layout.payload_ty, storage_class);
5252 const pl_ptr_ty_id = try self.ptrType(layout.payload_ty, storage_class, .indirect);
54195253 const pl_ptr_id = try self.accessChain(pl_ptr_ty_id, object_ptr, &.{layout.payload_index});
54205254
54215255 const active_pl_ptr_id = self.spv.allocId();
......@@ -5456,7 +5290,7 @@ const NavGen = struct {
54565290 ty: Type,
54575291 options: AllocOptions,
54585292 ) !IdRef {
5459 const ptr_fn_ty_id = try self.ptrType(ty, .Function);
5293 const ptr_fn_ty_id = try self.ptrType(ty, .Function, .indirect);
54605294
54615295 // SPIR-V requires that OpVariable declarations for locals go into the first block, so we are just going to
54625296 // directly generate them into func.prologue instead of the body.
......@@ -5468,14 +5302,11 @@ const NavGen = struct {
54685302 .initializer = options.initializer,
54695303 });
54705304
5471 const target = self.getTarget();
5472 if (target.os.tag == .vulkan) {
5473 return var_id;
5474 }
5305 if (self.spv.hasFeature(.shader)) return var_id;
54755306
54765307 switch (options.storage_class) {
54775308 .Generic => {
5478 const ptr_gn_ty_id = try self.ptrType(ty, .Generic);
5309 const ptr_gn_ty_id = try self.ptrType(ty, .Generic, .indirect);
54795310 // Convert to a generic pointer
54805311 return self.castToGeneric(ptr_gn_ty_id, var_id);
54815312 },
......@@ -5724,7 +5555,7 @@ const NavGen = struct {
57245555 assert(cf.block_stack.items.len > 0);
57255556
57265557 // Check if the target of the branch was this current block.
5727 const this_block = try self.constInt(Type.u32, @intFromEnum(inst), .direct);
5558 const this_block = try self.constInt(Type.u32, @intFromEnum(inst));
57285559 const jump_to_this_block_id = self.spv.allocId();
57295560 const bool_ty_id = try self.resolveType(Type.bool, .direct);
57305561 try self.func.body.emit(self.spv.gpa, .OpIEqual, .{
......@@ -5804,7 +5635,7 @@ const NavGen = struct {
58045635 try self.store(operand_ty, block_result_var_id, operand_id, .{});
58055636 }
58065637
5807 const next_block = try self.constInt(Type.u32, @intFromEnum(br.block_inst), .direct);
5638 const next_block = try self.constInt(Type.u32, @intFromEnum(br.block_inst));
58085639 try self.structuredBreak(next_block);
58095640 },
58105641 .unstructured => |cf| {
......@@ -5968,7 +5799,7 @@ const NavGen = struct {
59685799 // Functions with an empty error set are emitted with an error code
59695800 // return type and return zero so they can be function pointers coerced
59705801 // to functions that return anyerror.
5971 const no_err_id = try self.constInt(Type.anyerror, 0, .direct);
5802 const no_err_id = try self.constInt(Type.anyerror, 0);
59725803 return try self.func.body.emit(self.spv.gpa, .OpReturnValue, .{ .value = no_err_id });
59735804 } else {
59745805 return try self.func.body.emit(self.spv.gpa, .OpReturn, {});
......@@ -5992,7 +5823,7 @@ const NavGen = struct {
59925823 // Functions with an empty error set are emitted with an error code
59935824 // return type and return zero so they can be function pointers coerced
59945825 // to functions that return anyerror.
5995 const no_err_id = try self.constInt(Type.anyerror, 0, .direct);
5826 const no_err_id = try self.constInt(Type.anyerror, 0);
59965827 return try self.func.body.emit(self.spv.gpa, .OpReturnValue, .{ .value = no_err_id });
59975828 } else {
59985829 return try self.func.body.emit(self.spv.gpa, .OpReturn, {});
......@@ -6026,7 +5857,7 @@ const NavGen = struct {
60265857 else
60275858 err_union_id;
60285859
6029 const zero_id = try self.constInt(Type.anyerror, 0, .direct);
5860 const zero_id = try self.constInt(Type.anyerror, 0);
60305861 const is_err_id = self.spv.allocId();
60315862 try self.func.body.emit(self.spv.gpa, .OpINotEqual, .{
60325863 .id_result_type = bool_ty_id,
......@@ -6134,7 +5965,8 @@ const NavGen = struct {
61345965 types[eu_layout.errorFieldIndex()] = Type.anyerror;
61355966 types[eu_layout.payloadFieldIndex()] = payload_ty;
61365967
6137 return try self.constructStruct(err_union_ty, &types, &members);
5968 const err_union_ty_id = try self.resolveType(err_union_ty, .direct);
5969 return try self.constructComposite(err_union_ty_id, &members);
61385970 }
61395971
61405972 fn airWrapErrUnionPayload(self: *NavGen, inst: Air.Inst.Index) !?IdRef {
......@@ -6145,18 +5977,19 @@ const NavGen = struct {
61455977 const eu_layout = self.errorUnionLayout(payload_ty);
61465978
61475979 if (!eu_layout.payload_has_bits) {
6148 return try self.constInt(Type.anyerror, 0, .direct);
5980 return try self.constInt(Type.anyerror, 0);
61495981 }
61505982
61515983 var members: [2]IdRef = undefined;
6152 members[eu_layout.errorFieldIndex()] = try self.constInt(Type.anyerror, 0, .direct);
5984 members[eu_layout.errorFieldIndex()] = try self.constInt(Type.anyerror, 0);
61535985 members[eu_layout.payloadFieldIndex()] = try self.convertToIndirect(payload_ty, operand_id);
61545986
61555987 var types: [2]Type = undefined;
61565988 types[eu_layout.errorFieldIndex()] = Type.anyerror;
61575989 types[eu_layout.payloadFieldIndex()] = payload_ty;
61585990
6159 return try self.constructStruct(err_union_ty, &types, &members);
5991 const err_union_ty_id = try self.resolveType(err_union_ty, .direct);
5992 return try self.constructComposite(err_union_ty_id, &members);
61605993 }
61615994
61625995 fn airIsNull(self: *NavGen, inst: Air.Inst.Index, is_pointer: bool, pred: enum { is_null, is_non_null }) !?IdRef {
......@@ -6204,7 +6037,7 @@ const NavGen = struct {
62046037 if (is_pointer) {
62056038 if (payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
62066039 const storage_class = self.spvStorageClass(operand_ty.ptrAddressSpace(zcu));
6207 const bool_ptr_ty_id = try self.ptrType(Type.bool, storage_class);
6040 const bool_ptr_ty_id = try self.ptrType(Type.bool, storage_class, .indirect);
62086041 const tag_ptr_id = try self.accessChain(bool_ptr_ty_id, operand_id, &.{1});
62096042 break :blk try self.load(Type.bool, tag_ptr_id, .{});
62106043 }
......@@ -6267,7 +6100,7 @@ const NavGen = struct {
62676100 .id_result_type = bool_ty_id,
62686101 .id_result = result_id,
62696102 .operand_1 = error_id,
6270 .operand_2 = try self.constInt(Type.anyerror, 0, .direct),
6103 .operand_2 = try self.constInt(Type.anyerror, 0),
62716104 },
62726105 ),
62736106 }
......@@ -6335,14 +6168,14 @@ const NavGen = struct {
63356168
63366169 const payload_id = try self.convertToIndirect(payload_ty, operand_id);
63376170 const members = [_]IdRef{ payload_id, try self.constBool(true, .indirect) };
6338 const types = [_]Type{ payload_ty, Type.bool };
6339 return try self.constructStruct(optional_ty, &types, &members);
6171 const optional_ty_id = try self.resolveType(optional_ty, .direct);
6172 return try self.constructComposite(optional_ty_id, &members);
63406173 }
63416174
63426175 fn airSwitchBr(self: *NavGen, inst: Air.Inst.Index) !void {
63436176 const pt = self.pt;
63446177 const zcu = pt.zcu;
6345 const target = self.getTarget();
6178 const target = self.spv.target;
63466179 const switch_br = self.air.unwrapSwitch(inst);
63476180 const cond_ty = self.typeOf(switch_br.operand);
63486181 const cond = try self.resolve(switch_br.operand);
......@@ -6605,9 +6438,8 @@ const NavGen = struct {
66056438
66066439 .undef => return self.fail("assembly input with 'c' constraint cannot be undefined", .{}),
66076440
6608 .int => {
6609 try as.value_map.put(as.gpa, name, .{ .constant = @intCast(val.toUnsignedInt(zcu)) });
6610 },
6441 .int => try as.value_map.put(as.gpa, name, .{ .constant = @intCast(val.toUnsignedInt(zcu)) }),
6442 .enum_literal => |str| try as.value_map.put(as.gpa, name, .{ .string = str.toSlice(ip) }),
66116443
66126444 else => unreachable, // TODO
66136445 }
......@@ -6689,7 +6521,7 @@ const NavGen = struct {
66896521 .just_declared, .unresolved_forward_reference => unreachable,
66906522 .ty => return self.fail("cannot return spir-v type as value from assembly", .{}),
66916523 .value => |ref| return ref,
6692 .constant => return self.fail("cannot return constant from assembly", .{}),
6524 .constant, .string => return self.fail("cannot return constant from assembly", .{}),
66936525 }
66946526
66956527 // TODO: Multiple results
......@@ -6752,13 +6584,13 @@ const NavGen = struct {
67526584
67536585 fn builtin3D(self: *NavGen, result_ty: Type, builtin: spec.BuiltIn, dimension: u32, out_of_range_value: anytype) !IdRef {
67546586 if (dimension >= 3) {
6755 return try self.constInt(result_ty, out_of_range_value, .direct);
6587 return try self.constInt(result_ty, out_of_range_value);
67566588 }
67576589 const vec_ty = try self.pt.vectorType(.{
67586590 .len = 3,
67596591 .child = result_ty.toIntern(),
67606592 });
6761 const ptr_ty_id = try self.ptrType(vec_ty, .Input);
6593 const ptr_ty_id = try self.ptrType(vec_ty, .Input, .indirect);
67626594 const spv_decl_index = try self.spv.builtin(ptr_ty_id, builtin);
67636595 try self.func.decl_deps.put(self.spv.gpa, spv_decl_index, {});
67646596 const ptr = self.spv.declPtr(spv_decl_index).result_id;
src/codegen/spirv/Assembler.zig+36
......@@ -135,6 +135,9 @@ const AsmValue = union(enum) {
135135 /// This is a pre-supplied constant integer value.
136136 constant: u32,
137137
138 /// This is a pre-supplied constant string value.
139 string: []const u8,
140
138141 /// Retrieve the result-id of this AsmValue. Asserts that this AsmValue
139142 /// is of a variant that allows the result to be obtained (not an unresolved
140143 /// forward declaration, not in the process of being declared, etc).
......@@ -144,6 +147,7 @@ const AsmValue = union(enum) {
144147 .unresolved_forward_reference,
145148 // TODO: Lower this value as constant?
146149 .constant,
150 .string,
147151 => unreachable,
148152 .value => |result| result,
149153 .ty => |result| result,
......@@ -274,6 +278,16 @@ fn processInstruction(self: *Assembler) !void {
274278 .OpEntryPoint => {
275279 return self.fail(0, "cannot export entry points via OpEntryPoint, export the kernel using callconv(.Kernel)", .{});
276280 },
281 .OpCapability => {
282 try self.spv.addCapability(@enumFromInt(self.inst.operands.items[0].value));
283 return;
284 },
285 .OpExtension => {
286 const ext_name_offset = self.inst.operands.items[0].string;
287 const ext_name = std.mem.sliceTo(self.inst.string_bytes.items[ext_name_offset..], 0);
288 try self.spv.addExtension(ext_name);
289 return;
290 },
277291 .OpExtInstImport => blk: {
278292 const set_name_offset = self.inst.operands.items[1].string;
279293 const set_name = std.mem.sliceTo(self.inst.string_bytes.items[set_name_offset..], 0);
......@@ -635,6 +649,28 @@ fn parseBitEnum(self: *Assembler, kind: spec.OperandKind) !void {
635649/// Also handles parsing any required extra operands.
636650fn parseValueEnum(self: *Assembler, kind: spec.OperandKind) !void {
637651 const tok = self.currentToken();
652 if (self.eatToken(.placeholder)) {
653 const name = self.tokenText(tok)[1..];
654 const value = self.value_map.get(name) orelse {
655 return self.fail(tok.start, "invalid placeholder '${s}'", .{name});
656 };
657 switch (value) {
658 .constant => |literal32| {
659 try self.inst.operands.append(self.gpa, .{ .value = literal32 });
660 },
661 .string => |str| {
662 const enumerant = for (kind.enumerants()) |enumerant| {
663 if (std.mem.eql(u8, enumerant.name, str)) break enumerant;
664 } else {
665 return self.fail(tok.start, "'{s}' is not a valid value for enumeration {s}", .{ str, @tagName(kind) });
666 };
667 try self.inst.operands.append(self.gpa, .{ .value = enumerant.value });
668 },
669 else => return self.fail(tok.start, "value '{s}' cannot be used as placeholder", .{name}),
670 }
671 return;
672 }
673
638674 try self.expectToken(.value);
639675
640676 const text = self.tokenText(tok);
src/codegen/spirv/Module.zig+181-26
......@@ -10,6 +10,8 @@ const Module = @This();
1010const std = @import("std");
1111const Allocator = std.mem.Allocator;
1212const assert = std.debug.assert;
13const autoHashStrat = std.hash.autoHashStrat;
14const Wyhash = std.hash.Wyhash;
1315
1416const spec = @import("spec.zig");
1517const Word = spec.Word;
......@@ -19,6 +21,19 @@ const IdResultType = spec.IdResultType;
1921
2022const Section = @import("Section.zig");
2123
24/// Helper HashMap type to hash deeply
25fn DeepHashMap(K: type, V: type) type {
26 return std.HashMapUnmanaged(K, V, struct {
27 pub fn hash(ctx: @This(), key: K) u64 {
28 _ = ctx;
29 var hasher = Wyhash.init(0);
30 autoHashStrat(&hasher, key, .Deep);
31 return hasher.final();
32 }
33 pub const eql = std.hash_map.getAutoEqlFn(K, @This());
34 }, std.hash_map.default_max_load_percentage);
35}
36
2237/// This structure represents a function that isc in-progress of being emitted.
2338/// Commonly, the contents of this structure will be merged with the appropriate
2439/// sections of the module and re-used. Note that the SPIR-V module system makes
......@@ -103,6 +118,12 @@ gpa: Allocator,
103118/// Arena for things that need to live for the length of this program.
104119arena: std.heap.ArenaAllocator,
105120
121/// Target info
122target: std.Target,
123
124/// The target SPIR-V version
125version: spec.Version,
126
106127/// Module layout, according to SPIR-V Spec section 2.4, "Logical Layout of a Module".
107128sections: struct {
108129 /// Capability instructions
......@@ -159,8 +180,16 @@ cache: struct {
159180 // This cache is required so that @Vector(X, u1) in direct representation has the
160181 // same ID as @Vector(X, bool) in indirect representation.
161182 vector_types: std.AutoHashMapUnmanaged(struct { IdRef, u32 }, IdRef) = .empty,
183 array_types: std.AutoHashMapUnmanaged(struct { IdRef, IdRef }, IdRef) = .empty,
184 function_types: DeepHashMap(struct { IdRef, []const IdRef }, IdRef) = .empty,
162185
186 capabilities: std.AutoHashMapUnmanaged(spec.Capability, void) = .empty,
187 extensions: std.StringHashMapUnmanaged(void) = .empty,
188 extended_instruction_set: std.AutoHashMapUnmanaged(spec.InstructionSet, IdRef) = .empty,
189 decorations: std.AutoHashMapUnmanaged(struct { IdRef, spec.Decoration }, void) = .empty,
163190 builtins: std.AutoHashMapUnmanaged(struct { IdRef, spec.BuiltIn }, Decl.Index) = .empty,
191
192 bool_const: [2]?IdRef = .{ null, null },
164193} = .{},
165194
166195/// Set of Decls, referred to by Decl.Index.
......@@ -173,13 +202,23 @@ decl_deps: std.ArrayListUnmanaged(Decl.Index) = .empty,
173202/// The list of entry points that should be exported from this module.
174203entry_points: std.ArrayListUnmanaged(EntryPoint) = .empty,
175204
176/// The list of extended instruction sets that should be imported.
177extended_instruction_set: std.AutoHashMapUnmanaged(spec.InstructionSet, IdRef) = .empty,
205pub fn init(gpa: Allocator, target: std.Target) Module {
206 const version_minor: u8 = blk: {
207 // Prefer higher versions
208 if (std.Target.spirv.featureSetHas(target.cpu.features, .v1_6)) break :blk 6;
209 if (std.Target.spirv.featureSetHas(target.cpu.features, .v1_5)) break :blk 5;
210 if (std.Target.spirv.featureSetHas(target.cpu.features, .v1_4)) break :blk 4;
211 if (std.Target.spirv.featureSetHas(target.cpu.features, .v1_3)) break :blk 3;
212 if (std.Target.spirv.featureSetHas(target.cpu.features, .v1_2)) break :blk 2;
213 if (std.Target.spirv.featureSetHas(target.cpu.features, .v1_1)) break :blk 1;
214 break :blk 0;
215 };
178216
179pub fn init(gpa: Allocator) Module {
180217 return .{
181218 .gpa = gpa,
182219 .arena = std.heap.ArenaAllocator.init(gpa),
220 .target = target,
221 .version = .{ .major = 1, .minor = version_minor },
183222 .next_result_id = 1, // 0 is an invalid SPIR-V result id, so start counting at 1.
184223 };
185224}
......@@ -201,14 +240,18 @@ pub fn deinit(self: *Module) void {
201240 self.cache.int_types.deinit(self.gpa);
202241 self.cache.float_types.deinit(self.gpa);
203242 self.cache.vector_types.deinit(self.gpa);
243 self.cache.array_types.deinit(self.gpa);
244 self.cache.function_types.deinit(self.gpa);
245 self.cache.capabilities.deinit(self.gpa);
246 self.cache.extensions.deinit(self.gpa);
247 self.cache.extended_instruction_set.deinit(self.gpa);
248 self.cache.decorations.deinit(self.gpa);
204249 self.cache.builtins.deinit(self.gpa);
205250
206251 self.decls.deinit(self.gpa);
207252 self.decl_deps.deinit(self.gpa);
208
209253 self.entry_points.deinit(self.gpa);
210254
211 self.extended_instruction_set.deinit(self.gpa);
212255 self.arena.deinit();
213256
214257 self.* = undefined;
......@@ -240,6 +283,10 @@ pub fn idBound(self: Module) Word {
240283 return self.next_result_id;
241284}
242285
286pub fn hasFeature(self: *Module, feature: std.Target.spirv.Feature) bool {
287 return std.Target.spirv.featureSetHas(self.target.cpu.features, feature);
288}
289
243290fn addEntryPointDeps(
244291 self: *Module,
245292 decl_index: Decl.Index,
......@@ -292,25 +339,68 @@ fn entryPoints(self: *Module) !Section {
292339 return entry_points;
293340}
294341
295pub fn finalize(self: *Module, a: Allocator, target: std.Target) ![]Word {
342pub fn finalize(self: *Module, a: Allocator) ![]Word {
343 // Emit capabilities and extensions
344 for (std.Target.spirv.all_features) |feature| {
345 if (self.target.cpu.features.isEnabled(feature.index)) {
346 const feature_tag: std.Target.spirv.Feature = @enumFromInt(feature.index);
347 switch (feature_tag) {
348 .v1_0, .v1_1, .v1_2, .v1_3, .v1_4, .v1_5, .v1_6 => {},
349 .int8 => try self.addCapability(.Int8),
350 .int16 => try self.addCapability(.Int16),
351 .int64 => try self.addCapability(.Int64),
352 .float16 => try self.addCapability(.Float16),
353 .float64 => try self.addCapability(.Float64),
354 .addresses => if (self.hasFeature(.shader)) {
355 try self.addCapability(.PhysicalStorageBufferAddresses);
356 try self.addExtension("SPV_KHR_physical_storage_buffer");
357 } else {
358 try self.addCapability(.Addresses);
359 },
360 .matrix => try self.addCapability(.Matrix),
361 .kernel => try self.addCapability(.Kernel),
362 .generic_pointer => try self.addCapability(.GenericPointer),
363 .vector16 => try self.addCapability(.Vector16),
364 .shader => try self.addCapability(.Shader),
365 }
366 }
367 }
368
369 // Emit memory model
370 const addressing_model: spec.AddressingModel = blk: {
371 if (self.hasFeature(.shader)) {
372 break :blk switch (self.target.cpu.arch) {
373 .spirv32 => .Logical, // TODO: I don't think this will ever be implemented.
374 .spirv64 => .PhysicalStorageBuffer64,
375 else => unreachable,
376 };
377 } else if (self.hasFeature(.kernel)) {
378 break :blk switch (self.target.cpu.arch) {
379 .spirv32 => .Physical32,
380 .spirv64 => .Physical64,
381 else => unreachable,
382 };
383 }
384
385 unreachable;
386 };
387 try self.sections.memory_model.emit(self.gpa, .OpMemoryModel, .{
388 .addressing_model = addressing_model,
389 .memory_model = switch (self.target.os.tag) {
390 .opencl => .OpenCL,
391 .vulkan, .opengl => .GLSL450,
392 else => unreachable,
393 },
394 });
395
296396 // See SPIR-V Spec section 2.3, "Physical Layout of a SPIR-V Module and Instruction"
297397 // TODO: Audit calls to allocId() in this function to make it idempotent.
298
299398 var entry_points = try self.entryPoints();
300399 defer entry_points.deinit(self.gpa);
301400
302401 const header = [_]Word{
303402 spec.magic_number,
304 // TODO: From cpu features
305 spec.Version.toWord(.{
306 .major = 1,
307 .minor = switch (target.os.tag) {
308 // Emit SPIR-V 1.3 for now. This is the highest version that Vulkan 1.1 supports.
309 .vulkan => 3,
310 // Emit SPIR-V 1.4 for now. This is the highest version that Intel's CPU OpenCL supports.
311 else => 4,
312 },
313 }),
403 self.version.toWord(),
314404 spec.zig_generator_id,
315405 self.idBound(),
316406 0, // Schema (currently reserved for future use)
......@@ -319,7 +409,7 @@ pub fn finalize(self: *Module, a: Allocator, target: std.Target) ![]Word {
319409 var source = Section{};
320410 defer source.deinit(self.gpa);
321411 try self.sections.debug_strings.emit(self.gpa, .OpSource, .{
322 .source_language = .Unknown,
412 .source_language = .Zig,
323413 .version = 0,
324414 // We cannot emit these because the Khronos translator does not parse this instruction
325415 // correctly.
......@@ -368,11 +458,23 @@ pub fn addFunction(self: *Module, decl_index: Decl.Index, func: Fn) !void {
368458 try self.declareDeclDeps(decl_index, func.decl_deps.keys());
369459}
370460
461pub fn addCapability(self: *Module, cap: spec.Capability) !void {
462 const entry = try self.cache.capabilities.getOrPut(self.gpa, cap);
463 if (entry.found_existing) return;
464 try self.sections.capabilities.emit(self.gpa, .OpCapability, .{ .capability = cap });
465}
466
467pub fn addExtension(self: *Module, ext: []const u8) !void {
468 const entry = try self.cache.extensions.getOrPut(self.gpa, ext);
469 if (entry.found_existing) return;
470 try self.sections.extensions.emit(self.gpa, .OpExtension, .{ .name = ext });
471}
472
371473/// Imports or returns the existing id of an extended instruction set
372474pub fn importInstructionSet(self: *Module, set: spec.InstructionSet) !IdRef {
373475 assert(set != .core);
374476
375 const gop = try self.extended_instruction_set.getOrPut(self.gpa, set);
477 const gop = try self.cache.extended_instruction_set.getOrPut(self.gpa, set);
376478 if (gop.found_existing) return gop.value_ptr.*;
377479
378480 const result_id = self.allocId();
......@@ -477,20 +579,69 @@ pub fn floatType(self: *Module, bits: u16) !IdRef {
477579 return entry.value_ptr.*;
478580}
479581
480pub fn vectorType(self: *Module, len: u32, child_id: IdRef) !IdRef {
481 const entry = try self.cache.vector_types.getOrPut(self.gpa, .{ child_id, len });
582pub fn vectorType(self: *Module, len: u32, child_ty_id: IdRef) !IdRef {
583 const entry = try self.cache.vector_types.getOrPut(self.gpa, .{ child_ty_id, len });
482584 if (!entry.found_existing) {
483585 const result_id = self.allocId();
484586 entry.value_ptr.* = result_id;
485587 try self.sections.types_globals_constants.emit(self.gpa, .OpTypeVector, .{
486588 .id_result = result_id,
487 .component_type = child_id,
589 .component_type = child_ty_id,
488590 .component_count = len,
489591 });
490592 }
491593 return entry.value_ptr.*;
492594}
493595
596pub fn arrayType(self: *Module, len_id: IdRef, child_ty_id: IdRef) !IdRef {
597 const entry = try self.cache.array_types.getOrPut(self.gpa, .{ child_ty_id, len_id });
598 if (!entry.found_existing) {
599 const result_id = self.allocId();
600 entry.value_ptr.* = result_id;
601 try self.sections.types_globals_constants.emit(self.gpa, .OpTypeArray, .{
602 .id_result = result_id,
603 .element_type = child_ty_id,
604 .length = len_id,
605 });
606 }
607 return entry.value_ptr.*;
608}
609
610pub fn functionType(self: *Module, return_ty_id: IdRef, param_type_ids: []const IdRef) !IdRef {
611 const entry = try self.cache.function_types.getOrPut(self.gpa, .{ return_ty_id, param_type_ids });
612 if (!entry.found_existing) {
613 const result_id = self.allocId();
614 entry.value_ptr.* = result_id;
615 try self.sections.types_globals_constants.emit(self.gpa, .OpTypeFunction, .{
616 .id_result = result_id,
617 .return_type = return_ty_id,
618 .id_ref_2 = param_type_ids,
619 });
620 }
621 return entry.value_ptr.*;
622}
623
624pub fn constBool(self: *Module, value: bool) !IdRef {
625 if (self.cache.bool_const[@intFromBool(value)]) |b| return b;
626
627 const result_ty_id = try self.boolType();
628 const result_id = self.allocId();
629 self.cache.bool_const[@intFromBool(value)] = result_id;
630
631 switch (value) {
632 inline else => |value_ct| try self.sections.types_globals_constants.emit(
633 self.gpa,
634 if (value_ct) .OpConstantTrue else .OpConstantFalse,
635 .{
636 .id_result_type = result_ty_id,
637 .id_result = result_id,
638 },
639 ),
640 }
641
642 return result_id;
643}
644
494645/// Return a pointer to a builtin variable. `result_ty_id` must be a **pointer**
495646/// with storage class `.Input`.
496647pub fn builtin(self: *Module, result_ty_id: IdRef, spirv_builtin: spec.BuiltIn) !Decl.Index {
......@@ -534,13 +685,17 @@ pub fn decorate(
534685 target: IdRef,
535686 decoration: spec.Decoration.Extended,
536687) !void {
537 try self.sections.annotations.emit(self.gpa, .OpDecorate, .{
538 .target = target,
539 .decoration = decoration,
540 });
688 const entry = try self.cache.decorations.getOrPut(self.gpa, .{ target, decoration });
689 if (!entry.found_existing) {
690 try self.sections.annotations.emit(self.gpa, .OpDecorate, .{
691 .target = target,
692 .decoration = decoration,
693 });
694 }
541695}
542696
543697/// Decorate a result-id which is a member of some struct.
698/// We really don't have to and shouldn't need to cache this.
544699pub fn decorateMember(
545700 self: *Module,
546701 structure_type: IdRef,
src/link/SpirV.zig+3-63
......@@ -75,7 +75,7 @@ pub fn createEmpty(
7575 .disable_lld_caching = options.disable_lld_caching,
7676 .build_id = options.build_id,
7777 },
78 .object = codegen.Object.init(gpa),
78 .object = codegen.Object.init(gpa, comp.getTarget()),
7979 };
8080 errdefer self.deinit();
8181
......@@ -172,7 +172,7 @@ pub fn updateExports(
172172 const spv_decl_index = try self.object.resolveNav(zcu, nav_index);
173173 const cc = Type.fromInterned(nav_ty).fnCallingConvention(zcu);
174174 const execution_model: spec.ExecutionModel = switch (target.os.tag) {
175 .vulkan => switch (cc) {
175 .vulkan, .opengl => switch (cc) {
176176 .spirv_vertex => .Vertex,
177177 .spirv_fragment => .Fragment,
178178 .spirv_kernel => .GLCompute,
......@@ -231,15 +231,10 @@ pub fn flushModule(
231231 const spv = &self.object.spv;
232232 const diags = &comp.link_diags;
233233 const gpa = comp.gpa;
234 const target = comp.getTarget();
235
236 try writeCapabilities(spv, target);
237 try writeMemoryModel(spv, target);
238234
239235 // We need to export the list of error names somewhere so that we can pretty-print them in the
240236 // executor. This is not really an important thing though, so we can just dump it in any old
241237 // nonsemantic instruction. For now, just put it in OpSourceExtension with a special name.
242
243238 var error_info = std.ArrayList(u8).init(self.object.gpa);
244239 defer error_info.deinit();
245240
......@@ -269,7 +264,7 @@ pub fn flushModule(
269264 .extension = error_info.items,
270265 });
271266
272 const module = try spv.finalize(arena, target);
267 const module = try spv.finalize(arena);
273268 errdefer arena.free(module);
274269
275270 const linked_module = self.linkModule(arena, module, sub_prog_node) catch |err| switch (err) {
......@@ -298,58 +293,3 @@ fn linkModule(self: *SpirV, a: Allocator, module: []Word, progress: std.Progress
298293
299294 return binary.finalize(a);
300295}
301
302fn writeCapabilities(spv: *SpvModule, target: std.Target) !void {
303 const gpa = spv.gpa;
304 // TODO: Integrate with a hypothetical feature system
305 const caps: []const spec.Capability = switch (target.os.tag) {
306 .opencl => &.{ .Kernel, .Addresses, .Int8, .Int16, .Int64, .Float64, .Float16, .Vector16, .GenericPointer },
307 .vulkan => &.{ .Shader, .PhysicalStorageBufferAddresses, .Int8, .Int16, .Int64, .Float64, .Float16, .VariablePointers, .VariablePointersStorageBuffer },
308 else => unreachable,
309 };
310
311 for (caps) |cap| {
312 try spv.sections.capabilities.emit(gpa, .OpCapability, .{
313 .capability = cap,
314 });
315 }
316
317 switch (target.os.tag) {
318 .vulkan => {
319 try spv.sections.extensions.emit(gpa, .OpExtension, .{
320 .name = "SPV_KHR_physical_storage_buffer",
321 });
322 },
323 else => {},
324 }
325}
326
327fn writeMemoryModel(spv: *SpvModule, target: std.Target) !void {
328 const gpa = spv.gpa;
329
330 const addressing_model: spec.AddressingModel = switch (target.os.tag) {
331 .opencl => switch (target.cpu.arch) {
332 .spirv32 => .Physical32,
333 .spirv64 => .Physical64,
334 else => unreachable,
335 },
336 .opengl, .vulkan => switch (target.cpu.arch) {
337 .spirv32 => .Logical, // TODO: I don't think this will ever be implemented.
338 .spirv64 => .PhysicalStorageBuffer64,
339 else => unreachable,
340 },
341 else => unreachable,
342 };
343
344 const memory_model: spec.MemoryModel = switch (target.os.tag) {
345 .opencl => .OpenCL,
346 .opengl => .GLSL450,
347 .vulkan => .GLSL450,
348 else => unreachable,
349 };
350
351 try spv.sections.memory_model.emit(gpa, .OpMemoryModel, .{
352 .addressing_model = addressing_model,
353 .memory_model = memory_model,
354 });
355}
src/link/SpirV/deduplicate.zig+1-1
......@@ -155,7 +155,7 @@ const ModuleInfo = struct {
155155 }
156156 }
157157
158 return ModuleInfo{
158 return .{
159159 .entities = entities.unmanaged,
160160 .operand_is_id = operand_is_id,
161161 // There may be unrelated decorations at the end, so make sure to
src/link/SpirV/prune_unused.zig+1-1
......@@ -166,7 +166,7 @@ const ModuleInfo = struct {
166166 return error.InvalidPhysicalFormat;
167167 }
168168
169 return ModuleInfo{
169 return .{
170170 .functions = functions.unmanaged,
171171 .callee_store = callee_store.items,
172172 .result_id_to_code_offset = result_id_to_code_offset.unmanaged,
test/standalone/build.zig-1
......@@ -43,7 +43,6 @@ pub fn build(b: *std.Build) void {
4343 "../../tools/update_clang_options.zig",
4444 "../../tools/update_cpu_features.zig",
4545 "../../tools/update_glibc.zig",
46 "../../tools/update_spirv_features.zig",
4746 }) |tool_src_path| {
4847 const tool = b.addTest(.{
4948 .name = std.fs.path.stem(tool_src_path),
tools/update_cpu_features.zig-7
......@@ -1072,13 +1072,6 @@ const targets = [_]ArchTarget{
10721072 .td_name = "Sparc",
10731073 },
10741074 },
1075 // TODO: merge tools/update_spirv_features.zig into this script
1076 //.{
1077 // .zig_name = "spirv",
1078 // .llvm = .{
1079 // .name = "SPIRV",
1080 // },
1081 //},
10821075 .{
10831076 .zig_name = "s390x",
10841077 .llvm = .{
tools/update_spirv_features.zig deleted-328
......@@ -1,328 +0,0 @@
1//! This tool generates SPIR-V features from the grammar files in the SPIRV-Headers
2//! (https://github.com/KhronosGroup/SPIRV-Headers/) and SPIRV-Registry (https://github.com/KhronosGroup/SPIRV-Registry/)
3//! repositories. Currently it only generates a basic feature set definition consisting of versions, extensions and capabilities.
4//! There is a lot left to be desired, as currently dependencies of extensions and dependencies on extensions aren't generated.
5//! This is because there are some peculiarities in the SPIR-V registries:
6//! - Capabilities may depend on multiple extensions, which cannot be modelled yet by std.Target.
7//! - Extension dependencies are not documented in a machine-readable manner.
8//! - Note that the grammar spec also contains definitions from extensions which aren't actually official. Most of these seem to be
9//! from an intel project (https://github.com/intel/llvm/, https://github.com/intel/llvm/tree/sycl/sycl/doc/extensions/SPIRV),
10//! and so ONLY extensions in the SPIRV-Registry should be included.
11
12const std = @import("std");
13const fs = std.fs;
14const Allocator = std.mem.Allocator;
15const g = @import("spirv/grammar.zig");
16
17const Version = struct {
18 major: u32,
19 minor: u32,
20
21 fn parse(str: []const u8) !Version {
22 var it = std.mem.splitScalar(u8, str, '.');
23
24 const major = it.first();
25 const minor = it.next() orelse return error.InvalidVersion;
26
27 if (it.next() != null) return error.InvalidVersion;
28
29 return Version{
30 .major = std.fmt.parseInt(u32, major, 10) catch return error.InvalidVersion,
31 .minor = std.fmt.parseInt(u32, minor, 10) catch return error.InvalidVersion,
32 };
33 }
34
35 fn eql(a: Version, b: Version) bool {
36 return a.major == b.major and a.minor == b.minor;
37 }
38
39 fn lessThan(ctx: void, a: Version, b: Version) bool {
40 _ = ctx;
41 return if (a.major == b.major)
42 a.minor < b.minor
43 else
44 a.major < b.major;
45 }
46};
47
48pub fn main() !void {
49 var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
50 defer arena.deinit();
51 const allocator = arena.allocator();
52
53 const args = try std.process.argsAlloc(allocator);
54
55 if (args.len <= 1) {
56 usageAndExit(std.io.getStdErr(), args[0], 1);
57 }
58 if (std.mem.eql(u8, args[1], "--help")) {
59 usageAndExit(std.io.getStdErr(), args[0], 0);
60 }
61 if (args.len != 3) {
62 usageAndExit(std.io.getStdErr(), args[0], 1);
63 }
64
65 const spirv_headers_root = args[1];
66 const spirv_registry_root = args[2];
67
68 if (std.mem.startsWith(u8, spirv_headers_root, "-") or std.mem.startsWith(u8, spirv_registry_root, "-")) {
69 usageAndExit(std.io.getStdErr(), args[0], 1);
70 }
71
72 // Required for json parsing.
73 @setEvalBranchQuota(10000);
74
75 const registry_path = try fs.path.join(allocator, &.{ spirv_headers_root, "include", "spirv", "unified1", "spirv.core.grammar.json" });
76 const registry_json = try std.fs.cwd().readFileAlloc(allocator, registry_path, std.math.maxInt(usize));
77 var scanner = std.json.Scanner.initCompleteInput(allocator, registry_json);
78 var diagnostics = std.json.Diagnostics{};
79 scanner.enableDiagnostics(&diagnostics);
80 const registry = std.json.parseFromTokenSourceLeaky(g.CoreRegistry, allocator, &scanner, .{}) catch |err| {
81 std.debug.print("line,col: {},{}\n", .{ diagnostics.getLine(), diagnostics.getColumn() });
82 return err;
83 };
84
85 const capabilities = for (registry.operand_kinds) |opkind| {
86 if (std.mem.eql(u8, opkind.kind, "Capability"))
87 break opkind.enumerants orelse return error.InvalidRegistry;
88 } else return error.InvalidRegistry;
89
90 const extensions = try gather_extensions(allocator, spirv_registry_root);
91 const versions = try gatherVersions(allocator, registry);
92
93 var bw = std.io.bufferedWriter(std.io.getStdOut().writer());
94 const w = bw.writer();
95
96 try w.writeAll(
97 \\//! This file is auto-generated by tools/update_spirv_features.zig.
98 \\//! TODO: Dependencies of capabilities on extensions.
99 \\//! TODO: Dependencies of extensions on extensions.
100 \\//! TODO: Dependencies of extensions on versions.
101 \\
102 \\const std = @import("../std.zig");
103 \\const CpuFeature = std.Target.Cpu.Feature;
104 \\const CpuModel = std.Target.Cpu.Model;
105 \\
106 \\pub const Feature = enum {
107 \\
108 );
109
110 for (versions) |ver| {
111 try w.print(" v{}_{},\n", .{ ver.major, ver.minor });
112 }
113
114 for (extensions) |ext| {
115 try w.print(" {p},\n", .{std.zig.fmtId(ext)});
116 }
117
118 for (capabilities) |cap| {
119 try w.print(" {p},\n", .{std.zig.fmtId(cap.enumerant)});
120 }
121
122 try w.writeAll(
123 \\};
124 \\
125 \\pub const featureSet = CpuFeature.FeatureSetFns(Feature).featureSet;
126 \\pub const featureSetHas = CpuFeature.FeatureSetFns(Feature).featureSetHas;
127 \\pub const featureSetHasAny = CpuFeature.FeatureSetFns(Feature).featureSetHasAny;
128 \\pub const featureSetHasAll = CpuFeature.FeatureSetFns(Feature).featureSetHasAll;
129 \\
130 \\pub const all_features = blk: {
131 \\ @setEvalBranchQuota(2000);
132 \\ const len = @typeInfo(Feature).@"enum".fields.len;
133 \\ std.debug.assert(len <= CpuFeature.Set.needed_bit_count);
134 \\ var result: [len]CpuFeature = undefined;
135 \\
136 );
137
138 for (versions, 0..) |ver, i| {
139 try w.print(
140 \\ result[@intFromEnum(Feature.v{0}_{1})] = .{{
141 \\ .llvm_name = null,
142 \\ .description = "SPIR-V version {0}.{1}",
143 \\
144 , .{ ver.major, ver.minor });
145
146 if (i == 0) {
147 try w.writeAll(
148 \\ .dependencies = featureSet(&[_]Feature{}),
149 \\ };
150 \\
151 );
152 } else {
153 try w.print(
154 \\ .dependencies = featureSet(&[_]Feature{{
155 \\ .v{}_{},
156 \\ }}),
157 \\ }};
158 \\
159 , .{ versions[i - 1].major, versions[i - 1].minor });
160 }
161 }
162
163 // TODO: Extension dependencies.
164 for (extensions) |ext| {
165 try w.print(
166 \\ result[@intFromEnum(Feature.{p_})] = .{{
167 \\ .llvm_name = null,
168 \\ .description = "SPIR-V extension {s}",
169 \\ .dependencies = featureSet(&[_]Feature{{}}),
170 \\ }};
171 \\
172 , .{
173 std.zig.fmtId(ext),
174 ext,
175 });
176 }
177
178 // TODO: Capability extension dependencies.
179 for (capabilities) |cap| {
180 try w.print(
181 \\ result[@intFromEnum(Feature.{p_})] = .{{
182 \\ .llvm_name = null,
183 \\ .description = "Enable SPIR-V capability {s}",
184 \\ .dependencies = featureSet(&[_]Feature{{
185 \\
186 , .{
187 std.zig.fmtId(cap.enumerant),
188 cap.enumerant,
189 });
190
191 if (cap.version) |ver_str| {
192 if (!std.mem.eql(u8, ver_str, "None")) {
193 const ver = try Version.parse(ver_str);
194 try w.print(" .v{}_{},\n", .{ ver.major, ver.minor });
195 }
196 }
197
198 for (cap.capabilities) |cap_dep| {
199 try w.print(" .{p_},\n", .{std.zig.fmtId(cap_dep)});
200 }
201
202 try w.writeAll(
203 \\ }),
204 \\ };
205 \\
206 );
207 }
208
209 try w.writeAll(
210 \\ const ti = @typeInfo(Feature);
211 \\ for (&result, 0..) |*elem, i| {
212 \\ elem.index = i;
213 \\ elem.name = ti.@"enum".fields[i].name;
214 \\ }
215 \\ break :blk result;
216 \\};
217 \\
218 );
219
220 try bw.flush();
221}
222
223/// SPIRV-Registry should hold all extensions currently registered for SPIR-V.
224/// The *.grammar.json in SPIRV-Headers should have most of these as well, but with this we're sure to get only the actually
225/// registered ones.
226/// TODO: Unfortunately, neither repository contains a machine-readable list of extension dependencies.
227fn gather_extensions(allocator: Allocator, spirv_registry_root: []const u8) ![]const []const u8 {
228 const extensions_path = try fs.path.join(allocator, &.{ spirv_registry_root, "extensions" });
229 var extensions_dir = try fs.cwd().openDir(extensions_path, .{ .iterate = true });
230 defer extensions_dir.close();
231
232 var extensions = std.ArrayList([]const u8).init(allocator);
233
234 var vendor_it = extensions_dir.iterate();
235 while (try vendor_it.next()) |vendor_entry| {
236 std.debug.assert(vendor_entry.kind == .directory); // If this fails, the structure of SPIRV-Registry has changed.
237
238 const vendor_dir = try extensions_dir.openDir(vendor_entry.name, .{ .iterate = true });
239 var ext_it = vendor_dir.iterate();
240 while (try ext_it.next()) |ext_entry| {
241 // There is both a HTML and asciidoc version of every spec (as well as some other directories),
242 // we need just the name, but to avoid duplicates here we will just skip anything thats not asciidoc.
243 if (!std.mem.endsWith(u8, ext_entry.name, ".asciidoc"))
244 continue;
245
246 // Unfortunately, some extension filenames are incorrect, so we need to look for the string in the 'Name Strings' section.
247 // This has the following format:
248 // ```
249 // Name Strings
250 // ------------
251 //
252 // SPV_EXT_name
253 // ```
254 // OR
255 // ```
256 // == Name Strings
257 //
258 // SPV_EXT_name
259 // ```
260
261 const ext_spec = try vendor_dir.readFileAlloc(allocator, ext_entry.name, std.math.maxInt(usize));
262 const name_strings = "Name Strings";
263
264 const name_strings_offset = std.mem.indexOf(u8, ext_spec, name_strings) orelse return error.InvalidRegistry;
265
266 // As the specs are inconsistent on this next part, just skip any newlines/minuses
267 var ext_start = name_strings_offset + name_strings.len + 1;
268 while (ext_spec[ext_start] == '\n' or ext_spec[ext_start] == '-') {
269 ext_start += 1;
270 }
271
272 const ext_end = std.mem.indexOfScalarPos(u8, ext_spec, ext_start, '\n') orelse return error.InvalidRegistry;
273 const ext = ext_spec[ext_start..ext_end];
274
275 std.debug.assert(std.mem.startsWith(u8, ext, "SPV_")); // Sanity check, all extensions should have a name like SPV_VENDOR_extension.
276
277 try extensions.append(try allocator.dupe(u8, ext));
278 }
279 }
280
281 return extensions.items;
282}
283
284fn insertVersion(versions: *std.ArrayList(Version), version: ?[]const u8) !void {
285 const ver_str = version orelse return;
286 if (std.mem.eql(u8, ver_str, "None"))
287 return;
288
289 const ver = try Version.parse(ver_str);
290 for (versions.items) |existing_ver| {
291 if (ver.eql(existing_ver)) return;
292 }
293
294 try versions.append(ver);
295}
296
297fn gatherVersions(allocator: Allocator, registry: g.CoreRegistry) ![]const Version {
298 // Expected number of versions is small
299 var versions = std.ArrayList(Version).init(allocator);
300
301 for (registry.instructions) |inst| {
302 try insertVersion(&versions, inst.version);
303 }
304
305 for (registry.operand_kinds) |opkind| {
306 const enumerants = opkind.enumerants orelse continue;
307 for (enumerants) |enumerant| {
308 try insertVersion(&versions, enumerant.version);
309 }
310 }
311
312 std.mem.sort(Version, versions.items, {}, Version.lessThan);
313
314 return versions.items;
315}
316
317fn usageAndExit(file: fs.File, arg0: []const u8, code: u8) noreturn {
318 file.writer().print(
319 \\Usage: {s} /path/git/SPIRV-Headers /path/git/SPIRV-Registry
320 \\
321 \\Prints to stdout Zig code which can be used to replace the file lib/std/target/spirv.zig.
322 \\
323 \\SPIRV-Headers can be cloned from https://github.com/KhronosGroup/SPIRV-Headers,
324 \\SPIRV-Registry can be cloned from https://github.com/KhronosGroup/SPIRV-Registry.
325 \\
326 , .{arg0}) catch std.process.exit(1);
327 std.process.exit(code);
328}