317 lines
15 KiB
Plaintext
317 lines
15 KiB
Plaintext
// Copyright (c) 2015-2017 The Khronos Group Inc.
|
|
// Copyright notice at https://www.khronos.org/registry/speccopyright.html
|
|
|
|
[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.
|
|
|
|
== Required Versions and Formats
|
|
|
|
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.
|
|
|
|
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
|
|
|
|
Implementations must: support the following capability operands declared by
|
|
code:OpCapability:
|
|
|
|
* code:Matrix
|
|
* code:Shader
|
|
* code:InputAttachment
|
|
* code:Sampled1D
|
|
* code:Image1D
|
|
* code:SampledBuffer
|
|
* code:ImageBuffer
|
|
* code:ImageQuery
|
|
* code:DerivativeControl
|
|
|
|
Implementations may: support features that are not required: by the
|
|
Specification, as described in the <<features-features,Features>> chapter.
|
|
If such a feature is supported, then any capability operand(s) corresponding
|
|
to that feature must: also be supported.
|
|
|
|
[[spirvenv-capabilities-table]]
|
|
.SPIR-V Capabilities which are not required:, and corresponding feature or extension names
|
|
[options="header"]
|
|
|====
|
|
| SPIR-V OpCapability | Vulkan feature or extension name
|
|
| 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_KHR_shader_draw_parameters[]
|
|
[[spirvenv-capabilities-table-drawparameters]]
|
|
| code:DrawParameters | <<VK_KHR_shader_draw_parameters,VK_KHR_shader_draw_parameters>>
|
|
endif::VK_KHR_shader_draw_parameters[]
|
|
ifdef::VK_EXT_shader_subgroup_ballot[]
|
|
[[spirvenv-capabilities-table-subgroupballot]]
|
|
| code:SubgroupBallotKHR | <<VK_EXT_shader_subgroup_ballot,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,VK_EXT_shader_subgroup_vote>>
|
|
endif::VK_EXT_shader_subgroup_vote[]
|
|
|====
|
|
|
|
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_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_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_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_KHR_shader_draw_parameters[]
|
|
|
|
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[]
|
|
|
|
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*
|
|
** *Invocation*
|
|
* 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
|
|
** 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:OpSampledImage 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.
|
|
* 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.
|
|
* code:OpTypeRuntimeArray must: only be used for the last member of an
|
|
code:OpTypeStruct in the code:Uniform storage class.
|
|
* Linkage: See <<interfaces,Shader Interfaces>> for additional linking and
|
|
validation rules.
|
|
* 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.
|
|
|
|
|
|
[[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.
|
|
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 + 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
|
|
|====
|