Generating command buffers each frame issue

Started by
2 comments, last by C0lumbo 8 years ago

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!

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.

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

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.

This topic is closed to new replies.

Advertisement