Created
July 19, 2024 14:01
-
-
Save romualdo97/b9deeb1735d9f4fc726c23d956bbf83a to your computer and use it in GitHub Desktop.
Snippet from Vulkan and Unreal VulkanRHI studies outlining a command buffer that clears an image and is submitted into GPU for processing then the result is presented, this will become more abstract as we advance in the RHI API studies, here we see the plain Vulkan API
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void FVulkanDynamicRHI::DoExperimentsSetup() | |
{ | |
// Create a swap chain and its surface | |
std::vector<VkImage> Images; | |
const FVulkanSwapChain SwapChain{Instance, *Device, GetWindowHandle(), 300, 300, Images}; | |
// Create a command memory pool | |
const VkCommandPoolCreateInfo CommandPoolCreateInfo | |
{ | |
VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, | |
nullptr, | |
0, | |
Device->PresentQueue->GetFamilyIndex() | |
}; | |
VkCommandPool CommandPool; | |
if (VulkanRHI::vkCreateCommandPool(Device->GetInstanceHandle(), &CommandPoolCreateInfo, nullptr, &CommandPool) != VK_SUCCESS) | |
{ | |
std::cerr << "Failed to create a command pool" << std::endl; | |
return; | |
} | |
// Allocate a command buffer for each image | |
const VkCommandBufferAllocateInfo CommandBufferAllocateInfo | |
{ | |
VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, | |
nullptr, | |
CommandPool, | |
VK_COMMAND_BUFFER_LEVEL_PRIMARY, | |
static_cast<uint32_t>(Images.size()) | |
}; | |
std::vector<VkCommandBuffer> CommandBuffers{ Images.size() }; | |
VulkanRHI::vkAllocateCommandBuffers(Device->GetInstanceHandle(), &CommandBufferAllocateInfo, CommandBuffers.data()); | |
for (uint32_t Index = 0; Index < CommandBuffers.size(); ++Index) | |
{ | |
// Cmd: Begin recording | |
constexpr VkCommandBufferBeginInfo CommandBufferBeginInfo | |
{ | |
VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, | |
nullptr, | |
VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT, | |
nullptr | |
}; | |
VulkanRHI::vkBeginCommandBuffer(CommandBuffers[Index], &CommandBufferBeginInfo); | |
// Cmd: Transition image layout from presentation to transfer | |
constexpr VkImageSubresourceRange ImageSubresourceRange | |
{ | |
VK_IMAGE_ASPECT_COLOR_BIT, | |
0, 1, | |
0, 1 | |
}; | |
const VkImageMemoryBarrier BarrierFromPresentToClear | |
{ | |
VK_STRUCTURE_TYPE_MEMORY_BARRIER, | |
nullptr, | |
VK_ACCESS_MEMORY_READ_BIT, | |
VK_ACCESS_MEMORY_WRITE_BIT, | |
VK_IMAGE_LAYOUT_UNDEFINED, | |
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, | |
Device->GetPresentQueue()->GetFamilyIndex(), | |
Device->GetPresentQueue()->GetFamilyIndex(), | |
Images[Index], | |
ImageSubresourceRange | |
}; | |
VulkanRHI::vkCmdPipelineBarrier( | |
CommandBuffers[Index], | |
VK_PIPELINE_STAGE_TRANSFER_BIT, | |
VK_PIPELINE_STAGE_TRANSFER_BIT, | |
0, | |
0, | |
nullptr, | |
0, | |
nullptr, | |
1, | |
&BarrierFromPresentToClear); | |
// Cmd: Clear color | |
VkClearColorValue ClearColorValue = { { 1.0f, 0.67f, 0.5f, 0.0f } }; | |
VulkanRHI::vkCmdClearColorImage(CommandBuffers[Index], Images[Index], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &ClearColorValue, 1, &ImageSubresourceRange); | |
// Cmd: Transition image layout from transfer to presentation | |
const VkImageMemoryBarrier BarrierFromClearToPresent | |
{ | |
VK_STRUCTURE_TYPE_MEMORY_BARRIER, | |
nullptr, | |
VK_ACCESS_MEMORY_WRITE_BIT, | |
VK_ACCESS_MEMORY_READ_BIT, | |
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, | |
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, | |
Device->GetPresentQueue()->GetFamilyIndex(), | |
Device->GetPresentQueue()->GetFamilyIndex(), | |
Images[Index], | |
ImageSubresourceRange | |
}; | |
VulkanRHI::vkCmdPipelineBarrier( | |
CommandBuffers[Index], | |
VK_PIPELINE_STAGE_TRANSFER_BIT, | |
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, | |
0, | |
0, | |
nullptr, | |
0, | |
nullptr, | |
1, | |
&BarrierFromClearToPresent); | |
// Cmd: End recording | |
if (VulkanRHI::vkEndCommandBuffer(CommandBuffers[Index]) != VK_SUCCESS) { | |
std::cerr << "Could not record command buffers!" << std::endl; | |
return; | |
} | |
} | |
// Create a semaphore to signal when rendering is finished (Rendering means the commands in the command buffer above) | |
constexpr VkSemaphoreCreateInfo SemaphoreCreateInfo | |
{ | |
VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, | |
nullptr, | |
VK_FENCE_CREATE_FLAG_BITS_MAX_ENUM | |
}; | |
VkSemaphore RenderingFinishedSemaphore; | |
VulkanRHI::vkCreateSemaphore(Device->GetInstanceHandle(), &SemaphoreCreateInfo, nullptr, &RenderingFinishedSemaphore); | |
// Create a semaphore to signal when an image is available to be acquired from the presentation engine | |
VkSemaphore ImageAvailableSemaphore; | |
VulkanRHI::vkCreateSemaphore(Device->GetInstanceHandle(), &SemaphoreCreateInfo, nullptr, &ImageAvailableSemaphore); | |
// Setup experiments globals | |
GExperimentsData.CommandPool = CommandPool; | |
GExperimentsData.CommandBuffers = CommandBuffers; | |
GExperimentsData.RenderingFinishedSemaphore = RenderingFinishedSemaphore; | |
GExperimentsData.ImageAvailableSemaphore = ImageAvailableSemaphore; | |
GExperimentsData.SwapChain = SwapChain.GetInstanceHandle(); | |
} | |
void FVulkanDynamicRHI::DoExperimentsTick() | |
{ | |
// Acquire an image from the presentation engine | |
uint32_t AcquiredImageIndex; | |
VulkanRHI::vkAcquireNextImageKHR( | |
Device->GetInstanceHandle(), | |
GExperimentsData.SwapChain, | |
UINT64_MAX, | |
GExperimentsData.ImageAvailableSemaphore, // Signaled when an image is available | |
VK_NULL_HANDLE, | |
&AcquiredImageIndex); | |
// Submit a CommandBuffer after ImageAvailableSemaphore is signaled | |
VkPipelineStageFlags WaitDstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT; | |
const VkSubmitInfo SubmitInfo | |
{ | |
VK_STRUCTURE_TYPE_SUBMIT_INFO, | |
nullptr, | |
1, &GExperimentsData.ImageAvailableSemaphore, // Wait for semaphore signaled | |
&WaitDstStageMask, | |
1, &GExperimentsData.CommandBuffers[AcquiredImageIndex], | |
1, &GExperimentsData.RenderingFinishedSemaphore // Signal semaphore | |
}; | |
VulkanRHI::vkQueueSubmit(Device->PresentQueue->GetHandle(), 1, &SubmitInfo, VK_NULL_HANDLE); | |
VkResult Results; | |
const VkPresentInfoKHR PresentInfo | |
{ | |
VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, | |
nullptr, | |
1, &GExperimentsData.RenderingFinishedSemaphore, | |
1, &GExperimentsData.SwapChain, | |
&AcquiredImageIndex, &Results | |
}; | |
VulkanRHI::vkQueuePresentKHR(Device->GetPresentQueue()->GetHandle(), &PresentInfo); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment