Push Constant not updating

I cant find why my push constant is not being updated in the compute pipeline. The struct which the push constant point is being updated, but it looks like the new values are not going forward the compute shader.

Here is the commandBuffer code:


	VkCommandBufferBeginInfo cmdBufInfo = commandBufferBeginInfo();

	ErrorCheck(vkBeginCommandBuffer(s_compute.commandBuffer[0], &cmdBufInfo));
        vkCmdPushConstants(
		s_compute.commandBuffer[0],
		s_compute.pipelineLayout,
		VK_SHADER_STAGE_COMPUTE_BIT,
		0,
		sizeof(computeValues),
		&computeValues);
	for (std::map<Material*, std::vector<RenderObject*>>::iterator it = _render_resource->materials.begin(); it != _render_resource->materials.end(); ++it)
	{
		// Add memory barrier to ensure that the indirect commands have been consumed before the compute shader updates them
		VkBufferMemoryBarrier bufferBarrier = bufferMemoryBarrier();
		bufferBarrier.buffer = it->first->buffers[indirectCommand].buffer;
		bufferBarrier.size = it->first->buffers[indirectCommand].descriptor.range;
		bufferBarrier.srcAccessMask = VK_ACCESS_INDIRECT_COMMAND_READ_BIT;
		bufferBarrier.dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
		bufferBarrier.srcQueueFamilyIndex = _graphics_family_index;
		bufferBarrier.dstQueueFamilyIndex = _compute_family_index;

		vkCmdPipelineBarrier(
			s_compute.commandBuffer[0],
			VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT,
			VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
			VK_FLAGS_NONE,
			0, nullptr,
			1, &bufferBarrier,
			0, nullptr);

		vkCmdBindPipeline(s_compute.commandBuffer[0], VK_PIPELINE_BIND_POINT_COMPUTE, s_compute.pipeline);

		vkCmdBindDescriptorSets(s_compute.commandBuffer[0], VK_PIPELINE_BIND_POINT_COMPUTE, s_compute.pipelineLayout, 0, 1, &it->first->descriptorSets[descriptionSet], 0, 0);
		vkCmdDispatch(s_compute.commandBuffer[0], it->second.size() / 16, 1, 1);

		// Add memory barrier to ensure that the compute shader has finished writing the indirect command buffer before it's consumed
		bufferBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
		bufferBarrier.dstAccessMask = VK_ACCESS_INDIRECT_COMMAND_READ_BIT;
		bufferBarrier.buffer = it->first->buffers[indirectCommand].buffer;
		bufferBarrier.size = it->first->buffers[indirectCommand].descriptor.range;
		bufferBarrier.srcQueueFamilyIndex = _compute_family_index;
		bufferBarrier.dstQueueFamilyIndex = _compute_family_index;

		vkCmdPipelineBarrier(
			s_compute.commandBuffer[0],
			VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
			VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT,
			VK_FLAGS_NONE,
			0, nullptr,
			1, &bufferBarrier,
			0, nullptr);

	}
	vkEndCommandBuffer(s_compute.commandBuffer[0]);

When the push contant was passed by uniform binding it was working great, but now i need it to be a push constant.

Do you know why it could be happening?

[QUOTE=Harukoxd;42730]I cant find why my push constant is not being updated in the compute pipeline. The struct which the push constant point is being updated, but it looks like the new values are not going forward the compute shader.

