Question about vulkan renderpass settings

I am a vulkan beginner and I am often confused by parameter settings. I have a question about the following code.

auto pipelineCreateInfo=vk::GraphicsPipelineCreateInfo{}.setRenderPass(renderpass).setSubpass(0);  // set renderpass to pipeline 
auto graphicsPipeline = device.createGraphicsPipeline(nullptr, pipelineCreateInfo);
auto renderPassBeginInfo = vk::RenderPassBeginInfo{}.setRenderPass(renderpass); // set renderpass to passbegin info
commandBuffer.beginRenderPass(renderPassBeginInfo, vk::SubpassContents::eInline);
commandBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, graphicsPipeline.value);

I have set the renderpass when creating the pipeline, and the cammandbuffer will be bound to this pipeline later, can’t vulkan directly use the renderpass bound to the pipeline? Why do I need to set renderpass again in RenderPassBeginInfo

No, the pipeline will be bound to that command buffer. There’s nothing stopping you from using two different render passes in the same command buffer. Just not with the same pipeline.

Thank you for your reply, but I don’t understand what you mean very well, could you give some simple code to explain the problem. There seems to be nothing wrong with command buffer binding different pipelines to use the corresponding renderpass in the pipeline.

My point is that a command buffer does not know what render passes are going to be used within them. That is, there is no association between a command buffer and a render pass.

Furthermore, render passes are not uniquely associated with a single pipeline. You can have multiple pipelines that use the same render pass. In fact, pipelines are not associated with a specific render pass; they’re associated with a specific subpass within a render pass. So if a render pass uses two subpasses, then by definition, you are going to have to use at least two pipelines in that render pass.

So when you say:

can’t vulkan directly use the renderpass bound to the pipeline?

The answer is no. Binding a pipeline and starting a render pass are fundamentally distinct operations.

Vulkan design generally avoids performing memoization. For example you need to keep retelling Vulkan what Layout an Image is in at every use.

Secondly, you did not “set” Render Pass. You provided it to Pipeline creation as a template. The Render Pass you provide to vkCmdBeginRenderPass can be a different ( “compatible”) object from the one you used for Pipeline creation.

1 Like

	class GraphicsPipelineCreateInfo
	{
		void setRenderPass(RenderPass renderPass)
		{
			renderPass_ = MaybeASubPassEvaluator(renderPass);
		}

		void setSubpass(uint32_t subPass)
		{
			subPass_ = subPass;
		}
	};

	auto Device::createGraphicsPipeline(GraphicsPipelineCreateInfo* info)
	{
		return new Pipeline(info);
	}

	// Possibility 1
	Pipeline::Pipeline(GraphicsPipelineCreateInfo* info)
	{
		renderPass_ = info->renderPass_;			// pipeline will hold a rendpass member, so when a commandbuffer bind a pipeline it can get the rendpass member from pipeline object.
		subPass_ = info->subPass_;
	}

	// Possibility 2
	Pipeline::Pipeline(GraphicsPipelineCreateInfo* info)
	{
		subPassInfo_ = MaybeASubPassInfoEvaluator{ info->renderPass_, info->subPass_ }.GetValue();		//pipeline will not hold a renderPass member
	}

@Alfonse_Reinheart @krOoze
Through your answers, I think what I have been confused is based on the first possibility, but the actual implement may be based on the second possibility.

I mean your pipeline abstractions can hold whatever they want.

Vulkan’s Pipeline object does not hold it though. You can do:

VkRenderPassCreateInfo rpci;
VkRenderPass rp;
vkCreateRenderPass( rpci, &rp );

VkGraphicsPipelineCreateInfo gpci;
gpci.renderpass = rp;
vkCreateGraphicsPipelines( gpci, &p );

vkDestroyRenderPass( rp ); // can safely destroy rp here

vkCreateRenderPass( rpci, &rp ); // different render pass
vkBeginCommandBuffer(cb);
    vkCmdBindPipeline(p);
    vkCmdBeginRenderPass(rp);
    // can destroy rp here, but would invalidate the command buffer
    vkCmdEndRenderPass(rp);
    // can destroy rp here, but would invalidate the command buffer
vkEndCommandBuffer(cb);

// can destroy rp here, but would invalidate the command buffer

vkQueueSubmit(q, cb);

// not allowed to destroy rp here

vkQueueWaitIdle(q);

vkDestroyRenderPass( rp ); // can safely destroy rp here

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.