API Interactions
- 
Interacts with VK_VERSION_1_1 
- 
Interacts with VK_VERSION_1_3 
- 
Interacts with VK_EXT_blend_operation_advanced 
- 
Interacts with VK_EXT_conservative_rasterization 
- 
Interacts with VK_EXT_depth_clamp_control 
- 
Interacts with VK_EXT_depth_clip_control 
- 
Interacts with VK_EXT_depth_clip_enable 
- 
Interacts with VK_EXT_fragment_density_map 
- 
Interacts with VK_EXT_line_rasterization 
- 
Interacts with VK_EXT_mesh_shader 
- 
Interacts with VK_EXT_provoking_vertex 
- 
Interacts with VK_EXT_sample_locations 
- 
Interacts with VK_EXT_subgroup_size_control 
- 
Interacts with VK_EXT_transform_feedback 
- 
Interacts with VK_KHR_device_group 
- 
Interacts with VK_KHR_fragment_shading_rate 
- 
Interacts with VK_NV_clip_space_w_scaling 
- 
Interacts with VK_NV_coverage_reduction_mode 
- 
Interacts with VK_NV_fragment_coverage_to_color 
- 
Interacts with VK_NV_framebuffer_mixed_samples 
- 
Interacts with VK_NV_mesh_shader 
- 
Interacts with VK_NV_representative_fragment_test 
- 
Interacts with VK_NV_shading_rate_image 
- 
Interacts with VK_NV_viewport_swizzle 
Contact
- 
Daniel Story [GitHub]daniel-story 
Other Extension Metadata
- Last Modified Date
- 
2023-03-30 
- Interactions and External Dependencies
- 
- 
Interacts with VK_EXT_extended_dynamic_state
- 
Interacts with VK_EXT_extended_dynamic_state2
- 
Interacts with VK_EXT_extended_dynamic_state3
- 
Interacts with VK_EXT_vertex_input_dynamic_state
 
- 
- IP Status
- 
No known IP claims. 
- Contributors
- 
- 
Piers Daniell, NVIDIA 
- 
Sandy Jamieson, Nintendo 
- 
Žiga Markuš, LunarG 
- 
Tobias Hector, AMD 
- 
Alex Walters, Imagination 
- 
Shahbaz Youssefi, Google 
- 
Ralph Potter, Samsung 
- 
Jan-Harald Fredriksen, ARM 
- 
Connor Abott, Valve 
- 
Arseny Kapoulkine, Roblox 
- 
Patrick Doane, Activision 
- 
Jeff Leger, Qualcomm 
- 
Stu Smith, AMD 
- 
Chris Glover, Google 
- 
Ricardo Garcia, Igalia 
- 
Faith Ekstrand, Collabora 
- 
Timur Kristóf, Valve 
- 
Caterina Shablia, Collabora 
- 
Daniel Koch, NVIDIA 
- 
Alyssa Rosenzweig, Collabora 
- 
Mike Blumenkrantz, Valve 
- 
Samuel Pitoiset, Valve 
- 
Qun Lin, AMD 
- 
Spencer Fricke, LunarG 
- 
Soroush Faghihi Kashani, Imagination 
 
- 
Description
This extension introduces a new VkShaderEXT object type which represents a single compiled shader stage. Shader objects provide a more flexible alternative to VkPipeline objects, which may be helpful in certain use cases.
New Commands
If VK_EXT_blend_operation_advanced is supported:
If VK_EXT_conservative_rasterization is supported:
If VK_EXT_depth_clamp_control is supported:
If VK_EXT_depth_clip_control is supported:
If VK_EXT_depth_clip_enable is supported:
If VK_EXT_line_rasterization is supported:
If VK_EXT_provoking_vertex is supported:
If VK_EXT_sample_locations is supported:
If VK_EXT_transform_feedback is supported:
If VK_NV_clip_space_w_scaling is supported:
If VK_NV_coverage_reduction_mode is supported:
If VK_NV_fragment_coverage_to_color is supported:
If VK_NV_framebuffer_mixed_samples is supported:
If VK_NV_representative_fragment_test is supported:
If VK_NV_shading_rate_image is supported:
If VK_NV_viewport_swizzle is supported:
New Structures
- 
Extending VkPhysicalDeviceFeatures2, VkDeviceCreateInfo: 
- 
Extending VkPhysicalDeviceProperties2: 
- 
Extending VkPipelineShaderStageCreateInfo, VkShaderCreateInfoEXT: 
New Enum Constants
- 
VK_EXT_SHADER_OBJECT_EXTENSION_NAME
- 
VK_EXT_SHADER_OBJECT_SPEC_VERSION
- 
Extending VkObjectType: - 
VK_OBJECT_TYPE_SHADER_EXT
 
- 
- 
Extending VkResult: - 
VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT
- 
VK_INCOMPATIBLE_SHADER_BINARY_EXT
 
- 
- 
Extending VkStructureType: - 
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_OBJECT_FEATURES_EXT
- 
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_OBJECT_PROPERTIES_EXT
- 
VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT
- 
VK_STRUCTURE_TYPE_SHADER_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT
- 
VK_STRUCTURE_TYPE_VERTEX_INPUT_ATTRIBUTE_DESCRIPTION_2_EXT
- 
VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT
 
- 
If VK_EXT_fragment_density_map is supported:
- 
Extending VkShaderCreateFlagBitsEXT: - 
VK_SHADER_CREATE_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT
 
- 
If VK_EXT_mesh_shader or VK_NV_mesh_shader is supported:
- 
Extending VkShaderCreateFlagBitsEXT: - 
VK_SHADER_CREATE_NO_TASK_SHADER_BIT_EXT
 
- 
If VK_EXT_subgroup_size_control or Vulkan Version 1.3 is supported:
- 
Extending VkShaderCreateFlagBitsEXT: - 
VK_SHADER_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT_EXT
- 
VK_SHADER_CREATE_REQUIRE_FULL_SUBGROUPS_BIT_EXT
 
- 
If VK_KHR_device_group or Vulkan Version 1.1 is supported:
- 
Extending VkShaderCreateFlagBitsEXT: - 
VK_SHADER_CREATE_DISPATCH_BASE_BIT_EXT
 
- 
If VK_KHR_fragment_shading_rate is supported:
- 
Extending VkShaderCreateFlagBitsEXT: - 
VK_SHADER_CREATE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_EXT
 
