Sanity question about primary and secondary command buffers

Hi everyone. I think I’ve got the basics down on creating a Vulkan renderer, and I have a sanity question regarding my intended usage. I require dynamic scissors/viewports and intend to structure the rendering commands like this:

  • I have a primary command buffer (x number_frames)
    • I have a render pass
      • I have a few secondary command buffers (x number frames) which are logic dependant, and have unique scissor regions. Eg. background, HUD, GUI.
      • the render pass can only execute secondary command buffers

This seems to work nicely. Is this design sane?

I’ve also noticed that I have to maintain a copy of vk::CommandBufferInheritanceInfo in vk::CommandBufferBeginInfo::pInheritanceInfo. ie. I cannot use a local / stack version of the info structure. One thing that I find inconsistent with Vulkan is that some API calls are immediate and can use a stack local version of an Info structure, while others use the data at a later time, hence I need to preserve a copy when passing the structure. Is there a way (without trial and error) to know when to reserve memory for an Info structure, and when a local stack version is fine? The driver will either copy the passed structure or use a pointer, and I dont know which will happen without testing (on 2 different OS’s and video cards to detect memory trampoline issues)

Why not? What happens if you do?

This is untrue. From the specification:

The ownership of application-owned memory is immediately acquired by any Vulkan command it is passed into. Ownership of such memory must be released back to the application at the end of the duration of the command, so that the application can alter or free this memory as soon as all the commands that acquired it have returned.

So, unless otherwise stated, the implementation will finish with all application owned memory by the time a function returns control to you, except where otherwise specified.

Why not? What happens if you do?

void SomeFunction()
{
   vk::CommandBufferInheritanceInfo  **inheritancy_info**(...);
   vk::CommandBufferBeginInfo  command_buffer_info(..., **&**inheritance_info);   
   secondary_buffer.begin(begin_info);
   ...
   secondary_buffer.end();
   command_buffer.exectuteCommands(secondary_buffer); // will crash here since **inheritence_info** may have left function scope.
}

If on the other hand I store inheritence_info somewhere, everything is fine. The memory is still in scope (eg. class member, heap, global variable anything not in local function scope). This is what I’m observing (that when calling queue submit, the memory must still be valid), but since I’m new to Vulkan I may have wrong interpretation, thats why I’m asking around. This isn’t the first function I’ve run into with this issue, the learn vulkan tutorials also has a few info structures as class members to ensure the struct memory still exists when referenced much later.

It seems far more likely that the reason it’s crashing is somewhere inside your C++ wrapper of Vulkan.

Uninitialized variables or bad memory can behave this way. If you comment or reorder random stuff it sometimes works.

Get a VK_LAYER_LUNARG_api_dump. We will see what is Vulkan actually getting and we can proceed from there.