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