• 9
• 10
• 9
• 10
• 10
• Similar Content

• By khawk
LunarG has released new Vulkan SDKs for Windows, Linux, and macOS based on the 1.1.73 header. The new SDK includes:

View full story
• By khawk
LunarG has released new Vulkan SDKs for Windows, Linux, and macOS based on the 1.1.73 header. The new SDK includes:

• I have a pretty good experience with multi gpu programming in D3D12. Now looking at Vulkan, although there are a few similarities, I cannot wrap my head around a few things due to the extremely sparse documentation (typical Khronos...)
In D3D12 -> You create a resource on GPU0 that is visible to GPU1 by setting the VisibleNodeMask to (00000011 where last two bits set means its visible to GPU0 and GPU1)
In Vulkan - I can see there is the VkBindImageMemoryDeviceGroupInfoKHR struct which you add to the pNext chain of VkBindImageMemoryInfoKHR and then call vkBindImageMemory2KHR. You also set the device indices which I assume is the same as the VisibleNodeMask except instead of a mask it is an array of indices. Till now it's fine.
Let's look at a typical SFR scenario:  Render left eye using GPU0 and right eye using GPU1
You have two textures. pTextureLeft is exclusive to GPU0 and pTextureRight is created on GPU1 but is visible to GPU0 so it can be sampled from GPU0 when we want to draw it to the swapchain. This is in the D3D12 world. How do I map this in Vulkan? Do I just set the device indices for pTextureRight as { 0, 1 }
Now comes the command buffer submission part that is even more confusing.
There is the struct VkDeviceGroupCommandBufferBeginInfoKHR. It accepts a device mask which I understand is similar to creating a command list with a certain NodeMask in D3D12.
So for GPU1 -> Since I am only rendering to the pTextureRight, I need to set the device mask as 2? (00000010)
For GPU0 -> Since I only render to pTextureLeft and finally sample pTextureLeft and pTextureRight to render to the swap chain, I need to set the device mask as 1? (00000001)
The same applies to VkDeviceGroupSubmitInfoKHR?
Now the fun part is it does not work  . Both command buffers render to the textures correctly. I verified this by reading back the textures and storing as png. The left texture is sampled correctly in the final composite pass. But I get a black in the area where the right texture should appear. Is there something that I am missing in this? Here is a code snippet too
void Init() { RenderTargetInfo info = {}; info.pDeviceIndices = { 0, 0 }; CreateRenderTarget(&info, &pTextureLeft); // Need to share this on both GPUs info.pDeviceIndices = { 0, 1 }; CreateRenderTarget(&info, &pTextureRight); } void DrawEye(CommandBuffer* pCmd, uint32_t eye) { // Do the draw // Begin with device mask depending on eye pCmd->Open((1 << eye)); // If eye is 0, we need to do some extra work to composite pTextureRight and pTextureLeft if (eye == 0) { DrawTexture(0, 0, width * 0.5, height, pTextureLeft); DrawTexture(width * 0.5, 0, width * 0.5, height, pTextureRight); } // Submit to the correct GPU pQueue->Submit(pCmd, (1 << eye)); } void Draw() { DrawEye(pRightCmd, 1); DrawEye(pLeftCmd, 0); }

• Hi,
I finally managed to get the DX11 emulating Vulkan device working but everything is flipped vertically now because Vulkan has a different clipping space. What are the best practices out there to keep these implementation consistent? I tried using a vertically flipped viewport, and while it works on Nvidia 1050, the Vulkan debug layer is throwing error messages that this is not supported in the spec so it might not work on others. There is also the possibility to flip the clip scpace position Y coordinate before writing out with vertex shader, but that requires changing and recompiling every shader. I could also bake it into the camera projection matrices, though I want to avoid that because then I need to track down for the whole engine where I upload matrices... Any chance of an easy extension or something? If not, I will probably go with changing the vertex shaders.

• I publishing for manufacturing our ray tracing engines and products on graphics API (C++, Vulkan API, GLSL460, SPIR-V): https://github.com/world8th/satellite-oem
For end users I have no more products or test products. Also, have one simple gltf viewer example (only source code).
In 2016 year had idea for replacement of screen space reflections, but in 2018 we resolved to finally re-profile project as "basis of render engine". In Q3 of 2017 year finally merged to Vulkan API.

Vulkan Generating command buffers each frame issue

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

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;

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.

Share on other sites

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 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.

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.