1// Copyright (c) 2020-2024 Huawei Technologies Co. Ltd. 2// 3// SPDX-License-Identifier: CC-BY-4.0 4 5include::{generated}/meta/{refprefix}VK_HUAWEI_subpass_shading.adoc[] 6 7=== Other Extension Metadata 8 9*Last Modified Date*:: 10 2021-06-01 11*Interactions and External Dependencies*:: 12 - This extension requires 13 {spirv}/HUAWEI/SPV_HUAWEI_subpass_shading.html[`SPV_HUAWEI_subpass_shading`]. 14 - This extension provides API support for 15 {GLSLregistry}/huawei/GLSL_HUAWEI_subpass_shading.txt[`GL_HUAWEI_subpass_shading`]. 16*Contributors*:: 17 - Hueilong Wang 18 - Juntao Li, Huawei 19 - Renmiao Lu, Huawei 20 - Pan Gao, Huawei 21 22=== Description 23 24This extension allows applications to execute a subpass shading pipeline in 25a subpass of a render pass in order to save memory bandwidth for algorithms 26like tile-based deferred rendering and forward plus. 27A subpass shading pipeline is a pipeline with the compute pipeline ability, 28allowed to read values from input attachments, and only allowed to be 29dispatched inside a stand-alone subpass. 30Its work dimension is defined by the render pass's render area size. 31Its workgroup size (width, height) shall be a power-of-two number in width 32or height, with minimum value from 8, and maximum value shall be decided 33from the render pass attachments and sample counts but depends on 34implementation. 35 36The code:GlobalInvocationId.xy of a subpass shading pipeline is equal to the 37code:FragCoord.xy of a graphic pipeline in the same render pass subtracted 38the <<VkRect2D,pname:offset>> of the 39slink:VkRenderPassBeginInfo::pname:renderArea. 40code:GlobalInvocationId.z is mapped to the Layer if 41`apiext:VK_EXT_shader_viewport_index_layer` is supported. 42The code:GlobalInvocationId.xy is equal to the index of the local workgroup 43multiplied by the size of the local workgroup plus the 44code:LocalInvocationId and the <<VkRect2D,pname:offset>> of the 45slink:VkRenderPassBeginInfo::pname:renderArea. 46 47This extension allows a subpass's pipeline bind point to be 48ename:VK_PIPELINE_BIND_POINT_SUBPASS_SHADING_HUAWEI. 49 50include::{generated}/interfaces/VK_HUAWEI_subpass_shading.adoc[] 51 52 53=== Sample Code 54 55Example of subpass shading in a GLSL shader 56 57[source,c] 58--------------------------------------------------- 59#extension GL_HUAWEI_subpass_shading: enable 60#extension GL_KHR_shader_subgroup_arithmetic: enable 61 62layout(constant_id = 0) const uint tileWidth = 8; 63layout(constant_id = 1) const uint tileHeight = 8; 64layout(local_size_x_id = 0, local_size_y_id = 1, local_size_z = 1) in; 65layout(set=0, binding=0, input_attachment_index=0) uniform subpassInput depth; 66 67void main() 68{ 69 float d = subpassLoad(depth).x; 70 float minD = subgroupMin(d); 71 float maxD = subgroupMax(d); 72} 73--------------------------------------------------- 74 75Example of subpass shading dispatching in a subpass 76 77[source,c] 78--------------------------------------------------- 79vkCmdNextSubpass(commandBuffer, VK_SUBPASS_CONTENTS_INLINE); 80vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_SUBPASS_SHADING_HUAWEI, subpassShadingPipeline); 81vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_SUBPASS_SHADING_HUAWEI, subpassShadingPipelineLayout, 82 firstSet, descriptorSetCount, pDescriptorSets, dynamicOffsetCount, pDynamicOffsets); 83vkCmdSubpassShadingHUAWEI(commandBuffer) 84vkCmdEndRenderPass(commandBuffer); 85--------------------------------------------------- 86 87Example of subpass shading render pass creation 88 89[source,c] 90--------------------------------------------------- 91VkAttachmentDescription2 attachments[] = { 92 { 93 VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, NULL, 94 0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT, 95 VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_DONT_CARE, 96 VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_LOAD_OP_DONT_CARE, 97 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL 98 }, 99 { 100 VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, NULL, 101 0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT, 102 VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_DONT_CARE, 103 VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_LOAD_OP_DONT_CARE, 104 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL 105 }, 106 { 107 VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, NULL, 108 0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT, 109 VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_DONT_CARE, 110 VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_LOAD_OP_DONT_CARE, 111 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL 112 }, 113 { 114 VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, NULL, 115 0, VK_FORMAT_D24_UNORM_S8_UINT, VK_SAMPLE_COUNT_1_BIT, 116 VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_DONT_CARE, 117 VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_LOAD_OP_DONT_CARE, 118 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL 119 }, 120 { 121 VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, NULL, 122 0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT, 123 VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_STORE, 124 VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_LOAD_OP_DONT_CARE, 125 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL 126 } 127}; 128 129VkAttachmentReference2 gBufferAttachmentReferences[] = { 130 { VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, NULL, 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_ASPECT_COLOR_BIT }, 131 { VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, NULL, 1, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_ASPECT_COLOR_BIT }, 132 { VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, NULL, 2, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_ASPECT_COLOR_BIT } 133}; 134VkAttachmentReference2 gBufferDepthStencilAttachmentReferences = 135 { VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, NULL, 3, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_ASPECT_DEPTH_BIT|VK_IMAGE_ASPECT_STENCIL_BIT }; 136VkAttachmentReference2 depthInputAttachmentReferences[] = { 137 { VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, NULL, 3, VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, VK_IMAGE_ASPECT_DEPTH_BIT|VK_IMAGE_ASPECT_STENCIL_BIT }; 138}; 139VkAttachmentReference2 preserveAttachmentReferences[] = { 140 { VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, NULL, 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_ASPECT_COLOR_BIT }, 141 { VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, NULL, 1, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_ASPECT_COLOR_BIT }, 142 { VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, NULL, 2, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_ASPECT_COLOR_BIT }, 143 { VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, NULL, 3, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_ASPECT_DEPTH_BIT|VK_IMAGE_ASPECT_STENCIL_BIT } 144}; // G buffer including depth/stencil 145VkAttachmentReference2 colorAttachmentReferences[] = { 146 { VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, NULL, 4, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_ASPECT_COLOR_BIT } 147}; 148VkAttachmentReference2 resolveAttachmentReference = 149 { VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, NULL, 4, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_ASPECT_COLOR_BIT }; 150 151VkSubpassDescription2 subpasses[] = { 152 { 153 VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2, NULL, 0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, 154 0, NULL, // input 155 sizeof(gBufferAttachmentReferences)/sizeof(gBufferAttachmentReferences[0]), gBufferAttachmentReferences, // color 156 NULL, &gBufferDepthStencilAttachmentReferences, // resolve & DS 157 0, NULL 158 }, 159 { 160 VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2, NULL, 0, VK_PIPELINE_BIND_POINT_SUBPASS_SHADING_HUAWEI , 0, 161 sizeof(depthInputAttachmentReferences)/sizeof(depthInputAttachmentReferences[0]), depthInputAttachmentReferences, // input 162 0, NULL, // color 163 NULL, NULL, // resolve & DS 164 sizeof(preserveAttachmentReferences)/sizeof(preserveAttachmentReferences[0]), preserveAttachmentReferences, 165 }, 166 { 167 VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2, NULL, 0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, 168 sizeof(gBufferAttachmentReferences)/sizeof(gBufferAttachmentReferences[0]), gBufferAttachmentReferences, // input 169 sizeof(colorAttachmentReferences)/sizeof(colorAttachmentReferences[0]), colorAttachmentReferences, // color 170 &resolveAttachmentReference, &gBufferDepthStencilAttachmentReferences, // resolve & DS 171 0, NULL 172 }, 173}; 174 175VkMemoryBarrier2KHR fragmentToSubpassShading = { 176 VK_STRUCTURE_TYPE_MEMORY_BARRIER_2_KHR, NULL, 177 VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT_KHR, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT|VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, 178 VK_PIPELINE_STAGE_2_SUBPASS_SHADING_BIT_HUAWEI, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT 179}; 180 181VkMemoryBarrier2KHR subpassShadingToFragment = { 182 VK_STRUCTURE_TYPE_MEMORY_BARRIER_2_KHR, NULL, 183 VK_PIPELINE_STAGE_2_SUBPASS_SHADING_BIT_HUAWEI, VK_ACCESS_SHADER_WRITE_BIT, 184 VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT_KHR, VK_ACCESS_SHADER_READ_BIT 185}; 186 187VkSubpassDependency2 dependencies[] = { 188 { 189 VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2, &fragmentToSubpassShading, 190 0, 1, 191 0, 0, 0, 0, 192 0, 0 193 }, 194 { 195 VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2, &subpassShadingToFragment, 196 1, 2, 197 0, 0, 0, 0, 198 0, 0 199 }, 200}; 201 202VkRenderPassCreateInfo2 renderPassCreateInfo = { 203 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2, NULL, 0, 204 sizeof(attachments)/sizeof(attachments[0]), attachments, 205 sizeof(subpasses)/sizeof(subpasses[0]), subpasses, 206 sizeof(dependencies)/sizeof(dependencies[0]), dependencies, 207 0, NULL 208}; 209VKRenderPass renderPass; 210vkCreateRenderPass2(device, &renderPassCreateInfo, NULL, &renderPass); 211--------------------------------------------------- 212 213Example of subpass shading pipeline creation 214 215[source,c] 216--------------------------------------------------- 217VkExtent2D maxWorkgroupSize; 218 219VkSpecializationMapEntry subpassShadingConstantMapEntries[] = { 220 { 0, 0 * sizeof(uint32_t), sizeof(uint32_t) }, 221 { 1, 1 * sizeof(uint32_t), sizeof(uint32_t) } 222}; 223 224VkSpecializationInfo subpassShadingConstants = { 225 2, subpassShadingConstantMapEntries, 226 sizeof(VkExtent2D), &maxWorkgroupSize 227}; 228 229VkSubpassShadingPipelineCreateInfoHUAWEI subpassShadingPipelineCreateInfo { 230 VK_STRUCTURE_TYPE_SUBPASSS_SHADING_PIPELINE_CREATE_INFO_HUAWEI, NULL, 231 renderPass, 1 232}; 233 234VkPipelineShaderStageCreateInfo subpassShadingPipelineStageCreateInfo { 235 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, NULL, 236 0, VK_SHADER_STAGE_SUBPASS_SHADING_BIT_HUAWEI, 237 shaderModule, "main", 238 &subpassShadingConstants 239}; 240 241VkComputePipelineCreateInfo subpassShadingComputePipelineCreateInfo = { 242 VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, &subpassShadingPipelineCreateInfo, 243 0, &subpassShadingPipelineStageCreateInfo, 244 pipelineLayout, basePipelineHandle, basePipelineIndex 245}; 246 247VKPipeline pipeline; 248 249vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI(device, renderPass, &maxWorkgroupSize); 250vkCreateComputePipelines(device, pipelineCache, 1, &subpassShadingComputePipelineCreateInfo, NULL, &pipeline); 251 252--------------------------------------------------- 253 254 255=== Version History 256 257 * Revision 2, 2021-06-28 (Hueilong Wang) 258 ** Change vkGetSubpassShadingMaxWorkgroupSizeHUAWEI to 259 vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI to resolve issue 260 https://github.com/KhronosGroup/Vulkan-Docs/issues/1564[`pub1564`] 261 * Revision 1, 2020-12-15 (Hueilong Wang) 262 ** Initial draft. 263 264