Here is the commandBuffer code:


	VkCommandBufferBeginInfo cmdBufInfo = commandBufferBeginInfo();

	ErrorCheck(vkBeginCommandBuffer(s_compute.commandBuffer[0], &cmdBufInfo));
        vkCmdPushConstants(
		s_compute.commandBuffer[0],
		s_compute.pipelineLayout,
		VK_SHADER_STAGE_COMPUTE_BIT,
		0,
		sizeof(computeValues),
		&computeValues);
	for (std::map<Material*, std::vector<RenderObject*>>::iterator it = _render_resource->materials.begin(); it != _render_resource->materials.end(); ++it)
	{
		// Add memory barrier to ensure that the indirect commands have been consumed before the compute shader updates them
		VkBufferMemoryBarrier bufferBarrier = bufferMemoryBarrier();
		bufferBarrier.buffer = it->first->buffers[indirectCommand].buffer;
		bufferBarrier.size = it->first->buffers[indirectCommand].descriptor.range;
		bufferBarrier.srcAccessMask = VK_ACCESS_INDIRECT_COMMAND_READ_BIT;
		bufferBarrier.dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
		bufferBarrier.srcQueueFamilyIndex = _graphics_family_index;
		bufferBarrier.dstQueueFamilyIndex = _compute_family_index;

		vkCmdPipelineBarrier(
			s_compute.commandBuffer[0],
			VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT,
			VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
			VK_FLAGS_NONE,
			0, nullptr,
			1, &bufferBarrier,
			0, nullptr);

		vkCmdBindPipeline(s_compute.commandBuffer[0], VK_PIPELINE_BIND_POINT_COMPUTE, s_compute.pipeline);

		vkCmdBindDescriptorSets(s_compute.commandBuffer[0], VK_PIPELINE_BIND_POINT_COMPUTE, s_compute.pipelineLayout, 0, 1, &it->first->descriptorSets[descriptionSet], 0, 0);
		vkCmdDispatch(s_compute.commandBuffer[0], it->second.size() / 16, 1, 1);

		// Add memory barrier to ensure that the compute shader has finished writing the indirect command buffer before it's consumed
		bufferBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
		bufferBarrier.dstAccessMask = VK_ACCESS_INDIRECT_COMMAND_READ_BIT;
		bufferBarrier.buffer = it->first->buffers[indirectCommand].buffer;
		bufferBarrier.size = it->first->buffers[indirectCommand].descriptor.range;
		bufferBarrier.srcQueueFamilyIndex = _compute_family_index;
		bufferBarrier.dstQueueFamilyIndex = _compute_family_index;

		vkCmdPipelineBarrier(
			s_compute.commandBuffer[0],
			VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
			VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT,
			VK_FLAGS_NONE,
			0, nullptr,
			1, &bufferBarrier,
			0, nullptr);

	}
	vkEndCommandBuffer(s_compute.commandBuffer[0]);

When the push contant was passed by uniform binding it was working great, but now i need it to be a push constant.

Do you know why it could be happening?[/QUOTE]

Can someone please tell me an advice? Do you need some more info? What ever im stuck with this

Can you add all other relevant parts? Especially the pipeline layout creation part where you define your push constant ranges.

		VkDescriptorSetLayoutCreateInfo descriptorLayout =
		descriptorSetLayoutCreateInfo(
			setLayoutBindings.data(),
			static_cast<uint32_t>(setLayoutBindings.size()));

	ErrorCheck(vkCreateDescriptorSetLayout(_device, &descriptorLayout, nullptr, &compute.descriptorSetLayout));

	VkPipelineLayoutCreateInfo pPipelineLayoutCreateInfo =
		pipelineLayoutCreateInfo(
			&compute.descriptorSetLayout,
			1);
	VkPushConstantRange _pushConstantRange =
		pushConstantRange(
			VK_SHADER_STAGE_COMPUTE_BIT,
			sizeof(computeValues),
			0);

	// Push constant ranges are part of the pipeline layout
	pPipelineLayoutCreateInfo.pushConstantRangeCount = 1;
	pPipelineLayoutCreateInfo.pPushConstantRanges = &_pushConstantRange;
	
	ErrorCheck(vkCreatePipelineLayout(_device, &pPipelineLayoutCreateInfo, nullptr, &compute.pipelineLayout));

And the push constant struct


	struct ComputeValues{
		glm::vec4 cameraPos;
		glm::vec4 frustumPlanes[6];
	} computeValues;

And here is where this values are updated, it works when i use uniforms, then they are being updated:


void Renderer::UpdateUniformBuffers(bool forced, bool breakFrustum)
{
............
	if(_camera->cameraChanged || forced)
	{
		if (!breakFrustum)
		{
			computeValues.cameraPos = glm::vec4(_camera->GetPosition(), 1);
			frustum.update(_camera->Matrices.projection * _camera->Matrices.view);
			memcpy(computeValues.frustumPlanes, frustum.planes.data(), sizeof(glm::vec4) * 6);
		}
		memcpy(_camera->uniformBuffer.mapped, &_camera->Matrices, sizeof(_camera->Matrices));
	}

Unlike uniforms, push constant values are stored in the command buffer where you call the vkCmdPushConstants, so if you want to update your (push constant) values you need to recreate/update the command buffer.

1 Like