| // Copyright (c) 2015-2018 Khronos Group. This work is licensed under a |
| // Creative Commons Attribution 4.0 International License; see |
| // http://creativecommons.org/licenses/by/4.0/ |
| |
| [appendix] |
| [[spirvenv]] |
| = Vulkan Environment for SPIR-V |
| |
| Shaders for Vulkan are defined by the <<spirv-spec,Khronos SPIR-V |
| Specification>> as well as the <<spirv-extended,Khronos SPIR-V Extended |
| Instructions for GLSL>> Specification. |
| This appendix defines additional SPIR-V requirements applying to Vulkan |
| shaders. |
| |
| == Versions and Formats |
| |
| ifdef::VK_VERSION_1_1[] |
| A Vulkan 1.1 implementation must: support the 1.0, 1.1, 1.2, and 1.3 |
| versions of SPIR-V and the 1.0 version of the SPIR-V Extended Instructions |
| for GLSL. |
| endif::VK_VERSION_1_1[] |
| ifndef::VK_VERSION_1_1[] |
| A Vulkan 1.0 implementation must: support the 1.0 version of SPIR-V and the |
| 1.0 version of the SPIR-V Extended Instructions for GLSL. |
| endif::VK_VERSION_1_1[] |
| |
| A SPIR-V module passed into flink:vkCreateShaderModule is interpreted as a |
| series of 32-bit words in host endianness, with literal strings packed as |
| described in section 2.2 of the SPIR-V Specification. |
| The first few words of the SPIR-V module must: be a magic number and a |
| SPIR-V version number, as described in section 2.3 of the SPIR-V |
| Specification. |
| |
| |
| [[spirvenv-capabilities]] |
| == Capabilities |
| |
| The SPIR-V capabilities listed below must: be supported if the corresponding |
| feature or extension is enabled, or if no features or extensions are listed |
| for that capability. |
| Extensions are only listed when there is not also a feature bit associated |
| with that capability. |
| |
| [[spirvenv-capabilities-table]] |
| .List of SPIR-V Capabilities and enabling features or extensions |
| [options="header"] |
| |==== |
| | SPIR-V code:OpCapability | Vulkan feature or extension name |
| |
| | code:Matrix | |
| | code:Shader | |
| | code:InputAttachment | |
| | code:Sampled1D | |
| | code:Image1D | |
| | code:SampledBuffer | |
| | code:ImageBuffer | |
| | code:ImageQuery | |
| | code:DerivativeControl | |
| | code:Geometry | <<features-features-geometryShader,geometryShader>> |
| | code:Tessellation | <<features-features-tessellationShader,tessellationShader>> |
| | code:Float64 | <<features-features-shaderFloat64,shaderFloat64>> |
| | code:Int64 | <<features-features-shaderInt64,shaderInt64>> |
| | code:Int16 | <<features-features-shaderInt16,shaderInt16>> |
| | code:TessellationPointSize | <<features-features-shaderTessellationAndGeometryPointSize,shaderTessellationAndGeometryPointSize>> |
| | code:GeometryPointSize | <<features-features-shaderTessellationAndGeometryPointSize,shaderTessellationAndGeometryPointSize>> |
| | code:ImageGatherExtended | <<features-features-shaderImageGatherExtended,shaderImageGatherExtended>> |
| | code:StorageImageMultisample | <<features-features-shaderStorageImageMultisample,shaderStorageImageMultisample>> |
| | code:UniformBufferArrayDynamicIndexing | <<features-features-shaderUniformBufferArrayDynamicIndexing,shaderUniformBufferArrayDynamicIndexing>> |
| | code:SampledImageArrayDynamicIndexing | <<features-features-shaderSampledImageArrayDynamicIndexing,shaderSampledImageArrayDynamicIndexing>> |
| | code:StorageBufferArrayDynamicIndexing | <<features-features-shaderStorageBufferArrayDynamicIndexing,shaderStorageBufferArrayDynamicIndexing>> |
| | code:StorageImageArrayDynamicIndexing | <<features-features-shaderStorageImageArrayDynamicIndexing,shaderStorageImageArrayDynamicIndexing>> |
| | code:ClipDistance | <<features-features-shaderClipDistance,shaderClipDistance>> |
| | code:CullDistance | <<features-features-shaderCullDistance,shaderCullDistance>> |
| | code:ImageCubeArray | <<features-features-imageCubeArray,imageCubeArray>> |
| | code:SampleRateShading | <<features-features-sampleRateShading,sampleRateShading>> |
| | code:SparseResidency | <<features-features-shaderResourceResidency,shaderResourceResidency>> |
| | code:MinLod | <<features-features-shaderResourceMinLod,shaderResourceMinLod>> |
| | code:SampledCubeArray | <<features-features-imageCubeArray,imageCubeArray>> |
| | code:ImageMSArray | <<features-features-shaderStorageImageMultisample,shaderStorageImageMultisample>> |
| | code:StorageImageExtendedFormats | <<features-features-shaderStorageImageExtendedFormats,shaderStorageImageExtendedFormats>> |
| | code:InterpolationFunction | <<features-features-sampleRateShading,sampleRateShading>> |
| | code:StorageImageReadWithoutFormat | <<features-features-shaderStorageImageReadWithoutFormat,shaderStorageImageReadWithoutFormat>> |
| | code:StorageImageWriteWithoutFormat | <<features-features-shaderStorageImageWriteWithoutFormat,shaderStorageImageWriteWithoutFormat>> |
| | code:MultiViewport | <<features-features-multiViewport,multiViewport>> |
| ifdef::VK_VERSION_1_1,VK_KHR_shader_draw_parameters[] |
| | code:DrawParameters | |
| ifdef::VK_VERSION_1_1[] |
| <<features-features-shaderDrawParameters,shaderDrawParameters>> |
| endif::VK_VERSION_1_1[] |
| ifdef::VK_KHR_shader_draw_parameters+VK_VERSION_1_1[] |
| or |
| endif::VK_KHR_shader_draw_parameters+VK_VERSION_1_1[] |
| ifdef::VK_KHR_shader_draw_parameters[] |
| <<VK_KHR_shader_draw_parameters>> |
| endif::VK_KHR_shader_draw_parameters[] |
| endif::VK_VERSION_1_1,VK_KHR_shader_draw_parameters[] |
| ifdef::VK_VERSION_1_1,VK_KHR_multiview[] |
| [[spirvenv-capabilities-multiview]] |
| | code:MultiView | |
| ifndef::VK_VERSION_1_1[] |
| <<VK_KHR_multiview,VK_KHR_multiview>> |
| endif::VK_VERSION_1_1[] |
| endif::VK_VERSION_1_1,VK_KHR_multiview[] |
| ifdef::VK_VERSION_1_1,VK_KHR_device_group[] |
| | code:DeviceGroup | |
| ifndef::VK_VERSION_1_1[] |
| <<VK_KHR_device_group,VK_KHR_device_group>> |
| endif::VK_VERSION_1_1[] |
| endif::VK_VERSION_1_1,VK_KHR_device_group[] |
| ifdef::VK_VERSION_1_1,VK_KHR_variable_pointers[] |
| [[spirvenv-capabilities-table-variablepointers]] |
| | code:VariablePointersStorageBuffer | <<features-features-variablePointersStorageBuffer,variablePointersStorageBuffer>> |
| | code:VariablePointers | <<features-features-variablePointers,variablePointers>> |
| endif::VK_VERSION_1_1,VK_KHR_variable_pointers[] |
| ifdef::VK_EXT_shader_stencil_export[] |
| [[spirvenv-capabilities-table-shaderstencilexportext]] |
| | code:StencilExportEXT | `<<VK_EXT_shader_stencil_export>>` |
| endif::VK_EXT_shader_stencil_export[] |
| ifdef::VK_EXT_shader_subgroup_ballot[] |
| [[spirvenv-capabilities-table-subgroupballot]] |
| | code:SubgroupBallotKHR | `<<VK_EXT_shader_subgroup_ballot>>` |
| endif::VK_EXT_shader_subgroup_ballot[] |
| ifdef::VK_EXT_shader_subgroup_vote[] |
| [[spirvenv-capabilities-table-subgroupvote]] |
| | code:SubgroupVoteKHR | `<<VK_EXT_shader_subgroup_vote>>` |
| endif::VK_EXT_shader_subgroup_vote[] |
| ifdef::VK_AMD_shader_image_load_store_lod[] |
| [[spirvenv-capabilities-table-imagereadwritelodamd]] |
| | code:ImageReadWriteLodAMD | `<<VK_AMD_shader_image_load_store_lod>>` |
| endif::VK_AMD_shader_image_load_store_lod[] |
| ifdef::VK_AMD_texture_gather_bias_lod[] |
| [[spirvenv-capabilities-table-imagegatherbiaslodamd]] |
| | code:ImageGatherBiasLodAMD | `<<VK_AMD_texture_gather_bias_lod>>` |
| endif::VK_AMD_texture_gather_bias_lod[] |
| ifdef::VK_AMD_shader_fragment_mask[] |
| [[spirvenv-capabilities-table-fragmentmaskamd]] |
| | code:FragmentMaskAMD | `<<VK_AMD_shader_fragment_mask>>` |
| endif::VK_AMD_shader_fragment_mask[] |
| ifdef::VK_NV_sample_mask_override_coverage[] |
| [[spirvenv-capabilities-table-samplemaskoverridecoverage]] |
| | code:SampleMaskOverrideCoverageNV | `<<VK_NV_sample_mask_override_coverage>>` |
| endif::VK_NV_sample_mask_override_coverage[] |
| ifdef::VK_NV_geometry_shader_passthrough[] |
| [[spirvenv-capabilities-table-geometryshaderpassthrough]] |
| | code:GeometryShaderPassthroughNV | `<<VK_NV_geometry_shader_passthrough>>` |
| endif::VK_NV_geometry_shader_passthrough[] |
| ifdef::VK_EXT_shader_viewport_index_layer[] |
| [[spirvenv-capabilities-table-shader-viewport-index-layer]] |
| | code:ShaderViewportIndexLayerEXT | `<<VK_EXT_shader_viewport_index_layer>>` |
| endif::VK_EXT_shader_viewport_index_layer[] |
| ifdef::VK_NV_viewport_array2[] |
| [[spirvenv-capabilities-table-viewportarray2]] |
| | code:ShaderViewportIndexLayerNV | `<<VK_NV_viewport_array2>>` |
| | code:ShaderViewportMaskNV | `<<VK_NV_viewport_array2>>` |
| endif::VK_NV_viewport_array2[] |
| ifdef::VK_NVX_multiview_per_view_attributes[] |
| [[spirvenv-capabilities-table-perviewattributes]] |
| | code:PerViewAttributesNV | `<<VK_NVX_multiview_per_view_attributes>>` |
| endif::VK_NVX_multiview_per_view_attributes[] |
| ifdef::VK_VERSION_1_1,VK_KHR_16bit_storage[] |
| [[spirvenv-capabilities-table-16bitstorage]] |
| | code:StorageBuffer16BitAccess | <<features-features-storageBuffer16BitAccess, StorageBuffer16BitAccess>> |
| | code:UniformAndStorageBuffer16BitAccess | <<features-features-uniformAndStorageBuffer16BitAccess,UniformAndStorageBuffer16BitAccess>> |
| | code:StoragePushConstant16 | <<features-features-storagePushConstant16,storagePushConstant16>> |
| | code:StorageInputOutput16 | <<features-features-storageInputOutput16,storageInputOutput16>> |
| endif::VK_VERSION_1_1,VK_KHR_16bit_storage[] |
| ifdef::VK_VERSION_1_1[] |
| [[spirvenv-capabilities-table-subgroup]] |
| | code:GroupNonUniform | <<features-features-subgroup-basic,VK_SUBGROUP_FEATURE_BASIC_BIT>> |
| | code:GroupNonUniformVote | <<features-features-subgroup-vote,VK_SUBGROUP_FEATURE_VOTE_BIT>> |
| | code:GroupNonUniformArithmetic | <<features-features-subgroup-arithmetic,VK_SUBGROUP_FEATURE_ARITHMETIC_BIT>> |
| | code:GroupNonUniformBallot | <<features-features-subgroup-ballot,VK_SUBGROUP_FEATURE_BALLOT_BIT>> |
| | code:GroupNonUniformShuffle | <<features-features-subgroup-shuffle,VK_SUBGROUP_FEATURE_SHUFFLE_BIT>> |
| | code:GroupNonUniformShuffleRelative | <<features-features-subgroup-shuffle-relative,VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT>> |
| | code:GroupNonUniformClustered | <<features-features-subgroup-clustered,VK_SUBGROUP_FEATURE_CLUSTERED_BIT>> |
| | code:GroupNonUniformQuad | <<features-features-subgroup-quad,VK_SUBGROUP_FEATURE_QUAD_BIT>> |
| ifdef::VK_NV_shader_subgroup_partitioned[] |
| | code:GroupNonUniformPartitionedNV | <<features-features-subgroup-partitioned,VK_SUBGROUP_FEATURE_PARTITIONED_BIT_NV>> |
| endif::VK_NV_shader_subgroup_partitioned[] |
| endif::VK_VERSION_1_1[] |
| ifdef::VK_EXT_post_depth_coverage[] |
| [[spirvenv-capabilities-table-postdepthcoverage]] |
| | code:SampleMaskPostDepthCoverage | `<<VK_EXT_post_depth_coverage>>` |
| endif::VK_EXT_post_depth_coverage[] |
| ifdef::VK_EXT_descriptor_indexing[] |
| [[spirvenv-capabilities-table-descriptorindexing]] |
| | code:ShaderNonUniformEXT | `<<VK_EXT_descriptor_indexing>>` |
| | code:RuntimeDescriptorArrayEXT | <<features-features-runtimeDescriptorArray,runtimeDescriptorArray>> |
| | code:InputAttachmentArrayDynamicIndexingEXT | <<features-features-shaderInputAttachmentArrayDynamicIndexing,shaderInputAttachmentArrayDynamicIndexing>> |
| | code:UniformTexelBufferArrayDynamicIndexingEXT | <<features-features-shaderUniformTexelBufferArrayDynamicIndexing,shaderUniformTexelBufferArrayDynamicIndexing>> |
| | code:StorageTexelBufferArrayDynamicIndexingEXT | <<features-features-shaderStorageTexelBufferArrayDynamicIndexing,shaderStorageTexelBufferArrayDynamicIndexing>> |
| | code:UniformBufferArrayNonUniformIndexingEXT | <<features-features-shaderUniformBufferArrayNonUniformIndexing,shaderUniformBufferArrayNonUniformIndexing>> |
| | code:SampledImageArrayNonUniformIndexingEXT | <<features-features-shaderSampledImageArrayNonUniformIndexing,shaderSampledImageArrayNonUniformIndexing>> |
| | code:StorageBufferArrayNonUniformIndexingEXT | <<features-features-shaderStorageBufferArrayNonUniformIndexing,shaderStorageBufferArrayNonUniformIndexing>> |
| | code:StorageImageArrayNonUniformIndexingEXT | <<features-features-shaderStorageImageArrayNonUniformIndexing,shaderStorageImageArrayNonUniformIndexing>> |
| | code:InputAttachmentArrayNonUniformIndexingEXT | <<features-features-shaderInputAttachmentArrayNonUniformIndexing,shaderInputAttachmentArrayNonUniformIndexing>> |
| | code:UniformTexelBufferArrayNonUniformIndexingEXT | <<features-features-shaderUniformTexelBufferArrayNonUniformIndexing,shaderUniformTexelBufferArrayNonUniformIndexing>> |
| | code:StorageTexelBufferArrayNonUniformIndexingEXT | <<features-features-shaderStorageTexelBufferArrayNonUniformIndexing,shaderStorageTexelBufferArrayNonUniformIndexing>> |
| endif::VK_EXT_descriptor_indexing[] |
| ifdef::VK_AMD_gpu_shader_half_float[] |
| | code:Float16 | `<<VK_AMD_gpu_shader_half_float>>` |
| endif::VK_AMD_gpu_shader_half_float[] |
| ifdef::VK_KHR_8bit_storage[] |
| [[spirvenv-capabilities-table-8bitstorage]] |
| | code:StorageBuffer8BitAccess | <<features-features-storageBuffer8BitAccess,StorageBuffer8BitAccess>> |
| | code:UniformAndStorageBuffer8BitAccess | <<features-features-uniformAndStorageBuffer8BitAccess,UniformAndStorageBuffer8BitAccess>> |
| | code:StoragePushConstant8 | <<features-features-storagePushConstant8,StoragePushConstant8>> |
| endif::VK_KHR_8bit_storage[] |
| |==== |
| |
| ifdef::VK_VERSION_1_1,VK_KHR_variable_pointers[] |
| The application can: pass a SPIR-V module to flink:vkCreateShaderModule that |
| uses the `SPV_KHR_variable_pointers` SPIR-V extension. |
| endif::VK_VERSION_1_1,VK_KHR_variable_pointers[] |
| |
| ifdef::VK_AMD_shader_explicit_vertex_parameter[] |
| The application can: pass a SPIR-V module to flink:vkCreateShaderModule that |
| uses the `SPV_AMD_shader_explicit_vertex_parameter` SPIR-V extension. |
| endif::VK_AMD_shader_explicit_vertex_parameter[] |
| |
| ifdef::VK_AMD_gcn_shader[] |
| The application can: pass a SPIR-V module to flink:vkCreateShaderModule that |
| uses the `SPV_AMD_gcn_shader` SPIR-V extension. |
| endif::VK_AMD_gcn_shader[] |
| |
| ifdef::VK_AMD_gpu_shader_half_float[] |
| The application can: pass a SPIR-V module to flink:vkCreateShaderModule that |
| uses the `SPV_AMD_gpu_shader_half_float` SPIR-V extension. |
| endif::VK_AMD_gpu_shader_half_float[] |
| |
| ifdef::VK_AMD_gpu_shader_int16[] |
| The application can: pass a SPIR-V module to flink:vkCreateShaderModule that |
| uses the `SPV_AMD_gpu_shader_int16` SPIR-V extension. |
| endif::VK_AMD_gpu_shader_int16[] |
| |
| ifdef::VK_AMD_shader_ballot[] |
| The application can: pass a SPIR-V module to flink:vkCreateShaderModule that |
| uses the `SPV_AMD_shader_ballot` SPIR-V extension. |
| endif::VK_AMD_shader_ballot[] |
| |
| ifdef::VK_AMD_shader_fragment_mask[] |
| The application can: pass a SPIR-V module to flink:vkCreateShaderModule that |
| uses the `SPV_AMD_shader_fragment_mask` SPIR-V extension. |
| endif::VK_AMD_shader_fragment_mask[] |
| |
| ifdef::VK_AMD_shader_image_load_store_lod[] |
| The application can: pass a SPIR-V module to flink:vkCreateShaderModule that |
| uses the `SPV_AMD_shader_image_load_store_lod` SPIR-V extension. |
| endif::VK_AMD_shader_image_load_store_lod[] |
| |
| ifdef::VK_AMD_shader_trinary_minmax[] |
| The application can: pass a SPIR-V module to flink:vkCreateShaderModule that |
| uses the `SPV_AMD_shader_trinary_minmax` SPIR-V extension. |
| endif::VK_AMD_shader_trinary_minmax[] |
| |
| ifdef::VK_AMD_texture_gather_bias_lod[] |
| The application can: pass a SPIR-V module to flink:vkCreateShaderModule that |
| uses the `SPV_AMD_texture_gather_bias_lod` SPIR-V extension. |
| endif::VK_AMD_texture_gather_bias_lod[] |
| |
| ifdef::VK_VERSION_1_1,VK_KHR_shader_draw_parameters[] |
| The application can: pass a SPIR-V module to flink:vkCreateShaderModule that |
| uses the `SPV_KHR_shader_draw_parameters` SPIR-V extension. |
| endif::VK_VERSION_1_1,VK_KHR_shader_draw_parameters[] |
| |
| ifdef::VK_KHR_8bit_storage[] |
| The application can: pass a SPIR-V module to flink:vkCreateShaderModule that |
| uses the +SPV_KHR_8bit_storage+ SPIR-V extension. |
| endif::VK_KHR_8bit_storage[] |
| |
| ifdef::VK_VERSION_1_1,VK_KHR_16bit_storage[] |
| The application can: pass a SPIR-V module to flink:vkCreateShaderModule that |
| uses the |
| https://www.khronos.org/registry/spir-v/extensions/KHR/SPV_KHR_16bit_storage.html[`SPV_KHR_16bit_storage`] |
| SPIR-V extension. |
| endif::VK_VERSION_1_1,VK_KHR_16bit_storage[] |
| |
| ifdef::VK_VERSION_1_1,VK_KHR_storage_buffer_storage_class[] |
| The application can: pass a SPIR-V module to flink:vkCreateShaderModule that |
| uses the |
| https://www.khronos.org/registry/spir-v/extensions/KHR/SPV_KHR_storage_buffer_storage_class.html[`SPV_KHR_storage_buffer_storage_class`] |
| SPIR-V extension. |
| endif::VK_VERSION_1_1,VK_KHR_storage_buffer_storage_class[] |
| |
| ifdef::VK_EXT_post_depth_coverage[] |
| The application can: pass a SPIR-V module to flink:vkCreateShaderModule that |
| uses the `SPV_KHR_post_depth_coverage` SPIR-V extension. |
| endif::VK_EXT_post_depth_coverage[] |
| |
| ifdef::VK_EXT_shader_stencil_export[] |
| The application can: pass a SPIR-V module to flink:vkCreateShaderModule that |
| uses the `SPV_EXT_shader_stencil_export` SPIR-V extension. |
| endif::VK_EXT_shader_stencil_export[] |
| |
| ifdef::VK_EXT_shader_subgroup_ballot[] |
| The application can: pass a SPIR-V module to flink:vkCreateShaderModule that |
| uses the `SPV_KHR_shader_ballot` SPIR-V extension. |
| endif::VK_EXT_shader_subgroup_ballot[] |
| |
| ifdef::VK_EXT_shader_subgroup_vote[] |
| The application can: pass a SPIR-V module to flink:vkCreateShaderModule that |
| uses the `SPV_KHR_subgroup_vote` SPIR-V extension. |
| endif::VK_EXT_shader_subgroup_vote[] |
| |
| ifdef::VK_NV_sample_mask_override_coverage[] |
| The application can: pass a SPIR-V module to flink:vkCreateShaderModule that |
| uses the `SPV_NV_sample_mask_override_coverage` SPIR-V extension. |
| endif::VK_NV_sample_mask_override_coverage[] |
| |
| ifdef::VK_NV_geometry_shader_passthrough[] |
| The application can: pass a SPIR-V module to flink:vkCreateShaderModule that |
| uses the `SPV_NV_geometry_shader_passthrough` SPIR-V extension. |
| endif::VK_NV_geometry_shader_passthrough[] |
| |
| ifdef::VK_NV_viewport_array2[] |
| The application can: pass a SPIR-V module to flink:vkCreateShaderModule that |
| uses the `SPV_NV_viewport_array2` SPIR-V extension. |
| endif::VK_NV_viewport_array2[] |
| |
| ifdef::VK_EXT_shader_viewport_index_layer[] |
| The application can: pass a SPIR-V module to flink:vkCreateShaderModule that |
| uses the `SPV_EXT_shader_viewport_index_layer` SPIR-V extension. |
| endif::VK_EXT_shader_viewport_index_layer[] |
| |
| ifdef::VK_NVX_multiview_per_view_attributes[] |
| The application can: pass a SPIR-V module to flink:vkCreateShaderModule that |
| uses the `SPV_NVX_multiview_per_view_attributes` SPIR-V extension. |
| endif::VK_NVX_multiview_per_view_attributes[] |
| |
| ifdef::VK_EXT_descriptor_indexing[] |
| The application can: pass a SPIR-V module to flink:vkCreateShaderModule that |
| uses the +SPV_EXT_descriptor_indexing+ SPIR-V extension. |
| endif::VK_EXT_descriptor_indexing[] |
| |
| The application must: not pass a SPIR-V module containing any of the |
| following to flink:vkCreateShaderModule: |
| |
| * any OpCapability not listed above, |
| * an unsupported capability, or |
| * a capability which corresponds to a Vulkan feature or extension which |
| has not been enabled. |
| |
| |
| [[spirvenv-module-validation]] |
| == Validation Rules within a Module |
| |
| A SPIR-V module passed to flink:vkCreateShaderModule must: conform to the |
| following rules: |
| |
| * Every entry point must: have no return value and accept no arguments. |
| * Recursion: The static function-call graph for an entry point must: not |
| contain cycles. |
| * The *Logical* addressing model must: be selected. |
| * *Scope* for execution must: be limited to: |
| ** *Workgroup* |
| ** *Subgroup* |
| * *Scope* for memory must: be limited to: |
| ** *Device* |
| ** *Workgroup* |
| ifdef::VK_VERSION_1_1[] |
| ** *Subgroup* |
| endif::VK_VERSION_1_1[] |
| ** *Invocation* |
| ifdef::VK_VERSION_1_1[] |
| * *Scope* for *Non Uniform Group Operations* must: be limited to: |
| ** *Subgroup* |
| endif::VK_VERSION_1_1[] |
| * *Storage Class* must: be limited to: |
| ** *UniformConstant* |
| ** *Input* |
| ** *Uniform* |
| ** *Output* |
| ** *Workgroup* |
| ** *Private* |
| ** *Function* |
| ** *PushConstant* |
| ** *Image* |
| ifdef::VK_VERSION_1_1,VK_KHR_storage_buffer_storage_class[] |
| ** *StorageBuffer* |
| endif::VK_VERSION_1_1,VK_KHR_storage_buffer_storage_class[] |
| * Memory semantics must: obey the following rules: |
| ** *Acquire* must: not be used with code:OpAtomicStore. |
| ** *Release* must: not be used with code:OpAtomicLoad. |
| ** *AcquireRelease* must: not be used with code:OpAtomicStore or |
| code:OpAtomicLoad. |
| ** Sequentially consistent atomics and barriers are not supported and |
| *SequentiallyConsistent* is treated as *AcquireRelease*. |
| *SequentiallyConsistent* should: not be used. |
| ** code:OpMemoryBarrier must: use one of *Acquire*, *Release*, |
| *AcquireRelease*, or *SequentiallyConsistent* and must: include at |
| least one storage class. |
| ** If the semantics for code:OpControlBarrier includes one of *Acquire*, |
| *Release*, *AcquireRelease*, or *SequentiallyConsistent*, then it must: |
| include at least one storage class. |
| ** *SubgroupMemory*, *CrossWorkgroupMemory*, and *AtomicCounterMemory* are |
| ignored. |
| * Any code:OpVariable with an code:Initializer operand must: have one of |
| the following as its code:Storage code:Class operand: |
| ** *Output* |
| ** *Private* |
| ** *Function* |
| * The code:OriginLowerLeft execution mode must: not be used; fragment |
| entry points must: declare code:OriginUpperLeft. |
| * The code:PixelCenterInteger execution mode must: not be used. |
| Pixels are always centered at half-integer coordinates. |
| * Images and Samplers |
| ** code:OpTypeImage must: declare a scalar 32-bit float or 32-bit integer |
| type for the "`Sampled Type`". |
| (code:RelaxedPrecision can: be applied to a sampling instruction and to |
| the variable holding the result of a sampling instruction.) |
| ** code:OpTypeImage must: have a "`Sampled`" operand of 1 (sampled image) |
| or 2 (storage image). |
| ** If |
| <<features-features-shaderStorageImageReadWithoutFormat,shaderStorageImageReadWithoutFormat>> |
| is not enabled and an code:OpTypeImage has "`Image Format`" operand of |
| code:Unknown, any variables created with the given type must be |
| decorated with code:NonReadable. |
| ** If |
| <<features-features-shaderStorageImageWriteWithoutFormat,shaderStorageImageWriteWithoutFormat>> |
| is not enabled and an code:OpTypeImage has "`Image Format`" operand of |
| code:Unknown, any variables created with the given type must be |
| decorated with code:NonWritable. |
| ** code:OpImageQuerySizeLod, and code:OpImageQueryLevels must: only |
| consume an "`Image`" operand whose type has its "`Sampled`" operand set |
| to 1. |
| ** The [eq]#(u,v)# coordinates used for a code:SubpassData must: be the |
| <id> of a constant vector [eq]#(0,0)#, or if a layer coordinate is |
| used, must: be a vector that was formed with constant 0 for the [eq]#u# |
| and [eq]#v# components. |
| ** The "`Depth`" operand of code:OpTypeImage is ignored. |
| ** Objects of types code:OpTypeImage, code:OpTypeSampler, |
| code:OpTypeSampledImage, and arrays of these types must: not be stored |
| to or modified. |
| * Decorations |
| ** The code:GLSLShared and code:GLSLPacked decorations must: not be used. |
| ** The code:Flat, code:NoPerspective, code:Sample, and code:Centroid |
| decorations must: not be used on variables with storage class other |
| than code:Input or on variables used in the interface of non-fragment |
| shader entry points. |
| ** The code:Patch decoration must: not be used on variables in the |
| interface of a vertex, geometry, or fragment shader stage's entry |
| point. |
| ifdef::VK_NV_viewport_array2[] |
| ** The code:ViewportRelativeNV decoration must: only be used on a variable |
| decorated with code:Layer in the vertex, tessellation evaluation, or |
| geometry shader stages. |
| ** The code:ViewportRelativeNV decoration must: not be used unless a |
| variable decorated with one of code:ViewportIndex or |
| code:ViewportMaskNV is also statically used by the same |
| code:OpEntryPoint. |
| ** The code:ViewportMaskNV and code:ViewportIndex decorations must: not |
| both be statically used by one or more code:OpEntryPoint's that form |
| the vertex processing stages of a graphics pipeline. |
| endif::VK_NV_viewport_array2[] |
| ifdef::VK_VERSION_1_1,VK_KHR_16bit_storage[] |
| ** Only the round-to-nearest-even and the round-to-zero rounding modes |
| can: be used for the code:FPRoundingMode decoration. |
| ** The code:FPRoundingMode decoration can: only be used for the |
| floating-point conversion instructions as described in the |
| https://www.khronos.org/registry/spir-v/extensions/KHR/SPV_KHR_16bit_storage.html[`SPV_KHR_16bit_storage`] |
| SPIR-V extension. |
| endif::VK_VERSION_1_1,VK_KHR_16bit_storage[] |
| ** code:DescriptorSet and code:Binding decorations must: obey the |
| constraints on storage class, type, and descriptor type described in |
| <<interfaces-resources-setandbinding,DescriptorSet and Binding |
| Assignment>> |
| * code:OpTypeRuntimeArray must: only be used for: |
| ** the last member of an code:OpTypeStruct |
| ifdef::VK_VERSION_1_1,VK_KHR_storage_buffer_storage_class[] |
| that is in the code:StorageBuffer storage class decorated as |
| code:Block, or |
| endif::VK_VERSION_1_1,VK_KHR_storage_buffer_storage_class[] |
| that is in the code:Uniform storage class decorated as |
| code:BufferBlock. |
| ifdef::VK_EXT_descriptor_indexing[] |
| ** If the code:RuntimeDescriptorArrayEXT capability is supported, an array |
| of variables with storage class code:Uniform, |
| ifdef::VK_VERSION_1_1,VK_KHR_storage_buffer_storage_class[] |
| code:StorageBuffer, |
| endif::VK_VERSION_1_1,VK_KHR_storage_buffer_storage_class[] |
| or code:UniformConstant, or for the outermost dimension of an array of |
| arrays of such variables. |
| endif::VK_EXT_descriptor_indexing[] |
| * Linkage: See <<interfaces,Shader Interfaces>> for additional linking and |
| validation rules. |
| ifdef::VK_VERSION_1_1[] |
| * If code:OpControlBarrier is used in fragment, vertex, tessellation |
| evaluation, or geometry stages, the execution Scope must: be |
| code:Subgroup. |
| endif::VK_VERSION_1_1[] |
| * Compute Shaders |
| ** For each compute shader entry point, either a code:LocalSize execution |
| mode or an object decorated with the code:WorkgroupSize decoration |
| must: be specified. |
| ifdef::VK_VERSION_1_1[] |
| * "`Result Type`" for *Non Uniform Group Operations* must: be limited to |
| 32-bit float, 32-bit integer, boolean, or vectors of these types. |
| If the code:Float64 capability is enabled, double and vector of double |
| types are also permitted. |
| * "`Mask`" for code:OpGroupNonUniformShuffleXor must: be a specialization |
| constant or a constant, or if the dynamic instance is called within a |
| loop construct it must: be one of: |
| . A specialization constant. |
| . A constant. |
| . An arthimetic operation whose operands are 1., 2., or 4. |
| . A phi node whose operands are 1., 2., or 3. |
| * If code:OpGroupNonUniformBallotBitCount is used, the group operation |
| must: be one of: |
| ** *Reduce* |
| ** *InclusiveScan* |
| ** *ExclusiveScan* |
| endif::VK_VERSION_1_1[] |
| * Atomic instructions must: declare a scalar 32-bit integer type for the |
| _Result Type_ and the type of the value pointed to by _Pointer_. |
| ifdef::VK_EXT_descriptor_indexing[] |
| * If an instruction loads from or stores to a resource (including atomics |
| and image instructions) and the resource descriptor being accessed is |
| not dynamically uniform, then the operand corresponding to that resource |
| (e.g. the pointer or sampled image operand) must: be decorated with |
| code:NonUniformEXT. |
| endif::VK_EXT_descriptor_indexing[] |
| |
| |
| [[spirvenv-precision-operation]] |
| == Precision and Operation of SPIR-V Instructions |
| |
| The following rules apply to both single and double-precision floating point |
| instructions: |
| |
| * Positive and negative infinities and positive and negative zeros are |
| generated as dictated by <<ieee-754,IEEE 754>>, but subject to the |
| precisions allowed in the following table. |
| * Dividing a non-zero by a zero results in the appropriately signed |
| <<ieee-754,IEEE 754>> infinity. |
| * Any denormalized value input into a shader or potentially generated by |
| any instruction in a shader may: be flushed to 0. |
| * The rounding mode cannot: be set and is undefined. |
| * [eq]##NaN##s may: not be generated. |
| Instructions that operate on a [eq]#NaN# may: not result in a [eq]#NaN#. |
| * Support for signaling [eq]##NaN##s is optional: and exceptions are never |
| raised. |
| |
| The precision of double-precision instructions is at least that of single |
| precision. |
| |
| The precision of operations is defined either in terms of rounding, as an |
| error bound in ULP, or as inherited from a formula as follows. |
| |
| .Correctly Rounded |
| Operations described as "correctly rounded" will return the infinitely |
| precise result, [eq]#x#, rounded so as to be representable in |
| floating-point. |
| The rounding mode used is not defined but if [eq]#x# is exactly |
| representable then [eq]#x# will be returned. |
| Otherwise, either the floating-point value closest to and no less than |
| [eq]#x# or the value closest to and no greater than [eq]#x# will be |
| returned. |
| |
| .ULP |
| Where an error bound of [eq]#n# ULP (units in the last place) is given, for |
| an operation with infinitely precise result #x# the value returned must be |
| in the range #[x - n * ulp(x), x + n * ulp(x)]#. |
| The function #ulp(x)# is defined as follows: |
| |
| :: If there exist non-equal floating-point numbers #a# and #b# such that |
| [eq]#a {leq} x {leq} b# then #ulp(x)# is the minimum possible distance |
| between such numbers, latexmath:[ulp(x) = \mathrm{min}_{a,b} | b - a |]. |
| If such numbers do not exist then #ulp(x)# is defined to be the difference |
| between the two finite floating-point numbers nearest to #x#. |
| |
| Where the range of allowed return values includes any value of magnitude |
| larger than that of the largest representable finite floating-point number, |
| operations may return an infinity of the appropriate sign. |
| If the infinitely precise result of the operation is not mathematically |
| defined then the value returned is undefined. |
| |
| .Inherited From ... |
| Where an operation's precision is described as being inherited from a |
| formula, the result returned must be at least as accurate as the result of |
| computing an approximation to [eq]#x# using a formula equivalent to the |
| given formula applied to the supplied inputs. |
| Specifically, the formula given may be transformed using the mathematical |
| associativity, commutativity and distributivity of the operators involved to |
| yield an equivalent formula. |
| The SPIR-V precision rules, when applied to each such formula and the given |
| input values, define a range of permitted values. |
| If [eq]#NaN# is one of the permitted values then the operation may return |
| any result, otherwise let the largest permitted value in any of the ranges |
| be [eq]#F~max~# and the smallest be [eq]#F~min~#. |
| The operation must return a value in the range [eq]#[x - E, x + E]# where |
| latexmath:[E = \mathrm{max} \left( | x - F_{\mathrm{min}} |, | x - |
| F_{\mathrm{max}} | \right) ] |
| |
| For single precision (32 bit) instructions, precisions are required: to be |
| at least as follows, unless decorated with RelaxedPrecision: |
| |
| .Precision of core SPIR-V Instructions |
| [options="header"] |
| |==== |
| | Instruction | Precision |
| | code:OpFAdd | Correctly rounded. |
| | code:OpFSub | Correctly rounded. |
| | code:OpFMul | Correctly rounded. |
| | code:OpFOrdEqual, code:OpFUnordEqual | Correct result. |
| | code:OpFOrdLessThan, code:OpFUnordLessThan | Correct result. |
| | code:OpFOrdGreaterThan, code:OpFUnordGreaterThan | Correct result. |
| | code:OpFOrdLessThanEqual, code:OpFUnordLessThanEqual | Correct result. |
| | code:OpFOrdGreaterThanEqual, code:OpFUnordGreaterThanEqual| Correct result. |
| | code:OpFDiv | 2.5 ULP for b in the range [2^-126^, 2^126^]. |
| | conversions between types | Correctly rounded. |
| |==== |
| |
| .Precision of GLSL.std.450 Instructions |
| [options="header"] |
| |==== |
| |Instruction | Precision |
| | code:fma() | Inherited from code:OpFMul followed by code:OpFAdd. |
| | code:exp(x), code:exp2(x) | [eq]#3 {plus} 2 {times} {vert}x{vert}# ULP. |
| | code:log(), code:log2() | 3 ULP outside the range [eq]#[0.5, 2.0]#. Absolute error < [eq]#2^-21^# inside the range [eq]#[0.5, 2.0]#. |
| | code:pow(x, y) | Inherited from code:exp2(y {times} code:log2(x)). |
| | code:sqrt() | Inherited from 1.0 / code:inversesqrt(). |
| | code:inversesqrt() | 2 ULP. |
| |==== |
| |
| GLSL.std.450 extended instructions specifically defined in terms of the |
| above instructions inherit the above errors. |
| GLSL.std.450 extended instructions not listed above and not defined in terms |
| of the above have undefined precision. |
| These include, for example, the trigonometric functions and determinant. |
| |
| For the code:OpSRem and code:OpSMod instructions, if either operand is |
| negative the result is undefined. |
| |
| [NOTE] |
| .Note |
| ==== |
| While the code:OpSRem and code:OpSMod instructions are supported by the |
| Vulkan environment, they require non-negative values and thus do not enable |
| additional functionality beyond what code:OpUMod provides. |
| ==== |
| |
| |
| [[spirvenv-image-formats]] |
| == Compatibility Between SPIR-V Image Formats And Vulkan Formats |
| |
| Images which are read from or written to by shaders must: have SPIR-V image |
| formats compatible with the Vulkan image formats backing the image under the |
| circumstances described for <<textures-operation-validation,texture image |
| validation>>. |
| The compatibile formats are: |
| |
| .SPIR-V and Vulkan Image Format Compatibility |
| [cols="2*", options="header"] |
| |==== |
| |SPIR-V Image Format |Compatible Vulkan Format |
| |code:Rgba32f |ename:VK_FORMAT_R32G32B32A32_SFLOAT |
| |code:Rgba16f |ename:VK_FORMAT_R16G16B16A16_SFLOAT |
| |code:R32f |ename:VK_FORMAT_R32_SFLOAT |
| |code:Rgba8 |ename:VK_FORMAT_R8G8B8A8_UNORM |
| |code:Rgba8Snorm |ename:VK_FORMAT_R8G8B8A8_SNORM |
| |code:Rg32f |ename:VK_FORMAT_R32G32_SFLOAT |
| |code:Rg16f |ename:VK_FORMAT_R16G16_SFLOAT |
| |code:R11fG11fB10f |ename:VK_FORMAT_B10G11R11_UFLOAT_PACK32 |
| |code:R16f |ename:VK_FORMAT_R16_SFLOAT |
| |code:Rgba16 |ename:VK_FORMAT_R16G16B16A16_UNORM |
| |code:Rgb10A2 |ename:VK_FORMAT_A2B10G10R10_UNORM_PACK32 |
| |code:Rg16 |ename:VK_FORMAT_R16G16_UNORM |
| |code:Rg8 |ename:VK_FORMAT_R8G8_UNORM |
| |code:R16 |ename:VK_FORMAT_R16_UNORM |
| |code:R8 |ename:VK_FORMAT_R8_UNORM |
| |code:Rgba16Snorm |ename:VK_FORMAT_R16G16B16A16_SNORM |
| |code:Rg16Snorm |ename:VK_FORMAT_R16G16_SNORM |
| |code:Rg8Snorm |ename:VK_FORMAT_R8G8_SNORM |
| |code:R16Snorm |ename:VK_FORMAT_R16_SNORM |
| |code:R8Snorm |ename:VK_FORMAT_R8_SNORM |
| |code:Rgba32i |ename:VK_FORMAT_R32G32B32A32_SINT |
| |code:Rgba16i |ename:VK_FORMAT_R16G16B16A16_SINT |
| |code:Rgba8i |ename:VK_FORMAT_R8G8B8A8_SINT |
| |code:R32i |ename:VK_FORMAT_R32_SINT |
| |code:Rg32i |ename:VK_FORMAT_R32G32_SINT |
| |code:Rg16i |ename:VK_FORMAT_R16G16_SINT |
| |code:Rg8i |ename:VK_FORMAT_R8G8_SINT |
| |code:R16i |ename:VK_FORMAT_R16_SINT |
| |code:R8i |ename:VK_FORMAT_R8_SINT |
| |code:Rgba32ui |ename:VK_FORMAT_R32G32B32A32_UINT |
| |code:Rgba16ui |ename:VK_FORMAT_R16G16B16A16_UINT |
| |code:Rgba8ui |ename:VK_FORMAT_R8G8B8A8_UINT |
| |code:R32ui |ename:VK_FORMAT_R32_UINT |
| |code:Rgb10a2ui |ename:VK_FORMAT_A2B10G10R10_UINT_PACK32 |
| |code:Rg32ui |ename:VK_FORMAT_R32G32_UINT |
| |code:Rg16ui |ename:VK_FORMAT_R16G16_UINT |
| |code:Rg8ui |ename:VK_FORMAT_R8G8_UINT |
| |code:R16ui |ename:VK_FORMAT_R16_UINT |
| |code:R8ui |ename:VK_FORMAT_R8_UINT |
| |==== |