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,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
6const std = @import("../std.zig");1const std = @import("../std.zig");
7const CpuFeature = std.Target.Cpu.Feature;2const CpuFeature = std.Target.Cpu.Feature;
8const CpuModel = std.Target.Cpu.Model;3const CpuModel = std.Target.Cpu.Model;
94
10pub const Feature = enum {5pub const Feature = enum {
6 v1_0,
11 v1_1,7 v1_1,
12 v1_2,8 v1_2,
13 v1_3,9 v1_3,
14 v1_4,10 v1_4,
15 v1_5,11 v1_5,
16 SPV_AMD_shader_fragment_mask,12 v1_6,
17 SPV_AMD_gpu_shader_int16,13 int8,
18 SPV_AMD_gpu_shader_half_float,14 int16,
19 SPV_AMD_texture_gather_bias_lod,15 int64,
20 SPV_AMD_shader_ballot,16 float16,
21 SPV_AMD_gcn_shader,17 float64,
22 SPV_AMD_shader_image_load_store_lod,18 addresses,
23 SPV_AMD_shader_explicit_vertex_parameter,19 matrix,
24 SPV_AMD_shader_trinary_minmax,20 kernel,
25 SPV_AMD_gpu_shader_half_float_fetch,21 generic_pointer,
26 SPV_GOOGLE_hlsl_functionality1,22 vector16,
27 SPV_GOOGLE_user_type,23 shader,
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,
295};24};
29625
297pub const featureSet = CpuFeature.FeatureSetFns(Feature).featureSet;26pub const featureSet = CpuFeature.FeatureSetFns(Feature).featureSet;
...@@ -304,1788 +33,120 @@ pub const all_features = blk: {...@@ -304,1788 +33,120 @@ pub const all_features = blk: {
304 const len = @typeInfo(Feature).@"enum".fields.len;33 const len = @typeInfo(Feature).@"enum".fields.len;
305 std.debug.assert(len <= CpuFeature.Set.needed_bit_count);34 std.debug.assert(len <= CpuFeature.Set.needed_bit_count);
306 var result: [len]CpuFeature = undefined;35 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 };
307 result[@intFromEnum(Feature.v1_1)] = .{41 result[@intFromEnum(Feature.v1_1)] = .{
308 .llvm_name = null,42 .llvm_name = null,
309 .description = "SPIR-V version 1.1",43 .description = "SPIR-V version 1.1",
310 .dependencies = featureSet(&[_]Feature{}),44 .dependencies = featureSet(&[_]Feature{.v1_0}),
311 };45 };
312 result[@intFromEnum(Feature.v1_2)] = .{46 result[@intFromEnum(Feature.v1_2)] = .{
313 .llvm_name = null,47 .llvm_name = null,
314 .description = "SPIR-V version 1.2",48 .description = "SPIR-V version 1.2",
315 .dependencies = featureSet(&[_]Feature{49 .dependencies = featureSet(&[_]Feature{.v1_1}),
316 .v1_1,
317 }),
318 };50 };
319 result[@intFromEnum(Feature.v1_3)] = .{51 result[@intFromEnum(Feature.v1_3)] = .{
320 .llvm_name = null,52 .llvm_name = null,
321 .description = "SPIR-V version 1.3",53 .description = "SPIR-V version 1.3",
322 .dependencies = featureSet(&[_]Feature{54 .dependencies = featureSet(&[_]Feature{.v1_2}),
323 .v1_2,
324 }),
325 };55 };
326 result[@intFromEnum(Feature.v1_4)] = .{56 result[@intFromEnum(Feature.v1_4)] = .{
327 .llvm_name = null,57 .llvm_name = null,
328 .description = "SPIR-V version 1.4",58 .description = "SPIR-V version 1.4",
329 .dependencies = featureSet(&[_]Feature{59 .dependencies = featureSet(&[_]Feature{.v1_3}),
330 .v1_3,
331 }),
332 };60 };
333 result[@intFromEnum(Feature.v1_5)] = .{61 result[@intFromEnum(Feature.v1_5)] = .{
334 .llvm_name = null,62 .llvm_name = null,
335 .description = "SPIR-V version 1.5",63 .description = "SPIR-V version 1.5",
336 .dependencies = featureSet(&[_]Feature{64 .dependencies = featureSet(&[_]Feature{.v1_4}),
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{}),
544 };65 };
545 result[@intFromEnum(Feature.SPV_KHR_8bit_storage)] = .{66 result[@intFromEnum(Feature.v1_6)] = .{
546 .llvm_name = null,67 .llvm_name = null,
547 .description = "SPIR-V extension SPV_KHR_8bit_storage",68 .description = "SPIR-V version 1.6",
548 .dependencies = featureSet(&[_]Feature{}),69 .dependencies = featureSet(&[_]Feature{.v1_5}),
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{}),
654 };70 };
655 result[@intFromEnum(Feature.SPV_KHR_ray_query)] = .{71 result[@intFromEnum(Feature.int8)] = .{
656 .llvm_name = null,72 .llvm_name = null,
657 .description = "SPIR-V extension SPV_KHR_ray_query",73 .description = "Enable SPIR-V capability Int8",
658 .dependencies = featureSet(&[_]Feature{}),74 .dependencies = featureSet(&[_]Feature{.v1_0}),
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{}),
694 };75 };
695 result[@intFromEnum(Feature.SPV_NV_stereo_view_rendering)] = .{76 result[@intFromEnum(Feature.int16)] = .{
696 .llvm_name = null,77 .llvm_name = null,
697 .description = "SPIR-V extension SPV_NV_stereo_view_rendering",78 .description = "Enable SPIR-V capability Int16",
698 .dependencies = featureSet(&[_]Feature{}),79 .dependencies = featureSet(&[_]Feature{.v1_0}),
699 };80 };
700 result[@intFromEnum(Feature.SPV_NV_compute_shader_derivatives)] = .{81 result[@intFromEnum(Feature.int64)] = .{
701 .llvm_name = null,82 .llvm_name = null,
702 .description = "SPIR-V extension SPV_NV_compute_shader_derivatives",83 .description = "Enable SPIR-V capability Int64",
703 .dependencies = featureSet(&[_]Feature{}),84 .dependencies = featureSet(&[_]Feature{.v1_0}),
704 };85 };
705 result[@intFromEnum(Feature.SPV_NV_shader_sm_builtins)] = .{86 result[@intFromEnum(Feature.float16)] = .{
706 .llvm_name = null,87 .llvm_name = null,
707 .description = "SPIR-V extension SPV_NV_shader_sm_builtins",88 .description = "Enable SPIR-V capability Float16",
708 .dependencies = featureSet(&[_]Feature{}),89 .dependencies = featureSet(&[_]Feature{.v1_0}),
709 };90 };
710 result[@intFromEnum(Feature.SPV_NV_mesh_shader)] = .{91 result[@intFromEnum(Feature.float64)] = .{
711 .llvm_name = null,92 .llvm_name = null,
712 .description = "SPIR-V extension SPV_NV_mesh_shader",93 .description = "Enable SPIR-V capability Float64",
713 .dependencies = featureSet(&[_]Feature{}),94 .dependencies = featureSet(&[_]Feature{.v1_0}),
714 };95 };
715 result[@intFromEnum(Feature.SPV_NV_geometry_shader_passthrough)] = .{96 result[@intFromEnum(Feature.addresses)] = .{
716 .llvm_name = null,97 .llvm_name = null,
717 .description = "SPIR-V extension SPV_NV_geometry_shader_passthrough",98 .description = "Enable SPIR-V capability Addresses",
718 .dependencies = featureSet(&[_]Feature{}),99 .dependencies = featureSet(&[_]Feature{.v1_0}),
719 };100 };
720 result[@intFromEnum(Feature.SPV_NV_fragment_shader_barycentric)] = .{101 result[@intFromEnum(Feature.matrix)] = .{
721 .llvm_name = null,102 .llvm_name = null,
722 .description = "SPIR-V extension SPV_NV_fragment_shader_barycentric",103 .description = "Enable SPIR-V capability Matrix",
723 .dependencies = featureSet(&[_]Feature{}),104 .dependencies = featureSet(&[_]Feature{.v1_0}),
724 };105 };
725 result[@intFromEnum(Feature.SPV_NV_cooperative_matrix)] = .{106 result[@intFromEnum(Feature.kernel)] = .{
726 .llvm_name = null,107 .llvm_name = null,
727 .description = "SPIR-V extension SPV_NV_cooperative_matrix",108 .description = "Enable SPIR-V capability Kernel",
728 .dependencies = featureSet(&[_]Feature{}),109 .dependencies = featureSet(&[_]Feature{.v1_0}),
729 };110 };
730 result[@intFromEnum(Feature.SPV_NV_sample_mask_override_coverage)] = .{111 result[@intFromEnum(Feature.generic_pointer)] = .{
731 .llvm_name = null,112 .llvm_name = null,
732 .description = "SPIR-V extension SPV_NV_sample_mask_override_coverage",113 .description = "Enable SPIR-V capability GenericPointer",
733 .dependencies = featureSet(&[_]Feature{}),114 .dependencies = featureSet(&[_]Feature{ .v1_0, .addresses }),
734 };115 };
735 result[@intFromEnum(Feature.Matrix)] = .{116 result[@intFromEnum(Feature.vector16)] = .{
736 .llvm_name = null,117 .llvm_name = null,
737 .description = "Enable SPIR-V capability Matrix",118 .description = "Enable SPIR-V capability Vector16",
738 .dependencies = featureSet(&[_]Feature{}),119 .dependencies = featureSet(&[_]Feature{ .v1_0, .kernel }),
739 };120 };
740 result[@intFromEnum(Feature.Shader)] = .{121 result[@intFromEnum(Feature.shader)] = .{
741 .llvm_name = null,122 .llvm_name = null,
742 .description = "Enable SPIR-V capability Shader",123 .description = "Enable SPIR-V capability Shader",
743 .dependencies = featureSet(&[_]Feature{124 .dependencies = featureSet(&[_]Feature{ .v1_0, .matrix }),
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 }),
753 };125 };
754 result[@intFromEnum(Feature.Tessellation)] = .{126 const ti = @typeInfo(Feature);
755 .llvm_name = null,127 for (&result, 0..) |*elem, i| {
756 .description = "Enable SPIR-V capability Tessellation",128 elem.index = i;
757 .dependencies = featureSet(&[_]Feature{129 elem.name = ti.@"enum".fields[i].name;
758 .Shader,130 }
759 }),131 break :blk result;
760 };132};
761 result[@intFromEnum(Feature.Addresses)] = .{133
762 .llvm_name = null,134pub const cpu = struct {
763 .description = "Enable SPIR-V capability Addresses",135 pub const generic: CpuModel = .{
764 .dependencies = featureSet(&[_]Feature{}),136 .name = "generic",
137 .llvm_name = "generic",
138 .features = featureSet(&[_]Feature{.v1_0}),
765 };139 };
766 result[@intFromEnum(Feature.Linkage)] = .{140
141 pub const vulkan_v1_2: CpuModel = .{
142 .name = "vulkan_v1_2",
767 .llvm_name = null,143 .llvm_name = null,
768 .description = "Enable SPIR-V capability Linkage",144 .features = featureSet(&[_]Feature{ .v1_5, .shader, .addresses }),
769 .dependencies = featureSet(&[_]Feature{}),
770 };145 };
771 result[@intFromEnum(Feature.Kernel)] = .{146
147 pub const opencl_v2: CpuModel = .{
148 .name = "opencl_v2",
772 .llvm_name = null,149 .llvm_name = null,
773 .description = "Enable SPIR-V capability Kernel",150 .features = featureSet(&[_]Feature{ .v1_2, .kernel, .addresses, .generic_pointer }),
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{}),
2090 };151 };
2091};152};
lib/std/gpu.zig+20-28
...@@ -1,5 +1,4 @@...@@ -1,5 +1,4 @@
1const std = @import("std.zig");1const std = @import("std.zig");
2const comptimePrint = std.fmt.comptimePrint;
32
4/// Will make `ptr` contain the location of the current invocation within the3/// Will make `ptr` contain the location of the current invocation within the
5/// global workgroup. Each component is equal to the index of the local workgroup4/// 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 {...@@ -81,23 +80,23 @@ pub fn fragmentDepth(comptime ptr: *addrspace(.output) f32) void {
81/// Forms the main linkage for `input` and `output` address spaces.80/// Forms the main linkage for `input` and `output` address spaces.
82/// `ptr` must be a reference to variable or struct field.81/// `ptr` must be a reference to variable or struct field.
83pub fn location(comptime ptr: anytype, comptime loc: u32) void {82pub fn location(comptime ptr: anytype, comptime loc: u32) void {
84 const code = comptimePrint("OpDecorate %ptr Location {}", .{loc});83 asm volatile ("OpDecorate %ptr Location $loc"
85 asm volatile (code
86 :84 :
87 : [ptr] "" (ptr),85 : [ptr] "" (ptr),
86 [loc] "c" (loc),
88 );87 );
89}88}
9089
91/// Forms the main linkage for `input` and `output` address spaces.90/// Forms the main linkage for `input` and `output` address spaces.
92/// `ptr` must be a reference to variable or struct field.91/// `ptr` must be a reference to variable or struct field.
93pub fn binding(comptime ptr: anytype, comptime group: u32, comptime bind: u32) void {92pub fn binding(comptime ptr: anytype, comptime set: u32, comptime bind: u32) void {
94 const code = comptimePrint(93 asm volatile (
95 \\OpDecorate %ptr DescriptorSet {}94 \\OpDecorate %ptr DescriptorSet $set
96 \\OpDecorate %ptr Binding {}95 \\OpDecorate %ptr Binding $bind
97 , .{ group, bind });
98 asm volatile (code
99 :96 :
100 : [ptr] "" (ptr),97 : [ptr] "" (ptr),
98 [set] "c" (set),
99 [bind] "c" (bind),
101 );100 );
102}101}
103102
...@@ -111,13 +110,10 @@ pub const Origin = enum(u32) {...@@ -111,13 +110,10 @@ pub const Origin = enum(u32) {
111/// The coordinates appear to originate in the specified `origin`.110/// The coordinates appear to originate in the specified `origin`.
112/// Only valid with the `Fragment` calling convention.111/// Only valid with the `Fragment` calling convention.
113pub fn fragmentOrigin(comptime entry_point: anytype, comptime origin: Origin) void {112pub fn fragmentOrigin(comptime entry_point: anytype, comptime origin: Origin) void {
114 const origin_enum = switch (origin) {113 asm volatile ("OpExecutionMode %entry_point $origin"
115 .upper_left => .OriginUpperLeft,
116 .lower_left => .OriginLowerLeft,
117 };
118 asm volatile ("OpExecutionMode %entry_point " ++ @tagName(origin_enum)
119 :114 :
120 : [entry_point] "" (entry_point),115 : [entry_point] "" (entry_point),
116 [origin] "c" (@intFromEnum(origin)),
121 );117 );
122}118}
123119
...@@ -141,37 +137,33 @@ pub const DepthMode = enum(u32) {...@@ -141,37 +137,33 @@ pub const DepthMode = enum(u32) {
141137
142/// Only valid with the `Fragment` calling convention.138/// Only valid with the `Fragment` calling convention.
143pub fn depthMode(comptime entry_point: anytype, comptime mode: DepthMode) void {139pub fn depthMode(comptime entry_point: anytype, comptime mode: DepthMode) void {
144 const code = comptimePrint("OpExecutionMode %entry_point {}", .{@intFromEnum(mode)});140 asm volatile ("OpExecutionMode %entry_point $mode"
145 asm volatile (code
146 :141 :
147 : [entry_point] "" (entry_point),142 : [entry_point] "" (entry_point),
143 [mode] "c" (mode),
148 );144 );
149}145}
150146
151/// Indicates the workgroup size in the `x`, `y`, and `z` dimensions.147/// Indicates the workgroup size in the `x`, `y`, and `z` dimensions.
152/// Only valid with the `GLCompute` or `Kernel` calling conventions.148/// Only valid with the `GLCompute` or `Kernel` calling conventions.
153pub fn workgroupSize(comptime entry_point: anytype, comptime size: @Vector(3, u32)) void {149pub fn workgroupSize(comptime entry_point: anytype, comptime size: @Vector(3, u32)) void {
154 const code = comptimePrint("OpExecutionMode %entry_point LocalSize {} {} {}", .{150 asm volatile ("OpExecutionMode %entry_point LocalSize %x %y %z"
155 size[0],
156 size[1],
157 size[2],
158 });
159 asm volatile (code
160 :151 :
161 : [entry_point] "" (entry_point),152 : [entry_point] "" (entry_point),
153 [x] "c" (size[0]),
154 [y] "c" (size[1]),
155 [z] "c" (size[2]),
162 );156 );
163}157}
164158
165/// A hint to the client, which indicates the workgroup size in the `x`, `y`, and `z` dimensions.159/// A hint to the client, which indicates the workgroup size in the `x`, `y`, and `z` dimensions.
166/// Only valid with the `GLCompute` or `Kernel` calling conventions.160/// Only valid with the `GLCompute` or `Kernel` calling conventions.
167pub fn workgroupSizeHint(comptime entry_point: anytype, comptime size: @Vector(3, u32)) void {161pub fn workgroupSizeHint(comptime entry_point: anytype, comptime size: @Vector(3, u32)) void {
168 const code = comptimePrint("OpExecutionMode %entry_point LocalSizeHint {} {} {}", .{162 asm volatile ("OpExecutionMode %entry_point LocalSizeHint %x %y %z"
169 size[0],
170 size[1],
171 size[2],
172 });
173 asm volatile (code
174 :163 :
175 : [entry_point] "" (entry_point),164 : [entry_point] "" (entry_point),
165 [x] "c" (size[0]),
166 [y] "c" (size[1]),
167 [z] "c" (size[2]),
176 );168 );
177}169}
src/codegen/spirv.zig+209-377
...@@ -159,7 +159,7 @@ pub const Object = struct {...@@ -159,7 +159,7 @@ pub const Object = struct {
159 uav_link: std.AutoHashMapUnmanaged(struct { InternPool.Index, StorageClass }, SpvModule.Decl.Index) = .empty,159 uav_link: std.AutoHashMapUnmanaged(struct { InternPool.Index, StorageClass }, SpvModule.Decl.Index) = .empty,
160160
161 /// A map that maps AIR intern pool indices to SPIR-V result-ids.161 /// A map that maps AIR intern pool indices to SPIR-V result-ids.
162 intern_map: InternMap = .{},162 intern_map: InternMap = .empty,
163163
164 /// This map serves a dual purpose:164 /// This map serves a dual purpose:
165 /// - It keeps track of pointers that are currently being emitted, so that we can tell165 /// - It keeps track of pointers that are currently being emitted, so that we can tell
...@@ -176,10 +176,10 @@ pub const Object = struct {...@@ -176,10 +176,10 @@ pub const Object = struct {
176 push_constant_ptr: SpvModule.Decl.Index,176 push_constant_ptr: SpvModule.Decl.Index,
177 } = null,177 } = null,
178178
179 pub fn init(gpa: Allocator) Object {179 pub fn init(gpa: Allocator, target: std.Target) Object {
180 return .{180 return .{
181 .gpa = gpa,181 .gpa = gpa,
182 .spv = SpvModule.init(gpa),182 .spv = SpvModule.init(gpa, target),
183 };183 };
184 }184 }
185185
...@@ -314,7 +314,7 @@ const NavGen = struct {...@@ -314,7 +314,7 @@ const NavGen = struct {
314 next_arg_index: u32 = 0,314 next_arg_index: u32 = 0,
315315
316 /// A map keeping track of which instruction generated which result-id.316 /// A map keeping track of which instruction generated which result-id.
317 inst_results: InstMap = .{},317 inst_results: InstMap = .empty,
318318
319 /// A map that maps AIR intern pool indices to SPIR-V result-ids.319 /// A map that maps AIR intern pool indices to SPIR-V result-ids.
320 /// See `Object.intern_map`.320 /// See `Object.intern_map`.
...@@ -412,11 +412,6 @@ const NavGen = struct {...@@ -412,11 +412,6 @@ const NavGen = struct {
412 self.func.deinit(self.gpa);412 self.func.deinit(self.gpa);
413 }413 }
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
420 pub fn fail(self: *NavGen, comptime format: []const u8, args: anytype) Error {415 pub fn fail(self: *NavGen, comptime format: []const u8, args: anytype) Error {
421 @branchHint(.cold);416 @branchHint(.cold);
422 const zcu = self.pt.zcu;417 const zcu = self.pt.zcu;
...@@ -431,12 +426,12 @@ const NavGen = struct {...@@ -431,12 +426,12 @@ const NavGen = struct {
431 }426 }
432427
433 /// This imports the "default" extended instruction set for the target428 /// 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.
435 fn importExtendedSet(self: *NavGen) !IdResult {430 fn importExtendedSet(self: *NavGen) !IdResult {
436 const target = self.getTarget();431 const target = self.spv.target;
437 return switch (target.os.tag) {432 return switch (target.os.tag) {
438 .opencl => try self.spv.importInstructionSet(.@"OpenCL.std"),433 .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"),
440 else => unreachable,435 else => unreachable,
441 };436 };
442 }437 }
...@@ -469,7 +464,7 @@ const NavGen = struct {...@@ -469,7 +464,7 @@ const NavGen = struct {
469464
470 const zcu = self.pt.zcu;465 const zcu = self.pt.zcu;
471 const ty = Type.fromInterned(zcu.intern_pool.typeOf(val));466 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
474 const spv_decl_index = blk: {469 const spv_decl_index = blk: {
475 const entry = try self.object.uav_link.getOrPut(self.object.gpa, .{ val, .Function });470 const entry = try self.object.uav_link.getOrPut(self.object.gpa, .{ val, .Function });
...@@ -532,7 +527,7 @@ const NavGen = struct {...@@ -532,7 +527,7 @@ const NavGen = struct {
532527
533 try self.spv.debugNameFmt(initializer_id, "initializer of __anon_{d}", .{@intFromEnum(val)});528 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);
536 try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpExtInst, .{531 try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpExtInst, .{
537 .id_result_type = fn_decl_ptr_ty_id,532 .id_result_type = fn_decl_ptr_ty_id,
538 .id_result = result_id,533 .id_result = result_id,
...@@ -546,14 +541,10 @@ const NavGen = struct {...@@ -546,14 +541,10 @@ const NavGen = struct {
546 }541 }
547542
548 fn addFunctionDep(self: *NavGen, decl_index: SpvModule.Decl.Index, storage_class: StorageClass) !void {543 fn addFunctionDep(self: *NavGen, decl_index: SpvModule.Decl.Index, storage_class: StorageClass) !void {
549 const target = self.getTarget();544 if (self.spv.version.minor < 4) {
550 if (target.os.tag == .vulkan) {545 // Before version 1.4, the interface’s storage classes are limited to the Input and Output
551 // Shader entry point dependencies must be variables with Input or Output storage class546 if (storage_class == .Input or storage_class == .Output) {
552 switch (storage_class) {547 try self.func.decl_deps.put(self.spv.gpa, decl_index, {});
553 .Input, .Output => {
554 try self.func.decl_deps.put(self.spv.gpa, decl_index, {});
555 },
556 else => {},
557 }548 }
558 } else {549 } else {
559 try self.func.decl_deps.put(self.spv.gpa, decl_index, {});550 try self.func.decl_deps.put(self.spv.gpa, decl_index, {});
...@@ -561,11 +552,7 @@ const NavGen = struct {...@@ -561,11 +552,7 @@ const NavGen = struct {
561 }552 }
562553
563 fn castToGeneric(self: *NavGen, type_id: IdRef, ptr_id: IdRef) !IdRef {554 fn castToGeneric(self: *NavGen, type_id: IdRef, ptr_id: IdRef) !IdRef {
564 const target = self.getTarget();555 if (self.spv.hasFeature(.kernel)) {
565
566 if (target.os.tag == .vulkan) {
567 return ptr_id;
568 } else {
569 const result_id = self.spv.allocId();556 const result_id = self.spv.allocId();
570 try self.func.body.emit(self.spv.gpa, .OpPtrCastToGeneric, .{557 try self.func.body.emit(self.spv.gpa, .OpPtrCastToGeneric, .{
571 .id_result_type = type_id,558 .id_result_type = type_id,
...@@ -574,6 +561,8 @@ const NavGen = struct {...@@ -574,6 +561,8 @@ const NavGen = struct {
574 });561 });
575 return result_id;562 return result_id;
576 }563 }
564
565 return ptr_id;
577 }566 }
578567
579 /// Start a new SPIR-V block, Emits the label of the new block, and stores which568 /// Start a new SPIR-V block, Emits the label of the new block, and stores which
...@@ -596,29 +585,21 @@ const NavGen = struct {...@@ -596,29 +585,21 @@ const NavGen = struct {
596 /// TODO: This probably needs an ABI-version as well (especially in combination with SPV_INTEL_arbitrary_precision_integers).585 /// TODO: This probably needs an ABI-version as well (especially in combination with SPV_INTEL_arbitrary_precision_integers).
597 /// TODO: Should the result of this function be cached?586 /// TODO: Should the result of this function be cached?
598 fn backingIntBits(self: *NavGen, bits: u16) ?u16 {587 fn backingIntBits(self: *NavGen, bits: u16) ?u16 {
599 const target = self.getTarget();
600
601 // The backend will never be asked to compiler a 0-bit integer, so we won't have to handle those in this function.588 // The backend will never be asked to compiler a 0-bit integer, so we won't have to handle those in this function.
602 assert(bits != 0);589 assert(bits != 0);
603590
604 // 8, 16 and 64-bit integers require the Int8, Int16 and Inr64 capabilities respectively.591 // 8, 16 and 64-bit integers require the Int8, Int16 and Inr64 capabilities respectively.
605 // 32-bit integers are always supported (see spec, 2.16.1, Data rules).592 // 32-bit integers are always supported (see spec, 2.16.1, Data rules).
606 const ints = [_]struct { bits: u16, feature: ?Target.spirv.Feature }{593 const ints = [_]struct { bits: u16, feature: ?Target.spirv.Feature }{
607 .{ .bits = 8, .feature = .Int8 },594 .{ .bits = 8, .feature = .int8 },
608 .{ .bits = 16, .feature = .Int16 },595 .{ .bits = 16, .feature = .int16 },
609 .{ .bits = 32, .feature = null },596 .{ .bits = 32, .feature = null },
610 .{ .bits = 64, .feature = .Int64 },597 .{ .bits = 64, .feature = .int64 },
611 };598 };
612599
613 for (ints) |int| {600 for (ints) |int| {
614 const has_feature = if (int.feature) |feature|601 const has_feature = if (int.feature) |feature| self.spv.hasFeature(feature) else true;
615 Target.spirv.featureSetHas(target.cpu.features, feature)602 if (bits <= int.bits and has_feature) return int.bits;
616 else
617 true;
618
619 if (bits <= int.bits and has_feature) {
620 return int.bits;
621 }
622 }603 }
623604
624 return null;605 return null;
...@@ -631,11 +612,7 @@ const NavGen = struct {...@@ -631,11 +612,7 @@ const NavGen = struct {
631 /// is no way of knowing whether those are actually supported.612 /// is no way of knowing whether those are actually supported.
632 /// TODO: Maybe this should be cached?613 /// TODO: Maybe this should be cached?
633 fn largestSupportedIntBits(self: *NavGen) u16 {614 fn largestSupportedIntBits(self: *NavGen) u16 {
634 const target = self.getTarget();615 return if (self.spv.hasFeature(.int64)) 64 else 32;
635 return if (Target.spirv.featureSetHas(target.cpu.features, .Int64))
636 64
637 else
638 32;
639 }616 }
640617
641 /// Checks whether the type is "composite int", an integer consisting of multiple native integers. These are represented by618 /// 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 {...@@ -648,7 +625,6 @@ const NavGen = struct {
648 /// Checks whether the type can be directly translated to SPIR-V vectors625 /// Checks whether the type can be directly translated to SPIR-V vectors
649 fn isSpvVector(self: *NavGen, ty: Type) bool {626 fn isSpvVector(self: *NavGen, ty: Type) bool {
650 const zcu = self.pt.zcu;627 const zcu = self.pt.zcu;
651 const target = self.getTarget();
652 if (ty.zigTypeTag(zcu) != .vector) return false;628 if (ty.zigTypeTag(zcu) != .vector) return false;
653629
654 // TODO: This check must be expanded for types that can be represented630 // TODO: This check must be expanded for types that can be represented
...@@ -664,17 +640,19 @@ const NavGen = struct {...@@ -664,17 +640,19 @@ const NavGen = struct {
664 }640 }
665641
666 const elem_ty = ty.childType(zcu);642 const elem_ty = ty.childType(zcu);
667
668 const len = ty.vectorLen(zcu);643 const len = ty.vectorLen(zcu);
669 const is_scalar = elem_ty.isNumeric(zcu) or elem_ty.toIntern() == .bool_type;644
670 const spirv_len = len > 1 and len <= 4;645 if (elem_ty.isNumeric(zcu) or elem_ty.toIntern() == .bool_type) {
671 const opencl_len = if (target.os.tag == .opencl) (len == 8 or len == 16) else false;646 if (len > 1 and len <= 4) return true;
672 return is_scalar and (spirv_len or opencl_len);647 if (self.spv.hasFeature(.vector16)) return (len == 8 or len == 16);
648 }
649
650 return false;
673 }651 }
674652
675 fn arithmeticTypeInfo(self: *NavGen, ty: Type) ArithmeticTypeInfo {653 fn arithmeticTypeInfo(self: *NavGen, ty: Type) ArithmeticTypeInfo {
676 const zcu = self.pt.zcu;654 const zcu = self.pt.zcu;
677 const target = self.getTarget();655 const target = self.spv.target;
678 var scalar_ty = ty.scalarType(zcu);656 var scalar_ty = ty.scalarType(zcu);
679 if (scalar_ty.zigTypeTag(zcu) == .@"enum") {657 if (scalar_ty.zigTypeTag(zcu) == .@"enum") {
680 scalar_ty = scalar_ty.intTagType(zcu);658 scalar_ty = scalar_ty.intTagType(zcu);
...@@ -721,36 +699,16 @@ const NavGen = struct {...@@ -721,36 +699,16 @@ const NavGen = struct {
721699
722 /// Emits a bool constant in a particular representation.700 /// Emits a bool constant in a particular representation.
723 fn constBool(self: *NavGen, value: bool, repr: Repr) !IdRef {701 fn constBool(self: *NavGen, value: bool, repr: Repr) !IdRef {
724 // TODO: Cache?702 return switch (repr) {
725703 .indirect => self.constInt(Type.u1, @intFromBool(value)),
726 const section = &self.spv.sections.types_globals_constants;704 .direct => self.spv.constBool(value),
727 switch (repr) {705 };
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 }
747 }706 }
748707
749 /// Emits an integer constant.708 /// Emits an integer constant.
750 /// This function, unlike SpvModule.constInt, takes care to bitcast709 /// This function, unlike SpvModule.constInt, takes care to bitcast
751 /// the value to an unsigned int first for Kernels.710 /// the value to an unsigned int first for Kernels.
752 fn constInt(self: *NavGen, ty: Type, value: anytype, repr: Repr) !IdRef {711 fn constInt(self: *NavGen, ty: Type, value: anytype) !IdRef {
753 // TODO: Cache?
754 const zcu = self.pt.zcu;712 const zcu = self.pt.zcu;
755 const scalar_ty = ty.scalarType(zcu);713 const scalar_ty = ty.scalarType(zcu);
756 const int_info = scalar_ty.intInfo(zcu);714 const int_info = scalar_ty.intInfo(zcu);
...@@ -763,18 +721,18 @@ const NavGen = struct {...@@ -763,18 +721,18 @@ const NavGen = struct {
763 else => unreachable,721 else => unreachable,
764 };722 };
765723
766 const bits: u64 = switch (signedness) {724 const value64: u64 = switch (signedness) {
767 .signed => @bitCast(@as(i64, @intCast(value))),725 .signed => @bitCast(@as(i64, @intCast(value))),
768 .unsigned => @as(u64, @intCast(value)),726 .unsigned => @as(u64, @intCast(value)),
769 };727 };
770728
771 // Manually truncate the value to the right amount of bits.729 // Manually truncate the value to the right amount of bits.
772 const truncated_bits = if (backing_bits == 64)730 const truncated_value = if (backing_bits == 64)
773 bits731 value64
774 else732 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);
778 const result_id = self.spv.allocId();736 const result_id = self.spv.allocId();
779737
780 const section = &self.spv.sections.types_globals_constants;738 const section = &self.spv.sections.types_globals_constants;
...@@ -783,100 +741,42 @@ const NavGen = struct {...@@ -783,100 +741,42 @@ const NavGen = struct {
783 1...32 => try section.emit(self.spv.gpa, .OpConstant, .{741 1...32 => try section.emit(self.spv.gpa, .OpConstant, .{
784 .id_result_type = result_ty_id,742 .id_result_type = result_ty_id,
785 .id_result = result_id,743 .id_result = result_id,
786 .value = .{ .uint32 = @truncate(truncated_bits) },744 .value = .{ .uint32 = @truncate(truncated_value) },
787 }),745 }),
788 33...64 => try section.emit(self.spv.gpa, .OpConstant, .{746 33...64 => try section.emit(self.spv.gpa, .OpConstant, .{
789 .id_result_type = result_ty_id,747 .id_result_type = result_ty_id,
790 .id_result = result_id,748 .id_result = result_id,
791 .value = .{ .uint64 = truncated_bits },749 .value = .{ .uint64 = truncated_value },
792 }),750 }),
793 else => unreachable, // TODO: Large integer constants751 else => unreachable, // TODO: Large integer constants
794 }752 }
795753
796 if (!ty.isVector(zcu)) {754 if (!ty.isVector(zcu)) return result_id;
797 return result_id;755 return self.constructCompositeSplat(ty, 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;
813 }756 }
814757
815 /// Construct a struct at runtime.758 pub fn constructComposite(self: *NavGen, result_ty_id: IdRef, constituents: []const IdRef) !IdRef {
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
822 const result_id = self.spv.allocId();759 const result_id = self.spv.allocId();
823 try self.func.body.emit(self.spv.gpa, .OpCompositeConstruct, .{760 try self.func.body.emit(self.gpa, .OpCompositeConstruct, .{
824 .id_result_type = try self.resolveType(ty, .direct),761 .id_result_type = result_ty_id,
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),
849 .id_result = result_id,762 .id_result = result_id,
850 .constituents = constituents,763 .constituents = constituents,
851 });764 });
852 return result_id;765 return result_id;
853 }766 }
854767
855 /// Construct a vector at runtime with all lanes set to the same value.768 /// Construct a composite at runtime with all lanes set to the same value.
856 /// ty must be an vector type.769 /// ty must be an aggregate type.
857 fn constructVectorSplat(self: *NavGen, ty: Type, constituent: IdRef) !IdRef {770 fn constructCompositeSplat(self: *NavGen, ty: Type, constituent: IdRef) !IdRef {
858 const zcu = self.pt.zcu;771 const zcu = self.pt.zcu;
859 const n = ty.vectorLen(zcu);772 const n: usize = @intCast(ty.arrayLen(zcu));
860773
861 const constituents = try self.gpa.alloc(IdRef, n);774 const constituents = try self.gpa.alloc(IdRef, n);
862 defer self.gpa.free(constituents);775 defer self.gpa.free(constituents);
863 @memset(constituents, constituent);776 @memset(constituents, constituent);
864777
865 return try self.constructVector(ty, constituents);778 const result_ty_id = try self.resolveType(ty, .direct);
866 }779 return self.constructComposite(result_ty_id, constituents);
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;
880 }780 }
881781
882 /// This function generates a load for a constant in direct (ie, non-memory) representation.782 /// This function generates a load for a constant in direct (ie, non-memory) representation.
...@@ -895,7 +795,7 @@ const NavGen = struct {...@@ -895,7 +795,7 @@ const NavGen = struct {
895795
896 const pt = self.pt;796 const pt = self.pt;
897 const zcu = pt.zcu;797 const zcu = pt.zcu;
898 const target = self.getTarget();798 const target = self.spv.target;
899 const result_ty_id = try self.resolveType(ty, repr);799 const result_ty_id = try self.resolveType(ty, repr);
900 const ip = &zcu.intern_pool;800 const ip = &zcu.intern_pool;
901801
...@@ -947,9 +847,9 @@ const NavGen = struct {...@@ -947,9 +847,9 @@ const NavGen = struct {
947 },847 },
948 .int => {848 .int => {
949 if (ty.isSignedInt(zcu)) {849 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));
951 } else {851 } else {
952 break :cache try self.constInt(ty, val.toUnsignedInt(zcu), repr);852 break :cache try self.constInt(ty, val.toUnsignedInt(zcu));
953 }853 }
954 },854 },
955 .float => {855 .float => {
...@@ -970,7 +870,7 @@ const NavGen = struct {...@@ -970,7 +870,7 @@ const NavGen = struct {
970 },870 },
971 .err => |err| {871 .err => |err| {
972 const value = try pt.getErrorValue(err.name);872 const value = try pt.getErrorValue(err.name);
973 break :cache try self.constInt(ty, value, repr);873 break :cache try self.constInt(ty, value);
974 },874 },
975 .error_union => |error_union| {875 .error_union => |error_union| {
976 // TODO: Error unions may be constructed with constant instructions if the payload type876 // TODO: Error unions may be constructed with constant instructions if the payload type
...@@ -1011,7 +911,8 @@ const NavGen = struct {...@@ -1011,7 +911,8 @@ const NavGen = struct {
1011 types = .{ payload_ty, err_ty };911 types = .{ payload_ty, err_ty };
1012 }912 }
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);
1015 },916 },
1016 .enum_tag => {917 .enum_tag => {
1017 const int_val = try val.intFromEnum(ty, pt);918 const int_val = try val.intFromEnum(ty, pt);
...@@ -1020,14 +921,10 @@ const NavGen = struct {...@@ -1020,14 +921,10 @@ const NavGen = struct {
1020 },921 },
1021 .ptr => return self.constantPtr(val),922 .ptr => return self.constantPtr(val),
1022 .slice => |slice| {923 .slice => |slice| {
1023 const ptr_ty = ty.slicePtrFieldType(zcu);
1024 const ptr_id = try self.constantPtr(Value.fromInterned(slice.ptr));924 const ptr_id = try self.constantPtr(Value.fromInterned(slice.ptr));
1025 const len_id = try self.constant(Type.usize, Value.fromInterned(slice.len), .indirect);925 const len_id = try self.constant(Type.usize, Value.fromInterned(slice.len), .indirect);
1026 return self.constructStruct(926 const comp_ty_id = try self.resolveType(ty, .direct);
1027 ty,927 return try self.constructComposite(comp_ty_id, &.{ ptr_id, len_id });
1028 &.{ ptr_ty, Type.usize },
1029 &.{ ptr_id, len_id },
1030 );
1031 },928 },
1032 .opt => {929 .opt => {
1033 const payload_ty = ty.optionalChild(zcu);930 const payload_ty = ty.optionalChild(zcu);
...@@ -1053,11 +950,8 @@ const NavGen = struct {...@@ -1053,11 +950,8 @@ const NavGen = struct {
1053 else950 else
1054 try self.spv.constUndef(try self.resolveType(payload_ty, .indirect));951 try self.spv.constUndef(try self.resolveType(payload_ty, .indirect));
1055952
1056 return try self.constructStruct(953 const comp_ty_id = try self.resolveType(ty, .direct);
1057 ty,954 return try self.constructComposite(comp_ty_id, &.{ payload_id, has_pl_id });
1058 &.{ payload_ty, Type.bool },
1059 &.{ payload_id, has_pl_id },
1060 );
1061 },955 },
1062 .aggregate => |aggregate| switch (ip.indexToKey(ty.ip_index)) {956 .aggregate => |aggregate| switch (ip.indexToKey(ty.ip_index)) {
1063 inline .array_type, .vector_type => |array_type, tag| {957 inline .array_type, .vector_type => |array_type, tag| {
...@@ -1077,7 +971,7 @@ const NavGen = struct {...@@ -1077,7 +971,7 @@ const NavGen = struct {
1077 // TODO: This is really space inefficient, perhaps there is a better971 // TODO: This is really space inefficient, perhaps there is a better
1078 // way to do it?972 // way to do it?
1079 for (constituents, bytes.toSlice(constituents.len, ip)) |*constituent, byte| {973 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);
1081 }975 }
1082 },976 },
1083 .elems => |elems| {977 .elems => |elems| {
...@@ -1090,11 +984,8 @@ const NavGen = struct {...@@ -1090,11 +984,8 @@ const NavGen = struct {
1090 },984 },
1091 }985 }
1092986
1093 switch (tag) {987 const comp_ty_id = try self.resolveType(ty, .direct);
1094 .array_type => return self.constructArray(ty, constituents),988 return self.constructComposite(comp_ty_id, constituents);
1095 .vector_type => return self.constructVector(ty, constituents),
1096 else => unreachable,
1097 }
1098 },989 },
1099 .struct_type => {990 .struct_type => {
1100 const struct_type = zcu.typeToStruct(ty).?;991 const struct_type = zcu.typeToStruct(ty).?;
...@@ -1124,7 +1015,8 @@ const NavGen = struct {...@@ -1124,7 +1015,8 @@ const NavGen = struct {
1124 try constituents.append(field_id);1015 try constituents.append(field_id);
1125 }1016 }
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);
1128 },1020 },
1129 .tuple_type => unreachable, // TODO1021 .tuple_type => unreachable, // TODO
1130 else => unreachable,1022 else => unreachable,
...@@ -1149,8 +1041,6 @@ const NavGen = struct {...@@ -1149,8 +1041,6 @@ const NavGen = struct {
1149 }1041 }
11501042
1151 fn constantPtr(self: *NavGen, ptr_val: Value) Error!IdRef {1043 fn constantPtr(self: *NavGen, ptr_val: Value) Error!IdRef {
1152 // TODO: Caching??
1153
1154 const pt = self.pt;1044 const pt = self.pt;
11551045
1156 if (ptr_val.isUndef(pt.zcu)) {1046 if (ptr_val.isUndef(pt.zcu)) {
...@@ -1201,7 +1091,7 @@ const NavGen = struct {...@@ -1201,7 +1091,7 @@ const NavGen = struct {
1201 .elem_ptr => |elem| {1091 .elem_ptr => |elem| {
1202 const parent_ptr_id = try self.derivePtr(elem.parent.*);1092 const parent_ptr_id = try self.derivePtr(elem.parent.*);
1203 const parent_ptr_ty = try elem.parent.ptrType(pt);1093 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);
1205 return self.ptrElemPtr(parent_ptr_ty, parent_ptr_id, index_id);1095 return self.ptrElemPtr(parent_ptr_ty, parent_ptr_id, index_id);
1206 },1096 },
1207 .offset_and_cast => |oac| {1097 .offset_and_cast => |oac| {
...@@ -1255,7 +1145,7 @@ const NavGen = struct {...@@ -1255,7 +1145,7 @@ const NavGen = struct {
12551145
1256 // Uav refs are always generic.1146 // Uav refs are always generic.
1257 assert(ty.ptrAddressSpace(zcu) == .generic);1147 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);
1259 const ptr_id = try self.resolveUav(uav.val);1149 const ptr_id = try self.resolveUav(uav.val);
12601150
1261 if (decl_ptr_ty_id != ty_id) {1151 if (decl_ptr_ty_id != ty_id) {
...@@ -1310,7 +1200,7 @@ const NavGen = struct {...@@ -1310,7 +1200,7 @@ const NavGen = struct {
1310 const storage_class = self.spvStorageClass(nav.getAddrspace());1200 const storage_class = self.spvStorageClass(nav.getAddrspace());
1311 try self.addFunctionDep(spv_decl_index, storage_class);1201 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
1315 const ptr_id = switch (storage_class) {1205 const ptr_id = switch (storage_class) {
1316 .Generic => try self.castToGeneric(decl_ptr_ty_id, decl_id),1206 .Generic => try self.castToGeneric(decl_ptr_ty_id, decl_id),
...@@ -1351,31 +1241,20 @@ const NavGen = struct {...@@ -1351,31 +1241,20 @@ const NavGen = struct {
1351 };1241 };
13521242
1353 // Kernel only supports unsigned ints.1243 // Kernel only supports unsigned ints.
1354 if (self.getTarget().os.tag == .vulkan) {1244 if (self.spv.hasFeature(.kernel)) {
1355 return self.spv.intType(signedness, backing_bits);1245 return self.spv.intType(.unsigned, backing_bits);
1356 }1246 }
13571247
1358 return self.spv.intType(.unsigned, backing_bits);1248 return self.spv.intType(signedness, backing_bits);
1359 }1249 }
13601250
1361 fn arrayType(self: *NavGen, len: u32, child_ty: IdRef) !IdRef {1251 fn arrayType(self: *NavGen, len: u32, child_ty: IdRef) !IdRef {
1362 // TODO: Cache??1252 const len_id = try self.constInt(Type.u32, len);
1363 const len_id = try self.constInt(Type.u32, len, .direct);1253 return self.spv.arrayType(len_id, child_ty);
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);
1376 }1254 }
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;
1379 const key = .{ child_ty.toIntern(), storage_class, child_repr };1258 const key = .{ child_ty.toIntern(), storage_class, child_repr };
1380 const entry = try self.ptr_types.getOrPut(self.gpa, key);1259 const entry = try self.ptr_types.getOrPut(self.gpa, key);
1381 if (entry.found_existing) {1260 if (entry.found_existing) {
...@@ -1398,6 +1277,17 @@ const NavGen = struct {...@@ -1398,6 +1277,17 @@ const NavGen = struct {
13981277
1399 const child_ty_id = try self.resolveType(child_ty, child_repr);1278 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
1401 try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpTypePointer, .{1291 try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpTypePointer, .{
1402 .id_result = result_id,1292 .id_result = result_id,
1403 .storage_class = storage_class,1293 .storage_class = storage_class,
...@@ -1408,8 +1298,7 @@ const NavGen = struct {...@@ -1408,8 +1298,7 @@ const NavGen = struct {
1408 }1298 }
14091299
1410 fn functionType(self: *NavGen, return_ty: Type, param_types: []const Type) !IdRef {1300 fn functionType(self: *NavGen, return_ty: Type, param_types: []const Type) !IdRef {
1411 // TODO: Cache??1301 const return_ty_id = try self.resolveFnReturnType(return_ty);
1412
1413 const param_ids = try self.gpa.alloc(IdRef, param_types.len);1302 const param_ids = try self.gpa.alloc(IdRef, param_types.len);
1414 defer self.gpa.free(param_ids);1303 defer self.gpa.free(param_ids);
14151304
...@@ -1417,14 +1306,7 @@ const NavGen = struct {...@@ -1417,14 +1306,7 @@ const NavGen = struct {
1417 param_id.* = try self.resolveType(param_ty, .direct);1306 param_id.* = try self.resolveType(param_ty, .direct);
1418 }1307 }
14191308
1420 const ty_id = self.spv.allocId();1309 return self.spv.functionType(return_ty_id, param_ids);
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;
1428 }1310 }
14291311
1430 fn zigScalarOrVectorTypeLike(self: *NavGen, new_ty: Type, base_ty: Type) !Type {1312 fn zigScalarOrVectorTypeLike(self: *NavGen, new_ty: Type, base_ty: Type) !Type {
...@@ -1544,7 +1426,7 @@ const NavGen = struct {...@@ -1544,7 +1426,7 @@ const NavGen = struct {
1544 const zcu = pt.zcu;1426 const zcu = pt.zcu;
1545 const ip = &zcu.intern_pool;1427 const ip = &zcu.intern_pool;
1546 log.debug("resolveType: ty = {}", .{ty.fmt(pt)});1428 log.debug("resolveType: ty = {}", .{ty.fmt(pt)});
1547 const target = self.getTarget();1429 const target = self.spv.target;
15481430
1549 const section = &self.spv.sections.types_globals_constants;1431 const section = &self.spv.sections.types_globals_constants;
15501432
...@@ -1595,10 +1477,10 @@ const NavGen = struct {...@@ -1595,10 +1477,10 @@ const NavGen = struct {
1595 // so if the float is not supported, just return an error.1477 // so if the float is not supported, just return an error.
1596 const bits = ty.floatBits(target);1478 const bits = ty.floatBits(target);
1597 const supported = switch (bits) {1479 const supported = switch (bits) {
1598 16 => Target.spirv.featureSetHas(target.cpu.features, .Float16),1480 16 => self.spv.hasFeature(.float16),
1599 // 32-bit floats are always supported (see spec, 2.16.1, Data rules).1481 // 32-bit floats are always supported (see spec, 2.16.1, Data rules).
1600 32 => true,1482 32 => true,
1601 64 => Target.spirv.featureSetHas(target.cpu.features, .Float64),1483 64 => self.spv.hasFeature(.float64),
1602 else => false,1484 else => false,
1603 };1485 };
16041486
...@@ -1641,7 +1523,7 @@ const NavGen = struct {...@@ -1641,7 +1523,7 @@ const NavGen = struct {
1641 return try self.arrayType(1, elem_ty_id);1523 return try self.arrayType(1, elem_ty_id);
1642 } else {1524 } else {
1643 const result_id = try self.arrayType(total_len, elem_ty_id);1525 const result_id = try self.arrayType(total_len, elem_ty_id);
1644 if (target.os.tag == .vulkan) {1526 if (self.spv.hasFeature(.shader)) {
1645 try self.spv.decorate(result_id, .{ .ArrayStride = .{1527 try self.spv.decorate(result_id, .{ .ArrayStride = .{
1646 .array_stride = @intCast(elem_ty.abiSize(zcu)),1528 .array_stride = @intCast(elem_ty.abiSize(zcu)),
1647 } });1529 } });
...@@ -1702,13 +1584,7 @@ const NavGen = struct {...@@ -1702,13 +1584,7 @@ const NavGen = struct {
17021584
1703 const child_ty = Type.fromInterned(ptr_info.child);1585 const child_ty = Type.fromInterned(ptr_info.child);
1704 const storage_class = self.spvStorageClass(ptr_info.flags.address_space);1586 const storage_class = self.spvStorageClass(ptr_info.flags.address_space);
1705 const ptr_ty_id = try self.ptrType(child_ty, storage_class);1587 const ptr_ty_id = try self.ptrType(child_ty, storage_class, .indirect);
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 }
17121588
1713 if (ptr_info.flags.size != .slice) {1589 if (ptr_info.flags.size != .slice) {
1714 return ptr_ty_id;1590 return ptr_ty_id;
...@@ -1755,10 +1631,6 @@ const NavGen = struct {...@@ -1755,10 +1631,6 @@ const NavGen = struct {
1755 defer self.gpa.free(type_name);1631 defer self.gpa.free(type_name);
1756 try self.spv.debugName(result_id, type_name);1632 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
1762 return result_id;1634 return result_id;
1763 },1635 },
1764 .struct_type => ip.loadStructType(ty.toIntern()),1636 .struct_type => ip.loadStructType(ty.toIntern()),
...@@ -1785,7 +1657,7 @@ const NavGen = struct {...@@ -1785,7 +1657,7 @@ const NavGen = struct {
1785 continue;1657 continue;
1786 }1658 }
17871659
1788 if (target.os.tag == .vulkan) {1660 if (self.spv.hasFeature(.shader)) {
1789 try self.spv.decorateMember(result_id, index, .{ .Offset = .{1661 try self.spv.decorateMember(result_id, index, .{ .Offset = .{
1790 .byte_offset = @intCast(ty.structFieldOffset(field_index, zcu)),1662 .byte_offset = @intCast(ty.structFieldOffset(field_index, zcu)),
1791 } });1663 } });
...@@ -1804,10 +1676,6 @@ const NavGen = struct {...@@ -1804,10 +1676,6 @@ const NavGen = struct {
1804 defer self.gpa.free(type_name);1676 defer self.gpa.free(type_name);
1805 try self.spv.debugName(result_id, type_name);1677 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
1811 return result_id;1679 return result_id;
1812 },1680 },
1813 .optional => {1681 .optional => {
...@@ -1891,20 +1759,11 @@ const NavGen = struct {...@@ -1891,20 +1759,11 @@ const NavGen = struct {
1891 }1759 }
18921760
1893 fn spvStorageClass(self: *NavGen, as: std.builtin.AddressSpace) StorageClass {1761 fn spvStorageClass(self: *NavGen, as: std.builtin.AddressSpace) StorageClass {
1894 const target = self.getTarget();
1895 return switch (as) {1762 return switch (as) {
1896 .generic => switch (target.os.tag) {1763 .generic => if (self.spv.hasFeature(.generic_pointer)) .Generic else .Function,
1897 .vulkan => .Function,
1898 .opencl => .Generic,
1899 else => unreachable,
1900 },
1901 .shared => .Workgroup,1764 .shared => .Workgroup,
1902 .local => .Function,1765 .local => .Function,
1903 .global => switch (target.os.tag) {1766 .global => if (self.spv.hasFeature(.shader)) .PhysicalStorageBuffer else .CrossWorkgroup,
1904 .opencl => .CrossWorkgroup,
1905 .vulkan => .PhysicalStorageBuffer,
1906 else => unreachable,
1907 },
1908 .constant => .UniformConstant,1767 .constant => .UniformConstant,
1909 .push_constant => .PushConstant,1768 .push_constant => .PushConstant,
1910 .input => .Input,1769 .input => .Input,
...@@ -2073,12 +1932,13 @@ const NavGen = struct {...@@ -2073,12 +1932,13 @@ const NavGen = struct {
2073 .exploded_vector => |range| {1932 .exploded_vector => |range| {
2074 assert(self.ty.isVector(zcu));1933 assert(self.ty.isVector(zcu));
2075 assert(self.ty.vectorLen(zcu) == range.len);1934 assert(self.ty.vectorLen(zcu) == range.len);
2076 const consituents = try ng.gpa.alloc(IdRef, range.len);1935 const constituents = try ng.gpa.alloc(IdRef, range.len);
2077 defer ng.gpa.free(consituents);1936 defer ng.gpa.free(constituents);
2078 for (consituents, 0..range.len) |*id, i| {1937 for (constituents, 0..range.len) |*id, i| {
2079 id.* = range.at(i);1938 id.* = range.at(i);
2080 }1939 }
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);
2082 },1942 },
2083 }1943 }
2084 }1944 }
...@@ -2282,7 +2142,7 @@ const NavGen = struct {...@@ -2282,7 +2142,7 @@ const NavGen = struct {
2282 .child = tmp.ty.toIntern(),2142 .child = tmp.ty.toIntern(),
2283 });2143 });
22842144
2285 const vector = try ng.constructVectorSplat(vector_ty, id);2145 const vector = try ng.constructCompositeSplat(vector_ty, id);
2286 return .{2146 return .{
2287 .ty = vector_ty,2147 .ty = vector_ty,
2288 .value = .{ .spv_vectorwise = vector },2148 .value = .{ .spv_vectorwise = vector },
...@@ -2447,7 +2307,7 @@ const NavGen = struct {...@@ -2447,7 +2307,7 @@ const NavGen = struct {
2447 }2307 }
24482308
2449 fn buildFma(self: *NavGen, a: Temporary, b: Temporary, c: Temporary) !Temporary {2309 fn buildFma(self: *NavGen, a: Temporary, b: Temporary, c: Temporary) !Temporary {
2450 const target = self.getTarget();2310 const target = self.spv.target;
24512311
2452 const v = self.vectorization(.{ a, b, c });2312 const v = self.vectorization(.{ a, b, c });
2453 const ops = v.operations();2313 const ops = v.operations();
...@@ -2469,7 +2329,7 @@ const NavGen = struct {...@@ -2469,7 +2329,7 @@ const NavGen = struct {
2469 // NOTE: Vulkan's FMA instruction does *NOT* produce the right values!2329 // NOTE: Vulkan's FMA instruction does *NOT* produce the right values!
2470 // its precision guarantees do NOT match zigs and it does NOT match OpenCLs!2330 // its precision guarantees do NOT match zigs and it does NOT match OpenCLs!
2471 // it needs to be emulated!2331 // it needs to be emulated!
2472 .vulkan => unreachable, // TODO: See above2332 .vulkan, .opengl => unreachable, // TODO: See above
2473 else => unreachable,2333 else => unreachable,
2474 };2334 };
24752335
...@@ -2606,14 +2466,14 @@ const NavGen = struct {...@@ -2606,14 +2466,14 @@ const NavGen = struct {
2606 };2466 };
26072467
2608 fn buildUnary(self: *NavGen, op: UnaryOp, operand: Temporary) !Temporary {2468 fn buildUnary(self: *NavGen, op: UnaryOp, operand: Temporary) !Temporary {
2609 const target = self.getTarget();2469 const target = self.spv.target;
2610 const v = blk: {2470 const v = blk: {
2611 const v = self.vectorization(.{operand});2471 const v = self.vectorization(.{operand});
2612 break :blk switch (op) {2472 break :blk switch (op) {
2613 // TODO: These instructions don't seem to be working2473 // TODO: These instructions don't seem to be working
2614 // properly for LLVM-based backends on OpenCL for 8- and2474 // properly for LLVM-based backends on OpenCL for 8- and
2615 // 16-component vectors.2475 // 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,
2617 else => v,2477 else => v,
2618 };2478 };
2619 };2479 };
...@@ -2666,7 +2526,7 @@ const NavGen = struct {...@@ -2666,7 +2526,7 @@ const NavGen = struct {
2666 // Note: We'll need to check these for floating point accuracy2526 // Note: We'll need to check these for floating point accuracy
2667 // Vulkan does not put tight requirements on these, for correction2527 // Vulkan does not put tight requirements on these, for correction
2668 // we might want to emulate them at some point.2528 // we might want to emulate them at some point.
2669 .vulkan => switch (op) {2529 .vulkan, .opengl => switch (op) {
2670 .i_abs => 5, // SAbs2530 .i_abs => 5, // SAbs
2671 .f_abs => 4, // FAbs2531 .f_abs => 4, // FAbs
2672 .clz => unreachable, // TODO2532 .clz => unreachable, // TODO
...@@ -2736,7 +2596,7 @@ const NavGen = struct {...@@ -2736,7 +2596,7 @@ const NavGen = struct {
2736 };2596 };
27372597
2738 fn buildBinary(self: *NavGen, op: BinaryOp, lhs: Temporary, rhs: Temporary) !Temporary {2598 fn buildBinary(self: *NavGen, op: BinaryOp, lhs: Temporary, rhs: Temporary) !Temporary {
2739 const target = self.getTarget();2599 const target = self.spv.target;
27402600
2741 const v = self.vectorization(.{ lhs, rhs });2601 const v = self.vectorization(.{ lhs, rhs });
2742 const ops = v.operations();2602 const ops = v.operations();
...@@ -2795,7 +2655,7 @@ const NavGen = struct {...@@ -2795,7 +2655,7 @@ const NavGen = struct {
2795 .u_min => 159, // u_min2655 .u_min => 159, // u_min
2796 else => unreachable,2656 else => unreachable,
2797 },2657 },
2798 .vulkan => switch (op) {2658 .vulkan, .opengl => switch (op) {
2799 .f_max => 40, // FMax2659 .f_max => 40, // FMax
2800 .s_max => 42, // SMax2660 .s_max => 42, // SMax
2801 .u_max => 41, // UMax2661 .u_max => 41, // UMax
...@@ -2834,7 +2694,7 @@ const NavGen = struct {...@@ -2834,7 +2694,7 @@ const NavGen = struct {
2834 ) !struct { Temporary, Temporary } {2694 ) !struct { Temporary, Temporary } {
2835 const pt = self.pt;2695 const pt = self.pt;
2836 const zcu = pt.zcu;2696 const zcu = pt.zcu;
2837 const target = self.getTarget();2697 const target = self.spv.target;
2838 const ip = &zcu.intern_pool;2698 const ip = &zcu.intern_pool;
28392699
2840 const v = lhs.vectorization(self).unify(rhs.vectorization(self));2700 const v = lhs.vectorization(self).unify(rhs.vectorization(self));
...@@ -2877,7 +2737,7 @@ const NavGen = struct {...@@ -2877,7 +2737,7 @@ const NavGen = struct {
2877 });2737 });
2878 }2738 }
2879 },2739 },
2880 .vulkan => {2740 .vulkan, .opengl => {
2881 // Operations return a struct{T, T}2741 // Operations return a struct{T, T}
2882 // where T is maybe vectorized.2742 // where T is maybe vectorized.
2883 const op_result_ty: Type = .fromInterned(try ip.getTupleType(zcu.gpa, pt.tid, .{2743 const op_result_ty: Type = .fromInterned(try ip.getTupleType(zcu.gpa, pt.tid, .{
...@@ -2964,7 +2824,7 @@ const NavGen = struct {...@@ -2964,7 +2824,7 @@ const NavGen = struct {
29642824
2965 const section = &self.spv.sections.functions;2825 const section = &self.spv.sections.functions;
29662826
2967 const target = self.getTarget();2827 const target = self.spv.target;
29682828
2969 const p_error_id = self.spv.allocId();2829 const p_error_id = self.spv.allocId();
2970 switch (target.os.tag) {2830 switch (target.os.tag) {
...@@ -2987,7 +2847,7 @@ const NavGen = struct {...@@ -2987,7 +2847,7 @@ const NavGen = struct {
2987 .id_result = self.spv.allocId(),2847 .id_result = self.spv.allocId(),
2988 });2848 });
2989 },2849 },
2990 .vulkan => {2850 .vulkan, .opengl => {
2991 const ptr_ptr_anyerror_ty_id = self.spv.allocId();2851 const ptr_ptr_anyerror_ty_id = self.spv.allocId();
2992 try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpTypePointer, .{2852 try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpTypePointer, .{
2993 .id_result = ptr_ptr_anyerror_ty_id,2853 .id_result = ptr_ptr_anyerror_ty_id,
...@@ -3045,7 +2905,7 @@ const NavGen = struct {...@@ -3045,7 +2905,7 @@ const NavGen = struct {
3045 const spv_err_decl_index = self.object.error_push_constant.?.push_constant_ptr;2905 const spv_err_decl_index = self.object.error_push_constant.?.push_constant_ptr;
3046 const push_constant_id = self.spv.declPtr(spv_err_decl_index).result_id;2906 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);
3049 // We cannot use OpInBoundsAccessChain to dereference cross-storage class, so we have to use2909 // We cannot use OpInBoundsAccessChain to dereference cross-storage class, so we have to use
3050 // a load.2910 // a load.
3051 const tmp = self.spv.allocId();2911 const tmp = self.spv.allocId();
...@@ -3088,7 +2948,7 @@ const NavGen = struct {...@@ -3088,7 +2948,7 @@ const NavGen = struct {
3088 defer self.gpa.free(test_name);2948 defer self.gpa.free(test_name);
30892949
3090 const execution_mode: spec.ExecutionModel = switch (target.os.tag) {2950 const execution_mode: spec.ExecutionModel = switch (target.os.tag) {
3091 .vulkan => .GLCompute,2951 .vulkan, .opengl => .GLCompute,
3092 .opencl => .Kernel,2952 .opencl => .Kernel,
3093 else => unreachable,2953 else => unreachable,
3094 };2954 };
...@@ -3187,7 +3047,7 @@ const NavGen = struct {...@@ -3187,7 +3047,7 @@ const NavGen = struct {
3187 const storage_class = self.spvStorageClass(nav.getAddrspace());3047 const storage_class = self.spvStorageClass(nav.getAddrspace());
3188 assert(storage_class != .Generic); // These should be instance globals3048 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
3192 try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpVariable, .{3052 try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpVariable, .{
3193 .id_result_type = ptr_ty_id,3053 .id_result_type = ptr_ty_id,
...@@ -3208,7 +3068,7 @@ const NavGen = struct {...@@ -3208,7 +3068,7 @@ const NavGen = struct {
32083068
3209 try self.spv.declareDeclDeps(spv_decl_index, &.{});3069 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
3213 if (maybe_init_val) |init_val| {3073 if (maybe_init_val) |init_val| {
3214 // TODO: Combine with resolveAnonDecl?3074 // TODO: Combine with resolveAnonDecl?
...@@ -3265,8 +3125,8 @@ const NavGen = struct {...@@ -3265,8 +3125,8 @@ const NavGen = struct {
3265 }3125 }
32663126
3267 fn intFromBool2(self: *NavGen, value: Temporary, result_ty: Type) !Temporary {3127 fn intFromBool2(self: *NavGen, value: Temporary, result_ty: Type) !Temporary {
3268 const zero_id = try self.constInt(result_ty, 0, .direct);3128 const zero_id = try self.constInt(result_ty, 0);
3269 const one_id = try self.constInt(result_ty, 1, .direct);3129 const one_id = try self.constInt(result_ty, 1);
32703130
3271 return try self.buildSelect(3131 return try self.buildSelect(
3272 value,3132 value,
...@@ -3648,12 +3508,12 @@ const NavGen = struct {...@@ -3648,12 +3508,12 @@ const NavGen = struct {
3648 .strange_integer => switch (info.signedness) {3508 .strange_integer => switch (info.signedness) {
3649 .unsigned => {3509 .unsigned => {
3650 const mask_value = if (info.bits == 64) 0xFFFF_FFFF_FFFF_FFFF else (@as(u64, 1) << @as(u6, @intCast(info.bits))) - 1;3510 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);
3652 return try self.buildBinary(.bit_and, value, Temporary.init(ty.scalarType(zcu), mask_id));3512 return try self.buildBinary(.bit_and, value, Temporary.init(ty.scalarType(zcu), mask_id));
3653 },3513 },
3654 .signed => {3514 .signed => {
3655 // Shift left and right so that we can copy the sight bit that way.3515 // 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);
3657 const shift_amt = Temporary.init(ty.scalarType(zcu), shift_amt_id);3517 const shift_amt = Temporary.init(ty.scalarType(zcu), shift_amt_id);
3658 const left = try self.buildBinary(.sll, value, shift_amt);3518 const left = try self.buildBinary(.sll, value, shift_amt);
3659 return try self.buildBinary(.sra, left, shift_amt);3519 return try self.buildBinary(.sra, left, shift_amt);
...@@ -3687,7 +3547,7 @@ const NavGen = struct {...@@ -3687,7 +3547,7 @@ const NavGen = struct {
3687 const div = try self.buildBinary(.s_div, lhs, rhs);3547 const div = try self.buildBinary(.s_div, lhs, rhs);
3688 const rem = try self.buildBinary(.s_rem, lhs, rhs);3548 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
3692 const rem_is_not_zero = try self.buildCmp(.i_ne, rem, zero);3552 const rem_is_not_zero = try self.buildCmp(.i_ne, rem, zero);
36933553
...@@ -3791,7 +3651,6 @@ const NavGen = struct {...@@ -3791,7 +3651,6 @@ const NavGen = struct {
3791 }3651 }
37923652
3793 fn abs(self: *NavGen, result_ty: Type, value: Temporary) !Temporary {3653 fn abs(self: *NavGen, result_ty: Type, value: Temporary) !Temporary {
3794 const target = self.getTarget();
3795 const operand_info = self.arithmeticTypeInfo(value.ty);3654 const operand_info = self.arithmeticTypeInfo(value.ty);
37963655
3797 switch (operand_info.class) {3656 switch (operand_info.class) {
...@@ -3803,7 +3662,7 @@ const NavGen = struct {...@@ -3803,7 +3662,7 @@ const NavGen = struct {
3803 // depending on the result type. Do that when3662 // depending on the result type. Do that when
3804 // bitCast is implemented for vectors.3663 // bitCast is implemented for vectors.
3805 // This is only relevant for Vulkan3664 // This is only relevant for Vulkan
3806 assert(target.os.tag != .vulkan); // TODO3665 assert(self.spv.hasFeature(.kernel)); // TODO
38073666
3808 return try self.normalize(abs_value, self.arithmeticTypeInfo(result_ty));3667 return try self.normalize(abs_value, self.arithmeticTypeInfo(result_ty));
3809 },3668 },
...@@ -3863,7 +3722,7 @@ const NavGen = struct {...@@ -3863,7 +3722,7 @@ const NavGen = struct {
3863 // = (rhs < 0) == (value < lhs)3722 // = (rhs < 0) == (value < lhs)
3864 // = (rhs < 0) == (lhs > value)3723 // = (rhs < 0) == (lhs > value)
3865 .signed => blk: {3724 .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));
3867 const rhs_lt_zero = try self.buildCmp(.s_lt, rhs, zero);3726 const rhs_lt_zero = try self.buildCmp(.s_lt, rhs, zero);
3868 const result_gt_lhs = try self.buildCmp(scmp, lhs, result);3727 const result_gt_lhs = try self.buildCmp(scmp, lhs, result);
3869 break :blk try self.buildCmp(.l_eq, rhs_lt_zero, result_gt_lhs);3728 break :blk try self.buildCmp(.l_eq, rhs_lt_zero, result_gt_lhs);
...@@ -3872,15 +3731,11 @@ const NavGen = struct {...@@ -3872,15 +3731,11 @@ const NavGen = struct {
38723731
3873 const ov = try self.intFromBool(overflowed);3732 const ov = try self.intFromBool(overflowed);
38743733
3875 return try self.constructStruct(3734 const result_ty_id = try self.resolveType(result_ty, .direct);
3876 result_ty,3735 return try self.constructComposite(result_ty_id, &.{ try result.materialize(self), try ov.materialize(self) });
3877 &.{ result.ty, ov.ty },
3878 &.{ try result.materialize(self), try ov.materialize(self) },
3879 );
3880 }3736 }
38813737
3882 fn airMulOverflow(self: *NavGen, inst: Air.Inst.Index) !?IdRef {3738 fn airMulOverflow(self: *NavGen, inst: Air.Inst.Index) !?IdRef {
3883 const target = self.getTarget();
3884 const pt = self.pt;3739 const pt = self.pt;
38853740
3886 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;3741 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
...@@ -3904,7 +3759,7 @@ const NavGen = struct {...@@ -3904,7 +3759,7 @@ const NavGen = struct {
3904 // - Additionally, if info.bits != 32, we'll have to check the high bits3759 // - Additionally, if info.bits != 32, we'll have to check the high bits
3905 // of the result too.3760 // 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();
3908 // If non-null, the number of bits that the multiplication should be performed in. If3763 // If non-null, the number of bits that the multiplication should be performed in. If
3909 // null, we have to use wide multiplication.3764 // null, we have to use wide multiplication.
3910 const maybe_op_ty_bits: ?u16 = switch (info.bits) {3765 const maybe_op_ty_bits: ?u16 = switch (info.bits) {
...@@ -3928,11 +3783,11 @@ const NavGen = struct {...@@ -3928,11 +3783,11 @@ const NavGen = struct {
3928 const result = try self.normalize(low_bits, info);3783 const result = try self.normalize(low_bits, info);
39293784
3930 // Shift the result bits away to get the overflow bits.3785 // 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));
3932 const overflow = try self.buildBinary(.srl, full_result, shift);3787 const overflow = try self.buildBinary(.srl, full_result, shift);
39333788
3934 // Directly check if its zero in the op_ty without converting first.3789 // 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));
3936 const overflowed = try self.buildCmp(.i_ne, zero, overflow);3791 const overflowed = try self.buildCmp(.i_ne, zero, overflow);
39373792
3938 break :blk .{ result, overflowed };3793 break :blk .{ result, overflowed };
...@@ -3946,7 +3801,7 @@ const NavGen = struct {...@@ -3946,7 +3801,7 @@ const NavGen = struct {
3946 // Overflow happened if the high-bits of the result are non-zero OR if the3801 // Overflow happened if the high-bits of the result are non-zero OR if the
3947 // high bits of the low word of the result (those outside the range of the3802 // high bits of the low word of the result (those outside the range of the
3948 // int) are nonzero.3803 // 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));
3950 const high_overflowed = try self.buildCmp(.i_ne, zero, high_bits);3805 const high_overflowed = try self.buildCmp(.i_ne, zero, high_bits);
39513806
3952 // If no overflow bits in low_bits, no extra work needs to be done.3807 // If no overflow bits in low_bits, no extra work needs to be done.
...@@ -3955,7 +3810,7 @@ const NavGen = struct {...@@ -3955,7 +3810,7 @@ const NavGen = struct {
3955 }3810 }
39563811
3957 // Shift the result bits away to get the overflow bits.3812 // 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));
3959 const low_overflow = try self.buildBinary(.srl, low_bits, shift);3814 const low_overflow = try self.buildBinary(.srl, low_bits, shift);
3960 const low_overflowed = try self.buildCmp(.i_ne, zero, low_overflow);3815 const low_overflowed = try self.buildCmp(.i_ne, zero, low_overflow);
39613816
...@@ -3974,7 +3829,7 @@ const NavGen = struct {...@@ -3974,7 +3829,7 @@ const NavGen = struct {
3974 // overflow should be -1 when3829 // overflow should be -1 when
3975 // (lhs > 0 && rhs < 0) || (lhs < 0 && rhs > 0)3830 // (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));
3978 const lhs_negative = try self.buildCmp(.s_lt, lhs, zero);3833 const lhs_negative = try self.buildCmp(.s_lt, lhs, zero);
3979 const rhs_negative = try self.buildCmp(.s_lt, rhs, zero);3834 const rhs_negative = try self.buildCmp(.s_lt, rhs, zero);
3980 const lhs_positive = try self.buildCmp(.s_gt, lhs, zero);3835 const lhs_positive = try self.buildCmp(.s_gt, lhs, zero);
...@@ -4003,13 +3858,13 @@ const NavGen = struct {...@@ -4003,13 +3858,13 @@ const NavGen = struct {
4003 // bit for the expected overflow bits.3858 // bit for the expected overflow bits.
4004 // To do that, shift out everything bit the sign bit and3859 // To do that, shift out everything bit the sign bit and
4005 // then check what remains.3860 // 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));
4007 // Use SRA so that any sign bits are duplicated. Now we can just check if ALL bits are set3862 // Use SRA so that any sign bits are duplicated. Now we can just check if ALL bits are set
4008 // for negative cases.3863 // for negative cases.
4009 const overflow = try self.buildBinary(.sra, full_result, shift);3864 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));3866 const long_all_set = Temporary.init(full_result.ty, try self.constInt(full_result.ty, -1));
4012 const long_zero = Temporary.init(full_result.ty, try self.constInt(full_result.ty, 0, .direct));3867 const long_zero = Temporary.init(full_result.ty, try self.constInt(full_result.ty, 0));
4013 const mask = try self.buildSelect(expected_overflow_bit, long_all_set, long_zero);3868 const mask = try self.buildSelect(expected_overflow_bit, long_all_set, long_zero);
40143869
4015 const overflowed = try self.buildCmp(.i_ne, mask, overflow);3870 const overflowed = try self.buildCmp(.i_ne, mask, overflow);
...@@ -4022,7 +3877,7 @@ const NavGen = struct {...@@ -4022,7 +3877,7 @@ const NavGen = struct {
4022 // Truncate result if required.3877 // Truncate result if required.
4023 const result = try self.normalize(low_bits, info);3878 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));
4026 const mask = try self.buildSelect(expected_overflow_bit, all_set, zero);3881 const mask = try self.buildSelect(expected_overflow_bit, all_set, zero);
40273882
4028 // Like with unsigned, overflow happened if high_bits are not the ones we expect,3883 // Like with unsigned, overflow happened if high_bits are not the ones we expect,
...@@ -4038,7 +3893,7 @@ const NavGen = struct {...@@ -4038,7 +3893,7 @@ const NavGen = struct {
4038 }3893 }
40393894
4040 // Shift the result bits away to get the overflow bits.3895 // 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));
4042 // Use SRA so that any sign bits are duplicated. Now we can just check if ALL bits are set3897 // Use SRA so that any sign bits are duplicated. Now we can just check if ALL bits are set
4043 // for negative cases.3898 // for negative cases.
4044 const low_overflow = try self.buildBinary(.sra, low_bits, shift);3899 const low_overflow = try self.buildBinary(.sra, low_bits, shift);
...@@ -4052,11 +3907,8 @@ const NavGen = struct {...@@ -4052,11 +3907,8 @@ const NavGen = struct {
40523907
4053 const ov = try self.intFromBool(overflowed);3908 const ov = try self.intFromBool(overflowed);
40543909
4055 return try self.constructStruct(3910 const result_ty_id = try self.resolveType(result_ty, .direct);
4056 result_ty,3911 return try self.constructComposite(result_ty_id, &.{ try result.materialize(self), try ov.materialize(self) });
4057 &.{ result.ty, ov.ty },
4058 &.{ try result.materialize(self), try ov.materialize(self) },
4059 );
4060 }3912 }
40613913
4062 fn airShlOverflow(self: *NavGen, inst: Air.Inst.Index) !?IdRef {3914 fn airShlOverflow(self: *NavGen, inst: Air.Inst.Index) !?IdRef {
...@@ -4092,11 +3944,8 @@ const NavGen = struct {...@@ -4092,11 +3944,8 @@ const NavGen = struct {
4092 const overflowed = try self.buildCmp(.i_ne, base, right);3944 const overflowed = try self.buildCmp(.i_ne, base, right);
4093 const ov = try self.intFromBool(overflowed);3945 const ov = try self.intFromBool(overflowed);
40943946
4095 return try self.constructStruct(3947 const result_ty_id = try self.resolveType(result_ty, .direct);
4096 result_ty,3948 return try self.constructComposite(result_ty_id, &.{ try result.materialize(self), try ov.materialize(self) });
4097 &.{ result.ty, ov.ty },
4098 &.{ try result.materialize(self), try ov.materialize(self) },
4099 );
4100 }3949 }
41013950
4102 fn airMulAdd(self: *NavGen, inst: Air.Inst.Index) !?IdRef {3951 fn airMulAdd(self: *NavGen, inst: Air.Inst.Index) !?IdRef {
...@@ -4119,7 +3968,6 @@ const NavGen = struct {...@@ -4119,7 +3968,6 @@ const NavGen = struct {
4119 if (self.liveness.isUnused(inst)) return null;3968 if (self.liveness.isUnused(inst)) return null;
41203969
4121 const zcu = self.pt.zcu;3970 const zcu = self.pt.zcu;
4122 const target = self.getTarget();
4123 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;3971 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
4124 const operand = try self.temporary(ty_op.operand);3972 const operand = try self.temporary(ty_op.operand);
41253973
...@@ -4132,10 +3980,7 @@ const NavGen = struct {...@@ -4132,10 +3980,7 @@ const NavGen = struct {
4132 .float, .bool => unreachable,3980 .float, .bool => unreachable,
4133 }3981 }
41343982
4135 switch (target.os.tag) {3983 assert(self.spv.hasFeature(.kernel)); // TODO
4136 .vulkan => unreachable, // TODO
4137 else => {},
4138 }
41393984
4140 const count = try self.buildUnary(op, operand);3985 const count = try self.buildUnary(op, operand);
41413986
...@@ -4163,7 +4008,7 @@ const NavGen = struct {...@@ -4163,7 +4008,7 @@ const NavGen = struct {
4163 const operand_id = try self.resolve(ty_op.operand);4008 const operand_id = try self.resolve(ty_op.operand);
4164 const result_ty = self.typeOfIndex(inst);4009 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);
4167 }4012 }
41684013
4169 fn airReduce(self: *NavGen, inst: Air.Inst.Index) !?IdRef {4014 fn airReduce(self: *NavGen, inst: Air.Inst.Index) !?IdRef {
...@@ -4297,10 +4142,10 @@ const NavGen = struct {...@@ -4297,10 +4142,10 @@ const NavGen = struct {
42974142
4298 // Fall back to manually extracting and inserting components.4143 // Fall back to manually extracting and inserting components.
42994144
4300 const components = try self.gpa.alloc(IdRef, result_ty.vectorLen(zcu));4145 const constituents = try self.gpa.alloc(IdRef, result_ty.vectorLen(zcu));
4301 defer self.gpa.free(components);4146 defer self.gpa.free(constituents);
43024147
4303 for (components, 0..) |*id, i| {4148 for (constituents, 0..) |*id, i| {
4304 const elem = try mask.elemValue(pt, i);4149 const elem = try mask.elemValue(pt, i);
4305 if (elem.isUndef(zcu)) {4150 if (elem.isUndef(zcu)) {
4306 id.* = try self.spv.constUndef(scalar_ty_id);4151 id.* = try self.spv.constUndef(scalar_ty_id);
...@@ -4315,14 +4160,15 @@ const NavGen = struct {...@@ -4315,14 +4160,15 @@ const NavGen = struct {
4315 }4160 }
4316 }4161 }
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);
4319 }4165 }
43204166
4321 fn indicesToIds(self: *NavGen, indices: []const u32) ![]IdRef {4167 fn indicesToIds(self: *NavGen, indices: []const u32) ![]IdRef {
4322 const ids = try self.gpa.alloc(IdRef, indices.len);4168 const ids = try self.gpa.alloc(IdRef, indices.len);
4323 errdefer self.gpa.free(ids);4169 errdefer self.gpa.free(ids);
4324 for (indices, ids) |index, *id| {4170 for (indices, ids) |index, *id| {
4325 id.* = try self.constInt(Type.u32, index, .direct);4171 id.* = try self.constInt(Type.u32, index);
4326 }4172 }
43274173
4328 return ids;4174 return ids;
...@@ -4370,23 +4216,22 @@ const NavGen = struct {...@@ -4370,23 +4216,22 @@ const NavGen = struct {
4370 defer self.gpa.free(ids);4216 defer self.gpa.free(ids);
43714217
4372 const result_id = self.spv.allocId();4218 const result_id = self.spv.allocId();
4373 const target = self.getTarget();4219 if (self.spv.hasFeature(.kernel)) {
4374 switch (target.os.tag) {4220 try self.func.body.emit(self.spv.gpa, .OpInBoundsPtrAccessChain, .{
4375 .opencl => try self.func.body.emit(self.spv.gpa, .OpInBoundsPtrAccessChain, .{
4376 .id_result_type = result_ty_id,4221 .id_result_type = result_ty_id,
4377 .id_result = result_id,4222 .id_result = result_id,
4378 .base = base,4223 .base = base,
4379 .element = element,4224 .element = element,
4380 .indexes = ids,4225 .indexes = ids,
4381 }),4226 });
4382 .vulkan => try self.func.body.emit(self.spv.gpa, .OpPtrAccessChain, .{4227 } else {
4228 try self.func.body.emit(self.spv.gpa, .OpPtrAccessChain, .{
4383 .id_result_type = result_ty_id,4229 .id_result_type = result_ty_id,
4384 .id_result = result_id,4230 .id_result = result_id,
4385 .base = base,4231 .base = base,
4386 .element = element,4232 .element = element,
4387 .indexes = ids,4233 .indexes = ids,
4388 }),4234 });
4389 else => unreachable,
4390 }4235 }
4391 return result_id;4236 return result_id;
4392 }4237 }
...@@ -4676,7 +4521,7 @@ const NavGen = struct {...@@ -4676,7 +4521,7 @@ const NavGen = struct {
4676 break :blk result_id;4521 break :blk result_id;
4677 }4522 }
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
4681 const tmp_id = try self.alloc(src_ty, .{ .storage_class = .Function });4526 const tmp_id = try self.alloc(src_ty, .{ .storage_class = .Function });
4682 try self.store(src_ty, tmp_id, src_id, .{});4527 try self.store(src_ty, tmp_id, src_id, .{});
...@@ -4851,7 +4696,7 @@ const NavGen = struct {...@@ -4851,7 +4696,7 @@ const NavGen = struct {
4851 const elem_ptr_ty_id = try self.resolveType(elem_ptr_ty, .direct);4696 const elem_ptr_ty_id = try self.resolveType(elem_ptr_ty, .direct);
48524697
4853 const array_ptr_id = try self.resolve(ty_op.operand);4698 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
4856 const elem_ptr_id = if (!array_ty.hasRuntimeBitsIgnoreComptime(zcu))4701 const elem_ptr_id = if (!array_ty.hasRuntimeBitsIgnoreComptime(zcu))
4857 // Note: The pointer is something like *opaque{}, so we need to bitcast it to the element type.4702 // Note: The pointer is something like *opaque{}, so we need to bitcast it to the element type.
...@@ -4860,11 +4705,8 @@ const NavGen = struct {...@@ -4860,11 +4705,8 @@ const NavGen = struct {
4860 // Convert the pointer-to-array to a pointer to the first element.4705 // Convert the pointer-to-array to a pointer to the first element.
4861 try self.accessChain(elem_ptr_ty_id, array_ptr_id, &.{0});4706 try self.accessChain(elem_ptr_ty_id, array_ptr_id, &.{0});
48624707
4863 return try self.constructStruct(4708 const slice_ty_id = try self.resolveType(slice_ty, .direct);
4864 slice_ty,4709 return try self.constructComposite(slice_ty_id, &.{ elem_ptr_id, len_id });
4865 &.{ elem_ptr_ty, Type.usize },
4866 &.{ elem_ptr_id, len_id },
4867 );
4868 }4710 }
48694711
4870 fn airSlice(self: *NavGen, inst: Air.Inst.Index) !?IdRef {4712 fn airSlice(self: *NavGen, inst: Air.Inst.Index) !?IdRef {
...@@ -4872,16 +4714,9 @@ const NavGen = struct {...@@ -4872,16 +4714,9 @@ const NavGen = struct {
4872 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;4714 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
4873 const ptr_id = try self.resolve(bin_op.lhs);4715 const ptr_id = try self.resolve(bin_op.lhs);
4874 const len_id = try self.resolve(bin_op.rhs);4716 const len_id = try self.resolve(bin_op.rhs);
4875 const ptr_ty = self.typeOf(bin_op.lhs);
4876 const slice_ty = self.typeOfIndex(inst);4717 const slice_ty = self.typeOfIndex(inst);
48774718 const slice_ty_id = try self.resolveType(slice_ty, .direct);
4878 // Note: Types should not need to be converted to direct, these types4719 return try self.constructComposite(slice_ty_id, &.{ ptr_id, len_id });
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 );
4885 }4720 }
48864721
4887 fn airAggregateInit(self: *NavGen, inst: Air.Inst.Index) !?IdRef {4722 fn airAggregateInit(self: *NavGen, inst: Air.Inst.Index) !?IdRef {
...@@ -4936,11 +4771,8 @@ const NavGen = struct {...@@ -4936,11 +4771,8 @@ const NavGen = struct {
4936 else => unreachable,4771 else => unreachable,
4937 }4772 }
49384773
4939 return try self.constructStruct(4774 const result_ty_id = try self.resolveType(result_ty, .direct);
4940 result_ty,4775 return try self.constructComposite(result_ty_id, constituents[0..index]);
4941 types[0..index],
4942 constituents[0..index],
4943 );
4944 },4776 },
4945 .vector => {4777 .vector => {
4946 const n_elems = result_ty.vectorLen(zcu);4778 const n_elems = result_ty.vectorLen(zcu);
...@@ -4951,7 +4783,8 @@ const NavGen = struct {...@@ -4951,7 +4783,8 @@ const NavGen = struct {
4951 elem_ids[i] = try self.resolve(element);4783 elem_ids[i] = try self.resolve(element);
4952 }4784 }
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);
4955 },4788 },
4956 .array => {4789 .array => {
4957 const array_info = result_ty.arrayInfo(zcu);4790 const array_info = result_ty.arrayInfo(zcu);
...@@ -4968,7 +4801,8 @@ const NavGen = struct {...@@ -4968,7 +4801,8 @@ const NavGen = struct {
4968 elem_ids[n_elems - 1] = try self.constant(array_info.elem_type, sentinel_val, .indirect);4801 elem_ids[n_elems - 1] = try self.constant(array_info.elem_type, sentinel_val, .indirect);
4969 }4802 }
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);
4972 },4806 },
4973 else => unreachable,4807 else => unreachable,
4974 }4808 }
...@@ -4984,7 +4818,7 @@ const NavGen = struct {...@@ -4984,7 +4818,7 @@ const NavGen = struct {
4984 const elem_ty = array_ty.childType(zcu);4818 const elem_ty = array_ty.childType(zcu);
4985 const abi_size = elem_ty.abiSize(zcu);4819 const abi_size = elem_ty.abiSize(zcu);
4986 const size = array_ty.arrayLenIncludingSentinel(zcu) * abi_size;4820 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);
4988 },4822 },
4989 .many, .c => unreachable,4823 .many, .c => unreachable,
4990 }4824 }
...@@ -5060,7 +4894,7 @@ const NavGen = struct {...@@ -5060,7 +4894,7 @@ const NavGen = struct {
5060 const zcu = self.pt.zcu;4894 const zcu = self.pt.zcu;
5061 // Construct new pointer type for the resulting pointer4895 // Construct new pointer type for the resulting pointer
5062 const elem_ty = ptr_ty.elemType2(zcu); // use elemType() so that we get T for *[N]T.4896 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);
5064 if (ptr_ty.isSinglePointer(zcu)) {4898 if (ptr_ty.isSinglePointer(zcu)) {
5065 // Pointer-to-array. In this case, the resulting pointer is not of the same type4899 // Pointer-to-array. In this case, the resulting pointer is not of the same type
5066 // as the ptr_ty (we want a *T, not a *[N]T), and hence we need to use accessChain.4900 // 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 {...@@ -5115,8 +4949,8 @@ const NavGen = struct {
5115 const is_vector = array_ty.isVector(zcu);4949 const is_vector = array_ty.isVector(zcu);
51164950
5117 const elem_repr: Repr = if (is_vector) .direct else .indirect;4951 const elem_repr: Repr = if (is_vector) .direct else .indirect;
5118 const ptr_array_ty_id = try self.ptrType2(array_ty, .Function, .direct);4952 const ptr_array_ty_id = try self.ptrType(array_ty, .Function, .direct);
5119 const ptr_elem_ty_id = try self.ptrType2(elem_ty, .Function, elem_repr);4953 const ptr_elem_ty_id = try self.ptrType(elem_ty, .Function, elem_repr);
51204954
5121 const tmp_id = self.spv.allocId();4955 const tmp_id = self.spv.allocId();
5122 try self.func.prologue.emit(self.spv.gpa, .OpVariable, .{4956 try self.func.prologue.emit(self.spv.gpa, .OpVariable, .{
...@@ -5171,7 +5005,7 @@ const NavGen = struct {...@@ -5171,7 +5005,7 @@ const NavGen = struct {
5171 const scalar_ty = vector_ty.scalarType(zcu);5005 const scalar_ty = vector_ty.scalarType(zcu);
51725006
5173 const storage_class = self.spvStorageClass(vector_ptr_ty.ptrAddressSpace(zcu));5007 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
5176 const vector_ptr = try self.resolve(data.vector_ptr);5010 const vector_ptr = try self.resolve(data.vector_ptr);
5177 const index = try self.resolve(extra.lhs);5011 const index = try self.resolve(extra.lhs);
...@@ -5193,7 +5027,7 @@ const NavGen = struct {...@@ -5193,7 +5027,7 @@ const NavGen = struct {
5193 if (layout.tag_size == 0) return;5027 if (layout.tag_size == 0) return;
51945028
5195 const tag_ty = un_ty.unionTagTypeSafety(zcu).?;5029 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
5198 const union_ptr_id = try self.resolve(bin_op.lhs);5032 const union_ptr_id = try self.resolve(bin_op.lhs);
5199 const new_tag_id = try self.resolve(bin_op.rhs);5033 const new_tag_id = try self.resolve(bin_op.rhs);
...@@ -5252,23 +5086,23 @@ const NavGen = struct {...@@ -5252,23 +5086,23 @@ const NavGen = struct {
5252 } else 0;5086 } else 0;
52535087
5254 if (!layout.has_payload) {5088 if (!layout.has_payload) {
5255 return try self.constInt(tag_ty, tag_int, .direct);5089 return try self.constInt(tag_ty, tag_int);
5256 }5090 }
52575091
5258 const tmp_id = try self.alloc(ty, .{ .storage_class = .Function });5092 const tmp_id = try self.alloc(ty, .{ .storage_class = .Function });
52595093
5260 if (layout.tag_size != 0) {5094 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);
5262 const ptr_id = try self.accessChain(tag_ptr_ty_id, tmp_id, &.{@as(u32, @intCast(layout.tag_index))});5096 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);
5264 try self.store(tag_ty, ptr_id, tag_id, .{});5098 try self.store(tag_ty, ptr_id, tag_id, .{});
5265 }5099 }
52665100
5267 const payload_ty = Type.fromInterned(union_ty.field_types.get(ip)[active_field]);5101 const payload_ty = Type.fromInterned(union_ty.field_types.get(ip)[active_field]);
5268 if (payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {5102 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);
5270 const pl_ptr_id = try self.accessChain(pl_ptr_ty_id, tmp_id, &.{layout.payload_index});5104 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);
5272 const active_pl_ptr_id = self.spv.allocId();5106 const active_pl_ptr_id = self.spv.allocId();
5273 try self.func.body.emit(self.spv.gpa, .OpBitcast, .{5107 try self.func.body.emit(self.spv.gpa, .OpBitcast, .{
5274 .id_result_type = active_pl_ptr_ty_id,5108 .id_result_type = active_pl_ptr_ty_id,
...@@ -5332,10 +5166,10 @@ const NavGen = struct {...@@ -5332,10 +5166,10 @@ const NavGen = struct {
5332 const tmp_id = try self.alloc(object_ty, .{ .storage_class = .Function });5166 const tmp_id = try self.alloc(object_ty, .{ .storage_class = .Function });
5333 try self.store(object_ty, tmp_id, object_id, .{});5167 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);
5336 const pl_ptr_id = try self.accessChain(pl_ptr_ty_id, tmp_id, &.{layout.payload_index});5170 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);
5339 const active_pl_ptr_id = self.spv.allocId();5173 const active_pl_ptr_id = self.spv.allocId();
5340 try self.func.body.emit(self.spv.gpa, .OpBitcast, .{5174 try self.func.body.emit(self.spv.gpa, .OpBitcast, .{
5341 .id_result_type = active_pl_ptr_ty_id,5175 .id_result_type = active_pl_ptr_ty_id,
...@@ -5365,7 +5199,7 @@ const NavGen = struct {...@@ -5365,7 +5199,7 @@ const NavGen = struct {
5365 const base_ptr_int = base_ptr_int: {5199 const base_ptr_int = base_ptr_int: {
5366 if (field_offset == 0) break :base_ptr_int field_ptr_int;5200 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);
5369 const field_ptr_tmp = Temporary.init(Type.usize, field_ptr_int);5203 const field_ptr_tmp = Temporary.init(Type.usize, field_ptr_int);
5370 const field_offset_tmp = Temporary.init(Type.usize, field_offset_id);5204 const field_offset_tmp = Temporary.init(Type.usize, field_offset_id);
5371 const result = try self.buildBinary(.i_sub, field_ptr_tmp, field_offset_tmp);5205 const result = try self.buildBinary(.i_sub, field_ptr_tmp, field_offset_tmp);
...@@ -5415,7 +5249,7 @@ const NavGen = struct {...@@ -5415,7 +5249,7 @@ const NavGen = struct {
5415 }5249 }
54165250
5417 const storage_class = self.spvStorageClass(object_ptr_ty.ptrAddressSpace(zcu));5251 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);
5419 const pl_ptr_id = try self.accessChain(pl_ptr_ty_id, object_ptr, &.{layout.payload_index});5253 const pl_ptr_id = try self.accessChain(pl_ptr_ty_id, object_ptr, &.{layout.payload_index});
54205254
5421 const active_pl_ptr_id = self.spv.allocId();5255 const active_pl_ptr_id = self.spv.allocId();
...@@ -5456,7 +5290,7 @@ const NavGen = struct {...@@ -5456,7 +5290,7 @@ const NavGen = struct {
5456 ty: Type,5290 ty: Type,
5457 options: AllocOptions,5291 options: AllocOptions,
5458 ) !IdRef {5292 ) !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
5461 // SPIR-V requires that OpVariable declarations for locals go into the first block, so we are just going to5295 // SPIR-V requires that OpVariable declarations for locals go into the first block, so we are just going to
5462 // directly generate them into func.prologue instead of the body.5296 // directly generate them into func.prologue instead of the body.
...@@ -5468,14 +5302,11 @@ const NavGen = struct {...@@ -5468,14 +5302,11 @@ const NavGen = struct {
5468 .initializer = options.initializer,5302 .initializer = options.initializer,
5469 });5303 });
54705304
5471 const target = self.getTarget();5305 if (self.spv.hasFeature(.shader)) return var_id;
5472 if (target.os.tag == .vulkan) {
5473 return var_id;
5474 }
54755306
5476 switch (options.storage_class) {5307 switch (options.storage_class) {
5477 .Generic => {5308 .Generic => {
5478 const ptr_gn_ty_id = try self.ptrType(ty, .Generic);5309 const ptr_gn_ty_id = try self.ptrType(ty, .Generic, .indirect);
5479 // Convert to a generic pointer5310 // Convert to a generic pointer
5480 return self.castToGeneric(ptr_gn_ty_id, var_id);5311 return self.castToGeneric(ptr_gn_ty_id, var_id);
5481 },5312 },
...@@ -5724,7 +5555,7 @@ const NavGen = struct {...@@ -5724,7 +5555,7 @@ const NavGen = struct {
5724 assert(cf.block_stack.items.len > 0);5555 assert(cf.block_stack.items.len > 0);
57255556
5726 // Check if the target of the branch was this current block.5557 // 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));
5728 const jump_to_this_block_id = self.spv.allocId();5559 const jump_to_this_block_id = self.spv.allocId();
5729 const bool_ty_id = try self.resolveType(Type.bool, .direct);5560 const bool_ty_id = try self.resolveType(Type.bool, .direct);
5730 try self.func.body.emit(self.spv.gpa, .OpIEqual, .{5561 try self.func.body.emit(self.spv.gpa, .OpIEqual, .{
...@@ -5804,7 +5635,7 @@ const NavGen = struct {...@@ -5804,7 +5635,7 @@ const NavGen = struct {
5804 try self.store(operand_ty, block_result_var_id, operand_id, .{});5635 try self.store(operand_ty, block_result_var_id, operand_id, .{});
5805 }5636 }
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));
5808 try self.structuredBreak(next_block);5639 try self.structuredBreak(next_block);
5809 },5640 },
5810 .unstructured => |cf| {5641 .unstructured => |cf| {
...@@ -5968,7 +5799,7 @@ const NavGen = struct {...@@ -5968,7 +5799,7 @@ const NavGen = struct {
5968 // Functions with an empty error set are emitted with an error code5799 // Functions with an empty error set are emitted with an error code
5969 // return type and return zero so they can be function pointers coerced5800 // return type and return zero so they can be function pointers coerced
5970 // to functions that return anyerror.5801 // 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);
5972 return try self.func.body.emit(self.spv.gpa, .OpReturnValue, .{ .value = no_err_id });5803 return try self.func.body.emit(self.spv.gpa, .OpReturnValue, .{ .value = no_err_id });
5973 } else {5804 } else {
5974 return try self.func.body.emit(self.spv.gpa, .OpReturn, {});5805 return try self.func.body.emit(self.spv.gpa, .OpReturn, {});
...@@ -5992,7 +5823,7 @@ const NavGen = struct {...@@ -5992,7 +5823,7 @@ const NavGen = struct {
5992 // Functions with an empty error set are emitted with an error code5823 // Functions with an empty error set are emitted with an error code
5993 // return type and return zero so they can be function pointers coerced5824 // return type and return zero so they can be function pointers coerced
5994 // to functions that return anyerror.5825 // 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);
5996 return try self.func.body.emit(self.spv.gpa, .OpReturnValue, .{ .value = no_err_id });5827 return try self.func.body.emit(self.spv.gpa, .OpReturnValue, .{ .value = no_err_id });
5997 } else {5828 } else {
5998 return try self.func.body.emit(self.spv.gpa, .OpReturn, {});5829 return try self.func.body.emit(self.spv.gpa, .OpReturn, {});
...@@ -6026,7 +5857,7 @@ const NavGen = struct {...@@ -6026,7 +5857,7 @@ const NavGen = struct {
6026 else5857 else
6027 err_union_id;5858 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);
6030 const is_err_id = self.spv.allocId();5861 const is_err_id = self.spv.allocId();
6031 try self.func.body.emit(self.spv.gpa, .OpINotEqual, .{5862 try self.func.body.emit(self.spv.gpa, .OpINotEqual, .{
6032 .id_result_type = bool_ty_id,5863 .id_result_type = bool_ty_id,
...@@ -6134,7 +5965,8 @@ const NavGen = struct {...@@ -6134,7 +5965,8 @@ const NavGen = struct {
6134 types[eu_layout.errorFieldIndex()] = Type.anyerror;5965 types[eu_layout.errorFieldIndex()] = Type.anyerror;
6135 types[eu_layout.payloadFieldIndex()] = payload_ty;5966 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);
6138 }5970 }
61395971
6140 fn airWrapErrUnionPayload(self: *NavGen, inst: Air.Inst.Index) !?IdRef {5972 fn airWrapErrUnionPayload(self: *NavGen, inst: Air.Inst.Index) !?IdRef {
...@@ -6145,18 +5977,19 @@ const NavGen = struct {...@@ -6145,18 +5977,19 @@ const NavGen = struct {
6145 const eu_layout = self.errorUnionLayout(payload_ty);5977 const eu_layout = self.errorUnionLayout(payload_ty);
61465978
6147 if (!eu_layout.payload_has_bits) {5979 if (!eu_layout.payload_has_bits) {
6148 return try self.constInt(Type.anyerror, 0, .direct);5980 return try self.constInt(Type.anyerror, 0);
6149 }5981 }
61505982
6151 var members: [2]IdRef = undefined;5983 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);
6153 members[eu_layout.payloadFieldIndex()] = try self.convertToIndirect(payload_ty, operand_id);5985 members[eu_layout.payloadFieldIndex()] = try self.convertToIndirect(payload_ty, operand_id);
61545986
6155 var types: [2]Type = undefined;5987 var types: [2]Type = undefined;
6156 types[eu_layout.errorFieldIndex()] = Type.anyerror;5988 types[eu_layout.errorFieldIndex()] = Type.anyerror;
6157 types[eu_layout.payloadFieldIndex()] = payload_ty;5989 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);
6160 }5993 }
61615994
6162 fn airIsNull(self: *NavGen, inst: Air.Inst.Index, is_pointer: bool, pred: enum { is_null, is_non_null }) !?IdRef {5995 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 {...@@ -6204,7 +6037,7 @@ const NavGen = struct {
6204 if (is_pointer) {6037 if (is_pointer) {
6205 if (payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {6038 if (payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
6206 const storage_class = self.spvStorageClass(operand_ty.ptrAddressSpace(zcu));6039 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);
6208 const tag_ptr_id = try self.accessChain(bool_ptr_ty_id, operand_id, &.{1});6041 const tag_ptr_id = try self.accessChain(bool_ptr_ty_id, operand_id, &.{1});
6209 break :blk try self.load(Type.bool, tag_ptr_id, .{});6042 break :blk try self.load(Type.bool, tag_ptr_id, .{});
6210 }6043 }
...@@ -6267,7 +6100,7 @@ const NavGen = struct {...@@ -6267,7 +6100,7 @@ const NavGen = struct {
6267 .id_result_type = bool_ty_id,6100 .id_result_type = bool_ty_id,
6268 .id_result = result_id,6101 .id_result = result_id,
6269 .operand_1 = error_id,6102 .operand_1 = error_id,
6270 .operand_2 = try self.constInt(Type.anyerror, 0, .direct),6103 .operand_2 = try self.constInt(Type.anyerror, 0),
6271 },6104 },
6272 ),6105 ),
6273 }6106 }
...@@ -6335,14 +6168,14 @@ const NavGen = struct {...@@ -6335,14 +6168,14 @@ const NavGen = struct {
63356168
6336 const payload_id = try self.convertToIndirect(payload_ty, operand_id);6169 const payload_id = try self.convertToIndirect(payload_ty, operand_id);
6337 const members = [_]IdRef{ payload_id, try self.constBool(true, .indirect) };6170 const members = [_]IdRef{ payload_id, try self.constBool(true, .indirect) };
6338 const types = [_]Type{ payload_ty, Type.bool };6171 const optional_ty_id = try self.resolveType(optional_ty, .direct);
6339 return try self.constructStruct(optional_ty, &types, &members);6172 return try self.constructComposite(optional_ty_id, &members);
6340 }6173 }
63416174
6342 fn airSwitchBr(self: *NavGen, inst: Air.Inst.Index) !void {6175 fn airSwitchBr(self: *NavGen, inst: Air.Inst.Index) !void {
6343 const pt = self.pt;6176 const pt = self.pt;
6344 const zcu = pt.zcu;6177 const zcu = pt.zcu;
6345 const target = self.getTarget();6178 const target = self.spv.target;
6346 const switch_br = self.air.unwrapSwitch(inst);6179 const switch_br = self.air.unwrapSwitch(inst);
6347 const cond_ty = self.typeOf(switch_br.operand);6180 const cond_ty = self.typeOf(switch_br.operand);
6348 const cond = try self.resolve(switch_br.operand);6181 const cond = try self.resolve(switch_br.operand);
...@@ -6605,9 +6438,8 @@ const NavGen = struct {...@@ -6605,9 +6438,8 @@ const NavGen = struct {
66056438
6606 .undef => return self.fail("assembly input with 'c' constraint cannot be undefined", .{}),6439 .undef => return self.fail("assembly input with 'c' constraint cannot be undefined", .{}),
66076440
6608 .int => {6441 .int => try as.value_map.put(as.gpa, name, .{ .constant = @intCast(val.toUnsignedInt(zcu)) }),
6609 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) }),
6610 },
66116443
6612 else => unreachable, // TODO6444 else => unreachable, // TODO
6613 }6445 }
...@@ -6689,7 +6521,7 @@ const NavGen = struct {...@@ -6689,7 +6521,7 @@ const NavGen = struct {
6689 .just_declared, .unresolved_forward_reference => unreachable,6521 .just_declared, .unresolved_forward_reference => unreachable,
6690 .ty => return self.fail("cannot return spir-v type as value from assembly", .{}),6522 .ty => return self.fail("cannot return spir-v type as value from assembly", .{}),
6691 .value => |ref| return ref,6523 .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", .{}),
6693 }6525 }
66946526
6695 // TODO: Multiple results6527 // TODO: Multiple results
...@@ -6752,13 +6584,13 @@ const NavGen = struct {...@@ -6752,13 +6584,13 @@ const NavGen = struct {
67526584
6753 fn builtin3D(self: *NavGen, result_ty: Type, builtin: spec.BuiltIn, dimension: u32, out_of_range_value: anytype) !IdRef {6585 fn builtin3D(self: *NavGen, result_ty: Type, builtin: spec.BuiltIn, dimension: u32, out_of_range_value: anytype) !IdRef {
6754 if (dimension >= 3) {6586 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);
6756 }6588 }
6757 const vec_ty = try self.pt.vectorType(.{6589 const vec_ty = try self.pt.vectorType(.{
6758 .len = 3,6590 .len = 3,
6759 .child = result_ty.toIntern(),6591 .child = result_ty.toIntern(),
6760 });6592 });
6761 const ptr_ty_id = try self.ptrType(vec_ty, .Input);6593 const ptr_ty_id = try self.ptrType(vec_ty, .Input, .indirect);
6762 const spv_decl_index = try self.spv.builtin(ptr_ty_id, builtin);6594 const spv_decl_index = try self.spv.builtin(ptr_ty_id, builtin);
6763 try self.func.decl_deps.put(self.spv.gpa, spv_decl_index, {});6595 try self.func.decl_deps.put(self.spv.gpa, spv_decl_index, {});
6764 const ptr = self.spv.declPtr(spv_decl_index).result_id;6596 const ptr = self.spv.declPtr(spv_decl_index).result_id;
src/codegen/spirv/Assembler.zig+36
...@@ -135,6 +135,9 @@ const AsmValue = union(enum) {...@@ -135,6 +135,9 @@ const AsmValue = union(enum) {
135 /// This is a pre-supplied constant integer value.135 /// This is a pre-supplied constant integer value.
136 constant: u32,136 constant: u32,
137137
138 /// This is a pre-supplied constant string value.
139 string: []const u8,
140
138 /// Retrieve the result-id of this AsmValue. Asserts that this AsmValue141 /// Retrieve the result-id of this AsmValue. Asserts that this AsmValue
139 /// is of a variant that allows the result to be obtained (not an unresolved142 /// is of a variant that allows the result to be obtained (not an unresolved
140 /// forward declaration, not in the process of being declared, etc).143 /// forward declaration, not in the process of being declared, etc).
...@@ -144,6 +147,7 @@ const AsmValue = union(enum) {...@@ -144,6 +147,7 @@ const AsmValue = union(enum) {
144 .unresolved_forward_reference,147 .unresolved_forward_reference,
145 // TODO: Lower this value as constant?148 // TODO: Lower this value as constant?
146 .constant,149 .constant,
150 .string,
147 => unreachable,151 => unreachable,
148 .value => |result| result,152 .value => |result| result,
149 .ty => |result| result,153 .ty => |result| result,
...@@ -274,6 +278,16 @@ fn processInstruction(self: *Assembler) !void {...@@ -274,6 +278,16 @@ fn processInstruction(self: *Assembler) !void {
274 .OpEntryPoint => {278 .OpEntryPoint => {
275 return self.fail(0, "cannot export entry points via OpEntryPoint, export the kernel using callconv(.Kernel)", .{});279 return self.fail(0, "cannot export entry points via OpEntryPoint, export the kernel using callconv(.Kernel)", .{});
276 },280 },
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 },
277 .OpExtInstImport => blk: {291 .OpExtInstImport => blk: {
278 const set_name_offset = self.inst.operands.items[1].string;292 const set_name_offset = self.inst.operands.items[1].string;
279 const set_name = std.mem.sliceTo(self.inst.string_bytes.items[set_name_offset..], 0);293 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 {...@@ -635,6 +649,28 @@ fn parseBitEnum(self: *Assembler, kind: spec.OperandKind) !void {
635/// Also handles parsing any required extra operands.649/// Also handles parsing any required extra operands.
636fn parseValueEnum(self: *Assembler, kind: spec.OperandKind) !void {650fn parseValueEnum(self: *Assembler, kind: spec.OperandKind) !void {
637 const tok = self.currentToken();651 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
638 try self.expectToken(.value);674 try self.expectToken(.value);
639675
640 const text = self.tokenText(tok);676 const text = self.tokenText(tok);
src/codegen/spirv/Module.zig+181-26
...@@ -10,6 +10,8 @@ const Module = @This();...@@ -10,6 +10,8 @@ const Module = @This();
10const std = @import("std");10const std = @import("std");
11const Allocator = std.mem.Allocator;11const Allocator = std.mem.Allocator;
12const assert = std.debug.assert;12const assert = std.debug.assert;
13const autoHashStrat = std.hash.autoHashStrat;
14const Wyhash = std.hash.Wyhash;
1315
14const spec = @import("spec.zig");16const spec = @import("spec.zig");
15const Word = spec.Word;17const Word = spec.Word;
...@@ -19,6 +21,19 @@ const IdResultType = spec.IdResultType;...@@ -19,6 +21,19 @@ const IdResultType = spec.IdResultType;
1921
20const Section = @import("Section.zig");22const 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
22/// This structure represents a function that isc in-progress of being emitted.37/// This structure represents a function that isc in-progress of being emitted.
23/// Commonly, the contents of this structure will be merged with the appropriate38/// Commonly, the contents of this structure will be merged with the appropriate
24/// sections of the module and re-used. Note that the SPIR-V module system makes39/// sections of the module and re-used. Note that the SPIR-V module system makes
...@@ -103,6 +118,12 @@ gpa: Allocator,...@@ -103,6 +118,12 @@ gpa: Allocator,
103/// Arena for things that need to live for the length of this program.118/// Arena for things that need to live for the length of this program.
104arena: std.heap.ArenaAllocator,119arena: std.heap.ArenaAllocator,
105120
121/// Target info
122target: std.Target,
123
124/// The target SPIR-V version
125version: spec.Version,
126
106/// Module layout, according to SPIR-V Spec section 2.4, "Logical Layout of a Module".127/// Module layout, according to SPIR-V Spec section 2.4, "Logical Layout of a Module".
107sections: struct {128sections: struct {
108 /// Capability instructions129 /// Capability instructions
...@@ -159,8 +180,16 @@ cache: struct {...@@ -159,8 +180,16 @@ cache: struct {
159 // This cache is required so that @Vector(X, u1) in direct representation has the180 // This cache is required so that @Vector(X, u1) in direct representation has the
160 // same ID as @Vector(X, bool) in indirect representation.181 // same ID as @Vector(X, bool) in indirect representation.
161 vector_types: std.AutoHashMapUnmanaged(struct { IdRef, u32 }, IdRef) = .empty,182 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,
163 builtins: std.AutoHashMapUnmanaged(struct { IdRef, spec.BuiltIn }, Decl.Index) = .empty,190 builtins: std.AutoHashMapUnmanaged(struct { IdRef, spec.BuiltIn }, Decl.Index) = .empty,
191
192 bool_const: [2]?IdRef = .{ null, null },
164} = .{},193} = .{},
165194
166/// Set of Decls, referred to by Decl.Index.195/// Set of Decls, referred to by Decl.Index.
...@@ -173,13 +202,23 @@ decl_deps: std.ArrayListUnmanaged(Decl.Index) = .empty,...@@ -173,13 +202,23 @@ decl_deps: std.ArrayListUnmanaged(Decl.Index) = .empty,
173/// The list of entry points that should be exported from this module.202/// The list of entry points that should be exported from this module.
174entry_points: std.ArrayListUnmanaged(EntryPoint) = .empty,203entry_points: std.ArrayListUnmanaged(EntryPoint) = .empty,
175204
176/// The list of extended instruction sets that should be imported.205pub fn init(gpa: Allocator, target: std.Target) Module {
177extended_instruction_set: std.AutoHashMapUnmanaged(spec.InstructionSet, IdRef) = .empty,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 {
180 return .{217 return .{
181 .gpa = gpa,218 .gpa = gpa,
182 .arena = std.heap.ArenaAllocator.init(gpa),219 .arena = std.heap.ArenaAllocator.init(gpa),
220 .target = target,
221 .version = .{ .major = 1, .minor = version_minor },
183 .next_result_id = 1, // 0 is an invalid SPIR-V result id, so start counting at 1.222 .next_result_id = 1, // 0 is an invalid SPIR-V result id, so start counting at 1.
184 };223 };
185}224}
...@@ -201,14 +240,18 @@ pub fn deinit(self: *Module) void {...@@ -201,14 +240,18 @@ pub fn deinit(self: *Module) void {
201 self.cache.int_types.deinit(self.gpa);240 self.cache.int_types.deinit(self.gpa);
202 self.cache.float_types.deinit(self.gpa);241 self.cache.float_types.deinit(self.gpa);
203 self.cache.vector_types.deinit(self.gpa);242 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);
204 self.cache.builtins.deinit(self.gpa);249 self.cache.builtins.deinit(self.gpa);
205250
206 self.decls.deinit(self.gpa);251 self.decls.deinit(self.gpa);
207 self.decl_deps.deinit(self.gpa);252 self.decl_deps.deinit(self.gpa);
208
209 self.entry_points.deinit(self.gpa);253 self.entry_points.deinit(self.gpa);
210254
211 self.extended_instruction_set.deinit(self.gpa);
212 self.arena.deinit();255 self.arena.deinit();
213256
214 self.* = undefined;257 self.* = undefined;
...@@ -240,6 +283,10 @@ pub fn idBound(self: Module) Word {...@@ -240,6 +283,10 @@ pub fn idBound(self: Module) Word {
240 return self.next_result_id;283 return self.next_result_id;
241}284}
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
243fn addEntryPointDeps(290fn addEntryPointDeps(
244 self: *Module,291 self: *Module,
245 decl_index: Decl.Index,292 decl_index: Decl.Index,
...@@ -292,25 +339,68 @@ fn entryPoints(self: *Module) !Section {...@@ -292,25 +339,68 @@ fn entryPoints(self: *Module) !Section {
292 return entry_points;339 return entry_points;
293}340}
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
296 // See SPIR-V Spec section 2.3, "Physical Layout of a SPIR-V Module and Instruction"396 // See SPIR-V Spec section 2.3, "Physical Layout of a SPIR-V Module and Instruction"
297 // TODO: Audit calls to allocId() in this function to make it idempotent.397 // TODO: Audit calls to allocId() in this function to make it idempotent.
298
299 var entry_points = try self.entryPoints();398 var entry_points = try self.entryPoints();
300 defer entry_points.deinit(self.gpa);399 defer entry_points.deinit(self.gpa);
301400
302 const header = [_]Word{401 const header = [_]Word{
303 spec.magic_number,402 spec.magic_number,
304 // TODO: From cpu features403 self.version.toWord(),
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 }),
314 spec.zig_generator_id,404 spec.zig_generator_id,
315 self.idBound(),405 self.idBound(),
316 0, // Schema (currently reserved for future use)406 0, // Schema (currently reserved for future use)
...@@ -319,7 +409,7 @@ pub fn finalize(self: *Module, a: Allocator, target: std.Target) ![]Word {...@@ -319,7 +409,7 @@ pub fn finalize(self: *Module, a: Allocator, target: std.Target) ![]Word {
319 var source = Section{};409 var source = Section{};
320 defer source.deinit(self.gpa);410 defer source.deinit(self.gpa);
321 try self.sections.debug_strings.emit(self.gpa, .OpSource, .{411 try self.sections.debug_strings.emit(self.gpa, .OpSource, .{
322 .source_language = .Unknown,412 .source_language = .Zig,
323 .version = 0,413 .version = 0,
324 // We cannot emit these because the Khronos translator does not parse this instruction414 // We cannot emit these because the Khronos translator does not parse this instruction
325 // correctly.415 // correctly.
...@@ -368,11 +458,23 @@ pub fn addFunction(self: *Module, decl_index: Decl.Index, func: Fn) !void {...@@ -368,11 +458,23 @@ pub fn addFunction(self: *Module, decl_index: Decl.Index, func: Fn) !void {
368 try self.declareDeclDeps(decl_index, func.decl_deps.keys());458 try self.declareDeclDeps(decl_index, func.decl_deps.keys());
369}459}
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
371/// Imports or returns the existing id of an extended instruction set473/// Imports or returns the existing id of an extended instruction set
372pub fn importInstructionSet(self: *Module, set: spec.InstructionSet) !IdRef {474pub fn importInstructionSet(self: *Module, set: spec.InstructionSet) !IdRef {
373 assert(set != .core);475 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);
376 if (gop.found_existing) return gop.value_ptr.*;478 if (gop.found_existing) return gop.value_ptr.*;
377479
378 const result_id = self.allocId();480 const result_id = self.allocId();
...@@ -477,20 +579,69 @@ pub fn floatType(self: *Module, bits: u16) !IdRef {...@@ -477,20 +579,69 @@ pub fn floatType(self: *Module, bits: u16) !IdRef {
477 return entry.value_ptr.*;579 return entry.value_ptr.*;
478}580}
479581
480pub fn vectorType(self: *Module, len: u32, child_id: IdRef) !IdRef {582pub fn vectorType(self: *Module, len: u32, child_ty_id: IdRef) !IdRef {
481 const entry = try self.cache.vector_types.getOrPut(self.gpa, .{ child_id, len });583 const entry = try self.cache.vector_types.getOrPut(self.gpa, .{ child_ty_id, len });
482 if (!entry.found_existing) {584 if (!entry.found_existing) {
483 const result_id = self.allocId();585 const result_id = self.allocId();
484 entry.value_ptr.* = result_id;586 entry.value_ptr.* = result_id;
485 try self.sections.types_globals_constants.emit(self.gpa, .OpTypeVector, .{587 try self.sections.types_globals_constants.emit(self.gpa, .OpTypeVector, .{
486 .id_result = result_id,588 .id_result = result_id,
487 .component_type = child_id,589 .component_type = child_ty_id,
488 .component_count = len,590 .component_count = len,
489 });591 });
490 }592 }
491 return entry.value_ptr.*;593 return entry.value_ptr.*;
492}594}
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
494/// Return a pointer to a builtin variable. `result_ty_id` must be a **pointer**645/// Return a pointer to a builtin variable. `result_ty_id` must be a **pointer**
495/// with storage class `.Input`.646/// with storage class `.Input`.
496pub fn builtin(self: *Module, result_ty_id: IdRef, spirv_builtin: spec.BuiltIn) !Decl.Index {647pub fn builtin(self: *Module, result_ty_id: IdRef, spirv_builtin: spec.BuiltIn) !Decl.Index {
...@@ -534,13 +685,17 @@ pub fn decorate(...@@ -534,13 +685,17 @@ pub fn decorate(
534 target: IdRef,685 target: IdRef,
535 decoration: spec.Decoration.Extended,686 decoration: spec.Decoration.Extended,
536) !void {687) !void {
537 try self.sections.annotations.emit(self.gpa, .OpDecorate, .{688 const entry = try self.cache.decorations.getOrPut(self.gpa, .{ target, decoration });
538 .target = target,689 if (!entry.found_existing) {
539 .decoration = decoration,690 try self.sections.annotations.emit(self.gpa, .OpDecorate, .{
540 });691 .target = target,
692 .decoration = decoration,
693 });
694 }
541}695}
542696
543/// Decorate a result-id which is a member of some struct.697/// 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.
544pub fn decorateMember(699pub fn decorateMember(
545 self: *Module,700 self: *Module,
546 structure_type: IdRef,701 structure_type: IdRef,
src/link/SpirV.zig+3-63
...@@ -75,7 +75,7 @@ pub fn createEmpty(...@@ -75,7 +75,7 @@ pub fn createEmpty(
75 .disable_lld_caching = options.disable_lld_caching,75 .disable_lld_caching = options.disable_lld_caching,
76 .build_id = options.build_id,76 .build_id = options.build_id,
77 },77 },
78 .object = codegen.Object.init(gpa),78 .object = codegen.Object.init(gpa, comp.getTarget()),
79 };79 };
80 errdefer self.deinit();80 errdefer self.deinit();
8181
...@@ -172,7 +172,7 @@ pub fn updateExports(...@@ -172,7 +172,7 @@ pub fn updateExports(
172 const spv_decl_index = try self.object.resolveNav(zcu, nav_index);172 const spv_decl_index = try self.object.resolveNav(zcu, nav_index);
173 const cc = Type.fromInterned(nav_ty).fnCallingConvention(zcu);173 const cc = Type.fromInterned(nav_ty).fnCallingConvention(zcu);
174 const execution_model: spec.ExecutionModel = switch (target.os.tag) {174 const execution_model: spec.ExecutionModel = switch (target.os.tag) {
175 .vulkan => switch (cc) {175 .vulkan, .opengl => switch (cc) {
176 .spirv_vertex => .Vertex,176 .spirv_vertex => .Vertex,
177 .spirv_fragment => .Fragment,177 .spirv_fragment => .Fragment,
178 .spirv_kernel => .GLCompute,178 .spirv_kernel => .GLCompute,
...@@ -231,15 +231,10 @@ pub fn flushModule(...@@ -231,15 +231,10 @@ pub fn flushModule(
231 const spv = &self.object.spv;231 const spv = &self.object.spv;
232 const diags = &comp.link_diags;232 const diags = &comp.link_diags;
233 const gpa = comp.gpa;233 const gpa = comp.gpa;
234 const target = comp.getTarget();
235
236 try writeCapabilities(spv, target);
237 try writeMemoryModel(spv, target);
238234
239 // We need to export the list of error names somewhere so that we can pretty-print them in the235 // We need to export the list of error names somewhere so that we can pretty-print them in the
240 // executor. This is not really an important thing though, so we can just dump it in any old236 // executor. This is not really an important thing though, so we can just dump it in any old
241 // nonsemantic instruction. For now, just put it in OpSourceExtension with a special name.237 // nonsemantic instruction. For now, just put it in OpSourceExtension with a special name.
242
243 var error_info = std.ArrayList(u8).init(self.object.gpa);238 var error_info = std.ArrayList(u8).init(self.object.gpa);
244 defer error_info.deinit();239 defer error_info.deinit();
245240
...@@ -269,7 +264,7 @@ pub fn flushModule(...@@ -269,7 +264,7 @@ pub fn flushModule(
269 .extension = error_info.items,264 .extension = error_info.items,
270 });265 });
271266
272 const module = try spv.finalize(arena, target);267 const module = try spv.finalize(arena);
273 errdefer arena.free(module);268 errdefer arena.free(module);
274269
275 const linked_module = self.linkModule(arena, module, sub_prog_node) catch |err| switch (err) {270 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...@@ -298,58 +293,3 @@ fn linkModule(self: *SpirV, a: Allocator, module: []Word, progress: std.Progress
298293
299 return binary.finalize(a);294 return binary.finalize(a);
300}295}
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 {...@@ -155,7 +155,7 @@ const ModuleInfo = struct {
155 }155 }
156 }156 }
157157
158 return ModuleInfo{158 return .{
159 .entities = entities.unmanaged,159 .entities = entities.unmanaged,
160 .operand_is_id = operand_is_id,160 .operand_is_id = operand_is_id,
161 // There may be unrelated decorations at the end, so make sure to161 // 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 {...@@ -166,7 +166,7 @@ const ModuleInfo = struct {
166 return error.InvalidPhysicalFormat;166 return error.InvalidPhysicalFormat;
167 }167 }
168168
169 return ModuleInfo{169 return .{
170 .functions = functions.unmanaged,170 .functions = functions.unmanaged,
171 .callee_store = callee_store.items,171 .callee_store = callee_store.items,
172 .result_id_to_code_offset = result_id_to_code_offset.unmanaged,172 .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 {...@@ -43,7 +43,6 @@ pub fn build(b: *std.Build) void {
43 "../../tools/update_clang_options.zig",43 "../../tools/update_clang_options.zig",
44 "../../tools/update_cpu_features.zig",44 "../../tools/update_cpu_features.zig",
45 "../../tools/update_glibc.zig",45 "../../tools/update_glibc.zig",
46 "../../tools/update_spirv_features.zig",
47 }) |tool_src_path| {46 }) |tool_src_path| {
48 const tool = b.addTest(.{47 const tool = b.addTest(.{
49 .name = std.fs.path.stem(tool_src_path),48 .name = std.fs.path.stem(tool_src_path),
tools/update_cpu_features.zig-7
...@@ -1072,13 +1072,6 @@ const targets = [_]ArchTarget{...@@ -1072,13 +1072,6 @@ const targets = [_]ArchTarget{
1072 .td_name = "Sparc",1072 .td_name = "Sparc",
1073 },1073 },
1074 },1074 },
1075 // TODO: merge tools/update_spirv_features.zig into this script
1076 //.{
1077 // .zig_name = "spirv",
1078 // .llvm = .{
1079 // .name = "SPIRV",
1080 // },
1081 //},
1082 .{1075 .{
1083 .zig_name = "s390x",1076 .zig_name = "s390x",
1084 .llvm = .{1077 .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}