| // Copyright 2015-2023 The Khronos Group Inc. |
| // |
| // SPDX-License-Identifier: CC-BY-4.0 |
| |
| [[shaders]] |
| = Shaders |
| |
| A shader specifies programmable operations that execute for each vertex, |
| control point, tessellated vertex, primitive, fragment, or workgroup in the |
| corresponding stage(s) of the graphics and compute pipelines. |
| |
| Graphics pipelines include vertex shader execution as a result of |
| <<drawing,primitive assembly>>, followed, if enabled, by tessellation |
| control and evaluation shaders operating on <<drawing-patch-lists,patches>>, |
| geometry shaders, if enabled, operating on primitives, and fragment shaders, |
| if present, operating on fragments generated by <<primsrast,Rasterization>>. |
| In this specification, vertex, tessellation control, tessellation evaluation |
| and geometry shaders are collectively referred to as |
| <<pipelines-graphics-subsets-pre-rasterization,pre-rasterization shader |
| stage>>s and occur in the logical pipeline before rasterization. |
| The fragment shader occurs logically after rasterization. |
| |
| Only the compute shader stage is included in a compute pipeline. |
| Compute shaders operate on compute invocations in a workgroup. |
| |
| Shaders can: read from input variables, and read from and write to output |
| variables. |
| Input and output variables can: be used to transfer data between shader |
| stages, or to allow the shader to interact with values that exist in the |
| execution environment. |
| Similarly, the execution environment provides constants describing |
| capabilities. |
| |
| Shader variables are associated with execution environment-provided inputs |
| and outputs using _built-in_ decorations in the shader. |
| The available decorations for each stage are documented in the following |
| subsections. |
| |
| |
| ifdef::VK_EXT_shader_object[] |
| [[shaders-objects]] |
| == Shader Objects |
| |
| Shaders may: be compiled and linked into pipeline objects as described in |
| <<pipelines,Pipelines>> chapter, or if the <<features-shaderObject, |
| pname:shaderObject>> feature is enabled they may: be compiled into |
| individual per-stage _shader objects_ which can: be bound on a command |
| buffer independently from one another. |
| Unlike pipelines, shader objects are not intrinsically tied to any specific |
| set of state. |
| Instead, state is specified dynamically in the command buffer. |
| |
| Each shader object represents a single compiled shader stage, which may: |
| optionally: be linked with one or more other stages. |
| |
| [open,refpage='VkShaderEXT',desc='Opaque handle to a shader object',type='handles'] |
| -- |
| Shader objects are represented by sname:VkShaderEXT handles: |
| |
| include::{generated}/api/handles/VkShaderEXT.adoc[] |
| -- |
| |
| [[shaders-objects-creation]] |
| === Shader Object Creation |
| |
| Shader objects may: be created from shader code provided as SPIR-V, or in an |
| opaque, implementation-defined binary format specific to the physical |
| device. |
| |
| [open,refpage='vkCreateShadersEXT',desc='Create one or more new shaders',type='protos'] |
| -- |
| To create one or more shader objects, call: |
| |
| include::{generated}/api/protos/vkCreateShadersEXT.adoc[] |
| |
| * pname:device is the logical device that creates the shader objects. |
| * pname:createInfoCount is the length of the pname:pCreateInfos and |
| pname:pShaders arrays. |
| * pname:pCreateInfos is a pointer to an array of |
| slink:VkShaderCreateInfoEXT structures. |
| * pname:pAllocator controls host memory allocation as described in the |
| <<memory-allocation, Memory Allocation>> chapter. |
| * pname:pShaders is a pointer to an array of slink:VkShaderEXT handles in |
| which the resulting shader objects are returned. |
| |
| When this function returns, whether or not it succeeds, it is guaranteed |
| that every element of pname:pShaders will have been overwritten by either |
| dlink:VK_NULL_HANDLE or a valid sname:VkShaderEXT handle. |
| |
| This means that whenever shader creation fails, the application can: |
| determine which shader the returned error pertains to by locating the first |
| dlink:VK_NULL_HANDLE element in pname:pShaders. |
| It also means that an application can: reliably clean up from a failed call |
| by iterating over the pname:pShaders array and destroying every element that |
| is not dlink:VK_NULL_HANDLE. |
| |
| .Valid Usage |
| **** |
| * [[VUID-vkCreateShadersEXT-None-08400]] |
| The <<features-shaderObject, pname:shaderObject>> feature must: be |
| enabled |
| * [[VUID-vkCreateShadersEXT-pCreateInfos-08401]] |
| If pname:createInfoCount is 1, there must: be no element of |
| pname:pCreateInfos whose pname:flags member includes |
| ename:VK_SHADER_CREATE_LINK_STAGE_BIT_EXT |
| * [[VUID-vkCreateShadersEXT-pCreateInfos-08402]] |
| If the pname:flags member of any element of pname:pCreateInfos includes |
| ename:VK_SHADER_CREATE_LINK_STAGE_BIT_EXT, the pname:flags member of all |
| other elements of pname:pCreateInfos whose pname:stage is |
| ename:VK_SHADER_STAGE_VERTEX_BIT, |
| ename:VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, |
| ename:VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, |
| ename:VK_SHADER_STAGE_GEOMETRY_BIT, or |
| ename:VK_SHADER_STAGE_FRAGMENT_BIT must: also include |
| ename:VK_SHADER_CREATE_LINK_STAGE_BIT_EXT |
| ifdef::VK_NV_mesh_shader,VK_EXT_mesh_shader[] |
| * [[VUID-vkCreateShadersEXT-pCreateInfos-08403]] |
| If the pname:flags member of any element of pname:pCreateInfos includes |
| ename:VK_SHADER_CREATE_LINK_STAGE_BIT_EXT, the pname:flags member of all |
| other elements of pname:pCreateInfos whose pname:stage is |
| ename:VK_SHADER_STAGE_TASK_BIT_EXT or ename:VK_SHADER_STAGE_MESH_BIT_EXT |
| must: also include ename:VK_SHADER_CREATE_LINK_STAGE_BIT_EXT |
| * [[VUID-vkCreateShadersEXT-pCreateInfos-08404]] |
| If the pname:flags member of any element of pname:pCreateInfos whose |
| pname:stage is ename:VK_SHADER_STAGE_TASK_BIT_EXT or |
| ename:VK_SHADER_STAGE_MESH_BIT_EXT includes |
| ename:VK_SHADER_CREATE_LINK_STAGE_BIT_EXT, there must: be no member of |
| pname:pCreateInfos whose pname:stage is ename:VK_SHADER_STAGE_VERTEX_BIT |
| and whose pname:flags member includes |
| ename:VK_SHADER_CREATE_LINK_STAGE_BIT_EXT |
| * [[VUID-vkCreateShadersEXT-pCreateInfos-08405]] |
| If there is any element of pname:pCreateInfos whose pname:stage is |
| ename:VK_SHADER_STAGE_MESH_BIT_EXT and whose pname:flags member includes |
| both ename:VK_SHADER_CREATE_LINK_STAGE_BIT_EXT and |
| ename:VK_SHADER_CREATE_NO_TASK_SHADER_BIT_EXT, there must: be no element |
| of pname:pCreateInfos whose pname:stage is |
| ename:VK_SHADER_STAGE_TASK_BIT_EXT and whose pname:flags member includes |
| ename:VK_SHADER_CREATE_LINK_STAGE_BIT_EXT |
| endif::VK_NV_mesh_shader,VK_EXT_mesh_shader[] |
| * [[VUID-vkCreateShadersEXT-pCreateInfos-08409]] |
| For each element of pname:pCreateInfos whose pname:flags member includes |
| ename:VK_SHADER_CREATE_LINK_STAGE_BIT_EXT, if there is any other element |
| of pname:pCreateInfos whose pname:stage is logically later than the |
| pname:stage of the former and whose pname:flags member also includes |
| ename:VK_SHADER_CREATE_LINK_STAGE_BIT_EXT, the pname:nextStage of the |
| former must: be equal to the pname:stage of the element with the |
| logically earliest pname:stage following the pname:stage of the former |
| whose pname:flags member also includes |
| ename:VK_SHADER_CREATE_LINK_STAGE_BIT_EXT |
| * [[VUID-vkCreateShadersEXT-pCreateInfos-08410]] |
| The pname:stage member of each element of pname:pCreateInfos whose |
| pname:flags member includes ename:VK_SHADER_CREATE_LINK_STAGE_BIT_EXT |
| must: be unique |
| * [[VUID-vkCreateShadersEXT-pCreateInfos-08411]] |
| The pname:codeType member of all elements of pname:pCreateInfos whose |
| pname:flags member includes ename:VK_SHADER_CREATE_LINK_STAGE_BIT_EXT |
| must: be the same |
| * [[VUID-vkCreateShadersEXT-pCreateInfos-08867]] |
| If pname:pCreateInfos contains elements with both |
| ename:VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT and |
| ename:VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, both elements' |
| pname:flags include ename:VK_SHADER_CREATE_LINK_STAGE_BIT_EXT, both |
| elements' pname:codeType is ename:VK_SHADER_CODE_TYPE_SPIRV_EXT, and the |
| ename:VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT stage's pname:pCode |
| contains an code:OpExecutionMode instruction specifying the type of |
| subdivision, it must: match the subdivision type specified in the |
| ename:VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT stage |
| * [[VUID-vkCreateShadersEXT-pCreateInfos-08868]] |
| If pname:pCreateInfos contains elements with both |
| ename:VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT and |
| ename:VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, both elements' |
| pname:flags include ename:VK_SHADER_CREATE_LINK_STAGE_BIT_EXT, both |
| elements' pname:codeType is ename:VK_SHADER_CODE_TYPE_SPIRV_EXT, and the |
| ename:VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT stage's pname:pCode |
| contains an code:OpExecutionMode instruction specifying the orientation |
| of triangles, it must: match the triangle orientation specified in the |
| ename:VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT stage |
| * [[VUID-vkCreateShadersEXT-pCreateInfos-08869]] |
| If pname:pCreateInfos contains elements with both |
| ename:VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT and |
| ename:VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, both elements' |
| pname:flags include ename:VK_SHADER_CREATE_LINK_STAGE_BIT_EXT, both |
| elements' pname:codeType is ename:VK_SHADER_CODE_TYPE_SPIRV_EXT, and the |
| ename:VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT stage's pname:pCode |
| contains an code:OpExecutionMode instruction specifying code:PointMode, |
| the ename:VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT stage must: also |
| contain an code:OpExecutionMode instruction specifying code:PointMode |
| * [[VUID-vkCreateShadersEXT-pCreateInfos-08870]] |
| If pname:pCreateInfos contains elements with both |
| ename:VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT and |
| ename:VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, both elements' |
| pname:flags include ename:VK_SHADER_CREATE_LINK_STAGE_BIT_EXT, both |
| elements' pname:codeType is ename:VK_SHADER_CODE_TYPE_SPIRV_EXT, and the |
| ename:VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT stage's pname:pCode |
| contains an code:OpExecutionMode instruction specifying the spacing of |
| segments on the edges of tessellated primitives, it must: match the |
| segment spacing specified in the |
| ename:VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT stage |
| * [[VUID-vkCreateShadersEXT-pCreateInfos-08871]] |
| If pname:pCreateInfos contains elements with both |
| ename:VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT and |
| ename:VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, both elements' |
| pname:flags include ename:VK_SHADER_CREATE_LINK_STAGE_BIT_EXT, both |
| elements' pname:codeType is ename:VK_SHADER_CODE_TYPE_SPIRV_EXT, and the |
| ename:VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT stage's pname:pCode |
| contains an code:OpExecutionMode instruction specifying the output patch |
| size, it must: match the output patch size specified in the |
| ename:VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT stage |
| **** |
| |
| include::{generated}/validity/protos/vkCreateShadersEXT.adoc[] |
| -- |
| |
| [open,refpage='VkShaderCreateInfoEXT',desc='Structure specifying parameters of a newly created shader',type='structs'] |
| -- |
| :refpage: VkShaderCreateInfoEXT |
| |
| The sname:VkShaderCreateInfoEXT structure is defined as: |
| |
| include::{generated}/api/structs/VkShaderCreateInfoEXT.adoc[] |
| |
| * pname:sType is a elink:VkStructureType value identifying this structure. |
| * pname:pNext is `NULL` or a pointer to a structure extending this |
| structure. |
| * pname:flags is a bitmask of elink:VkShaderCreateFlagBitsEXT describing |
| additional parameters of the shader. |
| * pname:stage is a elink:VkShaderStageFlagBits value specifying a single |
| shader stage. |
| * pname:nextStage is a bitmask of elink:VkShaderStageFlagBits specifying |
| zero or stages which may: be used as a logically next bound stage when |
| drawing with the shader bound. |
| * pname:codeType is a elink:VkShaderCodeTypeEXT value specifying the type |
| of the shader code pointed to be pname:pCode. |
| * pname:codeSize is the size in bytes of the shader code pointed to be |
| pname:pCode. |
| * pname:pCode is a pointer to the shader code to use to create the shader. |
| * pname:pName is a pointer to a null-terminated UTF-8 string specifying |
| the entry point name of the shader for this stage. |
| * pname:setLayoutCount is the number of descriptor set layouts pointed to |
| by pname:pSetLayouts. |
| * pname:pSetLayouts is a pointer to an array of |
| slink:VkDescriptorSetLayout objects used by the shader stage. |
| * pname:pushConstantRangeCount is the number of push constant ranges |
| pointed to by pname:pPushConstantRanges. |
| * pname:pPushConstantRanges is a pointer to an array of |
| slink:VkPushConstantRange structures used by the shader stage. |
| * pname:pSpecializationInfo is a pointer to a slink:VkSpecializationInfo |
| structure, as described in |
| <<pipelines-specialization-constants,Specialization Constants>>, or |
| `NULL`. |
| |
| .Valid Usage |
| **** |
| :prefixCondition: If pname:codeType is ename:VK_SHADER_CODE_TYPE_SPIRV_EXT, |
| include::{chapters}/commonvalidity/shader_create_spv_common.adoc[] |
| * [[VUID-VkShaderCreateInfoEXT-flags-08412]] |
| If pname:stage is not ename:VK_SHADER_STAGE_TASK_BIT_EXT, |
| ename:VK_SHADER_STAGE_MESH_BIT_EXT, ename:VK_SHADER_STAGE_VERTEX_BIT, |
| ename:VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, |
| ename:VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, |
| ename:VK_SHADER_STAGE_GEOMETRY_BIT, or |
| ename:VK_SHADER_STAGE_FRAGMENT_BIT, pname:flags must: not include |
| ename:VK_SHADER_CREATE_LINK_STAGE_BIT_EXT |
| ifdef::VK_KHR_fragment_shading_rate[] |
| * [[VUID-VkShaderCreateInfoEXT-flags-08486]] |
| If pname:stage is not ename:VK_SHADER_STAGE_FRAGMENT_BIT, pname:flags |
| must: not include |
| ename:VK_SHADER_CREATE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_EXT |
| * [[VUID-VkShaderCreateInfoEXT-flags-08487]] |
| If the <<features-attachmentFragmentShadingRate, |
| pname:attachmentFragmentShadingRate>> feature is not enabled, |
| pname:flags must: not include |
| ename:VK_SHADER_CREATE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_EXT |
| endif::VK_KHR_fragment_shading_rate[] |
| ifdef::VK_EXT_fragment_density_map[] |
| * [[VUID-VkShaderCreateInfoEXT-flags-08488]] |
| If pname:stage is not ename:VK_SHADER_STAGE_FRAGMENT_BIT, pname:flags |
| must: not include |
| ename:VK_SHADER_CREATE_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT |
| * [[VUID-VkShaderCreateInfoEXT-flags-08489]] |
| If the <<features-fragmentDensityMap, pname:fragmentDensityMap>> feature |
| is not enabled, pname:flags must: not include |
| ename:VK_SHADER_CREATE_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT |
| endif::VK_EXT_fragment_density_map[] |
| ifdef::VK_VERSION_1_1,VK_EXT_subgroup_size_control[] |
| * [[VUID-VkShaderCreateInfoEXT-flags-09404]] |
| If pname:flags includes |
| ename:VK_SHADER_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT_EXT, the |
| <<features-subgroupSizeControl, pname:subgroupSizeControl>> feature |
| must: be enabled |
| * [[VUID-VkShaderCreateInfoEXT-flags-09405]] |
| If pname:flags includes |
| ename:VK_SHADER_CREATE_REQUIRE_FULL_SUBGROUPS_BIT_EXT, the |
| <<features-computeFullSubgroups, pname:computeFullSubgroups>> feature |
| must: be enabled |
| * [[VUID-VkShaderCreateInfoEXT-flags-08992]] |
| If pname:flags includes |
| ename:VK_SHADER_CREATE_REQUIRE_FULL_SUBGROUPS_BIT_EXT, pname:stage must: |
| be |
| ifdef::VK_NV_mesh_shader,VK_EXT_mesh_shader[] |
| one of ename:VK_SHADER_STAGE_MESH_BIT_EXT, |
| ename:VK_SHADER_STAGE_TASK_BIT_EXT, or |
| endif::VK_NV_mesh_shader,VK_EXT_mesh_shader[] |
| ename:VK_SHADER_STAGE_COMPUTE_BIT |
| endif::VK_VERSION_1_1,VK_EXT_subgroup_size_control[] |
| ifdef::VK_VERSION_1_1,VK_KHR_device_group[] |
| * [[VUID-VkShaderCreateInfoEXT-flags-08485]] |
| If pname:stage is not ename:VK_SHADER_STAGE_COMPUTE_BIT, pname:flags |
| must: not include ename:VK_SHADER_CREATE_DISPATCH_BASE_BIT_EXT |
| endif::VK_VERSION_1_1,VK_KHR_device_group[] |
| ifdef::VK_NV_mesh_shader,VK_EXT_mesh_shader[] |
| * [[VUID-VkShaderCreateInfoEXT-flags-08414]] |
| If pname:stage is not ename:VK_SHADER_STAGE_MESH_BIT_EXT, pname:flags |
| must: not include ename:VK_SHADER_CREATE_NO_TASK_SHADER_BIT_EXT |
| endif::VK_NV_mesh_shader,VK_EXT_mesh_shader[] |
| ifdef::VK_VERSION_1_1,VK_EXT_subgroup_size_control[] |
| * [[VUID-VkShaderCreateInfoEXT-flags-08416]] |
| If pname:flags includes both |
| ename:VK_SHADER_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT_EXT and |
| ename:VK_SHADER_CREATE_REQUIRE_FULL_SUBGROUPS_BIT_EXT, the local |
| workgroup size in the X dimension of the shader must: be a multiple of |
| <<limits-maxSubgroupSize,pname:maxSubgroupSize>> |
| * [[VUID-VkShaderCreateInfoEXT-flags-08417]] |
| If pname:flags includes |
| ename:VK_SHADER_CREATE_REQUIRE_FULL_SUBGROUPS_BIT_EXT but not |
| ename:VK_SHADER_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT_EXT and no |
| slink:VkShaderRequiredSubgroupSizeCreateInfoEXT structure is included in |
| the pname:pNext chain, the local workgroup size in the X dimension of |
| the shader must: be a multiple of |
| <<limits-subgroup-size,pname:subgroupSize>> |
| endif::VK_VERSION_1_1,VK_EXT_subgroup_size_control[] |
| * [[VUID-VkShaderCreateInfoEXT-stage-08418]] |
| pname:stage must: not be ename:VK_SHADER_STAGE_ALL_GRAPHICS or |
| ename:VK_SHADER_STAGE_ALL |
| * [[VUID-VkShaderCreateInfoEXT-stage-08419]] |
| If the <<features-tessellationShader, pname:tessellationShader>> feature |
| is not enabled, pname:stage must: not be |
| ename:VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT or |
| ename:VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT |
| * [[VUID-VkShaderCreateInfoEXT-stage-08420]] |
| If the <<features-geometryShader, pname:geometryShader>> feature is not |
| enabled, pname:stage must: not be ename:VK_SHADER_STAGE_GEOMETRY_BIT |
| ifdef::VK_NV_mesh_shader,VK_EXT_mesh_shader[] |
| * [[VUID-VkShaderCreateInfoEXT-stage-08421]] |
| If the <<features-taskShader, pname:taskShader>> feature is not enabled, |
| pname:stage must: not be ename:VK_SHADER_STAGE_TASK_BIT_EXT |
| * [[VUID-VkShaderCreateInfoEXT-stage-08422]] |
| If the <<features-meshShader, pname:meshShader>> feature is not enabled, |
| pname:stage must: not be ename:VK_SHADER_STAGE_MESH_BIT_EXT |
| endif::VK_NV_mesh_shader,VK_EXT_mesh_shader[] |
| ifdef::VK_HUAWEI_subpass_shading[] |
| * [[VUID-VkShaderCreateInfoEXT-stage-08425]] |
| pname:stage must: not be |
| ename:VK_SHADER_STAGE_SUBPASS_SHADING_BIT_HUAWEI |
| endif::VK_HUAWEI_subpass_shading[] |
| ifdef::VK_HUAWEI_cluster_culling_shader[] |
| * [[VUID-VkShaderCreateInfoEXT-stage-08426]] |
| pname:stage must: not be |
| ename:VK_SHADER_STAGE_CLUSTER_CULLING_BIT_HUAWEI |
| endif::VK_HUAWEI_cluster_culling_shader[] |
| * [[VUID-VkShaderCreateInfoEXT-nextStage-08427]] |
| If pname:stage is ename:VK_SHADER_STAGE_VERTEX_BIT, pname:nextStage |
| must: not include any bits other than |
| ename:VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, |
| ename:VK_SHADER_STAGE_GEOMETRY_BIT, and |
| ename:VK_SHADER_STAGE_FRAGMENT_BIT |
| * [[VUID-VkShaderCreateInfoEXT-nextStage-08428]] |
| If the <<features-tessellationShader, pname:tessellationShader>> feature |
| is not enabled, pname:nextStage must: not include |
| ename:VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT or |
| ename:VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT |
| * [[VUID-VkShaderCreateInfoEXT-nextStage-08429]] |
| If the <<features-geometryShader, pname:geometryShader>> feature is not |
| enabled, pname:nextStage must: not include |
| ename:VK_SHADER_STAGE_GEOMETRY_BIT |
| * [[VUID-VkShaderCreateInfoEXT-nextStage-08430]] |
| If pname:stage is ename:VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, |
| pname:nextStage must: not include any bits other than |
| ename:VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT |
| * [[VUID-VkShaderCreateInfoEXT-nextStage-08431]] |
| If pname:stage is ename:VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, |
| pname:nextStage must: not include any bits other than |
| ename:VK_SHADER_STAGE_GEOMETRY_BIT and |
| ename:VK_SHADER_STAGE_FRAGMENT_BIT |
| * [[VUID-VkShaderCreateInfoEXT-nextStage-08433]] |
| If pname:stage is ename:VK_SHADER_STAGE_GEOMETRY_BIT, pname:nextStage |
| must: not include any bits other than ename:VK_SHADER_STAGE_FRAGMENT_BIT |
| * [[VUID-VkShaderCreateInfoEXT-nextStage-08434]] |
| If pname:stage is ename:VK_SHADER_STAGE_FRAGMENT_BIT or |
| ename:VK_SHADER_STAGE_COMPUTE_BIT, pname:nextStage must: be 0 |
| ifdef::VK_NV_mesh_shader,VK_EXT_mesh_shader[] |
| * [[VUID-VkShaderCreateInfoEXT-nextStage-08435]] |
| If pname:stage is ename:VK_SHADER_STAGE_TASK_BIT_EXT, pname:nextStage |
| must: not include any bits other than ename:VK_SHADER_STAGE_MESH_BIT_EXT |
| * [[VUID-VkShaderCreateInfoEXT-nextStage-08436]] |
| If pname:stage is ename:VK_SHADER_STAGE_MESH_BIT_EXT, pname:nextStage |
| must: not include any bits other than ename:VK_SHADER_STAGE_FRAGMENT_BIT |
| endif::VK_NV_mesh_shader,VK_EXT_mesh_shader[] |
| * [[VUID-VkShaderCreateInfoEXT-pName-08440]] |
| If pname:codeType is ename:VK_SHADER_CODE_TYPE_SPIRV_EXT, pname:pName |
| must: be the name of an code:OpEntryPoint in pname:pCode with an |
| execution model that matches pname:stage |
| * [[VUID-VkShaderCreateInfoEXT-pCode-08492]] |
| If pname:codeType is ename:VK_SHADER_CODE_TYPE_BINARY_EXT, pname:pCode |
| must: be aligned to `16` bytes |
| * [[VUID-VkShaderCreateInfoEXT-pCode-08493]] |
| If pname:codeType is ename:VK_SHADER_CODE_TYPE_SPIRV_EXT, pname:pCode |
| must: be aligned to `4` bytes |
| * [[VUID-VkShaderCreateInfoEXT-pCode-08448]] |
| If pname:codeType is ename:VK_SHADER_CODE_TYPE_SPIRV_EXT, and the |
| identified entry point includes any variable in its interface that is |
| declared with the code:ClipDistance code:BuiltIn decoration, that |
| variable must: not have an array size greater than |
| sname:VkPhysicalDeviceLimits::pname:maxClipDistances |
| * [[VUID-VkShaderCreateInfoEXT-pCode-08449]] |
| If pname:codeType is ename:VK_SHADER_CODE_TYPE_SPIRV_EXT, and the |
| identified entry point includes any variable in its interface that is |
| declared with the code:CullDistance code:BuiltIn decoration, that |
| variable must: not have an array size greater than |
| sname:VkPhysicalDeviceLimits::pname:maxCullDistances |
| * [[VUID-VkShaderCreateInfoEXT-pCode-08450]] |
| If pname:codeType is ename:VK_SHADER_CODE_TYPE_SPIRV_EXT, and the |
| identified entry point includes any variables in its interface that are |
| declared with the code:ClipDistance or code:CullDistance code:BuiltIn |
| decoration, those variables must: not have array sizes which sum to more |
| than sname:VkPhysicalDeviceLimits::pname:maxCombinedClipAndCullDistances |
| * [[VUID-VkShaderCreateInfoEXT-pCode-08451]] |
| If pname:codeType is ename:VK_SHADER_CODE_TYPE_SPIRV_EXT, and the |
| identified entry point includes any variable in its interface that is |
| declared with the code:SampleMask code:BuiltIn decoration, that variable |
| must: not have an array size greater than |
| sname:VkPhysicalDeviceLimits::pname:maxSampleMaskWords |
| * [[VUID-VkShaderCreateInfoEXT-pCode-08452]] |
| If pname:codeType is ename:VK_SHADER_CODE_TYPE_SPIRV_EXT, and |
| pname:stage is ename:VK_SHADER_STAGE_VERTEX_BIT, the identified entry |
| point must: not include any input variable in its interface that is |
| decorated with code:CullDistance |
| * [[VUID-VkShaderCreateInfoEXT-pCode-08453]] |
| If pname:codeType is ename:VK_SHADER_CODE_TYPE_SPIRV_EXT, and |
| pname:stage is ename:VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT or |
| ename:VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, and the identified |
| entry point has an code:OpExecutionMode instruction specifying a patch |
| size with code:OutputVertices, the patch size must: be greater than `0` |
| and less than or equal to |
| sname:VkPhysicalDeviceLimits::pname:maxTessellationPatchSize |
| * [[VUID-VkShaderCreateInfoEXT-pCode-08454]] |
| If pname:codeType is ename:VK_SHADER_CODE_TYPE_SPIRV_EXT, and |
| pname:stage is ename:VK_SHADER_STAGE_GEOMETRY_BIT, the identified entry |
| point must: have an code:OpExecutionMode instruction specifying a |
| maximum output vertex count that is greater than `0` and less than or |
| equal to sname:VkPhysicalDeviceLimits::pname:maxGeometryOutputVertices |
| * [[VUID-VkShaderCreateInfoEXT-pCode-08455]] |
| If pname:codeType is ename:VK_SHADER_CODE_TYPE_SPIRV_EXT, and |
| pname:stage is ename:VK_SHADER_STAGE_GEOMETRY_BIT, the identified entry |
| point must: have an code:OpExecutionMode instruction specifying an |
| invocation count that is greater than `0` and less than or equal to |
| sname:VkPhysicalDeviceLimits::pname:maxGeometryShaderInvocations |
| * [[VUID-VkShaderCreateInfoEXT-pCode-08456]] |
| If pname:codeType is ename:VK_SHADER_CODE_TYPE_SPIRV_EXT, and |
| pname:stage is a |
| <<pipelines-graphics-subsets-pre-rasterization,pre-rasterization shader |
| stage>>, and the identified entry point writes to code:Layer for any |
| primitive, it must: write the same value to code:Layer for all vertices |
| of a given primitive |
| * [[VUID-VkShaderCreateInfoEXT-pCode-08457]] |
| If pname:codeType is ename:VK_SHADER_CODE_TYPE_SPIRV_EXT, and |
| pname:stage is a |
| <<pipelines-graphics-subsets-pre-rasterization,pre-rasterization shader |
| stage>>, and the identified entry point writes to code:ViewportIndex for |
| any primitive, it must: write the same value to code:ViewportIndex for |
| all vertices of a given primitive |
| * [[VUID-VkShaderCreateInfoEXT-pCode-08458]] |
| If pname:codeType is ename:VK_SHADER_CODE_TYPE_SPIRV_EXT, and |
| pname:stage is ename:VK_SHADER_STAGE_FRAGMENT_BIT, the identified entry |
| point must: not include any output variables in its interface decorated |
| with code:CullDistance |
| * [[VUID-VkShaderCreateInfoEXT-pCode-08459]] |
| If pname:codeType is ename:VK_SHADER_CODE_TYPE_SPIRV_EXT, and |
| pname:stage is ename:VK_SHADER_STAGE_FRAGMENT_BIT, and the identified |
| entry point writes to code:FragDepth in any execution path, all |
| execution paths that are not exclusive to helper invocations must: |
| either discard the fragment, or write or initialize the value of |
| code:FragDepth |
| * [[VUID-VkShaderCreateInfoEXT-pCode-08460]] |
| If pname:codeType is ename:VK_SHADER_CODE_TYPE_SPIRV_EXT, the shader |
| code in pname:pCode must: be valid as described by the |
| <<spirv-spec,Khronos SPIR-V Specification>> after applying the |
| specializations provided in pname:pSpecializationInfo, if any, and then |
| converting all specialization constants into fixed constants |
| * [[VUID-VkShaderCreateInfoEXT-codeType-08872]] |
| If pname:codeType is ename:VK_SHADER_CODE_TYPE_SPIRV_EXT, and |
| pname:stage is ename:VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, |
| pname:pCode must: contain an code:OpExecutionMode instruction specifying |
| the type of subdivision |
| * [[VUID-VkShaderCreateInfoEXT-codeType-08873]] |
| If pname:codeType is ename:VK_SHADER_CODE_TYPE_SPIRV_EXT, and |
| pname:stage is ename:VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, |
| pname:pCode must: contain an code:OpExecutionMode instruction specifying |
| the orientation of triangles generated by the tessellator |
| * [[VUID-VkShaderCreateInfoEXT-codeType-08874]] |
| If pname:codeType is ename:VK_SHADER_CODE_TYPE_SPIRV_EXT, and |
| pname:stage is ename:VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, |
| pname:pCode must: contain an code:OpExecutionMode instruction specifying |
| the spacing of segments on the edges of tessellated primitives |
| * [[VUID-VkShaderCreateInfoEXT-codeType-08875]] |
| If pname:codeType is ename:VK_SHADER_CODE_TYPE_SPIRV_EXT, and |
| pname:stage is ename:VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, |
| pname:pCode must: contain an code:OpExecutionMode instruction specifying |
| the output patch size |
| **** |
| |
| include::{generated}/validity/structs/VkShaderCreateInfoEXT.adoc[] |
| -- |
| |
| [open,refpage='VkShaderCreateFlagsEXT',desc='Bitmask of VkShaderCreateFlagBitsEXT',type='flags'] |
| -- |
| include::{generated}/api/flags/VkShaderCreateFlagsEXT.adoc[] |
| |
| tname:VkShaderCreateFlagsEXT is a bitmask type for setting a mask of zero or |
| more elink:VkShaderCreateFlagBitsEXT. |
| -- |
| |
| [open,refpage='VkShaderCreateFlagBitsEXT',desc='Bitmask controlling how a shader object is created',type='enums'] |
| -- |
| Possible values of the pname:flags member of slink:VkShaderCreateInfoEXT |
| specifying how a shader object is created, are: |
| |
| include::{generated}/api/enums/VkShaderCreateFlagBitsEXT.adoc[] |
| |
| * ename:VK_SHADER_CREATE_LINK_STAGE_BIT_EXT specifies that a shader is |
| linked to all other shaders created in the same flink:vkCreateShadersEXT |
| call whose slink:VkShaderCreateInfoEXT structures' pname:flags include |
| ename:VK_SHADER_CREATE_LINK_STAGE_BIT_EXT. |
| ifdef::VK_VERSION_1_1,VK_EXT_subgroup_size_control[] |
| * ename:VK_SHADER_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT_EXT specifies |
| that the <<interfaces-builtin-variables-sgs, code:SubgroupSize>> may: |
| vary in a |
| ifdef::VK_NV_mesh_shader,VK_EXT_mesh_shader[task, mesh, or] |
| compute shader. |
| * ename:VK_SHADER_CREATE_REQUIRE_FULL_SUBGROUPS_BIT_EXT specifies that the |
| subgroup sizes must: be launched with all invocations active in a |
| ifdef::VK_NV_mesh_shader,VK_EXT_mesh_shader[task, mesh, or] |
| compute shader. |
| endif::VK_VERSION_1_1,VK_EXT_subgroup_size_control[] |
| ifdef::VK_EXT_mesh_shader,VK_NV_mesh_shader[] |
| * ename:VK_SHADER_CREATE_NO_TASK_SHADER_BIT_EXT specifies that a mesh |
| shader must: only be used without a task shader. |
| Otherwise, the mesh shader must: only be used with a task shader. |
| endif::VK_EXT_mesh_shader,VK_NV_mesh_shader[] |
| ifdef::VK_VERSION_1_1,VK_KHR_device_group[] |
| * ename:VK_SHADER_CREATE_DISPATCH_BASE_BIT_EXT specifies that a compute |
| shader can: be used with flink:vkCmdDispatchBase with a non-zero base |
| workgroup. |
| endif::VK_VERSION_1_1,VK_KHR_device_group[] |
| ifdef::VK_KHR_fragment_shading_rate[] |
| * ename:VK_SHADER_CREATE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_EXT |
| specifies that a fragment shader can: be used with a fragment shading |
| rate attachment. |
| endif::VK_KHR_fragment_shading_rate[] |
| ifdef::VK_EXT_fragment_density_map[] |
| * ename:VK_SHADER_CREATE_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT specifies |
| that a fragment shader can: be used with a fragment density map |
| attachment. |
| endif::VK_EXT_fragment_density_map[] |
| -- |
| |
| ifdef::VK_KHR_fragment_shading_rate,VK_EXT_fragment_density_map[] |
| [NOTE] |
| .Note |
| ==== |
| The behavior of |
| ifdef::VK_KHR_fragment_shading_rate[] |
| ename:VK_SHADER_CREATE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_EXT |
| endif::VK_KHR_fragment_shading_rate[] |
| ifdef::VK_KHR_fragment_shading_rate+VK_EXT_fragment_density_map[and] |
| ifdef::VK_EXT_fragment_density_map[] |
| ename:VK_SHADER_CREATE_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT |
| endif::VK_EXT_fragment_density_map[] |
| differs subtly from the behavior of |
| ifdef::VK_KHR_fragment_shading_rate[] |
| ename:VK_PIPELINE_CREATE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR |
| endif::VK_KHR_fragment_shading_rate[] |
| ifdef::VK_KHR_fragment_shading_rate+VK_EXT_fragment_density_map[and] |
| ifdef::VK_EXT_fragment_density_map[] |
| ename:VK_PIPELINE_CREATE_RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT |
| endif::VK_EXT_fragment_density_map[] |
| in that the shader bit allows, but does not require the shader to be used |
| with that type of attachment. |
| This means that the application need not create multiple shaders when it |
| does not know in advance whether the shader will be used with or without the |
| attachment type, or when it needs the same shader to be compatible with |
| usage both with and without. |
| This may: come at some performance cost on some implementations, so |
| applications should: still only set bits that are actually necessary. |
| ==== |
| endif::VK_KHR_fragment_shading_rate,VK_EXT_fragment_density_map[] |
| |
| [open,refpage='VkShaderCodeTypeEXT',desc='Indicate a shader code type',type='enums'] |
| -- |
| Shader objects can: be created using different types of shader code. |
| Possible values of slink:VkShaderCreateInfoEXT::pname:codeType, are: |
| |
| include::{generated}/api/enums/VkShaderCodeTypeEXT.adoc[] |
| |
| * ename:VK_SHADER_CODE_TYPE_BINARY_EXT specifies shader code in an opaque, |
| implementation-defined binary format specific to the physical device. |
| * ename:VK_SHADER_CODE_TYPE_SPIRV_EXT specifies shader code in SPIR-V |
| format. |
| -- |
| |
| [[shaders-objects-binary-code]] |
| === Binary Shader Code |
| |
| [open,refpage='vkGetShaderBinaryDataEXT',desc='Get the binary shader code from a shader object',type='protos'] |
| -- |
| Binary shader code can: be retrieved from a shader object using the command: |
| |
| include::{generated}/api/protos/vkGetShaderBinaryDataEXT.adoc[] |
| |
| * pname:device is the logical device that shader object was created from. |
| * pname:shader is the shader object to retrieve binary shader code from. |
| * pname:pDataSize is a pointer to a code:size_t value related to the size |
| of the binary shader code, as described below. |
| * pname:pData is either `NULL` or a pointer to a buffer. |
| |
| If pname:pData is `NULL`, then the size of the binary shader code of the |
| shader object, in bytes, is returned in pname:pDataSize. |
| Otherwise, pname:pDataSize must: point to a variable set by the user to the |
| size of the buffer, in bytes, pointed to by pname:pData, and on return the |
| variable is overwritten with the amount of data actually written to |
| pname:pData. |
| If pname:pDataSize is less than the size of the binary shader code, nothing |
| is written to pname:pData, and ename:VK_INCOMPLETE will be returned instead |
| of ename:VK_SUCCESS. |
| |
| [NOTE] |
| .Note |
| ==== |
| The behavior of this command when pname:pDataSize is too small differs from |
| how some other getter-type commands work in Vulkan. |
| Because shader binary data is only usable in its entirety, it would never be |
| useful for the implementation to return partial data. |
| Because of this, nothing is written to pname:pData unless pname:pDataSize is |
| large enough to fit the data it its entirety. |
| ==== |
| |
| Binary shader code retrieved using fname:vkGetShaderBinaryDataEXT can: be |
| passed to a subsequent call to flink:vkCreateShadersEXT on a compatible |
| physical device by specifying ename:VK_SHADER_CODE_TYPE_BINARY_EXT in the |
| pname:codeType member of sname:VkShaderCreateInfoEXT. |
| |
| The shader code returned by repeated calls to this function with the same |
| sname:VkShaderEXT is guaranteed to be invariant for the lifetime of the |
| sname:VkShaderEXT object. |
| |
| .Valid Usage |
| **** |
| * [[VUID-vkGetShaderBinaryDataEXT-None-08461]] |
| The <<features-shaderObject,pname:shaderObject>> feature must: be |
| enabled |
| * [[VUID-vkGetShaderBinaryDataEXT-None-08499]] |
| If pname:pData is not `NULL`, it must: be aligned to `16` bytes |
| **** |
| |
| include::{generated}/validity/protos/vkGetShaderBinaryDataEXT.adoc[] |
| -- |
| |
| [[shaders-objects-binary-compatibility]] |
| === Binary Shader Compatibility |
| |
| Binary shader compatibility means that binary shader code returned from a |
| call to flink:vkGetShaderBinaryDataEXT can: be passed to a later call to |
| flink:vkCreateShadersEXT, potentially on a different logical and/or physical |
| device, and that this will result in the successful creation of a shader |
| object functionally equivalent to the shader object that the code was |
| originally queried from. |
| |
| Binary shader code queried from flink:vkGetShaderBinaryDataEXT is not |
| guaranteed to be compatible across all devices, but implementations are |
| required to provide some compatibility guarantees. |
| Applications may: determine binary shader compatibility using either (or |
| both) of two mechanisms. |
| |
| Guaranteed compatibility of shader binaries is expressed through a |
| combination of the pname:shaderBinaryUUID and pname:shaderBinaryVersion |
| members of the slink:VkPhysicalDeviceShaderObjectPropertiesEXT structure |
| queried from a physical device. |
| Binary shaders retrieved from a physical device with a certain |
| pname:shaderBinaryUUID are guaranteed to be compatible with all other |
| physical devices reporting the same pname:shaderBinaryUUID and the same or |
| higher pname:shaderBinaryVersion. |
| |
| Whenever a new version of an implementation incorporates any changes that |
| affect the output of flink:vkGetShaderBinaryDataEXT, the implementation |
| should: either increment pname:shaderBinaryVersion if binary shader code |
| retrieved from older versions remains compatible with the new |
| implementation, or else replace pname:shaderBinaryUUID with a new value if |
| backward compatibility has been broken. |
| Binary shader code queried from a device with a matching |
| pname:shaderBinaryUUID and lower pname:shaderBinaryVersion relative to the |
| device on which flink:vkCreateShadersEXT is being called may: be suboptimal |
| for the new device in ways that do not change shader functionality, but it |
| is still guaranteed to be usable to successfully create the shader |
| object(s). |
| |
| [NOTE] |
| .Note |
| ==== |
| Implementations are encouraged to share pname:shaderBinaryUUID between |
| devices and driver versions to the maximum extent their hardware naturally |
| allows, and are *strongly* discouraged from ever changing the |
| pname:shaderBinaryUUID for the same hardware except unless absolutely |
| necessary. |
| ==== |
| |
| In addition to the shader compatibility guarantees described above, it is |
| valid for an application to call flink:vkCreateShadersEXT with binary shader |
| code created on a device with a different or unknown pname:shaderBinaryUUID |
| and/or higher pname:shaderBinaryVersion. |
| In this case, the implementation may: use any unspecified means of its |
| choosing to determine whether the provided binary shader code is usable. |
| If it is, the flink:vkCreateShadersEXT call must: return ename:VK_SUCCESS, |
| and the created shader object is guaranteed to be valid. |
| Otherwise, in the absence of some other error, the flink:vkCreateShadersEXT |
| call must: return ename:VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT to indicate |
| that the provided binary shader code is not compatible with the device. |
| |
| [[shaders-objects-binding]] |
| === Binding Shader Objects |
| |
| [open,refpage='vkCmdBindShadersEXT',desc='Bind shader objects to a command buffer',type='protos'] |
| -- |
| Once shader objects have been created, they can: be bound to the command |
| buffer using the command: |
| |
| include::{generated}/api/protos/vkCmdBindShadersEXT.adoc[] |
| |
| * pname:commandBuffer is the command buffer that the shader object will be |
| bound to. |
| * pname:stageCount is the length of the pname:pStages and pname:pShaders |
| arrays. |
| * pname:pStages is a pointer to an array of elink:VkShaderStageFlagBits |
| values specifying one stage per array index that is affected by the |
| corresponding value in the pname:pShaders array. |
| * pname:pShaders is a pointer to an array of sname:VkShaderEXT handles |
| and/or dlink:VK_NULL_HANDLE values describing the shader binding |
| operations to be performed on each stage in pname:pStages. |
| |
| When binding linked shaders, an application may: bind them in any |
| combination of one or more calls to fname:vkCmdBindShadersEXT (i.e., shaders |
| that were created linked together do not need to be bound in the same |
| fname:vkCmdBindShadersEXT call). |
| |
| Any shader object bound to a particular stage may: be unbound by setting its |
| value in pname:pShaders to dlink:VK_NULL_HANDLE. |
| If pname:pShaders is `NULL`, fname:vkCmdBindShadersEXT behaves as if |
| pname:pShaders was an array of pname:stageCount dlink:VK_NULL_HANDLE values |
| (i.e., any shaders bound to the stages specified in pname:pStages are |
| unbound). |
| |
| .Valid Usage |
| **** |
| * [[VUID-vkCmdBindShadersEXT-None-08462]] |
| The <<features-shaderObject,pname:shaderObject>> feature must: be |
| enabled |
| * [[VUID-vkCmdBindShadersEXT-pStages-08463]] |
| Every element of pname:pStages must: be unique |
| * [[VUID-vkCmdBindShadersEXT-pStages-08464]] |
| pname:pStages must: not contain ename:VK_SHADER_STAGE_ALL_GRAPHICS or |
| ename:VK_SHADER_STAGE_ALL |
| ifdef::VK_KHR_ray_tracing_pipeline,VK_NV_ray_tracing[] |
| * [[VUID-vkCmdBindShadersEXT-pStages-08465]] |
| pname:pStages must: not contain ename:VK_SHADER_STAGE_RAYGEN_BIT_KHR, |
| ename:VK_SHADER_STAGE_ANY_HIT_BIT_KHR, |
| ename:VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, |
| ename:VK_SHADER_STAGE_MISS_BIT_KHR, |
| ename:VK_SHADER_STAGE_INTERSECTION_BIT_KHR, or |
| ename:VK_SHADER_STAGE_CALLABLE_BIT_KHR |
| endif::VK_KHR_ray_tracing_pipeline,VK_NV_ray_tracing[] |
| ifdef::VK_HUAWEI_subpass_shading[] |
| * [[VUID-vkCmdBindShadersEXT-pStages-08467]] |
| pname:pStages must: not contain |
| ename:VK_SHADER_STAGE_SUBPASS_SHADING_BIT_HUAWEI |
| endif::VK_HUAWEI_subpass_shading[] |
| ifdef::VK_HUAWEI_cluster_culling_shader[] |
| * [[VUID-vkCmdBindShadersEXT-pStages-08468]] |
| pname:pStages must: not contain |
| ename:VK_SHADER_STAGE_CLUSTER_CULLING_BIT_HUAWEI |
| endif::VK_HUAWEI_cluster_culling_shader[] |
| * [[VUID-vkCmdBindShadersEXT-pShaders-08469]] |
| For each element of pname:pStages, if pname:pShaders is not `NULL`, and |
| the element of the pname:pShaders array with the same index is not |
| dlink:VK_NULL_HANDLE, it must: have been created with a pname:stage |
| equal to the corresponding element of pname:pStages |
| ifdef::VK_NV_mesh_shader,VK_EXT_mesh_shader[] |
| * [[VUID-vkCmdBindShadersEXT-pShaders-08470]] |
| If pname:pStages contains both ename:VK_SHADER_STAGE_TASK_BIT_EXT and |
| ename:VK_SHADER_STAGE_VERTEX_BIT, and pname:pShaders is not `NULL`, and |
| the same index in pname:pShaders as ename:VK_SHADER_STAGE_TASK_BIT_EXT |
| in pname:pStages is not dlink:VK_NULL_HANDLE, the same index in |
| pname:pShaders as ename:VK_SHADER_STAGE_VERTEX_BIT in pname:pStages |
| must: be dlink:VK_NULL_HANDLE |
| * [[VUID-vkCmdBindShadersEXT-pShaders-08471]] |
| If pname:pStages contains both ename:VK_SHADER_STAGE_MESH_BIT_EXT and |
| ename:VK_SHADER_STAGE_VERTEX_BIT, and pname:pShaders is not `NULL`, and |
| the same index in pname:pShaders as ename:VK_SHADER_STAGE_MESH_BIT_EXT |
| in pname:pStages is not dlink:VK_NULL_HANDLE, the same index in |
| pname:pShaders as ename:VK_SHADER_STAGE_VERTEX_BIT in pname:pStages |
| must: be dlink:VK_NULL_HANDLE |
| endif::VK_NV_mesh_shader,VK_EXT_mesh_shader[] |
| * [[VUID-vkCmdBindShadersEXT-pShaders-08474]] |
| If the <<features-tessellationShader, pname:tessellationShader>> feature |
| is not enabled, and pname:pStages contains |
| ename:VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT or |
| ename:VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, and pname:pShaders is |
| not `NULL`, the same index or indices in pname:pShaders must: be |
| dlink:VK_NULL_HANDLE |
| * [[VUID-vkCmdBindShadersEXT-pShaders-08475]] |
| If the <<features-geometryShader, pname:geometryShader>> feature is not |
| enabled, and pname:pStages contains ename:VK_SHADER_STAGE_GEOMETRY_BIT, |
| and pname:pShaders is not `NULL`, the same index in pname:pShaders must: |
| be dlink:VK_NULL_HANDLE |
| ifdef::VK_NV_mesh_shader,VK_EXT_mesh_shader[] |
| * [[VUID-vkCmdBindShadersEXT-pShaders-08490]] |
| If the <<features-taskShader, pname:taskShader>> feature is not enabled, |
| and pname:pStages contains ename:VK_SHADER_STAGE_TASK_BIT_EXT, and |
| pname:pShaders is not `NULL`, the same index in pname:pShaders must: be |
| dlink:VK_NULL_HANDLE |
| * [[VUID-vkCmdBindShadersEXT-pShaders-08491]] |
| If the <<features-meshShader, pname:meshShader>> feature is not enabled, |
| and pname:pStages contains ename:VK_SHADER_STAGE_MESH_BIT_EXT, and |
| pname:pShaders is not `NULL`, the same index in pname:pShaders must: be |
| dlink:VK_NULL_HANDLE |
| endif::VK_NV_mesh_shader,VK_EXT_mesh_shader[] |
| * [[VUID-vkCmdBindShadersEXT-pShaders-08476]] |
| If pname:pStages contains ename:VK_SHADER_STAGE_COMPUTE_BIT, the |
| sname:VkCommandPool that pname:commandBuffer was allocated from must: |
| support compute operations |
| * [[VUID-vkCmdBindShadersEXT-pShaders-08477]] |
| If pname:pStages contains ename:VK_SHADER_STAGE_VERTEX_BIT, |
| ename:VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, |
| ename:VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, |
| ename:VK_SHADER_STAGE_GEOMETRY_BIT, or |
| ename:VK_SHADER_STAGE_FRAGMENT_BIT, the sname:VkCommandPool that |
| pname:commandBuffer was allocated from must: support graphics operations |
| ifdef::VK_NV_mesh_shader,VK_EXT_mesh_shader[] |
| * [[VUID-vkCmdBindShadersEXT-pShaders-08478]] |
| If pname:pStages contains ename:VK_SHADER_STAGE_MESH_BIT_EXT or |
| ename:VK_SHADER_STAGE_TASK_BIT_EXT, the sname:VkCommandPool that |
| pname:commandBuffer was allocated from must: support graphics operations |
| endif::VK_NV_mesh_shader,VK_EXT_mesh_shader[] |
| **** |
| |
| include::{generated}/validity/protos/vkCmdBindShadersEXT.adoc[] |
| -- |
| |
| [[shaders-objects-state]] |
| === Setting State |
| |
| Whenever shader objects are used to issue drawing commands, the appropriate |
| <<pipelines-dynamic-state, dynamic state>> setting commands must: have been |
| called to set the relevant state in the command buffer prior to drawing: |
| |
| * flink:vkCmdSetViewportWithCount |
| * flink:vkCmdSetScissorWithCount |
| * flink:vkCmdSetRasterizerDiscardEnable |
| |
| ifdef::VK_EXT_mesh_shader,VK_NV_mesh_shader[] |
| If a shader is bound to the ename:VK_SHADER_STAGE_VERTEX_BIT stage, the |
| following commands must: have been called in the command buffer prior to |
| drawing: |
| endif::VK_EXT_mesh_shader,VK_NV_mesh_shader[] |
| |
| * flink:vkCmdSetVertexInputEXT |
| * flink:vkCmdSetPrimitiveTopology |
| * flink:vkCmdSetPatchControlPointsEXT, if pname:primitiveTopology is |
| ename:VK_PRIMITIVE_TOPOLOGY_PATCH_LIST |
| * flink:vkCmdSetPrimitiveRestartEnable |
| |
| If a shader is bound to the |
| ename:VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT stage, the following |
| command must: have been called in the command buffer prior to drawing: |
| |
| * flink:vkCmdSetTessellationDomainOriginEXT |
| |
| If pname:rasterizerDiscardEnable is ename:VK_FALSE, the following commands |
| must: have been called in the command buffer prior to drawing: |
| |
| * flink:vkCmdSetRasterizationSamplesEXT |
| * flink:vkCmdSetSampleMaskEXT |
| * flink:vkCmdSetAlphaToCoverageEnableEXT |
| * flink:vkCmdSetAlphaToOneEnableEXT, if the <<features-alphaToOne, |
| alphaToOne>> feature is enabled on the device |
| * flink:vkCmdSetPolygonModeEXT |
| * flink:vkCmdSetLineWidth, if pname:polygonMode is |
| ename:VK_POLYGON_MODE_LINE, or if |
| ifdef::VK_EXT_mesh_shader,VK_NV_mesh_shader[] |
| a shader is bound to the ename:VK_SHADER_STAGE_VERTEX_BIT stage and |
| endif::VK_EXT_mesh_shader,VK_NV_mesh_shader[] |
| pname:primitiveTopology is a line topology, or if a shader which outputs |
| line primitives is bound to the |
| ename:VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT or |
| ename:VK_SHADER_STAGE_GEOMETRY_BIT stage |
| * flink:vkCmdSetCullMode |
| * flink:vkCmdSetFrontFace |
| * flink:vkCmdSetDepthTestEnable |
| * flink:vkCmdSetDepthWriteEnable |
| * flink:vkCmdSetDepthCompareOp, if pname:depthTestEnable is ename:VK_TRUE |
| * flink:vkCmdSetDepthBoundsTestEnable, if the <<features-depthBounds, |
| depthBounds>> feature is enabled on the device |
| * flink:vkCmdSetDepthBounds, if pname:depthBoundsTestEnable is |
| ename:VK_TRUE |
| * flink:vkCmdSetDepthBiasEnable |
| ifdef::VK_EXT_depth_bias_control[] |
| * flink:vkCmdSetDepthBias or flink:vkCmdSetDepthBias2EXT, |
| endif::VK_EXT_depth_bias_control[] |
| ifndef::VK_EXT_depth_bias_control[] |
| * flink:vkCmdSetDepthBias, |
| endif::VK_EXT_depth_bias_control[] |
| if pname:depthBiasEnable is ename:VK_TRUE |
| * flink:vkCmdSetDepthClampEnableEXT, if the <<features-depthClamp, |
| depthClamp>> feature is enabled on the device |
| * flink:vkCmdSetStencilTestEnable |
| * flink:vkCmdSetStencilOp, if pname:stencilTestEnable is ename:VK_TRUE |
| * flink:vkCmdSetStencilCompareMask, if pname:stencilTestEnable is |
| ename:VK_TRUE |
| * flink:vkCmdSetStencilWriteMask, if pname:stencilTestEnable is |
| ename:VK_TRUE |
| * flink:vkCmdSetStencilReference, if pname:stencilTestEnable is |
| ename:VK_TRUE |
| |
| If a shader is bound to the ename:VK_SHADER_STAGE_FRAGMENT_BIT stage, and |
| pname:rasterizerDiscardEnable is ename:VK_FALSE, the following commands |
| must: have been called in the command buffer prior to drawing: |
| |
| * flink:vkCmdSetLogicOpEnableEXT, if the <<features-logicOp, |
| pname:logicOp>> feature is enabled on the device |
| * flink:vkCmdSetLogicOpEXT, if pname:logicOpEnable is ename:VK_TRUE |
| * flink:vkCmdSetColorBlendEnableEXT, with values set for every color |
| attachment in the render pass instance active at draw time |
| ifdef::VK_EXT_blend_operation_advanced[] |
| * flink:vkCmdSetColorBlendEquationEXT or |
| flink:vkCmdSetColorBlendAdvancedEXT, |
| endif::VK_EXT_blend_operation_advanced[] |
| ifndef::VK_EXT_blend_operation_advanced[] |
| * flink:vkCmdSetColorBlendEquationEXT, |
| endif::VK_EXT_blend_operation_advanced[] |
| for every attachment whose index in pname:pColorBlendEnables is a |
| pointer to a value of ename:VK_TRUE |
| * flink:vkCmdSetBlendConstants, if any index in pname:pColorBlendEnables |
| is ename:VK_TRUE, and the same index in pname:pColorBlendEquations is a |
| sname:VkColorBlendEquationEXT structure with any elink:VkBlendFactor |
| member with a value of ename:VK_BLEND_FACTOR_CONSTANT_COLOR, |
| ename:VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR, |
| ename:VK_BLEND_FACTOR_CONSTANT_ALPHA, or |
| ename:VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA |
| * flink:vkCmdSetColorWriteMaskEXT |
| |
| ifdef::VK_KHR_fragment_shading_rate[] |
| If the <<features-pipelineFragmentShadingRate, |
| pname:pipelineFragmentShadingRate>> feature is enabled on the device, and a |
| shader is bound to the ename:VK_SHADER_STAGE_FRAGMENT_BIT stage, and |
| pname:rasterizerDiscardEnable is ename:VK_FALSE, the following command must: |
| have been called in the command buffer prior to drawing: |
| |
| * flink:vkCmdSetFragmentShadingRateKHR |
| endif::VK_KHR_fragment_shading_rate[] |
| |
| ifdef::VK_EXT_transform_feedback[] |
| If the <<features-geometryStreams, pname:geometryStreams>> feature is |
| enabled on the device, and a shader is bound to the |
| ename:VK_SHADER_STAGE_GEOMETRY_BIT stage, the following command must: have |
| been called in the command buffer prior to drawing: |
| |
| * flink:vkCmdSetRasterizationStreamEXT |
| endif::VK_EXT_transform_feedback[] |
| |
| ifdef::VK_EXT_discard_rectangles[] |
| If the `apiext:VK_EXT_discard_rectangles` extension is enabled on the |
| device, and pname:rasterizerDiscardEnable is ename:VK_FALSE, the following |
| commands must: have been called in the command buffer prior to drawing: |
| |
| * flink:vkCmdSetDiscardRectangleEnableEXT |
| * flink:vkCmdSetDiscardRectangleModeEXT, if `discardRectangleEnable` is |
| ename:VK_TRUE |
| * flink:vkCmdSetDiscardRectangleEXT, if `discardRectangleEnable` is |
| ename:VK_TRUE |
| endif::VK_EXT_discard_rectangles[] |
| |
| ifdef::VK_EXT_conservative_rasterization[] |
| If `apiext:VK_EXT_conservative_rasterization` extension is enabled on the |
| device, and pname:rasterizerDiscardEnable is ename:VK_FALSE, the following |
| commands must: have been called in the command buffer prior to drawing: |
| |
| * flink:vkCmdSetConservativeRasterizationModeEXT |
| * flink:vkCmdSetExtraPrimitiveOverestimationSizeEXT, if |
| pname:conservativeRasterizationMode is |
| ename:VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT |
| endif::VK_EXT_conservative_rasterization[] |
| |
| ifdef::VK_EXT_depth_clip_enable[] |
| If the <<features-depthClipEnable, pname:depthClipEnable>> feature is |
| enabled on the device, the following command must: have been called in the |
| command buffer prior to drawing: |
| |
| * flink:vkCmdSetDepthClipEnableEXT |
| endif::VK_EXT_depth_clip_enable[] |
| |
| ifdef::VK_EXT_sample_locations[] |
| If the `apiext:VK_EXT_sample_locations` extension is enabled on the device, |
| and pname:rasterizerDiscardEnable is ename:VK_FALSE, the following commands |
| must: have been called in the command buffer prior to drawing: |
| |
| * flink:vkCmdSetSampleLocationsEnableEXT |
| * flink:vkCmdSetSampleLocationsEXT, if pname:sampleLocationsEnable is |
| ename:VK_TRUE |
| endif::VK_EXT_sample_locations[] |
| |
| ifdef::VK_EXT_provoking_vertex[] |
| If the `apiext:VK_EXT_provoking_vertex` extension is enabled on the device, |
| and pname:rasterizerDiscardEnable is ename:VK_FALSE, and a shader is bound |
| to the ename:VK_SHADER_STAGE_VERTEX_BIT stage, the following command must: |
| have been called in the command buffer prior to drawing: |
| |
| * flink:vkCmdSetProvokingVertexModeEXT |
| endif::VK_EXT_provoking_vertex[] |
| |
| ifdef::VK_EXT_line_rasterization[] |
| If the `apiext:VK_EXT_line_rasterization` extension is enabled on the |
| device, and pname:rasterizerDiscardEnable is ename:VK_FALSE, and if |
| pname:polygonMode is ename:VK_POLYGON_MODE_LINE or a shader is bound to the |
| ename:VK_SHADER_STAGE_VERTEX_BIT stage and pname:primitiveTopology is a line |
| topology or a shader which outputs line primitives is bound to the |
| ename:VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT or |
| ename:VK_SHADER_STAGE_GEOMETRY_BIT stage, the following commands must: have |
| been called in the command buffer prior to drawing: |
| |
| * flink:vkCmdSetLineRasterizationModeEXT |
| * flink:vkCmdSetLineStippleEnableEXT |
| * flink:vkCmdSetLineStippleEXT, if pname:stippledLineEnable is |
| ename:VK_TRUE |
| endif::VK_EXT_line_rasterization[] |
| |
| ifdef::VK_EXT_depth_clip_control[] |
| If the <<features-depthClipControl, pname:depthClipControl>> feature is |
| enabled on the device, the following command must: have been called in the |
| command buffer prior to drawing: |
| |
| * flink:vkCmdSetDepthClipNegativeOneToOneEXT |
| endif::VK_EXT_depth_clip_control[] |
| |
| ifdef::VK_EXT_color_write_enable[] |
| If the <<features-colorWriteEnable, pname:colorWriteEnable>> feature is |
| enabled on the device, and a shader is bound to the |
| ename:VK_SHADER_STAGE_FRAGMENT_BIT stage, and pname:rasterizerDiscardEnable |
| is ename:VK_FALSE, the following command must: have been called in the |
| command buffer prior to drawing: |
| |
| * flink:vkCmdSetColorWriteEnableEXT, with values set for every color |
| attachment in the render pass instance active at draw time |
| endif::VK_EXT_color_write_enable[] |
| |
| ifdef::VK_EXT_attachment_feedback_loop_dynamic_state[] |
| If the <<features-attachmentFeedbackLoopDynamicState, |
| attachmentFeedbackLoopDynamicState>> feature is enabled on the device, and a |
| shader is bound to the ename:VK_SHADER_STAGE_FRAGMENT_BIT stage, and |
| pname:rasterizerDiscardEnable is ename:VK_FALSE, the following command must: |
| have been called in the command buffer prior to drawing: |
| |
| * flink:vkCmdSetAttachmentFeedbackLoopEnableEXT |
| endif::VK_EXT_attachment_feedback_loop_dynamic_state[] |
| |
| ifdef::VK_NV_clip_space_w_scaling[] |
| If the `apiext:VK_NV_clip_space_w_scaling` extension is enabled on the |
| device, the following commands must: have been called in the command buffer |
| prior to drawing: |
| |
| * flink:vkCmdSetViewportWScalingEnableNV |
| * flink:vkCmdSetViewportWScalingNV, if pname:viewportWScalingEnable is |
| ename:VK_TRUE |
| endif::VK_NV_clip_space_w_scaling[] |
| |
| ifdef::VK_NV_viewport_swizzle[] |
| If the `apiext:VK_NV_viewport_swizzle` extension is enabled on the device, |
| the following command must: have been called in the command buffer prior to |
| drawing: |
| |
| * flink:vkCmdSetViewportSwizzleNV |
| endif::VK_NV_viewport_swizzle[] |
| |
| ifdef::VK_NV_fragment_coverage_to_color[] |
| If the `apiext:VK_NV_fragment_coverage_to_color` extension is enabled on the |
| device, and a shader is bound to the ename:VK_SHADER_STAGE_FRAGMENT_BIT |
| stage, and pname:rasterizerDiscardEnable is ename:VK_FALSE, the following |
| commands must: have been called in the command buffer prior to drawing: |
| |
| * flink:vkCmdSetCoverageToColorEnableNV |
| * flink:vkCmdSetCoverageToColorLocationNV, if pname:coverageToColorEnable |
| is ename:VK_TRUE |
| endif::VK_NV_fragment_coverage_to_color[] |
| |
| ifdef::VK_NV_framebuffer_mixed_samples[] |
| If the `apiext:VK_NV_framebuffer_mixed_samples` extension is enabled on the |
| device, and pname:rasterizerDiscardEnable is ename:VK_FALSE, the following |
| commands must: have been called in the command buffer prior to drawing: |
| |
| * flink:vkCmdSetCoverageModulationModeNV |
| * flink:vkCmdSetCoverageModulationTableEnableNV, if |
| pname:coverageModulationMode is not |
| ename:VK_COVERAGE_MODULATION_MODE_NONE_NV |
| * flink:vkCmdSetCoverageModulationTableNV, if |
| pname:coverageModulationTableEnable is ename:VK_TRUE |
| endif::VK_NV_framebuffer_mixed_samples[] |
| |
| ifdef::VK_NV_coverage_reduction_mode[] |
| If the <<features-coverageReductionMode, pname:coverageReductionMode>> |
| feature is enabled on the device, and pname:rasterizerDiscardEnable is |
| ename:VK_FALSE, the following command must: have been called in the command |
| buffer prior to drawing: |
| |
| * flink:vkCmdSetCoverageReductionModeNV |
| endif::VK_NV_coverage_reduction_mode[] |
| |
| ifdef::VK_NV_representative_fragment_test[] |
| If the <<features-representativeFragmentTest, |
| pname:representativeFragmentTest>> feature is enabled on the device, and |
| pname:rasterizerDiscardEnable is ename:VK_FALSE, the following command must: |
| have been called in the command buffer prior to drawing: |
| |
| * flink:vkCmdSetRepresentativeFragmentTestEnableNV |
| endif::VK_NV_representative_fragment_test[] |
| |
| ifdef::VK_NV_shading_rate_image[] |
| If the <<features-shadingRateImage, pname:shadingRateImage>> feature is |
| enabled on the device, and pname:rasterizerDiscardEnable is ename:VK_FALSE, |
| the following commands must: have been called in the command buffer prior to |
| drawing: |
| |
| * flink:vkCmdSetCoarseSampleOrderNV |
| * flink:vkCmdSetShadingRateImageEnableNV |
| * flink:vkCmdSetViewportShadingRatePaletteNV, if |
| pname:shadingRateImageEnable is ename:VK_TRUE |
| endif::VK_NV_shading_rate_image[] |
| |
| ifdef::VK_NV_scissor_exclusive[] |
| If the <<features-exclusiveScissor, pname:exclusiveScissor>> feature is |
| enabled on the device, the following commands must: have been called in the |
| command buffer prior to drawing: |
| |
| * flink:vkCmdSetExclusiveScissorEnableNV |
| * flink:vkCmdSetExclusiveScissorNV, if any value in |
| pname:pExclusiveScissorEnables is ename:VK_TRUE |
| endif::VK_NV_scissor_exclusive[] |
| |
| State can: be set either at any time before or after shader objects are |
| bound, but all required state must: be set prior to issuing drawing |
| commands. |
| |
| [[shaders-objects-pipeline-interaction]] |
| === Interaction With Pipelines |
| |
| Calling flink:vkCmdBindShadersEXT causes the pipeline bind points |
| <<shaders-binding,corresponding to each stage>> in pname:pStages to be |
| disturbed, meaning that any <<pipelines, pipelines>> that had previously |
| been bound to those pipeline bind points are no longer bound. |
| |
| If ename:VK_PIPELINE_BIND_POINT_GRAPHICS is disturbed (i.e., if |
| pname:pStages contains any graphics stage), any graphics pipeline state that |
| the previously bound pipeline did not specify as <<pipelines-dynamic-state, |
| dynamic>> becomes undefined:, and must: be set in the command buffer before |
| issuing drawing commands using shader objects. |
| |
| Calls to flink:vkCmdBindPipeline likewise disturb the shader stage(s) |
| corresponding to pname:pipelineBindPoint, meaning that any shaders that had |
| previously been bound to any of those stages are no longer bound, even if |
| the pipeline was created without shaders for some of those stages. |
| |
| [[shaders-objects-destruction]] |
| === Shader Object Destruction |
| |
| [open,refpage='vkDestroyShaderEXT',desc='Destroy a shader object',type='protos'] |
| -- |
| To destroy a shader object, call: |
| |
| include::{generated}/api/protos/vkDestroyShaderEXT.adoc[] |
| |
| * pname:device is the logical device that destroys the shader object. |
| * pname:shader is the handle of the shader object to destroy. |
| * pname:pAllocator controls host memory allocation as described in the |
| <<memory-allocation, Memory Allocation>> chapter. |
| |
| Destroying a shader object used by one or more command buffers in the |
| <<commandbuffers-lifecycle, recording or executable state>> causes those |
| command buffers to move into the _invalid state_. |
| |
| .Valid Usage |
| **** |
| * [[VUID-vkDestroyShaderEXT-None-08481]] |
| The <<features-shaderObject, pname:shaderObject>> feature must: be |
| enabled |
| * [[VUID-vkDestroyShaderEXT-shader-08482]] |
| All submitted commands that refer to pname:shader must: have completed |
| execution |
| * [[VUID-vkDestroyShaderEXT-pAllocator-08483]] |
| If sname:VkAllocationCallbacks were provided when pname:shader was |
| created, a compatible set of callbacks must: be provided here |
| * [[VUID-vkDestroyShaderEXT-pAllocator-08484]] |
| If no sname:VkAllocationCallbacks were provided when pname:shader was |
| created, pname:pAllocator must: be `NULL` |
| **** |
| |
| include::{generated}/validity/protos/vkDestroyShaderEXT.adoc[] |
| -- |
| |
| endif::VK_EXT_shader_object[] |
| |
| [[shader-modules]] |
| == Shader Modules |
| |
| [open,refpage='VkShaderModule',desc='Opaque handle to a shader module object',type='handles'] |
| -- |
| _Shader modules_ contain _shader code_ and one or more entry points. |
| Shaders are selected from a shader module by specifying an entry point as |
| part of <<pipelines,pipeline>> creation. |
| The stages of a pipeline can: use shaders that come from different modules. |
| The shader code defining a shader module must: be in the SPIR-V format, as |
| described by the <<spirvenv,Vulkan Environment for SPIR-V>> appendix. |
| |
| Shader modules are represented by sname:VkShaderModule handles: |
| |
| include::{generated}/api/handles/VkShaderModule.adoc[] |
| |
| ifdef::VKSC_VERSION_1_0[] |
| Shader modules are not used in Vulkan SC, but the type has been retained for |
| compatibility <<SCID-8>>. |
| |
| In Vulkan SC, the shader modules and pipeline state are supplied to an |
| offline compiler which creates a pipeline cache entry which is loaded at |
| <<pipelines,pipeline>> creation time. |
| |
| ifdef::hidden[] |
| // tag::scremoved[] |
| * elink:VkStructureType |
| ** ename:VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO <<SCID-8>> |
| * elink:VkObjectType |
| ** ename:VK_OBJECT_TYPE_SHADER_MODULE <<SCID-8>> |
| * fname:vkCreateShaderModule, fname:vkDestroyShaderModule <<SCID-8>> |
| * sname:VkShaderModule, sname:VkShaderModuleCreateInfo <<SCID-8>> |
| * tname:VkShaderModuleCreateFlags <<SCID-8>> |
| * ename:VkShaderModuleCreateFlagBits <<SCID-8>> |
| // end::scremoved[] |
| endif::hidden[] |
| endif::VKSC_VERSION_1_0[] |
| -- |
| |
| ifndef::VKSC_VERSION_1_0[] |
| [open,refpage='vkCreateShaderModule',desc='Creates a new shader module object',type='protos'] |
| -- |
| To create a shader module, call: |
| |
| include::{generated}/api/protos/vkCreateShaderModule.adoc[] |
| |
| * pname:device is the logical device that creates the shader module. |
| * pname:pCreateInfo is a pointer to a slink:VkShaderModuleCreateInfo |
| structure. |
| * pname:pAllocator controls host memory allocation as described in the |
| <<memory-allocation, Memory Allocation>> chapter. |
| * pname:pShaderModule is a pointer to a slink:VkShaderModule handle in |
| which the resulting shader module object is returned. |
| |
| Once a shader module has been created, any entry points it contains can: be |
| used in pipeline shader stages as described in <<pipelines-compute,Compute |
| Pipelines>> and <<pipelines-graphics,Graphics Pipelines>>. |
| |
| ifdef::VK_EXT_graphics_pipeline_libraries,VK_KHR_maintenance5[] |
| [NOTE] |
| .Note |
| ==== |
| If |
| ifdef::VK_EXT_graphics_pipeline_libraries[] |
| the <<features-graphicsPipelineLibrary, pname:graphicsPipelineLibrary>> |
| feature |
| endif::VK_EXT_graphics_pipeline_libraries[] |
| ifdef::VK_EXT_graphics_pipeline_libraries+VK_KHR_maintenance5[or] |
| ifdef::VK_KHR_maintenance5[] |
| the <<features-maintenance5,pname:maintenance5>> feature |
| endif::VK_KHR_maintenance5[] |
| is enabled, shader module creation can be omitted entirely. |
| Instead, applications should provide the slink:VkShaderModuleCreateInfo |
| structure directly in to pipeline creation by chaining it to |
| slink:VkPipelineShaderStageCreateInfo. |
| This avoids the overhead of creating and managing an additional object. |
| ==== |
| endif::VK_EXT_graphics_pipeline_libraries,VK_KHR_maintenance5[] |
| |
| .Valid Usage |
| **** |
| * [[VUID-vkCreateShaderModule-pCreateInfo-06904]] |
| If pname:pCreateInfo is not `NULL`, pname:pCreateInfo->pNext must: be |
| `NULL` |
| ifdef::VK_EXT_validation_cache[] |
| or a pointer to a slink:VkShaderModuleValidationCacheCreateInfoEXT |
| structure |
| endif::VK_EXT_validation_cache[] |
| **** |
| |
| include::{generated}/validity/protos/vkCreateShaderModule.adoc[] |
| -- |
| |
| [open,refpage='VkShaderModuleCreateInfo',desc='Structure specifying parameters of a newly created shader module',type='structs'] |
| -- |
| :refpage: VkShaderModuleCreateInfo |
| |
| The sname:VkShaderModuleCreateInfo structure is defined as: |
| |
| include::{generated}/api/structs/VkShaderModuleCreateInfo.adoc[] |
| |
| * pname:sType is a elink:VkStructureType value identifying this structure. |
| * pname:pNext is `NULL` or a pointer to a structure extending this |
| structure. |
| * pname:flags is reserved for future use. |
| * pname:codeSize is the size, in bytes, of the code pointed to by |
| pname:pCode. |
| * pname:pCode is a pointer to code that is used to create the shader |
| module. |
| The type and format of the code is determined from the content of the |
| memory addressed by pname:pCode. |
| |
| .Valid Usage |
| **** |
| :prefixCondition: |
| ifdef::VK_NV_glsl_shader[] |
| :prefixCondition: If pCode is a pointer to SPIR-V code, |
| endif::VK_NV_glsl_shader[] |
| |
| include::{chapters}/commonvalidity/shader_create_spv_common.adoc[] |
| |
| ifdef::VK_NV_glsl_shader[] |
| * [[VUID-VkShaderModuleCreateInfo-pCode-07912]] |
| If the apiext:VK_NV_glsl_shader extension is not enabled, pname:pCode |
| must: be a pointer to SPIR-V code |
| * [[VUID-VkShaderModuleCreateInfo-pCode-01379]] |
| If pname:pCode is a pointer to GLSL code, it must: be valid GLSL code |
| written to the `GL_KHR_vulkan_glsl` GLSL extension specification |
| endif::VK_NV_glsl_shader[] |
| * [[VUID-VkShaderModuleCreateInfo-codeSize-01085]] |
| pname:codeSize must: be greater than 0 |
| **** |
| |
| include::{generated}/validity/structs/VkShaderModuleCreateInfo.adoc[] |
| -- |
| |
| [open,refpage='VkShaderModuleCreateFlags',desc='Reserved for future use',type='flags'] |
| -- |
| include::{generated}/api/flags/VkShaderModuleCreateFlags.adoc[] |
| |
| tname:VkShaderModuleCreateFlags is a bitmask type for setting a mask, but is |
| currently reserved for future use. |
| -- |
| |
| ifdef::VK_EXT_validation_cache[] |
| include::{chapters}/VK_EXT_validation_cache/shader-module-validation-cache.adoc[] |
| endif::VK_EXT_validation_cache[] |
| |
| |
| [open,refpage='vkDestroyShaderModule',desc='Destroy a shader module',type='protos'] |
| -- |
| To destroy a shader module, call: |
| |
| include::{generated}/api/protos/vkDestroyShaderModule.adoc[] |
| |
| * pname:device is the logical device that destroys the shader module. |
| * pname:shaderModule is the handle of the shader module to destroy. |
| * pname:pAllocator controls host memory allocation as described in the |
| <<memory-allocation, Memory Allocation>> chapter. |
| |
| A shader module can: be destroyed while pipelines created using its shaders |
| are still in use. |
| |
| .Valid Usage |
| **** |
| * [[VUID-vkDestroyShaderModule-shaderModule-01092]] |
| If sname:VkAllocationCallbacks were provided when pname:shaderModule was |
| created, a compatible set of callbacks must: be provided here |
| * [[VUID-vkDestroyShaderModule-shaderModule-01093]] |
| If no sname:VkAllocationCallbacks were provided when pname:shaderModule |
| was created, pname:pAllocator must: be `NULL` |
| **** |
| |
| include::{generated}/validity/protos/vkDestroyShaderModule.adoc[] |
| -- |
| endif::VKSC_VERSION_1_0[] |
| |
| |
| |
| ifdef::VK_EXT_shader_module_identifier[] |
| [[shaders-identifiers]] |
| == Shader Module Identifiers |
| |
| [open,refpage='vkGetShaderModuleIdentifierEXT',desc='Query a unique identifier for a shader module',type='protos'] |
| -- |
| Shader modules have unique identifiers associated with them. |
| To query an implementation provided identifier, call: |
| |
| include::{generated}/api/protos/vkGetShaderModuleIdentifierEXT.adoc[] |
| |
| * pname:device is the logical device that created the shader module. |
| * pname:shaderModule is the handle of the shader module. |
| * pname:pIdentifier is a pointer to the returned |
| slink:VkShaderModuleIdentifierEXT. |
| |
| The identifier returned by the implementation must: only depend on |
| pname:shaderIdentifierAlgorithmUUID and information provided in the |
| slink:VkShaderModuleCreateInfo which created pname:shaderModule. |
| The implementation may: return equal identifiers for two different |
| slink:VkShaderModuleCreateInfo structures if the difference does not affect |
| pipeline compilation. |
| Identifiers are only meaningful on different slink:VkDevice objects if the |
| device the identifier was queried from had the same |
| <<limits-shaderModuleIdentifierAlgorithmUUID, |
| pname:shaderModuleIdentifierAlgorithmUUID>> as the device consuming the |
| identifier. |
| |
| .Valid Usage |
| **** |
| * [[VUID-vkGetShaderModuleIdentifierEXT-shaderModuleIdentifier-06884]] |
| <<features-shaderModuleIdentifier, pname:shaderModuleIdentifier>> |
| feature must: be enabled |
| **** |
| |
| include::{generated}/validity/protos/vkGetShaderModuleIdentifierEXT.adoc[] |
| -- |
| |
| [open,refpage='vkGetShaderModuleCreateInfoIdentifierEXT',desc='Query a unique identifier for a shader module create info',type='protos'] |
| -- |
| slink:VkShaderModuleCreateInfo structures have unique identifiers associated |
| with them. |
| To query an implementation provided identifier, call: |
| |
| include::{generated}/api/protos/vkGetShaderModuleCreateInfoIdentifierEXT.adoc[] |
| |
| * pname:device is the logical device that can: create a |
| slink:VkShaderModule from pname:pCreateInfo. |
| * pname:pCreateInfo is a pointer to a slink:VkShaderModuleCreateInfo |
| structure. |
| * pname:pIdentifier is a pointer to the returned |
| slink:VkShaderModuleIdentifierEXT. |
| |
| The identifier returned by implementation must: only depend on |
| pname:shaderIdentifierAlgorithmUUID and information provided in the |
| slink:VkShaderModuleCreateInfo. |
| The implementation may: return equal identifiers for two different |
| slink:VkShaderModuleCreateInfo structures if the difference does not affect |
| pipeline compilation. |
| Identifiers are only meaningful on different slink:VkDevice objects if the |
| device the identifier was queried from had the same |
| <<limits-shaderModuleIdentifierAlgorithmUUID, |
| pname:shaderModuleIdentifierAlgorithmUUID>> as the device consuming the |
| identifier. |
| |
| The identifier returned by the implementation in |
| flink:vkGetShaderModuleCreateInfoIdentifierEXT must: be equal to the |
| identifier returned by flink:vkGetShaderModuleIdentifierEXT given equivalent |
| definitions of slink:VkShaderModuleCreateInfo and any chained pname:pNext |
| structures. |
| |
| .Valid Usage |
| **** |
| * [[VUID-vkGetShaderModuleCreateInfoIdentifierEXT-shaderModuleIdentifier-06885]] |
| <<features-shaderModuleIdentifier, pname:shaderModuleIdentifier>> |
| feature must: be enabled |
| **** |
| |
| include::{generated}/validity/protos/vkGetShaderModuleCreateInfoIdentifierEXT.adoc[] |
| -- |
| |
| [open,refpage='VkShaderModuleIdentifierEXT',desc='A unique identifier for a shader module',type='structs'] |
| -- |
| slink:VkShaderModuleIdentifierEXT represents a shader module identifier |
| returned by the implementation. |
| |
| include::{generated}/api/structs/VkShaderModuleIdentifierEXT.adoc[] |
| |
| * pname:sType is a elink:VkStructureType value identifying this structure. |
| * pname:pNext is `NULL` or a pointer to a structure extending this |
| structure. |
| * pname:identifierSize is the size, in bytes, of valid data returned in |
| pname:identifier. |
| * pname:identifier is a buffer of opaque data specifying an identifier. |
| |
| Any returned values beyond the first pname:identifierSize bytes are |
| undefined:. |
| Implementations must: return an pname:identifierSize greater than 0, and |
| less-or-equal to ename:VK_MAX_SHADER_MODULE_IDENTIFIER_SIZE_EXT. |
| |
| Two identifiers are considered equal if pname:identifierSize is equal and |
| the first pname:identifierSize bytes of pname:identifier compare equal. |
| |
| Implementations may: return a different pname:identifierSize for different |
| modules. |
| Implementations should: ensure that pname:identifierSize is large enough to |
| uniquely define a shader module. |
| |
| include::{generated}/validity/structs/VkShaderModuleIdentifierEXT.adoc[] |
| -- |
| |
| [open,refpage='VK_MAX_SHADER_MODULE_IDENTIFIER_SIZE_EXT',desc='Maximum length of a shader module identifier',type='consts'] |
| -- |
| ename:VK_MAX_SHADER_MODULE_IDENTIFIER_SIZE_EXT is the length in bytes of a |
| shader module identifier, as returned in |
| slink:VkShaderModuleIdentifierEXT::pname:identifierSize. |
| |
| include::{generated}/api/enums/VK_MAX_SHADER_MODULE_IDENTIFIER_SIZE_EXT.adoc[] |
| -- |
| endif::VK_EXT_shader_module_identifier[] |
| |
| [[shaders-binding]] |
| == Binding Shaders |
| |
| Before a shader can be used it must: be first bound to the command buffer. |
| |
| Calling flink:vkCmdBindPipeline binds all stages corresponding to the |
| elink:VkPipelineBindPoint. |
| ifdef::VK_EXT_shader_object[] |
| Calling flink:vkCmdBindShadersEXT binds all stages in pname:pStages |
| endif::VK_EXT_shader_object[] |
| |
| The following table describes the relationship between shader stages and |
| pipeline bind points: |
| |
| [cols="1,1,1"] |
| |==== |
| |Shader stage |Pipeline bind point | behavior controlled |
| |
| a| * ename:VK_SHADER_STAGE_VERTEX_BIT |
| * ename:VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT |
| * ename:VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT |
| * ename:VK_SHADER_STAGE_GEOMETRY_BIT |
| * ename:VK_SHADER_STAGE_FRAGMENT_BIT |
| ifdef::VK_EXT_mesh_shader[] |
| * ename:VK_SHADER_STAGE_TASK_BIT_EXT |
| * ename:VK_SHADER_STAGE_MESH_BIT_EXT |
| endif::VK_EXT_mesh_shader[] |
| ifndef::VK_EXT_mesh_shader[] |
| ifdef::VK_NV_mesh_shader[] |
| * ename:VK_SHADER_STAGE_TASK_BIT_NV |
| * ename:VK_SHADER_STAGE_MESH_BIT_NV |
| endif::VK_NV_mesh_shader[] |
| endif::VK_EXT_mesh_shader[] |
| | ename:VK_PIPELINE_BIND_POINT_GRAPHICS |
| | all <<drawing, drawing commands>> |
| |
| a| * ename:VK_SHADER_STAGE_COMPUTE_BIT |
| | ename:VK_PIPELINE_BIND_POINT_COMPUTE |
| | all <<dispatch, dispatch commands>> |
| |
| ifdef::VK_NV_ray_tracing,VK_KHR_ray_tracing_pipeline[] |
| a| * ename:VK_SHADER_STAGE_ANY_HIT_BIT_KHR |
| * ename:VK_SHADER_STAGE_CALLABLE_BIT_KHR |
| * ename:VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR |
| * ename:VK_SHADER_STAGE_INTERSECTION_BIT_KHR |
| * ename:VK_SHADER_STAGE_MISS_BIT_KHR |
| * ename:VK_SHADER_STAGE_RAYGEN_BIT_KHR |
| | ename:VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR |
| | flink:vkCmdTraceRaysKHR and flink:vkCmdTraceRaysIndirectKHR |
| endif::VK_NV_ray_tracing,VK_KHR_ray_tracing_pipeline[] |
| |
| ifdef::VK_HUAWEI_subpass_shading[] |
| a| * ename:VK_SHADER_STAGE_SUBPASS_SHADING_BIT_HUAWEI |
| * ename:VK_SHADER_STAGE_CLUSTER_CULLING_BIT_HUAWEI |
| | ename:VK_PIPELINE_BIND_POINT_SUBPASS_SHADING_HUAWEI |
| | flink:vkCmdSubpassShadingHUAWEI |
| endif::VK_HUAWEI_subpass_shading[] |
| |
| ifdef::VK_AMDX_shader_enqueue[] |
| a| * ename:VK_SHADER_STAGE_COMPUTE_BIT |
| | ename:VK_PIPELINE_BIND_POINT_EXECUTION_GRAPH_AMDX |
| | all <<executiongraphs, execution graph commands>> |
| endif::VK_AMDX_shader_enqueue[] |
| |==== |
| |
| [[shaders-execution]] |
| == Shader Execution |
| |
| At each stage of the pipeline, multiple invocations of a shader may: execute |
| simultaneously. |
| Further, invocations of a single shader produced as the result of different |
| commands may: execute simultaneously. |
| The relative execution order of invocations of the same shader type is |
| undefined:. |
| Shader invocations may: complete in a different order than that in which the |
| primitives they originated from were drawn or dispatched by the application. |
| However, fragment shader outputs are written to attachments in |
| <<primsrast-order,rasterization order>>. |
| |
| The relative execution order of invocations of different shader types is |
| largely undefined:. |
| However, when invoking a shader whose inputs are generated from a previous |
| pipeline stage, the shader invocations from the previous stage are |
| guaranteed to have executed far enough to generate input values for all |
| required inputs. |
| |
| |
| [[shaders-termination]] |
| === Shader Termination |
| |
| A shader invocation that is _terminated_ has finished executing |
| instructions. |
| |
| Executing code:OpReturn in the entry point, or executing |
| code:OpTerminateInvocation in any function will terminate an invocation. |
| Implementations may: also terminate a shader invocation when code:OpKill is |
| executed in any function; otherwise it becomes a |
| <<shaders-helper-invocations, helper invocation>>. |
| |
| In addition to the above conditions, <<shaders-helper-invocations,helper |
| invocations>> are terminated when all non-helper invocations in the same |
| <<shaders-derivative-operations,derivative group>> either terminate or |
| become <<shaders-helper-invocations,helper invocations>> via |
| ifdef::VK_EXT_shader_demote_to_helper_invocation[] |
| code:OpDemoteToHelperInvocationEXT or |
| endif::VK_EXT_shader_demote_to_helper_invocation[] |
| code:OpKill. |
| |
| A shader stage for a given command completes execution when all invocations |
| for that stage have terminated. |
| |
| |
| [[shaders-execution-memory-ordering]] |
| == Shader Memory Access Ordering |
| |
| The order in which image or buffer memory is read or written by shaders is |
| largely undefined:. |
| For some shader types (vertex, tessellation evaluation, and in some cases, |
| fragment), even the number of shader invocations that may: perform loads and |
| stores is undefined:. |
| |
| In particular, the following rules apply: |
| |
| * <<shaders-vertex-execution,Vertex>> and |
| <<shaders-tessellation-evaluation-execution,tessellation evaluation>> |
| shaders will be invoked at least once for each unique vertex, as defined |
| in those sections. |
| * <<fragops-shader,Fragment>> shaders will be invoked zero or more times, |
| as defined in that section. |
| * The relative execution order of invocations of the same shader type is |
| undefined:. |
| A store issued by a shader when working on primitive B might complete |
| prior to a store for primitive A, even if primitive A is specified prior |
| to primitive B. This applies even to fragment shaders; while fragment |
| shader outputs are always written to the framebuffer in |
| <<primsrast-order, rasterization order>>, stores executed by fragment |
| shader invocations are not. |
| * The relative execution order of invocations of different shader types is |
| largely undefined:. |
| |
| [NOTE] |
| .Note |
| ==== |
| The above limitations on shader invocation order make some forms of |
| synchronization between shader invocations within a single set of primitives |
| unimplementable. |
| For example, having one invocation poll memory written by another invocation |
| assumes that the other invocation has been launched and will complete its |
| writes in finite time. |
| ==== |
| |
| ifdef::VK_VERSION_1_2,VK_KHR_vulkan_memory_model[] |
| |
| The <<memory-model,Memory Model>> appendix defines the terminology and rules |
| for how to correctly communicate between shader invocations, such as when a |
| write is <<memory-model-visible-to,Visible-To>> a read, and what constitutes |
| a <<memory-model-access-data-race,Data Race>>. |
| |
| Applications must: not cause a data race. |
| |
| endif::VK_VERSION_1_2,VK_KHR_vulkan_memory_model[] |
| |
| ifndef::VK_VERSION_1_2,VK_KHR_vulkan_memory_model[] |
| |
| Stores issued to different memory locations within a single shader |
| invocation may: not be visible to other invocations, or may: not become |
| visible in the order they were performed. |
| |
| The code:OpMemoryBarrier instruction can: be used to provide stronger |
| ordering of reads and writes performed by a single invocation. |
| code:OpMemoryBarrier guarantees that any memory transactions issued by the |
| shader invocation prior to the instruction complete prior to the memory |
| transactions issued after the instruction. |
| Memory barriers are needed for algorithms that require multiple invocations |
| to access the same memory and require the operations to be performed in a |
| partially-defined relative order. |
| For example, if one shader invocation does a series of writes, followed by |
| an code:OpMemoryBarrier instruction, followed by another write, then the |
| results of the series of writes before the barrier become visible to other |
| shader invocations at a time earlier or equal to when the results of the |
| final write become visible to those invocations. |
| In practice it means that another invocation that sees the results of the |
| final write would also see the previous writes. |
| Without the memory barrier, the final write may: be visible before the |
| previous writes. |
| |
| Writes that are the result of shader stores through a variable decorated |
| with code:Coherent automatically have available writes to the same buffer, |
| buffer view, or image view made visible to them, and are themselves |
| automatically made available to access by the same buffer, buffer view, or |
| image view. |
| Reads that are the result of shader loads through a variable decorated with |
| code:Coherent automatically have available writes to the same buffer, buffer |
| view, or image view made visible to them. |
| The order that coherent writes to different locations become available is |
| undefined:, unless enforced by a memory barrier instruction or other memory |
| dependency. |
| |
| [NOTE] |
| .Note |
| ==== |
| Explicit memory dependencies must: still be used to guarantee availability |
| and visibility for access via other buffers, buffer views, or image views. |
| ==== |
| |
| The built-in atomic memory transaction instructions can: be used to read and |
| write a given memory address atomically. |
| While built-in atomic functions issued by multiple shader invocations are |
| executed in undefined: order relative to each other, these functions perform |
| both a read and a write of a memory address and guarantee that no other |
| memory transaction will write to the underlying memory between the read and |
| write. |
| Atomic operations ensure automatic availability and visibility for writes |
| and reads in the same way as those to code:Coherent variables. |
| |
| [NOTE] |
| .Note |
| ==== |
| Memory accesses performed on different resource descriptors with the same |
| memory backing may: not be well-defined even with the code:Coherent |
| decoration or via atomics, due to things such as image layouts or ownership |
| of the resource - as described in the <<synchronization, Synchronization and |
| Cache Control>> chapter. |
| ==== |
| |
| [NOTE] |
| .Note |
| ==== |
| Atomics allow shaders to use shared global addresses for mutual exclusion or |
| as counters, among other uses. |
| ==== |
| |
| endif::VK_VERSION_1_2,VK_KHR_vulkan_memory_model[] |
| |
| The SPIR-V *SubgroupMemory*, *CrossWorkgroupMemory*, and |
| *AtomicCounterMemory* memory semantics are ignored. |
| Sequentially consistent atomics and barriers are not supported and |
| *SequentiallyConsistent* is treated as *AcquireRelease*. |
| *SequentiallyConsistent* should: not be used. |
| |
| |
| [[shaders-inputs]] |
| == Shader Inputs and Outputs |
| |
| Data is passed into and out of shaders using variables with input or output |
| storage class, respectively. |
| User-defined inputs and outputs are connected between stages by matching |
| their code:Location decorations. |
| Additionally, data can: be provided by or communicated to special functions |
| provided by the execution environment using code:BuiltIn decorations. |
| |
| In many cases, the same code:BuiltIn decoration can: be used in multiple |
| shader stages with similar meaning. |
| The specific behavior of variables decorated as code:BuiltIn is documented |
| in the following sections. |
| |
| ifdef::VK_NV_mesh_shader,VK_EXT_mesh_shader[] |
| [[shaders-task]] |
| == Task Shaders |
| |
| Task shaders operate in conjunction with the mesh shaders to produce a |
| collection of primitives that will be processed by subsequent stages of the |
| graphics pipeline. |
| Its primary purpose is to create a variable amount of subsequent mesh shader |
| invocations. |
| |
| Task shaders are invoked via the execution of the |
| <<drawing-mesh-shading,programmable mesh shading>> pipeline. |
| |
| The task shader has no fixed-function inputs other than variables |
| identifying the specific workgroup and invocation. |
| ifdef::VK_NV_mesh_shader[] |
| In the code:TaskNV {ExecutionModel} the number of mesh shader workgroups to |
| create is specified via a code:TaskCountNV decorated output variable. |
| endif::VK_NV_mesh_shader[] |
| ifdef::VK_EXT_mesh_shader[] |
| In the code:TaskEXT {ExecutionModel} the number of mesh shader workgroups to |
| create is specified via the code:OpEmitMeshTasksEXT instruction. |
| endif::VK_EXT_mesh_shader[] |
| |
| The task shader can write additional outputs to task memory, which can be |
| read by all of the mesh shader workgroups it created. |
| |
| |
| === Task Shader Execution |
| |
| Task workloads are formed from groups of work items called workgroups and |
| processed by the task shader in the current graphics pipeline. |
| A workgroup is a collection of shader invocations that execute the same |
| shader, potentially in parallel. |
| Task shaders execute in _global workgroups_ which are divided into a number |
| of _local workgroups_ with a size that can: be set by assigning a value to |
| the code:LocalSize |
| ifdef::VK_VERSION_1_3,VK_KHR_maintenance4[or code:LocalSizeId] |
| execution mode or via an object decorated by the code:WorkgroupSize |
| decoration. |
| An invocation within a local workgroup can: share data with other members of |
| the local workgroup through shared variables and issue memory and control |
| flow barriers to synchronize with other members of the local workgroup. |
| ifdef::VK_EXT_mesh_shader[] |
| ifdef::VK_VERSION_1_1,VK_KHR_multiview[] |
| If the subpass includes multiple views in its view mask, a Task shader using |
| code:TaskEXT {ExecutionModel} may: be invoked separately for each view. |
| endif::VK_VERSION_1_1,VK_KHR_multiview[] |
| endif::VK_EXT_mesh_shader[] |
| |
| |
| [[shaders-mesh]] |
| == Mesh Shaders |
| |
| Mesh shaders operate in workgroups to produce a collection of primitives |
| that will be processed by subsequent stages of the graphics pipeline. |
| Each workgroup emits zero or more output primitives and the group of |
| vertices and their associated data required for each output primitive. |
| |
| Mesh shaders are invoked via the execution of the |
| <<drawing-mesh-shading,programmable mesh shading>> pipeline. |
| |
| The only inputs available to the mesh shader are variables identifying the |
| specific workgroup and invocation and, if applicable, any outputs written to |
| task memory by the task shader that spawned the mesh shader's workgroup. |
| The mesh shader can operate without a task shader as well. |
| |
| The invocations of the mesh shader workgroup write an output mesh, |
| comprising a set of primitives with per-primitive attributes, a set of |
| vertices with per-vertex attributes, and an array of indices identifying the |
| mesh vertices that belong to each primitive. |
| The primitives of this mesh are then processed by subsequent graphics |
| pipeline stages, where the outputs of the mesh shader form an interface with |
| the fragment shader. |
| |
| |
| === Mesh Shader Execution |
| |
| Mesh workloads are formed from groups of work items called workgroups and |
| processed by the mesh shader in the current graphics pipeline. |
| A workgroup is a collection of shader invocations that execute the same |
| shader, potentially in parallel. |
| Mesh shaders execute in _global workgroups_ which are divided into a number |
| of _local workgroups_ with a size that can: be set by assigning a value to |
| the code:LocalSize |
| ifdef::VK_VERSION_1_3,VK_KHR_maintenance4[or code:LocalSizeId] |
| execution mode or via an object decorated by the code:WorkgroupSize |
| decoration. |
| An invocation within a local workgroup can: share data with other members of |
| the local workgroup through shared variables and issue memory and control |
| flow barriers to synchronize with other members of the local workgroup. |
| |
| The _global workgroups_ may be generated explicitly via the API, or |
| implicitly through the task shader's work creation mechanism. |
| endif::VK_NV_mesh_shader,VK_EXT_mesh_shader[] |
| ifdef::VK_EXT_mesh_shader[] |
| ifdef::VK_VERSION_1_1,VK_KHR_multiview[] |
| If the subpass includes multiple views in its view mask, a Mesh shader using |
| code:MeshEXT {ExecutionModel} may: be invoked separately for each view. |
| endif::VK_VERSION_1_1,VK_KHR_multiview[] |
| endif::VK_EXT_mesh_shader[] |
| |
| ifdef::VK_HUAWEI_cluster_culling_shader[] |
| [[shaders-cluster-culling]] |
| |
| == Cluster Culling Shaders |
| Cluster Culling shaders are invoked via the execution of the |
| <<drawing-cluster-culling-shading,Programmable Cluster Culling Shading>> |
| pipeline. |
| |
| The only inputs available to the cluster culling shader are variables |
| identifying the specific workgroup and invocation. |
| |
| Cluster Culling shaders operate in workgroups to perform cluster-based |
| culling and produce zero or more cluster drawing command that will be |
| processed by subsequent stages of the graphics pipeline. |
| |
| The Cluster Drawing Command(CDC) is very similar to the MDI command, |
| invocations in workgroup can emit zero of more CDC to draw zero or more |
| visible cluster. |
| |
| === Cluster Culling Shader Execution |
| |
| Cluster Culling workloads are formed from groups of work items called |
| workgroups and processed by the cluster culling shader in the current |
| graphics pipeline. |
| A workgroup is a collection of shader invocations that execute the same |
| shader, potentially in parallel. |
| Cluster Culling shaders execute in _global workgroups_ which are divided |
| into a number of _local workgroups_ with a size that can: be set by |
| assigning a value to the code:LocalSize |
| ifdef::VK_VERSION_1_3,VK_KHR_maintenance4[or code:LocalSizeId] |
| execution mode or via an object decorated by the code:WorkgroupSize |
| decoration. |
| An invocation within a local workgroup can: share data with other members of |
| the local workgroup through shared variables and issue memory and control |
| flow barriers to synchronize with other members of the local workgroup. |
| endif::VK_HUAWEI_cluster_culling_shader[] |
| |
| [[shaders-vertex]] |
| == Vertex Shaders |
| |
| Each vertex shader invocation operates on one vertex and its associated |
| <<fxvertex-attrib,vertex attribute>> data, and outputs one vertex and |
| associated data. |
| ifndef::VK_NV_mesh_shader,VK_EXT_mesh_shader[] |
| Graphics pipelines must: include a vertex shader, and the vertex shader |
| stage is always the first shader stage in the graphics pipeline. |
| endif::VK_NV_mesh_shader,VK_EXT_mesh_shader[] |
| ifdef::VK_NV_mesh_shader,VK_EXT_mesh_shader[] |
| Graphics pipelines using primitive shading must: include a vertex shader, |
| and the vertex shader stage is always the first shader stage in the graphics |
| pipeline. |
| endif::VK_NV_mesh_shader,VK_EXT_mesh_shader[] |
| |
| |
| [[shaders-vertex-execution]] |
| === Vertex Shader Execution |
| |
| A vertex shader must: be executed at least once for each vertex specified by |
| a drawing command. |
| ifdef::VK_VERSION_1_1,VK_KHR_multiview[] |
| If the subpass includes multiple views in its view mask, the shader may: be |
| invoked separately for each view. |
| endif::VK_VERSION_1_1,VK_KHR_multiview[] |
| During execution, the shader is presented with the index of the vertex and |
| instance for which it has been invoked. |
| Input variables declared in the vertex shader are filled by the |
| implementation with the values of vertex attributes associated with the |
| invocation being executed. |
| |
| If the same vertex is specified multiple times in a drawing command (e.g. by |
| including the same index value multiple times in an index buffer) the |
| implementation may: reuse the results of vertex shading if it can statically |
| determine that the vertex shader invocations will produce identical results. |
| |
| [NOTE] |
| .Note |
| ==== |
| It is implementation-dependent when and if results of vertex shading are |
| reused, and thus how many times the vertex shader will be executed. |
| This is true also if the vertex shader contains stores or atomic operations |
| (see <<features-vertexPipelineStoresAndAtomics, |
| pname:vertexPipelineStoresAndAtomics>>). |
| ==== |
| |
| |
| [[shaders-tessellation-control]] |
| == Tessellation Control Shaders |
| |
| The tessellation control shader is used to read an input patch provided by |
| the application and to produce an output patch. |
| Each tessellation control shader invocation operates on an input patch |
| (after all control points in the patch are processed by a vertex shader) and |
| its associated data, and outputs a single control point of the output patch |
| and its associated data, and can: also output additional per-patch data. |
| The input patch is sized according to the pname:patchControlPoints member of |
| slink:VkPipelineTessellationStateCreateInfo, as part of input assembly. |
| |
| ifdef::VK_EXT_extended_dynamic_state2,VK_EXT_shader_object[] |
| The input patch can also be dynamically sized with pname:patchControlPoints |
| parameter of flink:vkCmdSetPatchControlPointsEXT. |
| |
| [open,refpage='vkCmdSetPatchControlPointsEXT',desc='Specify the number of control points per patch dynamically for a command buffer',type='protos'] |
| -- |
| To <<pipelines-dynamic-state, dynamically set>> the number of control points |
| per patch, call: |
| |
| include::{generated}/api/protos/vkCmdSetPatchControlPointsEXT.adoc[] |
| |
| * pname:commandBuffer is the command buffer into which the command will be |
| recorded. |
| * pname:patchControlPoints specifies the number of control points per |
| patch. |
| |
| This command sets the number of control points per patch for subsequent |
| drawing commands |
| ifdef::VK_EXT_shader_object[] |
| ifdef::VK_EXT_extended_dynamic_state2[when drawing using <<shaders-objects, shader objects>>, or] |
| ifndef::VK_EXT_extended_dynamic_state2[when drawing using <<shaders-objects, shader objects>>.] |
| endif::VK_EXT_shader_object[] |
| ifdef::VK_EXT_extended_dynamic_state2[] |
| when the graphics pipeline is created with |
| ename:VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT set in |
| slink:VkPipelineDynamicStateCreateInfo::pname:pDynamicStates. |
| endif::VK_EXT_extended_dynamic_state2[] |
| Otherwise, this state is specified by the |
| slink:VkPipelineTessellationStateCreateInfo::pname:patchControlPoints value |
| used to create the currently active pipeline. |
| |
| :refpage: vkCmdSetPatchControlPointsEXT |
| :requiredfeature: extendedDynamicState2PatchControlPoints |
| |
| .Valid Usage |
| **** |
| include::{chapters}/commonvalidity/dynamic_state2_optional_feature_common.adoc[] |
| * [[VUID-vkCmdSetPatchControlPointsEXT-patchControlPoints-04874]] |
| pname:patchControlPoints must: be greater than zero and less than or |
| equal to sname:VkPhysicalDeviceLimits::pname:maxTessellationPatchSize |
| **** |
| |
| include::{generated}/validity/protos/vkCmdSetPatchControlPointsEXT.adoc[] |
| -- |
| endif::VK_EXT_extended_dynamic_state2,VK_EXT_shader_object[] |
| |
| The size of the output patch is controlled by the code:OpExecutionMode |
| code:OutputVertices specified in the tessellation control or tessellation |
| evaluation shaders, which must: be specified in at least one of the shaders. |
| The size of the input and output patches must: each be greater than zero and |
| less than or equal to |
| sname:VkPhysicalDeviceLimits::pname:maxTessellationPatchSize. |
| |
| |
| [[shaders-tessellation-control-execution]] |
| === Tessellation Control Shader Execution |
| |
| A tessellation control shader is invoked at least once for each _output_ |
| vertex in a patch. |
| ifdef::VK_VERSION_1_1,VK_KHR_multiview[] |
| If the subpass includes multiple views in its view mask, the shader may: be |
| invoked separately for each view. |
| endif::VK_VERSION_1_1,VK_KHR_multiview[] |
| |
| Inputs to the tessellation control shader are generated by the vertex |
| shader. |
| Each invocation of the tessellation control shader can: read the attributes |
| of any incoming vertices and their associated data. |
| The invocations corresponding to a given patch execute logically in |
| parallel, with undefined: relative execution order. |
| However, the code:OpControlBarrier instruction can: be used to provide |
| limited control of the execution order by synchronizing invocations within a |
| patch, effectively dividing tessellation control shader execution into a set |
| of phases. |
| Tessellation control shaders will read undefined: values if one invocation |
| reads a per-vertex or per-patch output written by another invocation at any |
| point during the same phase, or if two invocations attempt to write |
| different values to the same per-patch output in a single phase. |
| |
| |
| [[shaders-tessellation-evaluation]] |
| == Tessellation Evaluation Shaders |
| |
| The Tessellation Evaluation Shader operates on an input patch of control |
| points and their associated data, and a single input barycentric coordinate |
| indicating the invocation's relative position within the subdivided patch, |
| and outputs a single vertex and its associated data. |
| |
| |
| [[shaders-tessellation-evaluation-execution]] |
| === Tessellation Evaluation Shader Execution |
| |
| A tessellation evaluation shader is invoked at least once for each unique |
| vertex generated by the tessellator. |
| ifdef::VK_VERSION_1_1,VK_KHR_multiview[] |
| If the subpass includes multiple views in its view mask, the shader may: be |
| invoked separately for each view. |
| endif::VK_VERSION_1_1,VK_KHR_multiview[] |
| |
| |
| [[shaders-geometry]] |
| == Geometry Shaders |
| |
| The geometry shader operates on a group of vertices and their associated |
| data assembled from a single input primitive, and emits zero or more output |
| primitives and the group of vertices and their associated data required for |
| each output primitive. |
| |
| |
| [[shaders-geometry-execution]] |
| === Geometry Shader Execution |
| |
| A geometry shader is invoked at least once for each primitive produced by |
| the tessellation stages, or at least once for each primitive generated by |
| <<drawing,primitive assembly>> when tessellation is not in use. |
| A shader can request that the geometry shader runs multiple |
| <<geometry-invocations, instances>>. |
| A geometry shader is invoked at least once for each instance. |
| ifdef::VK_VERSION_1_1,VK_KHR_multiview[] |
| If the subpass includes multiple views in its view mask, the shader may: be |
| invoked separately for each view. |
| endif::VK_VERSION_1_1,VK_KHR_multiview[] |
| |
| |
| [[shaders-fragment]] |
| == Fragment Shaders |
| |
| Fragment shaders are invoked as a <<fragops-shader, fragment operation>> in |
| a graphics pipeline. |
| Each fragment shader invocation operates on a single fragment and its |
| associated data. |
| With few exceptions, fragment shaders do not have access to any data |
| associated with other fragments and are considered to execute in isolation |
| of fragment shader invocations associated with other fragments. |
| |
| |
| [[shaders-compute]] |
| == Compute Shaders |
| |
| Compute shaders are invoked via flink:vkCmdDispatch and |
| flink:vkCmdDispatchIndirect commands. |
| In general, they have access to similar resources as shader stages executing |
| as part of a graphics pipeline. |
| |
| Compute workloads are formed from groups of work items called workgroups and |
| processed by the compute shader in the current compute pipeline. |
| A workgroup is a collection of shader invocations that execute the same |
| shader, potentially in parallel. |
| Compute shaders execute in _global workgroups_ which are divided into a |
| number of _local workgroups_ with a size that can: be set by assigning a |
| value to the code:LocalSize |
| ifdef::VK_VERSION_1_3,VK_KHR_maintenance4[or code:LocalSizeId] |
| execution mode or via an object decorated by the code:WorkgroupSize |
| decoration. |
| An invocation within a local workgroup can: share data with other members of |
| the local workgroup through shared variables and issue memory and control |
| flow barriers to synchronize with other members of the local workgroup. |
| |
| |
| ifdef::VK_NV_ray_tracing,VK_KHR_ray_tracing_pipeline[] |
| [[shaders-raytracing-shaders]] |
| [[shaders-ray-generation]] |
| == Ray Generation Shaders |
| |
| A ray generation shader is similar to a compute shader. |
| Its main purpose is to execute ray tracing queries using code:OpTraceRayKHR |
| instructions and process the results. |
| |
| |
| [[shaders-ray-generation-execution]] |
| === Ray Generation Shader Execution |
| |
| One ray generation shader is executed per ray tracing dispatch. |
| Its location in the shader binding table (see <<shader-binding-table,Shader |
| Binding Table>> for details) is passed directly into |
| ifdef::VK_KHR_ray_tracing_pipeline[] |
| flink:vkCmdTraceRaysKHR using the pname:pRaygenShaderBindingTable parameter |
| endif::VK_KHR_ray_tracing_pipeline[] |
| ifdef::VK_KHR_ray_tracing_pipeline+VK_KHR_ray_tracing_pipeline[or] |
| ifdef::VK_NV_ray_tracing[] |
| flink:vkCmdTraceRaysNV using the pname:raygenShaderBindingTableBuffer and |
| pname:raygenShaderBindingOffset parameters |
| endif::VK_NV_ray_tracing[] |
| . |
| |
| |
| [[shaders-intersection]] |
| == Intersection Shaders |
| |
| Intersection shaders enable the implementation of arbitrary, application |
| defined geometric primitives. |
| An intersection shader for a primitive is executed whenever its axis-aligned |
| bounding box is hit by a ray. |
| |
| Like other ray tracing shader domains, an intersection shader operates on a |
| single ray at a time. |
| It also operates on a single primitive at a time. |
| It is therefore the purpose of an intersection shader to compute the |
| ray-primitive intersections and report them. |
| To report an intersection, the shader calls the code:OpReportIntersectionKHR |
| instruction. |
| |
| An intersection shader communicates with any-hit and closest shaders by |
| generating attribute values that they can: read. |
| Intersection shaders cannot: read or modify the ray payload. |
| |
| |
| [[shaders-intersection-execution]] |
| === Intersection Shader Execution |
| The order in which intersections are found along a ray, and therefore the |
| order in which intersection shaders are executed, is unspecified. |
| |
| The intersection shader of the closest AABB which intersects the ray is |
| guaranteed to be executed at some point during traversal, unless the ray is |
| forcibly terminated. |
| |
| |
| [[shaders-any-hit]] |
| == Any-Hit Shaders |
| |
| The any-hit shader is executed after the intersection shader reports an |
| intersection that lies within the current [eq]#[t~min~,t~max~]# of the ray. |
| The main use of any-hit shaders is to programmatically decide whether or not |
| an intersection will be accepted. |
| The intersection will be accepted unless the shader calls the |
| code:OpIgnoreIntersectionKHR instruction. |
| Any-hit shaders have read-only access to the attributes generated by the |
| corresponding intersection shader, and can: read or modify the ray payload. |
| |
| |
| [[shaders-any-hit-execution]] |
| === Any-Hit Shader Execution |
| |
| The order in which intersections are found along a ray, and therefore the |
| order in which any-hit shaders are executed, is unspecified. |
| |
| The any-hit shader of the closest hit is guaranteed to be executed at some |
| point during traversal, unless the ray is forcibly terminated. |
| |
| |
| [[shaders-closest-hit]] |
| == Closest Hit Shaders |
| |
| Closest hit shaders have read-only access to the attributes generated by the |
| corresponding intersection shader, and can: read or modify the ray payload. |
| They also have access to a number of system-generated values. |
| Closest hit shaders can: call code:OpTraceRayKHR to recursively trace rays. |
| |
| |
| [[shaders-closest-hit-execution]] |
| === Closest Hit Shader Execution |
| |
| Exactly one closest hit shader is executed when traversal is finished and an |
| intersection has been found and accepted. |
| |
| |
| [[shaders-miss]] |
| == Miss Shaders |
| |
| Miss shaders can: access the ray payload and can: trace new rays through the |
| code:OpTraceRayKHR instruction, but cannot: access attributes since they are |
| not associated with an intersection. |
| |
| |
| [[shaders-miss-execution]] |
| === Miss Shader Execution |
| |
| A miss shader is executed instead of a closest hit shader if no intersection |
| was found during traversal. |
| |
| |
| [[shaders-callable]] |
| == Callable Shaders |
| |
| Callable shaders can: access a callable payload that works similarly to ray |
| payloads to do subroutine work. |
| |
| |
| [[shaders-callable-execution]] |
| === Callable Shader Execution |
| |
| A callable shader is executed by calling code:OpExecuteCallableKHR from an |
| allowed shader stage. |
| |
| endif::VK_NV_ray_tracing,VK_KHR_ray_tracing_pipeline[] |
| |
| |
| [[shaders-interpolation-decorations]] |
| == Interpolation Decorations |
| |
| Variables in the code:Input storage class in a fragment shader's interface |
| are interpolated from the values specified by the primitive being |
| rasterized. |
| |
| [NOTE] |
| .Note |
| ==== |
| Interpolation decorations can be present on input and output variables in |
| pre-rasterization shaders but have no effect on the interpolation performed. |
| ifdef::VK_EXT_graphics_pipeline_libraries[] |
| However, when linking graphics pipeline libraries, if the |
| <<limits-graphicsPipelineLibraryIndependentInterpolationDecoration, |
| pname:graphicsPipelineLibraryIndependentInterpolationDecoration>> limit is |
| not supported, interpolation qualifiers do need to match between the |
| fragment shader input and the last pre-rasterization shader output. |
| endif::VK_EXT_graphics_pipeline_libraries[] |
| ==== |
| |
| An undecorated input variable will be interpolated with perspective-correct |
| interpolation according to the primitive type being rasterized. |
| <<line_perspective_interpolation,Lines>> and |
| <<triangle_perspective_interpolation,polygons>> are interpolated in the same |
| way as the primitive's clip coordinates. |
| If the code:NoPerspective decoration is present, linear interpolation is |
| instead used for <<line_linear_interpolation,lines>> and |
| <<triangle_linear_interpolation,polygons>>. |
| For points, as there is only a single vertex, input values are never |
| interpolated and instead take the value written for the single vertex. |
| |
| If the code:Flat decoration is present on an input variable, the value is |
| not interpolated, and instead takes its value directly from the |
| <<vertexpostproc-flatshading,provoking vertex>>. |
| Fragment shader inputs that are signed or unsigned integers, integer |
| vectors, or any double-precision floating-point type must: be decorated with |
| code:Flat. |
| |
| Interpolation of input variables is performed at an implementation-defined |
| position within the fragment area being shaded. |
| The position is further constrained as follows: |
| |
| * If the code:Centroid decoration is used, the interpolation position used |
| for the variable must: also fall within the bounds of the primitive |
| being rasterized. |
| * If the code:Sample decoration is used, the interpolation position used |
| for the variable must: be at the position of the sample being shaded by |
| the current fragment shader invocation. |
| * If a sample count of 1 is used, the interpolation position must: be at |
| the center of the fragment area. |
| |
| [NOTE] |
| .Note |
| ==== |
| As code:Centroid restricts the possible interpolation position to the |
| covered area of the primitive, the position can be forced to vary between |
| neighboring fragments when it otherwise would not. |
| Derivatives calculated based on these differing locations can produce |
| inconsistent results compared to undecorated inputs. |
| It is recommended that input variables used in derivative calculations are |
| not decorated with code:Centroid. |
| ==== |
| |
| ifdef::VK_NV_fragment_shader_barycentric,VK_KHR_fragment_shader_barycentric[] |
| [[shaders-interpolation-decorations-pervertexkhr]] |
| If the code:PerVertexKHR decoration is present on an input variable, the |
| value is not interpolated, and instead values from all input vertices are |
| available in an array. |
| Each index of the array corresponds to one of the vertices of the primitive |
| that produced the fragment. |
| endif::VK_NV_fragment_shader_barycentric,VK_KHR_fragment_shader_barycentric[] |
| |
| ifdef::VK_AMD_shader_explicit_vertex_parameter[] |
| If the code:CustomInterpAMD decoration is present on an input variable, the |
| value cannot: be accessed directly; instead the extended instruction |
| code:InterpolateAtVertexAMD must: be used to obtain values from the input |
| vertices. |
| endif::VK_AMD_shader_explicit_vertex_parameter[] |
| |
| |
| [[shaders-staticuse]] |
| == Static Use |
| |
| A SPIR-V module declares a global object in memory using the code:OpVariable |
| instruction, which results in a pointer code:x to that object. |
| A specific entry point in a SPIR-V module is said to _statically use_ that |
| object if that entry point's call tree contains a function containing a |
| instruction with code:x as an code:id operand. |
| A shader entry point also _statically uses_ any variables explicitly |
| declared in its interface. |
| |
| |
| [[shaders-scope]] |
| == Scope |
| |
| A _scope_ describes a set of shader invocations, where each such set is a |
| _scope instance_. |
| Each invocation belongs to one or more scope instances, but belongs to no |
| more than one scope instance for each scope. |
| |
| The operations available between invocations in a given scope instance vary, |
| with smaller scopes generally able to perform more operations, and with |
| greater efficiency. |
| |
| |
| [[shaders-scope-cross-device]] |
| === Cross Device |
| |
| All invocations executed in a Vulkan instance fall into a single _cross |
| device scope instance_. |
| |
| Whilst the code:CrossDevice scope is defined in SPIR-V, it is disallowed in |
| Vulkan. |
| API <<synchronization, synchronization>> commands can: be used to |
| communicate between devices. |
| |
| |
| [[shaders-scope-device]] |
| === Device |
| |
| All invocations executed on a single device form a _device scope instance_. |
| |
| ifdef::VK_VERSION_1_2,VK_KHR_vulkan_memory_model[] |
| If the <<features-vulkanMemoryModel, pname:vulkanMemoryModel>> and |
| <<features-vulkanMemoryModelDeviceScope, |
| pname:vulkanMemoryModelDeviceScope>> features are enabled, this scope is |
| represented in SPIR-V by the code:Device code:Scope, which can: be used as a |
| code:Memory code:Scope for barrier and atomic operations. |
| |
| ifdef::VK_KHR_shader_clock[] |
| If both the <<features-shaderDeviceClock, pname:shaderDeviceClock>> and |
| <<features-vulkanMemoryModelDeviceScope, |
| pname:vulkanMemoryModelDeviceScope>> features are enabled, using the |
| code:Device code:Scope with the code:OpReadClockKHR instruction will read |
| from a clock that is consistent across invocations in the same device scope |
| instance. |
| endif::VK_KHR_shader_clock[] |
| endif::VK_VERSION_1_2,VK_KHR_vulkan_memory_model[] |
| |
| There is no method to synchronize the execution of these invocations within |
| SPIR-V, and this can: only be done with API synchronization primitives. |
| |
| ifdef::VK_VERSION_1_1,VK_KHR_device_group[] |
| Invocations executing on different devices in a device group operate in |
| separate device scope instances. |
| endif::VK_VERSION_1_1,VK_KHR_device_group[] |
| |
| ifndef::VK_VERSION_1_2,VK_KHR_vulkan_memory_model[] |
| The scope only extends to the queue family, not the whole device. |
| endif::VK_VERSION_1_2,VK_KHR_vulkan_memory_model[] |
| |
| |
| [[shaders-scope-queue-family]] |
| === Queue Family |
| |
| Invocations executed by queues in a given queue family form a _queue family |
| scope instance_. |
| |
| This scope is identified in SPIR-V as the |
| ifdef::VK_VERSION_1_2,VK_KHR_vulkan_memory_model[] |
| code:QueueFamily code:Scope if the <<features-vulkanMemoryModel, |
| pname:vulkanMemoryModel>> feature is enabled, or if not, the |
| endif::VK_VERSION_1_2,VK_KHR_vulkan_memory_model[] |
| code:Device code:Scope, which can: be used as a code:Memory code:Scope for |
| barrier and atomic operations. |
| |
| ifdef::VK_KHR_shader_clock[] |
| If the <<features-shaderDeviceClock, pname:shaderDeviceClock>> feature is |
| enabled, |
| ifdef::VK_VERSION_1_2,VK_KHR_vulkan_memory_model[] |
| but the <<features-vulkanMemoryModelDeviceScope, |
| pname:vulkanMemoryModelDeviceScope>> feature is not enabled, |
| endif::VK_VERSION_1_2,VK_KHR_vulkan_memory_model[] |
| using the code:Device code:Scope with the code:OpReadClockKHR instruction |
| will read from a clock that is consistent across invocations in the same |
| queue family scope instance. |
| endif::VK_KHR_shader_clock[] |
| |
| There is no method to synchronize the execution of these invocations within |
| SPIR-V, and this can: only be done with API synchronization primitives. |
| |
| Each invocation in a queue family scope instance must: be in the same |
| <<shaders-scope-device, device scope instance>>. |
| |
| |
| [[shaders-scope-command]] |
| === Command |
| |
| Any shader invocations executed as the result of a single command such as |
| flink:vkCmdDispatch or flink:vkCmdDraw form a _command scope instance_. |
| For indirect drawing commands with pname:drawCount greater than one, |
| invocations from separate draws are in separate command scope instances. |
| ifdef::VK_KHR_ray_tracing_pipeline,VK_NV_ray_tracing[] |
| For ray tracing shaders, an invocation group is an implementation-dependent |
| subset of the set of shader invocations of a given shader stage which are |
| produced by a single trace rays command. |
| endif::VK_KHR_ray_tracing_pipeline,VK_NV_ray_tracing[] |
| |
| There is no specific code:Scope for communication across invocations in a |
| command scope instance. |
| As this has a clear boundary at the API level, coordination here can: be |
| performed in the API, rather than in SPIR-V. |
| |
| Each invocation in a command scope instance must: be in the same |
| <<shaders-scope-queue-family, queue-family scope instance>>. |
| |
| For shaders without defined <<shaders-scope-workgroup, workgroups>>, this |
| set of invocations forms an _invocation group_ as defined in the |
| <<spirv-spec,SPIR-V specification>>. |
| |
| |
| [[shaders-scope-primitive]] |
| === Primitive |
| |
| Any fragment shader invocations executed as the result of rasterization of a |
| single primitive form a _primitive scope instance_. |
| |
| There is no specific code:Scope for communication across invocations in a |
| primitive scope instance. |
| |
| Any generated <<shaders-helper-invocations, helper invocations>> are |
| included in this scope instance. |
| |
| Each invocation in a primitive scope instance must: be in the same |
| <<shaders-scope-command, command scope instance>>. |
| |
| Any input variables decorated with code:Flat are uniform within a primitive |
| scope instance. |
| |
| |
| // intentionally no VK_NV_ray_tracing here since this scope does not exist there |
| ifdef::VK_KHR_ray_tracing_pipeline[] |
| [[shaders-scope-shadercall]] |
| === Shader Call |
| |
| Any <<shader-call-related,shader-call-related>> invocations that are |
| executed in one or more ray tracing execution models form a _shader call |
| scope instance_. |
| |
| The code:ShaderCallKHR code:Scope can be used as code:Memory code:Scope for |
| barrier and atomic operations. |
| |
| Each invocation in a shader call scope instance must: be in the same |
| <<shaders-scope-queue-family, queue family scope instance>>. |
| endif::VK_KHR_ray_tracing_pipeline[] |
| |
| |
| [[shaders-scope-workgroup]] |
| === Workgroup |
| |
| A _local workgroup_ is a set of invocations that can synchronize and share |
| data with each other using memory in the code:Workgroup storage class. |
| |
| The code:Workgroup code:Scope can be used as both an code:Execution |
| code:Scope and code:Memory code:Scope for barrier and atomic operations. |
| |
| Each invocation in a local workgroup must: be in the same |
| <<shaders-scope-command, command scope instance>>. |
| |
| Only |
| ifdef::VK_NV_mesh_shader,VK_EXT_mesh_shader[] |
| task, mesh, and |
| endif::VK_NV_mesh_shader,VK_EXT_mesh_shader[] |
| compute shaders have defined workgroups - other shader types cannot: use |
| workgroup functionality. |
| For shaders that have defined workgroups, this set of invocations forms an |
| _invocation group_ as defined in the <<spirv-spec,SPIR-V specification>>. |
| |
| [[workgroup-padding]] |
| ifdef::VK_KHR_workgroup_memory_explicit_layout[] |
| When variables declared with the code:Workgroup storage class are explicitly |
| laid out (hence they are also decorated with code:Block), the amount of |
| storage consumed is the size of the largest Block variable, not counting any |
| padding at the end. |
| endif::VK_KHR_workgroup_memory_explicit_layout[] |
| The amount of storage consumed by the |
| ifdef::VK_KHR_workgroup_memory_explicit_layout[] |
| non-Block |
| endif::VK_KHR_workgroup_memory_explicit_layout[] |
| variables declared with the code:Workgroup storage class is |
| implementation-dependent. |
| However, the amount of storage consumed may not exceed the largest block |
| size that would be obtained if all active |
| ifdef::VK_KHR_workgroup_memory_explicit_layout[] |
| non-Block |
| endif::VK_KHR_workgroup_memory_explicit_layout[] |
| variables declared with code:Workgroup storage class were assigned offsets |
| in an arbitrary order by successively taking the smallest valid offset |
| according to the <<interfaces-resources-standard-layout,Standard Storage |
| Buffer Layout>> rules, and with code:Boolean values considered as 32-bit |
| integer values for the purpose of this calculation. |
| (This is equivalent to using the GLSL std430 layout rules.) |
| |
| |
| ifdef::VK_VERSION_1_1[] |
| [[shaders-scope-subgroup]] |
| === Subgroup |
| |
| A _subgroup_ (see the subsection "`Control Flow`" of section 2 of the SPIR-V |
| 1.3 Revision 1 specification) is a set of invocations that can synchronize |
| and share data with each other efficiently. |
| |
| The code:Subgroup code:Scope can be used as both an code:Execution |
| code:Scope and code:Memory code:Scope for barrier and atomic operations. |
| Other <<VkSubgroupFeatureFlagBits, subgroup features>> allow the use of |
| <<shaders-group-operations, group operations>> with subgroup scope. |
| |
| ifdef::VK_KHR_shader_clock[] |
| If the <<features-shaderSubgroupClock, pname:shaderSubgroupClock>> feature |
| is enabled, using the code:Subgroup code:Scope with the code:OpReadClockKHR |
| instruction will read from a clock that is consistent across invocations in |
| the same subgroup. |
| endif::VK_KHR_shader_clock[] |
| |
| For <<shaders-scope-workgroup, shaders that have defined workgroups>>, each |
| invocation in a subgroup must: be in the same <<shaders-scope-workgroup, |
| local workgroup>>. |
| |
| In other shader stages, each invocation in a subgroup must: be in the same |
| <<shaders-scope-device, device scope instance>>. |
| |
| Only <<limits-subgroup-supportedStages, shader stages that support subgroup |
| operations>> have defined subgroups. |
| |
| [NOTE] |
| .Note |
| ==== |
| In shaders, there are two kinds of uniformity that are of primary interest |
| to applications: uniform within an invocation group (a.k.a. |
| dynamically uniform), and uniform within a subgroup scope. |
| |
| While one could make the assumption that being uniform in invocation group |
| implies being uniform in subgroup scope, it is not necessarily the case for |
| shader stages without defined workgroups. |
| |
| For shader stages with defined workgroups however, the relationship between |
| invocation group and subgroup scope is well defined as a subgroup is a |
| subset of the workgroup, and the workgroup is the invocation group. |
| If a value is uniform in invocation group, it is by definition also uniform |
| in subgroup scope. |
| This is important if writing code like: |
| |
| [source,glsl] |
| ---- |
| uniform texture2D Textures[]; |
| uint dynamicallyUniformValue = gl_WorkGroupID.x; |
| vec4 value = texelFetch(Textures[dynamicallyUniformValue], coord, 0); |
| |
| // subgroupUniformValue is guaranteed to be uniform within the subgroup. |
| // This value also happens to be dynamically uniform. |
| vec4 subgroupUniformValue = subgroupBroadcastFirst(dynamicallyUniformValue); |
| ---- |
| |
| In shader stages without defined workgroups, this gets complicated. |
| Due to scoping rules, there is no guarantee that a subgroup is a subset of |
| the invocation group, which in turn defines the scope for dynamically |
| uniform. |
| In graphics, the invocation group is a single draw command, except for |
| multi-draw situations, and indirect draws with drawCount > 1, where there |
| are multiple invocation groups, one per code:DrawIndex. |
| |
| [source,glsl] |
| ---- |
| // Assume SubgroupSize = 8, where 3 draws are packed together. |
| // Two subgroups were generated. |
| uniform texture2D Textures[]; |
| |
| // DrawIndex builtin is dynamically uniform |
| uint dynamicallyUniformValue = gl_DrawID; |
| // | gl_DrawID = 0 | gl_DrawID = 1 | } |
| // Subgroup 0: { 0, 0, 0, 0, 1, 1, 1, 1 } |
| // | DrawID = 2 | DrawID = 1 | } |
| // Subgroup 1: { 2, 2, 2, 2, 1, 1, 1, 1 } |
| |
| uint notActuallyDynamicallyUniformAnymore = |
| subgroupBroadcastFirst(dynamicallyUniformValue); |
| // | gl_DrawID = 0 | gl_DrawID = 1 | } |
| // Subgroup 0: { 0, 0, 0, 0, 0, 0, 0, 0 } |
| // | gl_DrawID = 2 | gl_DrawID = 1 | } |
| // Subgroup 1: { 2, 2, 2, 2, 2, 2, 2, 2 } |
| |
| // Bug. gl_DrawID = 1's invocation group observes both index 0 and 2. |
| vec4 value = texelFetch(Textures[notActuallyDynamicallyUniformAnymore], |
| coord, 0); |
| ---- |
| |
| Another problematic scenario is when a shader attempts to help the compiler |
| notice that a value is uniform in subgroup scope to potentially improve |
| performance. |
| |
| [source,c] |
| ---- |
| layout(location = 0) flat in dynamicallyUniformIndex; |
| // Vertex shader might have emitted a value that depends only on gl_DrawID, |
| // making it dynamically uniform. |
| // Give knowledge to compiler that the flat input is dynamically uniform, |
| // as this is not a guarantee otherwise. |
| |
| uint uniformIndex = subgroupBroadcastFirst(dynamicallyUniformIndex); |
| // Hazard: If different draw commands are packed into one subgroup, the uniformIndex is wrong. |
| |
| DrawData d = UBO.perDrawData[uniformIndex]; |
| ---- |
| |
| For implementations where subgroups are packed across draws, the |
| implementation must make sure to handle descriptor indexing correctly. |
| From the specification's point of view, a dynamically uniform index does not |
| require code:NonUniform decoration, and such an implementation will likely |
| either promote descriptor indexing into code:NonUniform on its own, or |
| handle non-uniformity implicitly. |
| ==== |
| endif::VK_VERSION_1_1[] |
| |
| |
| [[shaders-scope-quad]] |
| === Quad |
| |
| A _quad scope instance_ is formed of four shader invocations. |
| |
| In a fragment shader, each invocation in a quad scope instance is formed of |
| invocations in neighboring framebuffer locations [eq]#(x~i~, y~i~)#, where: |
| |
| * [eq]#i# is the index of the invocation within the scope instance. |
| * [eq]#w# and [eq]#h# are the number of pixels the fragment covers in the |
| [eq]#x# and [eq]#y# axes. |
| * [eq]#w# and [eq]#h# are identical for all participating invocations. |
| * [eq]#(x~0~) = (x~1~ - w) = (x~2~) = (x~3~ - w)# |
| * [eq]#(y~0~) = (y~1~) = (y~2~ - h) = (y~3~ - h)# |
| * Each invocation has the same layer and sample indices. |
| |
| ifdef::VK_NV_compute_shader_derivatives[] |
| In a compute shader, if the code:DerivativeGroupQuadsNV execution mode is |
| specified, each invocation in a quad scope instance is formed of invocations |
| with adjacent local invocation IDs [eq]#(x~i~, y~i~)#, where: |
| |
| * [eq]#i# is the index of the invocation within the quad scope instance. |
| * [eq]#(x~0~) = (x~1~ - 1) = (x~2~) = (x~3~ - 1)# |
| * [eq]#(y~0~) = (y~1~) = (y~2~ - 1) = (y~3~ - 1)# |
| * [eq]#x~0~# and [eq]#y~0~# are integer multiples of 2. |
| * Each invocation has the same [eq]#z# coordinate. |
| |
| In a compute shader, if the code:DerivativeGroupLinearNV execution mode is |
| specified, each invocation in a quad scope instance is formed of invocations |
| with adjacent local invocation indices [eq]#(l~i~)#, where: |
| |
| * [eq]#i# is the index of the invocation within the quad scope instance. |
| * [eq]#(l~0~) = (l~1~ - 1) = (l~2~ - 2) = (l~3~ - 3)# |
| * [eq]#l~0~# is an integer multiple of 4. |
| |
| endif::VK_NV_compute_shader_derivatives[] |
| |
| ifdef::VK_VERSION_1_1[] |
| In all shaders, each invocation in a quad scope instance is formed of |
| invocations in adjacent subgroup invocation indices [eq]#(s~i~)#, where: |
| |
| * [eq]#i# is the index of the invocation within the quad scope instance. |
| * [eq]#(s~0~) = (s~1~ - 1) = (s~2~ - 2) = (s~3~ - 3)# |
| * [eq]#s~0~# is an integer multiple of 4. |
| |
| Each invocation in a quad scope instance must: be in the same |
| <<shaders-scope-subgroup, subgroup>>. |
| endif::VK_VERSION_1_1[] |
| |
| ifndef::VK_VERSION_1_1[] |
| The specific set of invocations that make up a quad scope instance in other |
| shader stages is undefined:. |
| endif::VK_VERSION_1_1[] |
| |
| In a fragment shader, each invocation in a quad scope instance must: be in |
| the same <<shaders-scope-primitive, primitive scope instance>>. |
| |
| ifndef::VK_VERSION_1_1[] |
| For <<shaders-scope-workgroup, shaders that have defined workgroups>>, each |
| invocation in a quad scope instance must: be in the same |
| <<shaders-scope-workgroup, local workgroup>>. |
| |
| In other shader stages, each invocation in a quad scope instance must: be in |
| the same <<shaders-scope-device, device scope instance>>. |
| endif::VK_VERSION_1_1[] |
| |
| Fragment |
| ifdef::VK_NV_compute_shader_derivatives,VK_VERSION_1_1[] |
| and compute |
| endif::VK_NV_compute_shader_derivatives,VK_VERSION_1_1[] |
| shaders have defined quad scope instances. |
| ifdef::VK_VERSION_1_1[] |
| If the <<limits-subgroup-quadOperationsInAllStages, |
| pname:quadOperationsInAllStages>> limit is supported, any |
| <<limits-subgroup-supportedStages, shader stages that support subgroup |
| operations>> also have defined quad scope instances. |
| endif::VK_VERSION_1_1[] |
| |
| |
| ifdef::VK_EXT_fragment_shader_interlock[] |
| [[shaders-scope-fragment-interlock]] |
| === Fragment Interlock |
| |
| A _fragment interlock scope instance_ is formed of fragment shader |
| invocations based on their framebuffer locations [eq]#(x,y,layer,sample)#, |
| executed by commands inside a single <<renderpass,subpass>>. |
| |
| The specific set of invocations included varies based on the execution mode |
| as follows: |
| |
| * If the code:SampleInterlockOrderedEXT or |
| code:SampleInterlockUnorderedEXT execution modes are used, only |
| invocations with identical framebuffer locations |
| [eq]#(x,y,layer,sample)# are included. |
| * If the code:PixelInterlockOrderedEXT or code:PixelInterlockUnorderedEXT |
| execution modes are used, fragments with different sample ids are also |
| included. |
| ifdef::VK_NV_shading_rate_image,VK_KHR_fragment_shading_rate[] |
| * If the code:ShadingRateInterlockOrderedEXT or |
| code:ShadingRateInterlockUnorderedEXT execution modes are used, |
| fragments from neighbouring framebuffer locations are also included. |
| The |
| ifdef::VK_NV_shading_rate_image[<<primsrast-shading-rate-image, shading rate image>>] |
| ifdef::VK_KHR_fragment_shading_rate+VK_NV_shading_rate_image[or] |
| ifdef::VK_KHR_fragment_shading_rate[<<primsrast-fragment-shading-rate, fragment shading rate>>] |
| determines these fragments. |
| endif::VK_NV_shading_rate_image,VK_KHR_fragment_shading_rate[] |
| |
| Only fragment shaders with one of the above execution modes have defined |
| fragment interlock scope instances. |
| |
| There is no specific code:Scope value for communication across invocations |
| in a fragment interlock scope instance. |
| However, this is implicitly used as a memory scope by |
| code:OpBeginInvocationInterlockEXT and code:OpEndInvocationInterlockEXT. |
| |
| Each invocation in a fragment interlock scope instance must: be in the same |
| <<shaders-scope-queue-family, queue family scope instance>>. |
| endif::VK_EXT_fragment_shader_interlock[] |
| |
| |
| [[shaders-scope-invocation]] |
| === Invocation |
| |
| The smallest _scope_ is a single invocation; this is represented by the |
| code:Invocation code:Scope in SPIR-V. |
| |
| Fragment shader invocations must: be in a <<shaders-scope-primitive, |
| primitive scope instance>>. |
| |
| ifdef::VK_EXT_fragment_shader_interlock[] |
| Invocations in <<shaders-scope-fragment-interlock, fragment shaders that |
| have a defined fragment interlock scope>> must: be in a |
| <<shaders-scope-fragment-interlock, fragment interlock scope instance>>. |
| endif::VK_EXT_fragment_shader_interlock[] |
| |
| Invocations in <<shaders-scope-workgroup, shaders that have defined |
| workgroups>> must: be in a <<shaders-scope-workgroup, local workgroup>>. |
| |
| ifdef::VK_VERSION_1_1[] |
| Invocations in <<shaders-scope-subgroup, shaders that have a defined |
| subgroup scope>> must: be in a <<shaders-scope-subgroup, subgroup>>. |
| endif::VK_VERSION_1_1[] |
| |
| Invocations in <<shaders-scope-quad, shaders that have a defined quad |
| scope>> must: be in a <<shaders-scope-quad, quad scope instance>>. |
| |
| All invocations in all stages must: be in a <<shaders-scope-command,command |
| scope instance>>. |
| |
| |
| ifdef::VK_VERSION_1_1[] |
| [[shaders-group-operations]] |
| == Group Operations |
| |
| _Group operations_ are executed by multiple invocations within a |
| <<shaders-scope, scope instance>>; with each invocation involved in |
| calculating the result. |
| This provides a mechanism for efficient communication between invocations in |
| a particular scope instance. |
| |
| Group operations all take a code:Scope defining the desired |
| <<shaders-scope,scope instance>> to operate within. |
| Only the code:Subgroup scope can: be used for these operations; the |
| <<limits-subgroupSupportedOperations, pname:subgroupSupportedOperations>> |
| limit defines which types of operation can: be used. |
| |
| |
| [[shaders-group-operations-basic]] |
| === Basic Group Operations |
| |
| Basic group operations include the use of code:OpGroupNonUniformElect, |
| code:OpControlBarrier, code:OpMemoryBarrier, and atomic operations. |
| |
| code:OpGroupNonUniformElect can: be used to choose a single invocation to |
| perform a task for the whole group. |
| Only the invocation with the lowest id in the group will return code:true. |
| |
| The <<memory-model,Memory Model>> appendix defines the operation of barriers |
| and atomics. |
| |
| |
| [[shaders-group-operations-vote]] |
| === Vote Group Operations |
| |
| The vote group operations allow invocations within a group to compare values |
| across a group. |
| The types of votes enabled are: |
| |
| * Do all active group invocations agree that an expression is true? |
| * Do any active group invocations evaluate an expression to true? |
| * Do all active group invocations have the same value of an expression? |
| |
| [NOTE] |
| .Note |
| ==== |
| These operations are useful in combination with control flow in that they |
| allow for developers to check whether conditions match across the group and |
| choose potentially faster code-paths in these cases. |
| ==== |
| |
| |
| [[shaders-group-operations-arithmetic]] |
| === Arithmetic Group Operations |
| |
| The arithmetic group operations allow invocations to perform scans and |
| reductions across a group. |
| The operators supported are add, mul, min, max, and, or, xor. |
| |
| For reductions, every invocation in a group will obtain the cumulative |
| result of these operators applied to all values in the group. |
| For exclusive scans, each invocation in a group will obtain the cumulative |
| result of these operators applied to all values in invocations with a lower |
| index in the group. |
| Inclusive scans are identical to exclusive scans, except the cumulative |
| result includes the operator applied to the value in the current invocation. |
| |
| The order in which these operators are applied is implementation-dependent. |
| |
| |
| [[shaders-group-operations-ballot]] |
| === Ballot Group Operations |
| |
| The ballot group operations allow invocations to perform more complex votes |
| across the group. |
| The ballot functionality allows all invocations within a group to provide a |
| boolean value and get as a result what each invocation provided as their |
| boolean value. |
| The broadcast functionality allows values to be broadcast from an invocation |
| to all other invocations within the group. |
| |
| |
| [[shaders-group-operations-shuffle]] |
| === Shuffle Group Operations |
| |
| The shuffle group operations allow invocations to read values from other |
| invocations within a group. |
| |
| |
| [[shaders-group-operations-shuffle-relative]] |
| === Shuffle Relative Group Operations |
| |
| The shuffle relative group operations allow invocations to read values from |
| other invocations within the group relative to the current invocation in the |
| group. |
| The relative operations supported allow data to be shifted up and down |
| through the invocations within a group. |
| |
| |
| [[shaders-group-operations-clustered]] |
| === Clustered Group Operations |
| |
| The clustered group operations allow invocations to perform an operation |
| among partitions of a group, such that the operation is only performed |
| within the group invocations within a partition. |
| The partitions for clustered group operations are consecutive power-of-two |
| size groups of invocations and the cluster size must: be known at pipeline |
| creation time. |
| The operations supported are add, mul, min, max, and, or, xor. |
| |
| |
| [[shaders-quad-operations]] |
| == Quad Group Operations |
| |
| Quad group operations (code:OpGroupNonUniformQuad*) are a specialized type |
| of <<shaders-group-operations, group operations>> that only operate on |
| <<shaders-scope-quad, quad scope instances>>. |
| Whilst these instructions do include a code:Scope parameter, this scope is |
| always overridden; only the <<shaders-scope-quad, quad scope instance>> is |
| included in its execution scope. |
| |
| Fragment shaders that statically execute quad group operations must: launch |
| sufficient invocations to ensure their correct operation; additional |
| <<shaders-helper-invocations, helper invocations>> are launched for |
| framebuffer locations not covered by rasterized fragments if necessary. |
| |
| The index used to select participating invocations is [eq]#i#, as described |
| for a <<shaders-scope-quad, quad scope instance>>, defined as the _quad |
| index_ in the <<spirv-spec,SPIR-V specification>>. |
| |
| For code:OpGroupNonUniformQuadBroadcast this value is equal to code:Index. |
| For code:OpGroupNonUniformQuadSwap, it is equal to the implicit code:Index |
| used by each participating invocation. |
| endif::VK_VERSION_1_1[] |
| |
| |
| [[shaders-derivative-operations]] |
| == Derivative Operations |
| |
| Derivative operations calculate the partial derivative for an expression |
| [eq]#P# as a function of an invocation's [eq]#x# and [eq]#y# coordinates. |
| |
| Derivative operations operate on a set of invocations known as a _derivative |
| group_ as defined in the <<spirv-spec,SPIR-V specification>>. |
| A derivative group is equivalent to |
| ifdef::VK_NV_compute_shader_derivatives[] |
| the <<shaders-scope-quad, quad scope instance>> for a compute shader |
| invocation, or |
| endif::VK_NV_compute_shader_derivatives[] |
| the <<shaders-scope-primitive, primitive scope instance>> for a fragment |
| shader invocation. |
| |
| Derivatives are calculated assuming that [eq]#P# is piecewise linear and |
| continuous within the derivative group. |
| All dynamic instances of explicit derivative instructions (code:OpDPdx*, |
| code:OpDPdy*, and code:OpFwidth*) must: be executed in control flow that is |
| uniform within a derivative group. |
| For other derivative operations, results are undefined: if a dynamic |
| instance is executed in control flow that is not uniform within the |
| derivative group. |
| |
| Fragment shaders that statically execute derivative operations must: launch |
| sufficient invocations to ensure their correct operation; additional |
| <<shaders-helper-invocations, helper invocations>> are launched for |
| framebuffer locations not covered by rasterized fragments if necessary. |
| |
| ifdef::VK_NV_compute_shader_derivatives[] |
| [NOTE] |
| .Note |
| ==== |
| In a compute shader, it is the application's responsibility to ensure that |
| sufficient invocations are launched. |
| ==== |
| endif::VK_NV_compute_shader_derivatives[] |
| |
| Derivative operations calculate their results as the difference between the |
| result of [eq]#P# across invocations in the quad. |
| For fine derivative operations (code:OpDPdxFine and code:OpDPdyFine), the |
| values of [eq]#DPdx(P~i~)# are calculated as |
| |
| {empty}:: [eq]#DPdx(P~0~) = DPdx(P~1~) = P~1~ - P~0~# |
| {empty}:: [eq]#DPdx(P~2~) = DPdx(P~3~) = P~3~ - P~2~# |
| |
| and the values of [eq]#DPdy(P~i~)# are calculated as |
| |
| {empty}:: [eq]#DPdy(P~0~) = DPdy(P~2~) = P~2~ - P~0~# |
| {empty}:: [eq]#DPdy(P~1~) = DPdy(P~3~) = P~3~ - P~1~# |
| |
| where [eq]#i# is the index of each invocation as described in |
| <<shaders-scope-quad>>. |
| |
| Coarse derivative operations (code:OpDPdxCoarse and code:OpDPdyCoarse), |
| calculate their results in roughly the same manner, but may: only calculate |
| two values instead of four (one for each of [eq]#DPdx# and [eq]#DPdy#), |
| reusing the same result no matter the originating invocation. |
| If an implementation does this, it should: use the fine derivative |
| calculations described for [eq]#P~0~#. |
| |
| [NOTE] |
| .Note |
| ==== |
| Derivative values are calculated between fragments rather than pixels. |
| If the fragment shader invocations involved in the calculation cover |
| multiple pixels, these operations cover a wider area, resulting in larger |
| derivative values. |
| This in turn will result in a coarser LOD being selected for image sampling |
| operations using derivatives. |
| |
| Applications may want to account for this when using multi-pixel fragments; |
| if pixel derivatives are desired, applications should use explicit |
| derivative operations and divide the results by the size of the fragment in |
| each dimension as follows: |
| |
| {empty}:: [eq]#DPdx(P~n~)' = DPdx(P~n~) / w# |
| {empty}:: [eq]#DPdy(P~n~)' = DPdy(P~n~) / h# |
| |
| where [eq]#w# and [eq]#h# are the size of the fragments in the quad, and |
| [eq]#DPdx(P~n~)'# and [eq]#DPdy(P~n~)'# are the pixel derivatives. |
| ==== |
| |
| The results for code:OpDPdx and code:OpDPdy may: be calculated as either |
| fine or coarse derivatives, with implementations favouring the most |
| efficient approach. |
| Implementations must: choose coarse or fine consistently between the two. |
| |
| Executing code:OpFwidthFine, code:OpFwidthCoarse, or code:OpFwidth is |
| equivalent to executing the corresponding code:OpDPdx* and code:OpDPdy* |
| instructions, taking the absolute value of the results, and summing them. |
| |
| Executing an code:OpImage*Sample*ImplicitLod instruction is equivalent to |
| executing code:OpDPdx(code:Coordinate) and code:OpDPdy(code:Coordinate), and |
| passing the results as the code:Grad operands code:dx and code:dy. |
| |
| [NOTE] |
| .Note |
| ==== |
| It is expected that using the code:ImplicitLod variants of sampling |
| functions will be substantially more efficient than using the |
| code:ExplicitLod variants with explicitly generated derivatives. |
| ==== |
| |
| |
| [[shaders-helper-invocations]] |
| == Helper Invocations |
| |
| When performing <<shaders-derivative-operations, derivative>> |
| ifdef::VK_VERSION_1_1[] |
| or <<shaders-quad-operations, quad group>> |
| endif::VK_VERSION_1_1[] |
| operations in a fragment shader, additional invocations may: be spawned in |
| order to ensure correct results. |
| These additional invocations are known as _helper invocations_ and can: be |
| identified by a non-zero value in the code:HelperInvocation built-in. |
| Stores and atomics performed by helper invocations must: not have any effect |
| on memory except for the code:Function, code:Private and code:Output storage |
| classes, and values returned by atomic instructions in helper invocations |
| are undefined:. |
| |
| [NOTE] |
| .Note |
| ==== |
| While storage to code:Output storage class has an effect even in helper |
| invocations, it does not mean that helper invocations have an effect on the |
| framebuffer. |
| code:Output variables in fragment shaders can be read from as well, and they |
| behave more like code:Private variables for the duration of the shader |
| invocation. |
| ==== |
| |
| For <<shaders-group-operations, group operations>> other than |
| <<shaders-derivative-operations, derivative>> |
| ifdef::VK_VERSION_1_1[] |
| and <<shaders-quad-operations, quad group>> |
| endif::VK_VERSION_1_1[] |
| operations, helper invocations may: be treated as inactive even if they |
| would be considered otherwise active. |
| |
| ifdef::VK_VERSION_1_3,VK_EXT_shader_demote_to_helper_invocation[] |
| Helper invocations may: become permanently inactive if all invocations in a |
| quad scope instance become helper invocations. |
| endif::VK_VERSION_1_3,VK_EXT_shader_demote_to_helper_invocation[] |
| |
| |
| ifdef::VK_NV_cooperative_matrix,VK_KHR_cooperative_matrix[] |
| == Cooperative Matrices |
| |
| A _cooperative matrix_ type is a SPIR-V type where the storage for and |
| computations performed on the matrix are spread across the invocations in a |
| scope instance. |
| These types give the implementation freedom in how to optimize matrix |
| multiplies. |
| |
| SPIR-V defines the types and instructions, but does not specify rules about |
| what sizes/combinations are valid, and it is expected that different |
| implementations may: support different sizes. |
| |
| ifdef::VK_KHR_cooperative_matrix[] |
| [open,refpage='vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR',desc='Returns properties describing what cooperative matrix types are supported',type='protos'] |
| -- |
| To enumerate the supported cooperative matrix types and operations, call: |
| |
| include::{generated}/api/protos/vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR.adoc[] |
| |
| * pname:physicalDevice is the physical device. |
| * pname:pPropertyCount is a pointer to an integer related to the number of |
| cooperative matrix properties available or queried. |
| * pname:pProperties is either `NULL` or a pointer to an array of |
| slink:VkCooperativeMatrixPropertiesKHR structures. |
| |
| If pname:pProperties is `NULL`, then the number of cooperative matrix |
| properties available is returned in pname:pPropertyCount. |
| Otherwise, pname:pPropertyCount must: point to a variable set by the user to |
| the number of elements in the pname:pProperties array, and on return the |
| variable is overwritten with the number of structures actually written to |
| pname:pProperties. |
| If pname:pPropertyCount is less than the number of cooperative matrix |
| properties available, at most pname:pPropertyCount structures will be |
| written, and ename:VK_INCOMPLETE will be returned instead of |
| ename:VK_SUCCESS, to indicate that not all the available cooperative matrix |
| properties were returned. |
| |
| include::{generated}/validity/protos/vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR.adoc[] |
| -- |
| endif::VK_KHR_cooperative_matrix[] |
| |
| ifdef::VK_NV_cooperative_matrix[] |
| [open,refpage='vkGetPhysicalDeviceCooperativeMatrixPropertiesNV',desc='Returns properties describing what cooperative matrix types are supported',type='protos'] |
| -- |
| To enumerate the supported cooperative matrix types and operations, call: |
| |
| include::{generated}/api/protos/vkGetPhysicalDeviceCooperativeMatrixPropertiesNV.adoc[] |
| |
| * pname:physicalDevice is the physical device. |
| * pname:pPropertyCount is a pointer to an integer related to the number of |
| cooperative matrix properties available or queried. |
| * pname:pProperties is either `NULL` or a pointer to an array of |
| slink:VkCooperativeMatrixPropertiesNV structures. |
| |
| If pname:pProperties is `NULL`, then the number of cooperative matrix |
| properties available is returned in pname:pPropertyCount. |
| Otherwise, pname:pPropertyCount must: point to a variable set by the user to |
| the number of elements in the pname:pProperties array, and on return the |
| variable is overwritten with the number of structures actually written to |
| pname:pProperties. |
| If pname:pPropertyCount is less than the number of cooperative matrix |
| properties available, at most pname:pPropertyCount structures will be |
| written, and ename:VK_INCOMPLETE will be returned instead of |
| ename:VK_SUCCESS, to indicate that not all the available cooperative matrix |
| properties were returned. |
| |
| include::{generated}/validity/protos/vkGetPhysicalDeviceCooperativeMatrixPropertiesNV.adoc[] |
| -- |
| endif::VK_NV_cooperative_matrix[] |
| |
| Each |
| ifdef::VK_KHR_cooperative_matrix[slink:VkCooperativeMatrixPropertiesKHR] |
| ifdef::VK_KHR_cooperative_matrix+VK_NV_cooperative_matrix[or] |
| ifdef::VK_NV_cooperative_matrix[slink:VkCooperativeMatrixPropertiesNV] |
| structure describes a single supported combination of types for a matrix |
| multiply/add operation ( |
| ifdef::VK_KHR_cooperative_matrix[code:OpCooperativeMatrixMulAddKHR] |
| ifdef::VK_KHR_cooperative_matrix+VK_NV_cooperative_matrix[or] |
| ifdef::VK_NV_cooperative_matrix[code:OpCooperativeMatrixMulAddNV] |
| ). |
| The multiply can: be described in terms of the following variables and types |
| (in SPIR-V pseudocode): |
| |
| ifdef::VK_KHR_cooperative_matrix[] |
| [source,c] |
| ---- |
| %A is of type OpTypeCooperativeMatrixKHR %AType %scope %MSize %KSize %MatrixAKHR |
| %B is of type OpTypeCooperativeMatrixKHR %BType %scope %KSize %NSize %MatrixBKHR |
| %C is of type OpTypeCooperativeMatrixKHR %CType %scope %MSize %NSize %MatrixAccumulatorKHR |
| %Result is of type OpTypeCooperativeMatrixKHR %ResultType %scope %MSize %NSize %MatrixAccumulatorKHR |
| |
| %Result = %A * %B + %C // using OpCooperativeMatrixMulAddKHR |
| ---- |
| endif::VK_KHR_cooperative_matrix[] |
| |
| ifdef::VK_NV_cooperative_matrix[] |
| [source,c] |
| ---- |
| %A is of type OpTypeCooperativeMatrixNV %AType %scope %MSize %KSize |
| %B is of type OpTypeCooperativeMatrixNV %BType %scope %KSize %NSize |
| %C is of type OpTypeCooperativeMatrixNV %CType %scope %MSize %NSize |
| %D is of type OpTypeCooperativeMatrixNV %DType %scope %MSize %NSize |
| |
| %D = %A * %B + %C // using OpCooperativeMatrixMulAddNV |
| ---- |
| endif::VK_NV_cooperative_matrix[] |
| |
| A matrix multiply with these dimensions is known as an _MxNxK_ matrix |
| multiply. |
| |
| ifdef::VK_KHR_cooperative_matrix[] |
| [open,refpage='VkCooperativeMatrixPropertiesKHR',desc='Structure specifying cooperative matrix properties',type='structs'] |
| -- |
| The sname:VkCooperativeMatrixPropertiesKHR structure is defined as: |
| |
| include::{generated}/api/structs/VkCooperativeMatrixPropertiesKHR.adoc[] |
| |
| * pname:sType is a elink:VkStructureType value identifying this structure. |
| * pname:pNext is `NULL` or a pointer to a structure extending this |
| structure. |
| * pname:MSize is the number of rows in matrices code:A, code:C, and |
| code:Result. |
| * pname:KSize is the number of columns in matrix code:A and rows in matrix |
| code:B. |
| * pname:NSize is the number of columns in matrices code:B, code:C, |
| code:Result. |
| * pname:AType is the component type of matrix code:A, of type |
| elink:VkComponentTypeKHR. |
| * pname:BType is the component type of matrix code:B, of type |
| elink:VkComponentTypeKHR. |
| * pname:CType is the component type of matrix code:C, of type |
| elink:VkComponentTypeKHR. |
| * pname:ResultType is the component type of matrix code:Result, of type |
| elink:VkComponentTypeKHR. |
| * pname:saturatingAccumulation indicates whether the |
| code:SaturatingAccumulation operand to code:OpCooperativeMatrixMulAddKHR |
| must: be present. |
| * pname:scope is the scope of all the matrix types, of type |
| elink:VkScopeKHR. |
| |
| If some types are preferred over other types (e.g. for performance), they |
| should: appear earlier in the list enumerated by |
| flink:vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR. |
| |
| At least one entry in the list must: have power of two values for all of |
| pname:MSize, pname:KSize, and pname:NSize. |
| |
| include::{generated}/validity/structs/VkCooperativeMatrixPropertiesKHR.adoc[] |
| -- |
| endif::VK_KHR_cooperative_matrix[] |
| |
| ifdef::VK_NV_cooperative_matrix[] |
| [open,refpage='VkCooperativeMatrixPropertiesNV',desc='Structure specifying cooperative matrix properties',type='structs'] |
| -- |
| The sname:VkCooperativeMatrixPropertiesNV structure is defined as: |
| |
| include::{generated}/api/structs/VkCooperativeMatrixPropertiesNV.adoc[] |
| |
| * pname:sType is a elink:VkStructureType value identifying this structure. |
| * pname:pNext is `NULL` or a pointer to a structure extending this |
| structure. |
| * pname:MSize is the number of rows in matrices A, C, and D. |
| * pname:KSize is the number of columns in matrix A and rows in matrix B. |
| * pname:NSize is the number of columns in matrices B, C, D. |
| * pname:AType is the component type of matrix A, of type |
| elink:VkComponentTypeNV. |
| * pname:BType is the component type of matrix B, of type |
| elink:VkComponentTypeNV. |
| * pname:CType is the component type of matrix C, of type |
| elink:VkComponentTypeNV. |
| * pname:DType is the component type of matrix D, of type |
| elink:VkComponentTypeNV. |
| * pname:scope is the scope of all the matrix types, of type |
| elink:VkScopeNV. |
| |
| If some types are preferred over other types (e.g. for performance), they |
| should: appear earlier in the list enumerated by |
| flink:vkGetPhysicalDeviceCooperativeMatrixPropertiesNV. |
| |
| At least one entry in the list must: have power of two values for all of |
| pname:MSize, pname:KSize, and pname:NSize. |
| |
| include::{generated}/validity/structs/VkCooperativeMatrixPropertiesNV.adoc[] |
| -- |
| endif::VK_NV_cooperative_matrix[] |
| |
| [open,refpage='VkScopeKHR',desc='Specify SPIR-V scope',type='enums'] |
| -- |
| Possible values for elink:VkScopeKHR include: |
| |
| include::{generated}/api/enums/VkScopeKHR.adoc[] |
| |
| ifdef::VK_NV_cooperative_matrix[] |
| or the equivalent |
| |
| include::{generated}/api/enums/VkScopeNV.adoc[] |
| endif::VK_NV_cooperative_matrix[] |
| |
| * ename:VK_SCOPE_DEVICE_KHR corresponds to SPIR-V code:Device scope. |
| * ename:VK_SCOPE_WORKGROUP_KHR corresponds to SPIR-V code:Workgroup scope. |
| * ename:VK_SCOPE_SUBGROUP_KHR corresponds to SPIR-V code:Subgroup scope. |
| * ename:VK_SCOPE_QUEUE_FAMILY_KHR corresponds to SPIR-V code:QueueFamily |
| scope. |
| |
| All enum values match the corresponding SPIR-V value. |
| -- |
| |
| [open,refpage='VkComponentTypeKHR',desc='Specify SPIR-V cooperative matrix component type',type='enums'] |
| -- |
| Possible values for elink:VkComponentTypeKHR include: |
| |
| include::{generated}/api/enums/VkComponentTypeKHR.adoc[] |
| |
| ifdef::VK_NV_cooperative_matrix[] |
| or the equivalent |
| |
| include::{generated}/api/enums/VkComponentTypeNV.adoc[] |
| endif::VK_NV_cooperative_matrix[] |
| |
| * ename:VK_COMPONENT_TYPE_FLOAT16_KHR corresponds to SPIR-V |
| code:OpTypeFloat 16. |
| * ename:VK_COMPONENT_TYPE_FLOAT32_KHR corresponds to SPIR-V |
| code:OpTypeFloat 32. |
| * ename:VK_COMPONENT_TYPE_FLOAT64_KHR corresponds to SPIR-V |
| code:OpTypeFloat 64. |
| * ename:VK_COMPONENT_TYPE_SINT8_KHR corresponds to SPIR-V code:OpTypeInt 8 1. |
| * ename:VK_COMPONENT_TYPE_SINT16_KHR corresponds to SPIR-V code:OpTypeInt |
| 16 1. |
| * ename:VK_COMPONENT_TYPE_SINT32_KHR corresponds to SPIR-V code:OpTypeInt |
| 32 1. |
| * ename:VK_COMPONENT_TYPE_SINT64_KHR corresponds to SPIR-V code:OpTypeInt |
| 64 1. |
| * ename:VK_COMPONENT_TYPE_UINT8_KHR corresponds to SPIR-V code:OpTypeInt 8 0. |
| * ename:VK_COMPONENT_TYPE_UINT16_KHR corresponds to SPIR-V code:OpTypeInt |
| 16 0. |
| * ename:VK_COMPONENT_TYPE_UINT32_KHR corresponds to SPIR-V code:OpTypeInt |
| 32 0. |
| * ename:VK_COMPONENT_TYPE_UINT64_KHR corresponds to SPIR-V code:OpTypeInt |
| 64 0. |
| -- |
| endif::VK_NV_cooperative_matrix,VK_KHR_cooperative_matrix[] |
| |
| ifdef::VK_EXT_validation_cache[] |
| [[shaders-validation-cache]] |
| == Validation Cache |
| |
| [open,refpage='VkValidationCacheEXT',desc='Opaque handle to a validation cache object',type='handles'] |
| -- |
| Validation cache objects allow the result of internal validation to be |
| reused, both within a single application run and between multiple runs. |
| Reuse within a single run is achieved by passing the same validation cache |
| object when creating supported Vulkan objects. |
| Reuse across runs of an application is achieved by retrieving validation |
| cache contents in one run of an application, saving the contents, and using |
| them to preinitialize a validation cache on a subsequent run. |
| The contents of the validation cache objects are managed by the validation |
| layers. |
| Applications can: manage the host memory consumed by a validation cache |
| object and control the amount of data retrieved from a validation cache |
| object. |
| |
| Validation cache objects are represented by sname:VkValidationCacheEXT |
| handles: |
| |
| include::{generated}/api/handles/VkValidationCacheEXT.adoc[] |
| -- |
| |
| [open,refpage='vkCreateValidationCacheEXT',desc='Creates a new validation cache',type='protos'] |
| -- |
| To create validation cache objects, call: |
| |
| include::{generated}/api/protos/vkCreateValidationCacheEXT.adoc[] |
| |
| * pname:device is the logical device that creates the validation cache |
| object. |
| * pname:pCreateInfo is a pointer to a slink:VkValidationCacheCreateInfoEXT |
| structure containing the initial parameters for the validation cache |
| object. |
| * pname:pAllocator controls host memory allocation as described in the |
| <<memory-allocation, Memory Allocation>> chapter. |
| * pname:pValidationCache is a pointer to a slink:VkValidationCacheEXT |
| handle in which the resulting validation cache object is returned. |
| |
| [NOTE] |
| .Note |
| ==== |
| Applications can: track and manage the total host memory size of a |
| validation cache object using the pname:pAllocator. |
| Applications can: limit the amount of data retrieved from a validation cache |
| object in fname:vkGetValidationCacheDataEXT. |
| Implementations should: not internally limit the total number of entries |
| added to a validation cache object or the total host memory consumed. |
| ==== |
| |
| Once created, a validation cache can: be passed to the |
| fname:vkCreateShaderModule command by adding this object to the |
| slink:VkShaderModuleCreateInfo structure's pname:pNext chain. |
| If a slink:VkShaderModuleValidationCacheCreateInfoEXT object is included in |
| the slink:VkShaderModuleCreateInfo::pname:pNext chain, and its |
| pname:validationCache field is not dlink:VK_NULL_HANDLE, the implementation |
| will query it for possible reuse opportunities and update it with new |
| content. |
| The use of the validation cache object in these commands is internally |
| synchronized, and the same validation cache object can: be used in multiple |
| threads simultaneously. |
| |
| [NOTE] |
| .Note |
| ==== |
| Implementations should: make every effort to limit any critical sections to |
| the actual accesses to the cache, which is expected to be significantly |
| shorter than the duration of the fname:vkCreateShaderModule command. |
| ==== |
| |
| include::{generated}/validity/protos/vkCreateValidationCacheEXT.adoc[] |
| -- |
| |
| [open,refpage='VkValidationCacheCreateInfoEXT',desc='Structure specifying parameters of a newly created validation cache',type='structs'] |
| -- |
| The sname:VkValidationCacheCreateInfoEXT structure is defined as: |
| |
| include::{generated}/api/structs/VkValidationCacheCreateInfoEXT.adoc[] |
| |
| * pname:sType is a elink:VkStructureType value identifying this structure. |
| * pname:pNext is `NULL` or a pointer to a structure extending this |
| structure. |
| * pname:flags is reserved for future use. |
| * pname:initialDataSize is the number of bytes in pname:pInitialData. |
| If pname:initialDataSize is zero, the validation cache will initially be |
| empty. |
| * pname:pInitialData is a pointer to previously retrieved validation cache |
| data. |
| If the validation cache data is incompatible (as defined below) with the |
| device, the validation cache will be initially empty. |
| If pname:initialDataSize is zero, pname:pInitialData is ignored. |
| |
| .Valid Usage |
| **** |
| * [[VUID-VkValidationCacheCreateInfoEXT-initialDataSize-01534]] |
| If pname:initialDataSize is not `0`, it must: be equal to the size of |
| pname:pInitialData, as returned by fname:vkGetValidationCacheDataEXT |
| when pname:pInitialData was originally retrieved |
| * [[VUID-VkValidationCacheCreateInfoEXT-initialDataSize-01535]] |
| If pname:initialDataSize is not `0`, pname:pInitialData must: have been |
| retrieved from a previous call to fname:vkGetValidationCacheDataEXT |
| **** |
| |
| include::{generated}/validity/structs/VkValidationCacheCreateInfoEXT.adoc[] |
| -- |
| |
| [open,refpage='VkValidationCacheCreateFlagsEXT',desc='Reserved for future use',type='flags'] |
| -- |
| include::{generated}/api/flags/VkValidationCacheCreateFlagsEXT.adoc[] |
| |
| tname:VkValidationCacheCreateFlagsEXT is a bitmask type for setting a mask, |
| but is currently reserved for future use. |
| -- |
| |
| [open,refpage='vkMergeValidationCachesEXT',desc='Combine the data stores of validation caches',type='protos'] |
| -- |
| Validation cache objects can: be merged using the command: |
| |
| include::{generated}/api/protos/vkMergeValidationCachesEXT.adoc[] |
| |
| * pname:device is the logical device that owns the validation cache |
| objects. |
| * pname:dstCache is the handle of the validation cache to merge results |
| into. |
| * pname:srcCacheCount is the length of the pname:pSrcCaches array. |
| * pname:pSrcCaches is a pointer to an array of validation cache handles, |
| which will be merged into pname:dstCache. |
| The previous contents of pname:dstCache are included after the merge. |
| |
| [NOTE] |
| .Note |
| ==== |
| The details of the merge operation are implementation-dependent, but |
| implementations should: merge the contents of the specified validation |
| caches and prune duplicate entries. |
| ==== |
| |
| .Valid Usage |
| **** |
| * [[VUID-vkMergeValidationCachesEXT-dstCache-01536]] |
| pname:dstCache must: not appear in the list of source caches |
| **** |
| |
| include::{generated}/validity/protos/vkMergeValidationCachesEXT.adoc[] |
| -- |
| |
| [open,refpage='vkGetValidationCacheDataEXT',desc='Get the data store from a validation cache',type='protos'] |
| -- |
| Data can: be retrieved from a validation cache object using the command: |
| |
| include::{generated}/api/protos/vkGetValidationCacheDataEXT.adoc[] |
| |
| * pname:device is the logical device that owns the validation cache. |
| * pname:validationCache is the validation cache to retrieve data from. |
| * pname:pDataSize is a pointer to a value related to the amount of data in |
| the validation cache, as described below. |
| * pname:pData is either `NULL` or a pointer to a buffer. |
| |
| If pname:pData is `NULL`, then the maximum size of the data that can: be |
| retrieved from the validation cache, in bytes, is returned in |
| pname:pDataSize. |
| Otherwise, pname:pDataSize must: point to a variable set by the user to the |
| size of the buffer, in bytes, pointed to by pname:pData, and on return the |
| variable is overwritten with the amount of data actually written to |
| pname:pData. |
| If pname:pDataSize is less than the maximum size that can: be retrieved by |
| the validation cache, at most pname:pDataSize bytes will be written to |
| pname:pData, and fname:vkGetValidationCacheDataEXT will return |
| ename:VK_INCOMPLETE instead of ename:VK_SUCCESS, to indicate that not all of |
| the validation cache was returned. |
| |
| Any data written to pname:pData is valid and can: be provided as the |
| pname:pInitialData member of the slink:VkValidationCacheCreateInfoEXT |
| structure passed to fname:vkCreateValidationCacheEXT. |
| |
| Two calls to fname:vkGetValidationCacheDataEXT with the same parameters |
| must: retrieve the same data unless a command that modifies the contents of |
| the cache is called between them. |
| |
| [[validation-cache-header]] |
| Applications can: store the data retrieved from the validation cache, and |
| use these data, possibly in a future run of the application, to populate new |
| validation cache objects. |
| The results of validation, however, may: depend on the vendor ID, device ID, |
| driver version, and other details of the device. |
| To enable applications to detect when previously retrieved data is |
| incompatible with the device, the initial bytes written to pname:pData must: |
| be a header consisting of the following members: |
| |
| .Layout for validation cache header version ename:VK_VALIDATION_CACHE_HEADER_VERSION_ONE_EXT |
| [width="85%",cols="8%,21%,71%",options="header"] |
| |==== |
| | Offset | Size | Meaning |
| | 0 | 4 | length in bytes of the entire validation cache header |
| written as a stream of bytes, with the least |
| significant byte first |
| | 4 | 4 | a elink:VkValidationCacheHeaderVersionEXT value |
| written as a stream of bytes, with the least |
| significant byte first |
| | 8 | ename:VK_UUID_SIZE | a layer commit ID expressed as a UUID, which uniquely |
| identifies the version of the validation layers used |
| to generate these validation results |
| |==== |
| |
| The first four bytes encode the length of the entire validation cache |
| header, in bytes. |
| This value includes all fields in the header including the validation cache |
| version field and the size of the length field. |
| |
| The next four bytes encode the validation cache version, as described for |
| elink:VkValidationCacheHeaderVersionEXT. |
| A consumer of the validation cache should: use the cache version to |
| interpret the remainder of the cache header. |
| |
| If pname:pDataSize is less than what is necessary to store this header, |
| nothing will be written to pname:pData and zero will be written to |
| pname:pDataSize. |
| |
| include::{generated}/validity/protos/vkGetValidationCacheDataEXT.adoc[] |
| -- |
| |
| [open,refpage='VkValidationCacheHeaderVersionEXT',desc='Encode validation cache version',type='enums',xrefs='vkCreateValidationCacheEXT vkGetValidationCacheDataEXT'] |
| -- |
| Possible values of the second group of four bytes in the header returned by |
| flink:vkGetValidationCacheDataEXT, encoding the validation cache version, |
| are: |
| |
| include::{generated}/api/enums/VkValidationCacheHeaderVersionEXT.adoc[] |
| |
| * ename:VK_VALIDATION_CACHE_HEADER_VERSION_ONE_EXT specifies version one |
| of the validation cache. |
| -- |
| |
| [open,refpage='vkDestroyValidationCacheEXT',desc='Destroy a validation cache object',type='protos'] |
| -- |
| To destroy a validation cache, call: |
| |
| include::{generated}/api/protos/vkDestroyValidationCacheEXT.adoc[] |
| |
| * pname:device is the logical device that destroys the validation cache |
| object. |
| * pname:validationCache is the handle of the validation cache to destroy. |
| * pname:pAllocator controls host memory allocation as described in the |
| <<memory-allocation, Memory Allocation>> chapter. |
| |
| .Valid Usage |
| **** |
| * [[VUID-vkDestroyValidationCacheEXT-validationCache-01537]] |
| If sname:VkAllocationCallbacks were provided when pname:validationCache |
| was created, a compatible set of callbacks must: be provided here |
| * [[VUID-vkDestroyValidationCacheEXT-validationCache-01538]] |
| If no sname:VkAllocationCallbacks were provided when |
| pname:validationCache was created, pname:pAllocator must: be `NULL` |
| **** |
| |
| include::{generated}/validity/protos/vkDestroyValidationCacheEXT.adoc[] |
| -- |
| endif::VK_EXT_validation_cache[] |
| |
| ifdef::VK_NV_cuda_kernel_launch[] |
| include::{chapters}/VK_NV_cuda_kernel_launch/module.adoc[] |
| endif::VK_NV_cuda_kernel_launch[] |