- 
Examples
Example 1
Create linked pair of vertex and fragment shaders.
// Logical device created with the shaderObject feature enabled
VkDevice device;
// SPIR-V shader code for a vertex shader, along with its size in bytes
void* pVertexSpirv;
size_t vertexSpirvSize;
// SPIR-V shader code for a fragment shader, along with its size in bytes
void* pFragmentSpirv;
size_t fragmentSpirvSize;
// Descriptor set layout compatible with the shaders
VkDescriptorSetLayout descriptorSetLayout;
VkShaderCreateInfoEXT shaderCreateInfos[2] =
{
    {
        .sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT,
        .pNext = NULL,
        .flags = VK_SHADER_CREATE_LINK_STAGE_BIT_EXT,
        .stage = VK_SHADER_STAGE_VERTEX_BIT,
        .nextStage = VK_SHADER_STAGE_FRAGMENT_BIT,
        .codeType = VK_SHADER_CODE_TYPE_SPIRV_EXT,
        .codeSize = vertexSpirvSize,
        .pCode = pVertexSpirv,
        .pName = "main",
        .setLayoutCount = 1,
        .pSetLayouts = &descriptorSetLayout;
        .pushConstantRangeCount = 0,
        .pPushConstantRanges = NULL,
        .pSpecializationInfo = NULL
    },
    {
        .sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT,
        .pNext = NULL,
        .flags = VK_SHADER_CREATE_LINK_STAGE_BIT_EXT,
        .stage = VK_SHADER_STAGE_FRAGMENT_BIT,
        .nextStage = 0,
        .codeType = VK_SHADER_CODE_TYPE_SPIRV_EXT,
        .codeSize = fragmentSpirvSize,
        .pCode = pFragmentSpirv,
        .pName = "main",
        .setLayoutCount = 1,
        .pSetLayouts = &descriptorSetLayout;
        .pushConstantRangeCount = 0,
        .pPushConstantRanges = NULL,
        .pSpecializationInfo = NULL
    }
};
VkResult result;
VkShaderEXT shaders[2];
result = vkCreateShadersEXT(device, 2, &shaderCreateInfos, NULL, shaders);
if (result != VK_SUCCESS)
{
    // Handle error
}Later, during command buffer recording, bind the linked shaders and draw.
// Command buffer in the recording state
VkCommandBuffer commandBuffer;
// Vertex and fragment shader objects created above
VkShaderEXT shaders[2];
// Assume vertex buffers, descriptor sets, etc. have been bound, and existing
// state setting commands have been called to set all required state
const VkShaderStageFlagBits stages[2] =
{
    VK_SHADER_STAGE_VERTEX_BIT,
    VK_SHADER_STAGE_FRAGMENT_BIT
};
// Bind linked shaders
vkCmdBindShadersEXT(commandBuffer, 2, stages, shaders);
// Equivalent to the previous line. Linked shaders can be bound one at a time,
// in any order:
// vkCmdBindShadersEXT(commandBuffer, 1, &stages[1], &shaders[1]);
// vkCmdBindShadersEXT(commandBuffer, 1, &stages[0], &shaders[0]);
// The above is sufficient to draw if the device was created with the
// tessellationShader and geometryShader features disabled. Otherwise, since
// those stages should not execute, vkCmdBindShadersEXT() must be called at
// least once with each of their stages in pStages before drawing:
const VkShaderStageFlagBits unusedStages[3] =
{
    VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
    VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
    VK_SHADER_STAGE_GEOMETRY_BIT
};
// NULL pShaders is equivalent to an array of stageCount VK_NULL_HANDLE values,
// meaning no shaders are bound to those stages, and that any previously bound
// shaders are unbound
vkCmdBindShadersEXT(commandBuffer, 3, unusedStages, NULL);
// Graphics shader objects may only be used to draw inside dynamic render pass
// instances begun with vkCmdBeginRendering(), assume one has already been begun
// Draw a triangle
vkCmdDraw(commandBuffer, 3, 1, 0, 0);Example 2
Create unlinked vertex, geometry, and fragment shaders.
// Logical device created with the shaderObject feature enabled
VkDevice device;
// SPIR-V shader code for vertex shaders, along with their sizes in bytes
void* pVertexSpirv[2];
size_t vertexSpirvSize[2];
// SPIR-V shader code for a geometry shader, along with its size in bytes
void pGeometrySpirv;
size_t geometrySpirvSize;
// SPIR-V shader code for fragment shaders, along with their sizes in bytes
void* pFragmentSpirv[2];
size_t fragmentSpirvSize[2];
// Descriptor set layout compatible with the shaders
VkDescriptorSetLayout descriptorSetLayout;
VkShaderCreateInfoEXT shaderCreateInfos[5] =
{
    // Stage order does not matter
    {
        .sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT,
        .pNext = NULL,
        .flags = 0,
        .stage = VK_SHADER_STAGE_GEOMETRY_BIT,
        .nextStage = VK_SHADER_STAGE_FRAGMENT_BIT,
        .codeType = VK_SHADER_CODE_TYPE_SPIRV_EXT,
        .codeSize = pGeometrySpirv,
        .pCode = geometrySpirvSize,
        .pName = "main",
        .setLayoutCount = 1,
        .pSetLayouts = &descriptorSetLayout;
        .pushConstantRangeCount = 0,
        .pPushConstantRanges = NULL,
        .pSpecializationInfo = NULL
    },
    {
        .sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT,
        .pNext = NULL,
        .flags = 0,
        .stage = VK_SHADER_STAGE_VERTEX_BIT,
        .nextStage = VK_SHADER_STAGE_GEOMETRY_BIT,
        .codeType = VK_SHADER_CODE_TYPE_SPIRV_EXT,
        .codeSize = vertexSpirvSize[0],
        .pCode = pVertexSpirv[0],
        .pName = "main",
        .setLayoutCount = 1,
        .pSetLayouts = &descriptorSetLayout;
        .pushConstantRangeCount = 0,
        .pPushConstantRanges = NULL,
        .pSpecializationInfo = NULL
    },
    {
        .sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT,
        .pNext = NULL,
        .flags = 0,
        .stage = VK_SHADER_STAGE_FRAGMENT_BIT,
        .nextStage = 0,
        .codeType = VK_SHADER_CODE_TYPE_SPIRV_EXT,
        .codeSize = fragmentSpirvSize[0],
        .pCode = pFragmentSpirv[0],
        .pName = "main",
        .setLayoutCount = 1,
        .pSetLayouts = &descriptorSetLayout;
        .pushConstantRangeCount = 0,
        .pPushConstantRanges = NULL,
        .pSpecializationInfo = NULL
    },
    {
        .sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT,
        .pNext = NULL,
        .flags = 0,
        .stage = VK_SHADER_STAGE_FRAGMENT_BIT,
        .nextStage = 0,
        .codeType = VK_SHADER_CODE_TYPE_SPIRV_EXT,
        .codeSize = fragmentSpirvSize[1],
        .pCode = pFragmentSpirv[1],
        .pName = "main",
        .setLayoutCount = 1,
        .pSetLayouts = &descriptorSetLayout;
        .pushConstantRangeCount = 0,
        .pPushConstantRanges = NULL,
        .pSpecializationInfo = NULL
    },
    {
        .sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT,
        .pNext = NULL,
        .flags = 0,
        .stage = VK_SHADER_STAGE_VERTEX_BIT,
        // Suppose we want this vertex shader to be able to be followed by
        // either a geometry shader or fragment shader:
        .nextStage = VK_SHADER_STAGE_GEOMETRY_BIT | VK_SHADER_STAGE_FRAGMENT_BIT,
        .codeType = VK_SHADER_CODE_TYPE_SPIRV_EXT,
        .codeSize = vertexSpirvSize[1],
        .pCode = pVertexSpirv[1],
        .pName = "main",
        .setLayoutCount = 1,
        .pSetLayouts = &descriptorSetLayout;
        .pushConstantRangeCount = 0,
        .pPushConstantRanges = NULL,
        .pSpecializationInfo = NULL
    }
};
VkResult result;
VkShaderEXT shaders[5];
result = vkCreateShadersEXT(device, 5, &shaderCreateInfos, NULL, shaders);
if (result != VK_SUCCESS)
{
    // Handle error
}Later, during command buffer recording, bind the linked shaders in different combinations and draw.
// Command buffer in the recording state
VkCommandBuffer commandBuffer;
// Vertex, geometry, and fragment shader objects created above
VkShaderEXT shaders[5];
// Assume vertex buffers, descriptor sets, etc. have been bound, and existing
// state setting commands have been called to set all required state
const VkShaderStageFlagBits stages[3] =
{
    // Any order is allowed
    VK_SHADER_STAGE_FRAGMENT_BIT,
    VK_SHADER_STAGE_VERTEX_BIT,
    VK_SHADER_STAGE_GEOMETRY_BIT,
};
VkShaderEXT bindShaders[3] =
{
    shaders[2], // FS
    shaders[1], // VS
    shaders[0]  // GS
};
// Bind unlinked shaders
vkCmdBindShadersEXT(commandBuffer, 3, stages, bindShaders);
// Assume the tessellationShader feature is disabled, so vkCmdBindShadersEXT()
// need not have been called with either tessellation stage
// Graphics shader objects may only be used to draw inside dynamic render pass
// instances begun with vkCmdBeginRendering(), assume one has already been begun
// Draw a triangle
vkCmdDraw(commandBuffer, 3, 1, 0, 0);
// Bind a different unlinked fragment shader
const VkShaderStageFlagBits fragmentStage = VK_SHADER_STAGE_FRAGMENT_BIT;
vkCmdBindShadersEXT(commandBuffer, 1, &fragmentStage, &shaders[3]);
// Draw another triangle
vkCmdDraw(commandBuffer, 3, 1, 0, 0);
// Bind a different unlinked vertex shader
const VkShaderStageFlagBits vertexStage = VK_SHADER_STAGE_VERTEX_BIT;
vkCmdBindShadersEXT(commandBuffer, 1, &vertexStage, &shaders[4]);
// Draw another triangle
vkCmdDraw(commandBuffer, 3, 1, 0, 0);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.