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