Jump to content
  • Advertisement
Sign in to follow this  
simpler

Vulkan Generating command buffers each frame issue

This topic is 906 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Up until now I have only generated my command buffers once during initializtion. Now that I want to render several objects with different positions I see no other choice but to generate the command buffers each frame (please  correct me if I'm wrong) so that I can change the matrices in the shader using push constants.

 

But when I call my function that builds a command buffer each frame in my draw function the framerate rapidly drops with ~100fps EVERY second. Even when I remove most of the code and only keep vkBeginCommandBuffer() and vkCmdBeginRenderPass() the same thing happens with my framerate.

 

Here's how the RecordRenderingCommandBuffer() function looks:

void VulkanApp::RecordRenderingCommandBuffer()
{
	VkCommandBufferBeginInfo beginInfo = {};
	beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;

	VkClearValue clearValues[2];
	clearValues[0].color = { 1.0f, 0.8f, 0.4f, 0.0f };
	clearValues[1].depthStencil = { 1.0f, 0 };

	VkRenderPassBeginInfo renderPassBeginInfo = {};
	renderPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
	renderPassBeginInfo.renderPass = renderPass;
	renderPassBeginInfo.renderArea.extent.width = windowWidth;
	renderPassBeginInfo.renderArea.extent.height = windowHeight;
	renderPassBeginInfo.clearValueCount = 2;
	renderPassBeginInfo.pClearValues = clearValues;

	for (int i = 0; i < renderingCommandBuffers.size(); i++)
	{
		// Set target frame buffer
		renderPassBeginInfo.framebuffer = frameBuffers[i];

		// Begin command buffer recording & the render pass
		VulkanDebug::ErrorCheck(vkBeginCommandBuffer(renderingCommandBuffers[i], &beginInfo));
		vkCmdBeginRenderPass(renderingCommandBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);

                // End command buffer recording & the render pass
		vkCmdEndRenderPass(renderingCommandBuffers[i]);
		VulkanDebug::ErrorCheck(vkEndCommandBuffer(renderingCommandBuffers[i]));
	}	
}

And here's the Draw() function:

void VulkanApp::Draw()
{
	// Acquire the next image in the swap chain
	VulkanDebug::ErrorCheck(swapChain.acquireNextImage(presentComplete, &currentBuffer));
	
	SubmitPrePresentMemoryBarrier(swapChain.buffers[currentBuffer].image);

	// NOTE: Gets called every frame now!
	RecordRenderingCommandBuffer();

	// Submit the recorded draw command buffer to the queue
	VkSubmitInfo submitInfo = {};
	submitInfo.sType		= VK_STRUCTURE_TYPE_SUBMIT_INFO;
	submitInfo.commandBufferCount	= 1;
	submitInfo.pCommandBuffers	= &renderingCommandBuffers[currentBuffer];		// Draw commands for the current command buffer
	submitInfo.waitSemaphoreCount	= 1;
	submitInfo.signalSemaphoreCount = 1;
	submitInfo.pWaitSemaphores	= &presentComplete;					// Waits for swapChain.acquireNextImage to complete
	submitInfo.pSignalSemaphores	= &renderComplete;					// swapChain.queuePresent will wait for this submit to complete
	VkPipelineStageFlags stageFlags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
	submitInfo.pWaitDstStageMask	= &stageFlags;

	VulkanDebug::ErrorCheck(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE));

	SubmitPostPresentMemoryBarrier(swapChain.buffers[currentBuffer].image);

	// Present the image
	VulkanDebug::ErrorCheck(swapChain.queuePresent(queue, currentBuffer, renderComplete));
}

I must be doing something really wrong to make the framerate decrease so fast over time. 

 

Thanks for your time!

Share this post


Link to post
Share on other sites
Advertisement

Okey so the cause for the framerate dropping so fast over time had to do with the enabled validation layers. I created the VkInstance and VkDevice with the validation layer "VK_LAYER_LUNARG_standard_validation" and when I removed it the framerate issue disappeared.

 

I hope this can be helpful if someone runs into the same problem.

Share this post


Link to post
Share on other sites

Why are you using pushconstants for the matrices directly, if you intend to change them?

 

Alternative is to use UNIFORM_BUFFER_OFFSET for example

or use a pushconstant that encodes a matrix index, and then have all matrices stored in a TBO.

 

that way you can update the buffer content just fine without re-creating command-buffers.

https://github.com/nvpro-samples/gl_vk_threaded_cadscene makes use of various approaches

Share this post


Link to post
Share on other sites

I don't think there's an alternative to recording command lists per frame. Ideally, you want to use pre-recorded ones as much as possible, but too much stuff changes per frame in a real-world app to avoid recording some stuff on the fly.

The only time I saw a similar accumulating frame-rate drop was when my memory manager was leaking like crazy. I'd look into whether you are leaking anything.

Also, from what you've posted, it looks like you're re-recording ALL your command lists every frame. Surely you only want to be recording one command list per frame  as the others might still be being consumed by the GPU.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!