Vulkan-Sample-Note-Push-Constants - CYF Blog

Vulkan-Sample-Note-Push-Constants

Vulkan Sample Note: Push constants

The sample is from Sascha Williems

TL;DR

  • Using push constants to pass a small bit of static data to a shader
  • Perfect for passing e.g. static per-object data or parameters without the need for descriptor sets
  • The spec only requires a minimum of 128 bytes, so for passing larger blocks of data you’d use UBOs or SSBOs

Notes

The sample renders 16 different color and position spheres via pushing costant data.

struct SpherePushConstantData {
	glm::vec4 color;
	glm::vec4 position;
};
std::array<SpherePushConstantData, 16> spheres;

Resources

setupDescriptorSetLayout

We create a VkPushConstantRange for pushing constants

void setupDescriptorSetLayout()
{
	std::vector<VkDescriptorSetLayoutBinding> setLayoutBindings = {
	    // Binding 0 : Vertex shader uniform buffer
		vks::initializers::descriptorSetLayoutBinding(
			VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
			VK_SHADER_STAGE_VERTEX_BIT,				0),
        };

	VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings);
	VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout));

	// Define the push constant range used by the pipeline layout
	// Note that the spec only requires a minimum of 128 bytes, so for passing larger blocks of data you'd use UBOs or SSBOs
	VkPushConstantRange pushConstantRange{};
	pushConstantRange.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
	pushConstantRange.offset = 0;
	pushConstantRange.size = sizeof(SpherePushConstantData);

	VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1);
	pipelineLayoutCreateInfo.pushConstantRangeCount  = 1;
	pipelineLayoutCreateInfo.pPushConstantRanges = &pushConstantRange;
	VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout));
}

buildCommandBuffers

void buildCommandBuffers()
{
    // Set target frame buffer
    ...
    
    // [POI] Render the spheres passing color and position via push constants
    uint32_t spherecount = static_cast<uint32_t>(spheres.size());
    for (uint32_t j = 0; j < spherecount; j++) {
        // [POI] Pass static sphere data as push constants
        vkCmdPushConstants(
            drawCmdBuffers[i],
            pipelineLayout,
	    VK_SHADER_STAGE_VERTEX_BIT,
	    0,
	    sizeof(SpherePushConstantData),
	    &spheres[j]);
        model.draw(drawCmdBuffers[i]);
    }
    
    ...
}