Multi-subpasses rendering failed on second subpass

I was testing out multi-subpasses functionality of vulkan.I follwed SaschaWillems’s example here:

But after I added this command to my command buffer:

vkCmdDraw(graphics_command_buffers[i], 3, 1, 0, 0);

vkQueueSubmit function returns VK_SUCCESS in the first time it runs,yet returns VK_ERROR_DEVICE_LOST in the second time it runs.
If I only remove the statement:

vkCmdDraw(graphics_command_buffers[i], 3, 1, 0, 0);

my application would run successfully.Here’s the link of my code:

And basic skeleton(contained in App.cpp):

#include "App.h"

void App::Init()
{


	//global initialization
	window.Init();

	VkInitializer::CreateInstance(instance, validation_manager);

	VkValidationManager::SetupDebugMessenger(instance, validation_manager);

	VkInitializer::CreateSurface(instance, window);

	VkInitializer::PickPhysicalDevice(instance, window.GetSurface(), device_manager.GetPhysicalDeviceRef());

	device_manager.CreateLogicalDeviceAndQueues(window.GetSurface());

	swap_chain_manager.CreateSwapChainAndSwapImages(device_manager.GetPhysicalDeviceRef(), device_manager.GetLogicalDeviceRef(), window.GetSurface(), window);





}

void App::RendererSetUp()
{


	//renderer sets some references
	renderer.SetDeviceManager(device_manager);

	renderer.SetSwapChinManager(swap_chain_manager);

	renderer.SetWindow(window);

	renderer.SetGraphicsCommandPool(
		device_manager.CreateCommandPool(VkDeviceManager::CommandPoolType::graphics_command_pool, window.GetSurface())
	);
	renderer.SetTransforCommandPool(
		device_manager.CreateCommandPool(VkDeviceManager::CommandPoolType::transfor_command_pool, window.GetSurface())
	);



}

void App::RenderingPreparation()
{



	//prepare Images
	renderer.CreateAttachmentImages();
	renderer.CreateTextureImages();
	renderer.CreateDepthImages();
	//prepare Renderpass
	renderer.CreateRenderPass();
	//prepare Buffers
	renderer.CreateUniformBuffer();
	renderer.CreateFramebuffers();
	//prepare Descriptor Sets
	renderer.CreateDescriptorSetLayout();
	renderer.CreateDescriptorPool();
	renderer.CreateDescriptorSets();
	//prepare Pipline
	renderer.CreateGraphicsPiplineLayout();
	renderer.CreateGraphicsPipline();
	//prepare command buffer
	renderer.InitCommandBuffers();
	//prepare Models
	renderer.PrepareModels();
	//command buffer recording
	renderer.CommandBufferRecording();
	//prepare sync objects
	renderer.InitSynObjects();

	


}

void App::MainLoop()
{

	while (!glfwWindowShouldClose(window.GetWindowPtr())) {
		glfwPollEvents();
		renderer.DrawFrame();
	}

	vkDeviceWaitIdle(device_manager.GetLogicalDeviceRef());



}

void App::CleanUp()
{

	renderer.CleanUpSyncObjects();
	//clean up modles index buffer ,vertex buffer etc.
	renderer.CleanUpModels();
	renderer.CleanUpPiplineAndPiplineLayout();
	renderer.CleanUpRenderPass();
	renderer.CleanUpDescriptorSetLayoutAndDescriptorPool();
	renderer.CleanUpCommandBuffersAndCommandPool();
	renderer.CleanupFrameBuffers();
 //	clean up uniformBuffers;
	renderer.CleanUpImages();
	swap_chain_manager.CleanUp(device_manager.GetLogicalDeviceRef());
	device_manager.CleanUp();
	window.CleanUp(instance);
	validation_manager.CleanUp(instance);
	DestroyInstance();


}

void App::DestroyInstance()
{
	vkDestroyInstance(instance, nullptr);
}






void App::Run()
{

	Init();
	RendererSetUp();
	RenderingPreparation();
	MainLoop();
	CleanUp();

}

And I put my exe into RenderDoc,it doesn’t even show my second subpass!

You seem to be using input attachments, but your dependency is with VK_ACCESS_SHADER_READ_BIT, not VK_ACCESS_INPUT_ATTACHMENT_READ_BIT. Additionally you seem to be using depth too as input, but I don’t see VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT anywhere.

Make sure validation layers work, and you have sync checking subfeature enabled.

Additionally, I need to say Vulkan is not suitable API for trial-and-error playing. In Vulkan you should always be reasonably sure your code is correct before you even run it or use debugging tools. With Vulkan you need to get in the mindset that you need to understand all of your own code, not just throw stuff at the driver until it “accepts” something.

vkCmdDraw is an action command. I.e. only thing in the command buffer that actually “does” something. It is not surprising adding it can expose problem. Without any action command, the command buffer is basically no-op.

1 Like

I’ve used Vulkan Configuration to find more debug info,but Validation layer didn’t give too much info about it.


Turns out that I made a very simple error when I was creating VkDescriptorSetLayoutBinding.I noticed in RenderDoc my second subpass didn’t have any uniform buffer input.So I re-checked my descriptor setup process,and I used a vector of size 3,but I only needs two uniform input and I didn’t initialize the second element of my VkDescriptorSetLayoutBinding vector.