VK_HUAWEI_subpass_shading(3)

# VK_HUAWEI_subpass_shading(3) Manual Page

## Name

VK_HUAWEI_subpass_shading - device extension

## Registered Extension Number

370

## Revision

3

## Ratification Status

Not ratified

## Extension and Version Dependencies

VK_KHR_create_renderpass2
or
Vulkan Version 1.2
and
VK_KHR_synchronization2
or
Vulkan Version 1.3

## SPIR-V Dependencies

- SPV_HUAWEI_subpass_shading

## Contact

- Pan Gao [GitHub]PanGao-h

## 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

- vkCmdSubpassShadingHUAWEI

- vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI

## New Structures

- Extending VkComputePipelineCreateInfo:

  - VkSubpassShadingPipelineCreateInfoHUAWEI

- Extending VkPhysicalDeviceFeatures2, VkDeviceCreateInfo:

  - VkPhysicalDeviceSubpassShadingFeaturesHUAWEI

- Extending VkPhysicalDeviceProperties2:

  - VkPhysicalDeviceSubpassShadingPropertiesHUAWEI

## 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` to `VK_PIPELINE_STAGE_2_SUBPASS_SHADER_BIT_HUAWEI` to better aligned with naming of other pipeline stages

- Revision 2, 2021-06-28 (Hueilong Wang)

  - Change vkGetSubpassShadingMaxWorkgroupSizeHUAWEI to vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI to resolve issue `pub1564`

- Revision 1, 2020-12-15 (Hueilong Wang)

  - Initial draft.

## See Also

No cross-references are available

## Document Notes

For more information, see the Vulkan Specification.

This page is a generated document. Fixes and changes should be made to the generator scripts, not directly.

## Copyright

Copyright 2014-2026 The Khronos Group Inc.

SPDX-License-Identifier: CC-BY-4.0