| author | |
| committer | |
| log | 4720a79477e7f0faf30bcce3ea4bfd3056469a79 |
| tree | 917bd1ad111065e548971ffec88e2b6b5ac2f6c6 |
| parent | 0779e847f79851419dfeb39595b1817ce72ea9fa |
| parent | 787208293960a02fbaf175a442d911c426a205cd |
| signature |
spirv: miscellaneous stuff11 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 | |||
| 6 | const std = @import("../std.zig"); | 1 | const std = @import("../std.zig"); |
| 7 | const CpuFeature = std.Target.Cpu.Feature; | 2 | const CpuFeature = std.Target.Cpu.Feature; |
| 8 | const CpuModel = std.Target.Cpu.Model; | 3 | const CpuModel = std.Target.Cpu.Model; |
| 9 | 4 | ||
| 10 | pub const Feature = enum { | 5 | pub 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 | }; |
| 296 | 25 | ||
| 297 | pub const featureSet = CpuFeature.FeatureSetFns(Feature).featureSet; | 26 | pub 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, | 134 | pub 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 | |||
| 2085 | pub 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 @@ |
| 1 | const std = @import("std.zig"); | 1 | const std = @import("std.zig"); |
| 2 | const comptimePrint = std.fmt.comptimePrint; | ||
| 3 | 2 | ||
| 4 | /// Will make `ptr` contain the location of the current invocation within the | 3 | /// 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 workgroup | 4 | /// 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. |
| 83 | pub fn location(comptime ptr: anytype, comptime loc: u32) void { | 82 | pub 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 | } |
| 90 | 89 | ||
| 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. |
| 93 | pub fn binding(comptime ptr: anytype, comptime group: u32, comptime bind: u32) void { | 92 | pub 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 | } |
| 103 | 102 | ||
| ... | @@ -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. |
| 113 | pub fn fragmentOrigin(comptime entry_point: anytype, comptime origin: Origin) void { | 112 | pub 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 | } |
| 123 | 119 | ||
| ... | @@ -141,37 +137,33 @@ pub const DepthMode = enum(u32) { | ... | @@ -141,37 +137,33 @@ pub const DepthMode = enum(u32) { |
| 141 | 137 | ||
| 142 | /// Only valid with the `Fragment` calling convention. | 138 | /// Only valid with the `Fragment` calling convention. |
| 143 | pub fn depthMode(comptime entry_point: anytype, comptime mode: DepthMode) void { | 139 | pub 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 | } |
| 150 | 146 | ||
| 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. |
| 153 | pub fn workgroupSize(comptime entry_point: anytype, comptime size: @Vector(3, u32)) void { | 149 | pub 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 | } |
| 164 | 158 | ||
| 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. |
| 167 | pub fn workgroupSizeHint(comptime entry_point: anytype, comptime size: @Vector(3, u32)) void { | 161 | pub 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, |
| 160 | 160 | ||
| 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, |
| 163 | 163 | ||
| 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 tell | 165 | /// - 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, |
| 178 | 178 | ||
| 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 | } |
| 185 | 185 | ||
| ... | @@ -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, |
| 315 | 315 | ||
| 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, |
| 318 | 318 | ||
| 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 | } |
| 414 | 414 | ||
| 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 | } |
| 432 | 427 | ||
| 433 | /// This imports the "default" extended instruction set for the target | 428 | /// 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 { |
| 469 | 464 | ||
| 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); |
| 473 | 468 | ||
| 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 { |
| 532 | 527 | ||
| 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)}); |
| 534 | 529 | ||
| 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 | } |
| 547 | 542 | ||
| 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 class | 546 | 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 | } |
| 562 | 553 | ||
| 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 | } |
| 578 | 567 | ||
| 579 | /// Start a new SPIR-V block, Emits the label of the new block, and stores which | 568 | /// 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); |
| 603 | 590 | ||
| 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 | }; |
| 612 | 599 | ||
| 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 | } |
| 623 | 604 | ||
| 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 | } |
| 640 | 617 | ||
| 641 | /// Checks whether the type is "composite int", an integer consisting of multiple native integers. These are represented by | 618 | /// 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 vectors | 625 | /// 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; |
| 653 | 629 | ||
| 654 | // TODO: This check must be expanded for types that can be represented | 630 | // 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 | } |
| 665 | 641 | ||
| 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 | } |
| 674 | 652 | ||
| 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 { |
| 721 | 699 | ||
| 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) { |
| 725 | 703 | .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 | } |
| 748 | 707 | ||
| 749 | /// Emits an integer constant. | 708 | /// Emits an integer constant. |
| 750 | /// This function, unlike SpvModule.constInt, takes care to bitcast | 709 | /// 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 | }; |
| 765 | 723 | ||
| 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 | }; |
| 770 | 728 | ||
| 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 | bits | 731 | value64 |
| 774 | else | 732 | else |
| 775 | bits & (@as(u64, 1) << @intCast(backing_bits)) - 1; | 733 | value64 & (@as(u64, 1) << @intCast(backing_bits)) - 1; |
| 776 | 734 | ||
| 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(); |
| 779 | 737 | ||
| 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 constants | 751 | else => unreachable, // TODO: Large integer constants |
| 794 | } | 752 | } |
| 795 | 753 | ||
| 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 | } |
| 814 | 757 | ||
| 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 | } |
| 854 | 767 | ||
| 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)); |
| 860 | 773 | ||
| 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); |
| 864 | 777 | ||
| 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 | } |
| 881 | 781 | ||
| 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 { |
| 895 | 795 | ||
| 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; |
| 901 | 801 | ||
| ... | @@ -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 type | 876 | // 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 | } |
| 1013 | 913 | ||
| 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 | else | 950 | else |
| 1054 | try self.spv.constUndef(try self.resolveType(payload_ty, .indirect)); | 951 | try self.spv.constUndef(try self.resolveType(payload_ty, .indirect)); |
| 1055 | 952 | ||
| 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 better | 971 | // 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 | } |
| 1092 | 986 | ||
| 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 | } |
| 1126 | 1017 | ||
| 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, // TODO | 1021 | .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 | } |
| 1150 | 1042 | ||
| 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; |
| 1155 | 1045 | ||
| 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 { |
| 1255 | 1145 | ||
| 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); |
| 1260 | 1150 | ||
| 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); |
| 1312 | 1202 | ||
| 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); |
| 1314 | 1204 | ||
| 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 | }; |
| 1352 | 1242 | ||
| 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 | } |
| 1357 | 1247 | ||
| 1358 | return self.spv.intType(.unsigned, backing_bits); | 1248 | return self.spv.intType(signedness, backing_bits); |
| 1359 | } | 1249 | } |
| 1360 | 1250 | ||
| 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 | } |
| 1377 | 1255 | ||
| 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 { |
| 1398 | 1277 | ||
| 1399 | const child_ty_id = try self.resolveType(child_ty, child_repr); | 1278 | const child_ty_id = try self.resolveType(child_ty, child_repr); |
| 1400 | 1279 | ||
| 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 | } |
| 1409 | 1299 | ||
| 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); |
| 1415 | 1304 | ||
| ... | @@ -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 | } |
| 1419 | 1308 | ||
| 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 | } |
| 1429 | 1311 | ||
| 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; |
| 1548 | 1430 | ||
| 1549 | const section = &self.spv.sections.types_globals_constants; | 1431 | const section = &self.spv.sections.types_globals_constants; |
| 1550 | 1432 | ||
| ... | @@ -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 | }; |
| 1604 | 1486 | ||
| ... | @@ -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 { |
| 1702 | 1584 | ||
| 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 | } | ||
| 1712 | 1588 | ||
| 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); |
| 1757 | 1633 | ||
| 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 | } |
| 1787 | 1659 | ||
| 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); |
| 1806 | 1678 | ||
| 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 | } |
| 1892 | 1760 | ||
| 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 | }); |
| 2284 | 2144 | ||
| 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 | } |
| 2448 | 2308 | ||
| 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; |
| 2451 | 2311 | ||
| 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 above | 2332 | .vulkan, .opengl => unreachable, // TODO: See above |
| 2473 | else => unreachable, | 2333 | else => unreachable, |
| 2474 | }; | 2334 | }; |
| 2475 | 2335 | ||
| ... | @@ -2606,14 +2466,14 @@ const NavGen = struct { | ... | @@ -2606,14 +2466,14 @@ const NavGen = struct { |
| 2606 | }; | 2466 | }; |
| 2607 | 2467 | ||
| 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 working | 2473 | // TODO: These instructions don't seem to be working |
| 2614 | // properly for LLVM-based backends on OpenCL for 8- and | 2474 | // 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 accuracy | 2526 | // Note: We'll need to check these for floating point accuracy |
| 2667 | // Vulkan does not put tight requirements on these, for correction | 2527 | // 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, // SAbs | 2530 | .i_abs => 5, // SAbs |
| 2671 | .f_abs => 4, // FAbs | 2531 | .f_abs => 4, // FAbs |
| 2672 | .clz => unreachable, // TODO | 2532 | .clz => unreachable, // TODO |
| ... | @@ -2736,7 +2596,7 @@ const NavGen = struct { | ... | @@ -2736,7 +2596,7 @@ const NavGen = struct { |
| 2736 | }; | 2596 | }; |
| 2737 | 2597 | ||
| 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; |
| 2740 | 2600 | ||
| 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_min | 2655 | .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, // FMax | 2659 | .f_max => 40, // FMax |
| 2800 | .s_max => 42, // SMax | 2660 | .s_max => 42, // SMax |
| 2801 | .u_max => 41, // UMax | 2661 | .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; |
| 2839 | 2699 | ||
| 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 { |
| 2964 | 2824 | ||
| 2965 | const section = &self.spv.sections.functions; | 2825 | const section = &self.spv.sections.functions; |
| 2966 | 2826 | ||
| 2967 | const target = self.getTarget(); | 2827 | const target = self.spv.target; |
| 2968 | 2828 | ||
| 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; |
| 3047 | 2907 | ||
| 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 use | 2909 | // 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); |
| 3089 | 2949 | ||
| 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 globals | 3048 | assert(storage_class != .Generic); // These should be instance globals |
| 3189 | 3049 | ||
| 3190 | const ptr_ty_id = try self.ptrType(ty, storage_class); | 3050 | const ptr_ty_id = try self.ptrType(ty, storage_class, .indirect); |
| 3191 | 3051 | ||
| 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 { |
| 3208 | 3068 | ||
| 3209 | try self.spv.declareDeclDeps(spv_decl_index, &.{}); | 3069 | try self.spv.declareDeclDeps(spv_decl_index, &.{}); |
| 3210 | 3070 | ||
| 3211 | const ptr_ty_id = try self.ptrType(ty, .Function); | 3071 | const ptr_ty_id = try self.ptrType(ty, .Function, .indirect); |
| 3212 | 3072 | ||
| 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 | } |
| 3266 | 3126 | ||
| 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); |
| 3270 | 3130 | ||
| 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); |
| 3689 | 3549 | ||
| 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)); |
| 3691 | 3551 | ||
| 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); |
| 3693 | 3553 | ||
| ... | @@ -3791,7 +3651,6 @@ const NavGen = struct { | ... | @@ -3791,7 +3651,6 @@ const NavGen = struct { |
| 3791 | } | 3651 | } |
| 3792 | 3652 | ||
| 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); |
| 3796 | 3655 | ||
| 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 when | 3662 | // 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 Vulkan | 3664 | // This is only relevant for Vulkan |
| 3806 | assert(target.os.tag != .vulkan); // TODO | 3665 | assert(self.spv.hasFeature(.kernel)); // TODO |
| 3807 | 3666 | ||
| 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 { |
| 3872 | 3731 | ||
| 3873 | const ov = try self.intFromBool(overflowed); | 3732 | const ov = try self.intFromBool(overflowed); |
| 3874 | 3733 | ||
| 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 | } |
| 3881 | 3737 | ||
| 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; |
| 3885 | 3740 | ||
| 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 bits | 3759 | // - Additionally, if info.bits != 32, we'll have to check the high bits |
| 3905 | // of the result too. | 3760 | // of the result too. |
| 3906 | 3761 | ||
| 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. If | 3763 | // 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); |
| 3929 | 3784 | ||
| 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); |
| 3933 | 3788 | ||
| 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); |
| 3937 | 3792 | ||
| 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 the | 3801 | // 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 the | 3802 | // 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); |
| 3951 | 3806 | ||
| 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 | } |
| 3956 | 3811 | ||
| 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); |
| 3961 | 3816 | ||
| ... | @@ -3974,7 +3829,7 @@ const NavGen = struct { | ... | @@ -3974,7 +3829,7 @@ const NavGen = struct { |
| 3974 | // overflow should be -1 when | 3829 | // overflow should be -1 when |
| 3975 | // (lhs > 0 && rhs < 0) || (lhs < 0 && rhs > 0) | 3830 | // (lhs > 0 && rhs < 0) || (lhs < 0 && rhs > 0) |
| 3976 | 3831 | ||
| 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 and | 3859 | // 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 set | 3862 | // 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); |
| 4010 | 3865 | ||
| 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); |
| 4014 | 3869 | ||
| 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); |
| 4024 | 3879 | ||
| 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); |
| 4027 | 3882 | ||
| 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 | } |
| 4039 | 3894 | ||
| 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 set | 3897 | // 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 { |
| 4052 | 3907 | ||
| 4053 | const ov = try self.intFromBool(overflowed); | 3908 | const ov = try self.intFromBool(overflowed); |
| 4054 | 3909 | ||
| 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 | } |
| 4061 | 3913 | ||
| 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); |
| 4094 | 3946 | ||
| 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 | } |
| 4101 | 3950 | ||
| 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; |
| 4120 | 3969 | ||
| 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); |
| 4125 | 3973 | ||
| ... | @@ -4132,10 +3980,7 @@ const NavGen = struct { | ... | @@ -4132,10 +3980,7 @@ const NavGen = struct { |
| 4132 | .float, .bool => unreachable, | 3980 | .float, .bool => unreachable, |
| 4133 | } | 3981 | } |
| 4134 | 3982 | ||
| 4135 | switch (target.os.tag) { | 3983 | assert(self.spv.hasFeature(.kernel)); // TODO |
| 4136 | .vulkan => unreachable, // TODO | ||
| 4137 | else => {}, | ||
| 4138 | } | ||
| 4139 | 3984 | ||
| 4140 | const count = try self.buildUnary(op, operand); | 3985 | const count = try self.buildUnary(op, operand); |
| 4141 | 3986 | ||
| ... | @@ -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); |
| 4165 | 4010 | ||
| 4166 | return try self.constructVectorSplat(result_ty, operand_id); | 4011 | return try self.constructCompositeSplat(result_ty, operand_id); |
| 4167 | } | 4012 | } |
| 4168 | 4013 | ||
| 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 { |
| 4297 | 4142 | ||
| 4298 | // Fall back to manually extracting and inserting components. | 4143 | // Fall back to manually extracting and inserting components. |
| 4299 | 4144 | ||
| 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); |
| 4302 | 4147 | ||
| 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 | } |
| 4317 | 4162 | ||
| 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 | } |
| 4320 | 4166 | ||
| 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 | } |
| 4327 | 4173 | ||
| 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); |
| 4371 | 4217 | ||
| 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 | } |
| 4678 | 4523 | ||
| 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); |
| 4680 | 4525 | ||
| 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); |
| 4852 | 4697 | ||
| 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)); |
| 4855 | 4700 | ||
| 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}); |
| 4862 | 4707 | ||
| 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 | } |
| 4869 | 4711 | ||
| 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); |
| 4877 | 4718 | const slice_ty_id = try self.resolveType(slice_ty, .direct); | |
| 4878 | // Note: Types should not need to be converted to direct, these types | 4719 | 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 | } |
| 4886 | 4721 | ||
| 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 | } |
| 4938 | 4773 | ||
| 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 | } |
| 4953 | 4785 | ||
| 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 | } |
| 4970 | 4803 | ||
| 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 pointer | 4895 | // 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 type | 4899 | // 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); |
| 5116 | 4950 | ||
| 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); |
| 5120 | 4954 | ||
| 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); |
| 5172 | 5006 | ||
| 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); |
| 5175 | 5009 | ||
| 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; |
| 5194 | 5028 | ||
| 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); |
| 5197 | 5031 | ||
| 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; |
| 5253 | 5087 | ||
| 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 | } |
| 5257 | 5091 | ||
| 5258 | const tmp_id = try self.alloc(ty, .{ .storage_class = .Function }); | 5092 | const tmp_id = try self.alloc(ty, .{ .storage_class = .Function }); |
| 5259 | 5093 | ||
| 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 | } |
| 5266 | 5100 | ||
| 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, .{}); |
| 5334 | 5168 | ||
| 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}); |
| 5337 | 5171 | ||
| 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; |
| 5367 | 5201 | ||
| 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 | } |
| 5416 | 5250 | ||
| 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}); |
| 5420 | 5254 | ||
| 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); |
| 5460 | 5294 | ||
| 5461 | // SPIR-V requires that OpVariable declarations for locals go into the first block, so we are just going to | 5295 | // 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 | }); |
| 5470 | 5304 | ||
| 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 | } | ||
| 5475 | 5306 | ||
| 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 pointer | 5310 | // 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); |
| 5725 | 5556 | ||
| 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 | } |
| 5806 | 5637 | ||
| 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 code | 5799 | // Functions with an empty error set are emitted with an error code |
| 5969 | // return type and return zero so they can be function pointers coerced | 5800 | // 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 code | 5823 | // Functions with an empty error set are emitted with an error code |
| 5993 | // return type and return zero so they can be function pointers coerced | 5824 | // 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 | else | 5857 | else |
| 6027 | err_union_id; | 5858 | err_union_id; |
| 6028 | 5859 | ||
| 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; |
| 6136 | 5967 | ||
| 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 | } |
| 6139 | 5971 | ||
| 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); |
| 6146 | 5978 | ||
| 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 | } |
| 6150 | 5982 | ||
| 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); |
| 6154 | 5986 | ||
| 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; |
| 6158 | 5990 | ||
| 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 | } |
| 6161 | 5994 | ||
| 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 { |
| 6335 | 6168 | ||
| 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 | } |
| 6341 | 6174 | ||
| 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 { |
| 6605 | 6438 | ||
| 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", .{}), |
| 6607 | 6440 | ||
| 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 | }, | ||
| 6611 | 6443 | ||
| 6612 | else => unreachable, // TODO | 6444 | 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 | } |
| 6694 | 6526 | ||
| 6695 | // TODO: Multiple results | 6527 | // TODO: Multiple results |
| ... | @@ -6752,13 +6584,13 @@ const NavGen = struct { | ... | @@ -6752,13 +6584,13 @@ const NavGen = struct { |
| 6752 | 6584 | ||
| 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, |
| 137 | 137 | ||
| 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 AsmValue | 141 | /// 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 unresolved | 142 | /// 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. |
| 636 | fn parseValueEnum(self: *Assembler, kind: spec.OperandKind) !void { | 650 | fn 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); |
| 639 | 675 | ||
| 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(); |
| 10 | const std = @import("std"); | 10 | const std = @import("std"); |
| 11 | const Allocator = std.mem.Allocator; | 11 | const Allocator = std.mem.Allocator; |
| 12 | const assert = std.debug.assert; | 12 | const assert = std.debug.assert; |
| 13 | const autoHashStrat = std.hash.autoHashStrat; | ||
| 14 | const Wyhash = std.hash.Wyhash; | ||
| 13 | 15 | ||
| 14 | const spec = @import("spec.zig"); | 16 | const spec = @import("spec.zig"); |
| 15 | const Word = spec.Word; | 17 | const Word = spec.Word; |
| ... | @@ -19,6 +21,19 @@ const IdResultType = spec.IdResultType; | ... | @@ -19,6 +21,19 @@ const IdResultType = spec.IdResultType; |
| 19 | 21 | ||
| 20 | const Section = @import("Section.zig"); | 22 | const Section = @import("Section.zig"); |
| 21 | 23 | ||
| 24 | /// Helper HashMap type to hash deeply | ||
| 25 | fn 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 appropriate | 38 | /// 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 makes | 39 | /// 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. |
| 104 | arena: std.heap.ArenaAllocator, | 119 | arena: std.heap.ArenaAllocator, |
| 105 | 120 | ||
| 121 | /// Target info | ||
| 122 | target: std.Target, | ||
| 123 | |||
| 124 | /// The target SPIR-V version | ||
| 125 | version: 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". |
| 107 | sections: struct { | 128 | sections: struct { |
| 108 | /// Capability instructions | 129 | /// 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 the | 180 | // 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, | ||
| 162 | 185 | ||
| 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 | } = .{}, |
| 165 | 194 | ||
| 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. |
| 174 | entry_points: std.ArrayListUnmanaged(EntryPoint) = .empty, | 203 | entry_points: std.ArrayListUnmanaged(EntryPoint) = .empty, |
| 175 | 204 | ||
| 176 | /// The list of extended instruction sets that should be imported. | 205 | pub fn init(gpa: Allocator, target: std.Target) Module { |
| 177 | extended_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 | }; | ||
| 178 | 216 | ||
| 179 | pub 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); |
| 205 | 250 | ||
| 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); |
| 210 | 254 | ||
| 211 | self.extended_instruction_set.deinit(self.gpa); | ||
| 212 | self.arena.deinit(); | 255 | self.arena.deinit(); |
| 213 | 256 | ||
| 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 | } |
| 242 | 285 | ||
| 286 | pub fn hasFeature(self: *Module, feature: std.Target.spirv.Feature) bool { | ||
| 287 | return std.Target.spirv.featureSetHas(self.target.cpu.features, feature); | ||
| 288 | } | ||
| 289 | |||
| 243 | fn addEntryPointDeps( | 290 | fn 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 | } |
| 294 | 341 | ||
| 295 | pub fn finalize(self: *Module, a: Allocator, target: std.Target) ![]Word { | 342 | pub 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); |
| 301 | 400 | ||
| 302 | const header = [_]Word{ | 401 | const header = [_]Word{ |
| 303 | spec.magic_number, | 402 | spec.magic_number, |
| 304 | // TODO: From cpu features | 403 | 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 instruction | 414 | // 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 | } |
| 370 | 460 | ||
| 461 | pub 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 | |||
| 467 | pub 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 set | 473 | /// Imports or returns the existing id of an extended instruction set |
| 372 | pub fn importInstructionSet(self: *Module, set: spec.InstructionSet) !IdRef { | 474 | pub fn importInstructionSet(self: *Module, set: spec.InstructionSet) !IdRef { |
| 373 | assert(set != .core); | 475 | assert(set != .core); |
| 374 | 476 | ||
| 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.*; |
| 377 | 479 | ||
| 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 | } |
| 479 | 581 | ||
| 480 | pub fn vectorType(self: *Module, len: u32, child_id: IdRef) !IdRef { | 582 | pub 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 | } |
| 493 | 595 | ||
| 596 | pub 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 | |||
| 610 | pub 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 | |||
| 624 | pub 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`. |
| 496 | pub fn builtin(self: *Module, result_ty_id: IdRef, spirv_builtin: spec.BuiltIn) !Decl.Index { | 647 | pub 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 | } |
| 542 | 696 | ||
| 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. | ||
| 544 | pub fn decorateMember( | 699 | pub 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(); |
| 81 | 81 | ||
| ... | @@ -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); | ||
| 238 | 234 | ||
| 239 | // We need to export the list of error names somewhere so that we can pretty-print them in the | 235 | // 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 old | 236 | // 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(); |
| 245 | 240 | ||
| ... | @@ -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 | }); |
| 271 | 266 | ||
| 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); |
| 274 | 269 | ||
| 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 |
| 298 | 293 | ||
| 299 | return binary.finalize(a); | 294 | return binary.finalize(a); |
| 300 | } | 295 | } |
| 301 | |||
| 302 | fn 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 | |||
| 327 | fn 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 | } |
| 157 | 157 | ||
| 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 to | 161 | // 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 | } |
| 168 | 168 | ||
| 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 | |||
| 12 | const std = @import("std"); | ||
| 13 | const fs = std.fs; | ||
| 14 | const Allocator = std.mem.Allocator; | ||
| 15 | const g = @import("spirv/grammar.zig"); | ||
| 16 | |||
| 17 | const 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 | |||
| 48 | pub 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. | ||
| 227 | fn 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 | |||
| 284 | fn 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 | |||
| 297 | fn 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 | |||
| 317 | fn 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 | } | ||