VK_HUAWEI_subpass_shading
Other Extension Metadata
Last Modified Date
2021-06-01
Interactions and External Dependencies
- This extension provides API support for
GL_HUAWEI_subpass_shading
.
Contributors
- Hueilong Wang
- Juntao Li, Huawei
- Renmiao Lu, Huawei
- Pan Gao, Huawei
Description
This extension allows applications to execute a subpass shading pipeline in a subpass of a render pass in order to save memory bandwidth for algorithms like tile-based deferred rendering and forward plus. A subpass shading pipeline is a pipeline with the compute pipeline ability, allowed to read values from input attachments, and only allowed to be dispatched inside a stand-alone subpass. Its work dimension is defined by the render pass’s render area size. Its workgroup size (width, height) shall be a power-of-two number in width or height, with minimum value from 8, and maximum value shall be decided from the render pass attachments and sample counts but depends on implementation.
The GlobalInvocationId.xy
of a subpass shading pipeline is equal to the
FragCoord.xy
of a graphic pipeline in the same render pass subtracted
the offset
of the
VkRenderPassBeginInfo::renderArea
.
GlobalInvocationId.z
is mapped to the Layer if
VK_EXT_shader_viewport_index_layer is supported.
The GlobalInvocationId.xy
is equal to the index of the local workgroup
multiplied by the size of the local workgroup plus the
LocalInvocationId
and the offset
of the
VkRenderPassBeginInfo::renderArea
.
This extension allows a subpass’s pipeline bind point to be
VK_PIPELINE_BIND_POINT_SUBPASS_SHADING_HUAWEI
.
New Commands
New Structures
- Extending VkComputePipelineCreateInfo:
- Extending VkPhysicalDeviceFeatures2, VkDeviceCreateInfo:
- Extending VkPhysicalDeviceProperties2:
New Enum Constants
VK_HUAWEI_SUBPASS_SHADING_EXTENSION_NAME
VK_HUAWEI_SUBPASS_SHADING_SPEC_VERSION
- Extending VkPipelineBindPoint:
VK_PIPELINE_BIND_POINT_SUBPASS_SHADING_HUAWEI
- Extending VkPipelineStageFlagBits2:
VK_PIPELINE_STAGE_2_SUBPASS_SHADER_BIT_HUAWEI
VK_PIPELINE_STAGE_2_SUBPASS_SHADING_BIT_HUAWEI
- Extending VkShaderStageFlagBits:
VK_SHADER_STAGE_SUBPASS_SHADING_BIT_HUAWEI
- Extending VkStructureType:
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBPASS_SHADING_FEATURES_HUAWEI
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBPASS_SHADING_PROPERTIES_HUAWEI
VK_STRUCTURE_TYPE_SUBPASS_SHADING_PIPELINE_CREATE_INFO_HUAWEI
Sample Code
Example of subpass shading in a GLSL shader
#extension GL_HUAWEI_subpass_shading: enable
#extension GL_KHR_shader_subgroup_arithmetic: enable
layout(constant_id = 0) const uint tileWidth = 8;
layout(constant_id = 1) const uint tileHeight = 8;
layout(local_size_x_id = 0, local_size_y_id = 1, local_size_z = 1) in;
layout(set=0, binding=0, input_attachment_index=0) uniform subpassInput depth;
void main()
{
float d = subpassLoad(depth).x;
float minD = subgroupMin(d);
float maxD = subgroupMax(d);
}
Example of subpass shading dispatching in a subpass
vkCmdNextSubpass(commandBuffer, VK_SUBPASS_CONTENTS_INLINE);
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_SUBPASS_SHADING_HUAWEI, subpassShadingPipeline);
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_SUBPASS_SHADING_HUAWEI, subpassShadingPipelineLayout,
firstSet, descriptorSetCount, pDescriptorSets, dynamicOffsetCount, pDynamicOffsets);
vkCmdSubpassShadingHUAWEI(commandBuffer)
vkCmdEndRenderPass(commandBuffer);
Example of subpass shading render pass creation
VkAttachmentDescription2 attachments[] = {
{
VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, NULL,
0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT,
VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_DONT_CARE,
VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_LOAD_OP_DONT_CARE,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
},
{
VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, NULL,
0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT,
VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_DONT_CARE,
VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_LOAD_OP_DONT_CARE,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
},
{
VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, NULL,
0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT,
VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_DONT_CARE,
VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_LOAD_OP_DONT_CARE,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
},
{
VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, NULL,
0, VK_FORMAT_D24_UNORM_S8_UINT, VK_SAMPLE_COUNT_1_BIT,
VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_DONT_CARE,
VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_LOAD_OP_DONT_CARE,
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
},
{
VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, NULL,
0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT,
VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_STORE,
VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_LOAD_OP_DONT_CARE,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
}
};
VkAttachmentReference2 gBufferAttachmentReferences[] = {
{ VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, NULL, 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_ASPECT_COLOR_BIT },
{ VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, NULL, 1, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_ASPECT_COLOR_BIT },
{ VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, NULL, 2, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_ASPECT_COLOR_BIT }
};
VkAttachmentReference2 gBufferDepthStencilAttachmentReferences =
{ 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 };
VkAttachmentReference2 depthInputAttachmentReferences[] = {
{ 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 };
};
VkAttachmentReference2 preserveAttachmentReferences[] = {
{ VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, NULL, 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_ASPECT_COLOR_BIT },
{ VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, NULL, 1, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_ASPECT_COLOR_BIT },
{ VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, NULL, 2, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_ASPECT_COLOR_BIT },
{ 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 }
}; // G buffer including depth/stencil
VkAttachmentReference2 colorAttachmentReferences[] = {
{ VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, NULL, 4, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_ASPECT_COLOR_BIT }
};
VkAttachmentReference2 resolveAttachmentReference =
{ VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, NULL, 4, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_ASPECT_COLOR_BIT };
VkSubpassDescription2 subpasses[] = {
{
VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2, NULL, 0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0,
0, NULL, // input
sizeof(gBufferAttachmentReferences)/sizeof(gBufferAttachmentReferences[0]), gBufferAttachmentReferences, // color
NULL, &gBufferDepthStencilAttachmentReferences, // resolve & DS
0, NULL
},
{
VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2, NULL, 0, VK_PIPELINE_BIND_POINT_SUBPASS_SHADING_HUAWEI , 0,
sizeof(depthInputAttachmentReferences)/sizeof(depthInputAttachmentReferences[0]), depthInputAttachmentReferences, // input
0, NULL, // color
NULL, NULL, // resolve & DS
sizeof(preserveAttachmentReferences)/sizeof(preserveAttachmentReferences[0]), preserveAttachmentReferences,
},
{
VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2, NULL, 0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0,
sizeof(gBufferAttachmentReferences)/sizeof(gBufferAttachmentReferences[0]), gBufferAttachmentReferences, // input
sizeof(colorAttachmentReferences)/sizeof(colorAttachmentReferences[0]), colorAttachmentReferences, // color
&resolveAttachmentReference, &gBufferDepthStencilAttachmentReferences, // resolve & DS
0, NULL
},
};
VkMemoryBarrier2KHR fragmentToSubpassShading = {
VK_STRUCTURE_TYPE_MEMORY_BARRIER_2_KHR, NULL,
VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT_KHR, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT|VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
VK_PIPELINE_STAGE_2_SUBPASS_SHADER_BIT_HUAWEI, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT
};
VkMemoryBarrier2KHR subpassShadingToFragment = {
VK_STRUCTURE_TYPE_MEMORY_BARRIER_2_KHR, NULL,
VK_PIPELINE_STAGE_2_SUBPASS_SHADER_BIT_HUAWEI, VK_ACCESS_SHADER_WRITE_BIT,
VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT_KHR, VK_ACCESS_SHADER_READ_BIT
};
VkSubpassDependency2 dependencies[] = {
{
VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2, &fragmentToSubpassShading,
0, 1,
0, 0, 0, 0,
0, 0
},
{
VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2, &subpassShadingToFragment,
1, 2,
0, 0, 0, 0,
0, 0
},
};
VkRenderPassCreateInfo2 renderPassCreateInfo = {
VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2, NULL, 0,
sizeof(attachments)/sizeof(attachments[0]), attachments,
sizeof(subpasses)/sizeof(subpasses[0]), subpasses,
sizeof(dependencies)/sizeof(dependencies[0]), dependencies,
0, NULL
};
VKRenderPass renderPass;
vkCreateRenderPass2(device, &renderPassCreateInfo, NULL, &renderPass);
Example of subpass shading pipeline creation
VkExtent2D maxWorkgroupSize;
VkSpecializationMapEntry subpassShadingConstantMapEntries[] = {
{ 0, 0 * sizeof(uint32_t), sizeof(uint32_t) },
{ 1, 1 * sizeof(uint32_t), sizeof(uint32_t) }
};
VkSpecializationInfo subpassShadingConstants = {
2, subpassShadingConstantMapEntries,
sizeof(VkExtent2D), &maxWorkgroupSize
};
VkSubpassShadingPipelineCreateInfoHUAWEI subpassShadingPipelineCreateInfo {
VK_STRUCTURE_TYPE_SUBPASSS_SHADING_PIPELINE_CREATE_INFO_HUAWEI, NULL,
renderPass, 1
};
VkPipelineShaderStageCreateInfo subpassShadingPipelineStageCreateInfo {
VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, NULL,
0, VK_SHADER_STAGE_SUBPASS_SHADING_BIT_HUAWEI,
shaderModule, "main",
&subpassShadingConstants
};
VkComputePipelineCreateInfo subpassShadingComputePipelineCreateInfo = {
VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, &subpassShadingPipelineCreateInfo,
0, &subpassShadingPipelineStageCreateInfo,
pipelineLayout, basePipelineHandle, basePipelineIndex
};
VKPipeline pipeline;
vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI(device, renderPass, &maxWorkgroupSize);
vkCreateComputePipelines(device, pipelineCache, 1, &subpassShadingComputePipelineCreateInfo, NULL, &pipeline);
Version History
- Revision 3, 2023-06-19 (Pan Gao)
- Rename
VK_PIPELINE_STAGE_2_SUBPASS_SHADING_BIT_HUAWEI
toVK_PIPELINE_STAGE_2_SUBPASS_SHADER_BIT_HUAWEI
to better aligned with naming of other pipeline stages
- Rename
- Revision 2, 2021-06-28 (Hueilong Wang)
- Change vkGetSubpassShadingMaxWorkgroupSizeHUAWEI to
vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI to resolve issue
pub1564
- Change vkGetSubpassShadingMaxWorkgroupSizeHUAWEI to
vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI to resolve issue
- Revision 1, 2020-12-15 (Hueilong Wang)
- Initial draft.