Create Vulkan semaphores for swapchain synchronization
This commit is contained in:
@@ -47,6 +47,8 @@ int KRContext::KRENGINE_SYS_PAGE_SIZE;
|
||||
|
||||
#endif
|
||||
|
||||
std::mutex KRContext::g_SurfaceInfoMutex;
|
||||
std::mutex KRContext::g_DeviceInfoMutex;
|
||||
|
||||
const char *KRContext::extension_names[KRENGINE_NUM_EXTENSIONS] = {
|
||||
"GL_EXT_texture_storage"
|
||||
@@ -783,6 +785,7 @@ KRContext::createDeviceContexts()
|
||||
void
|
||||
KRContext::destroyDeviceContexts()
|
||||
{
|
||||
const std::lock_guard<std::mutex> lock(KRContext::g_DeviceInfoMutex);
|
||||
for (auto itr = m_devices.begin(); itr != m_devices.end(); itr++) {
|
||||
DeviceInfo* deviceInfo = &(*itr).second;
|
||||
vkDestroyCommandPool(deviceInfo->logicalDevice, deviceInfo->graphicsCommandPool, nullptr);
|
||||
@@ -803,6 +806,7 @@ KRContext::destroySurfaces()
|
||||
if (m_vulkanInstance == VK_NULL_HANDLE) {
|
||||
return;
|
||||
}
|
||||
const std::lock_guard<std::mutex> surfaceLock(KRContext::g_SurfaceInfoMutex);
|
||||
for (auto itr = m_surfaces.begin(); itr != m_surfaces.end(); itr++) {
|
||||
SurfaceInfo& surfaceInfo = (*itr).second;
|
||||
DeviceInfo& deviceInfo = GetDeviceInfo(surfaceInfo.deviceHandle);
|
||||
@@ -810,8 +814,9 @@ KRContext::destroySurfaces()
|
||||
vkDestroyFramebuffer(deviceInfo.logicalDevice, framebuffer, nullptr);
|
||||
}
|
||||
vkDestroySwapchainKHR(deviceInfo.logicalDevice, surfaceInfo.swapChain, nullptr);
|
||||
vkDestroySemaphore(deviceInfo.logicalDevice, surfaceInfo.renderFinishedSemaphore, nullptr);
|
||||
vkDestroySemaphore(deviceInfo.logicalDevice, surfaceInfo.imageAvailableSemaphore, nullptr);
|
||||
vkDestroySurfaceKHR(m_vulkanInstance, surfaceInfo.surface, nullptr);
|
||||
|
||||
}
|
||||
m_surfaces.clear();
|
||||
m_surfaceHandleMap.clear();
|
||||
@@ -918,13 +923,15 @@ KrResult KRContext::createWindowSurface(const KrCreateWindowSurfaceInfo* createW
|
||||
return KR_ERROR_NO_DEVICE;
|
||||
}
|
||||
|
||||
const std::lock_guard<std::mutex> surfaceLock(KRContext::g_SurfaceInfoMutex);
|
||||
const std::lock_guard<std::mutex> deviceLock(KRContext::g_DeviceInfoMutex);
|
||||
|
||||
DeviceInfo* deviceInfo = nullptr;
|
||||
|
||||
#ifdef WIN32
|
||||
HWND hWnd = static_cast<HWND>(createWindowSurfaceInfo->hWnd);
|
||||
|
||||
SurfaceInfo info{};
|
||||
info.surfaceHandle = createWindowSurfaceInfo->surfaceHandle;
|
||||
info.hWnd = hWnd;
|
||||
|
||||
VkWin32SurfaceCreateInfoKHR createInfo{};
|
||||
@@ -951,6 +958,18 @@ KrResult KRContext::createWindowSurface(const KrCreateWindowSurfaceInfo* createW
|
||||
return KR_ERROR_NO_DEVICE;
|
||||
}
|
||||
|
||||
VkSemaphoreCreateInfo semaphoreInfo{};
|
||||
semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
|
||||
if (vkCreateSemaphore(deviceInfo->logicalDevice, &semaphoreInfo, nullptr, &info.imageAvailableSemaphore) != VK_SUCCESS) {
|
||||
vkDestroySurfaceKHR(m_vulkanInstance, info.surface, nullptr);
|
||||
return KR_ERROR_VULKAN;
|
||||
}
|
||||
if (vkCreateSemaphore(deviceInfo->logicalDevice, &semaphoreInfo, nullptr, &info.renderFinishedSemaphore) != VK_SUCCESS) {
|
||||
vkDestroySemaphore(deviceInfo->logicalDevice, info.imageAvailableSemaphore, nullptr);
|
||||
vkDestroySurfaceKHR(m_vulkanInstance, info.surface, nullptr);
|
||||
return KR_ERROR_VULKAN;
|
||||
}
|
||||
|
||||
VkSurfaceCapabilitiesKHR surfaceCapabilities{};
|
||||
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(deviceInfo->device, info.surface, &surfaceCapabilities);
|
||||
|
||||
@@ -1039,6 +1058,8 @@ KrResult KRContext::createWindowSurface(const KrCreateWindowSurfaceInfo* createW
|
||||
swapChainCreateInfo.oldSwapchain = VK_NULL_HANDLE;
|
||||
|
||||
if (vkCreateSwapchainKHR(deviceInfo->logicalDevice, &swapChainCreateInfo, nullptr, &info.swapChain) != VK_SUCCESS) {
|
||||
vkDestroySemaphore(deviceInfo->logicalDevice, info.renderFinishedSemaphore, nullptr);
|
||||
vkDestroySemaphore(deviceInfo->logicalDevice, info.imageAvailableSemaphore, nullptr);
|
||||
vkDestroySurfaceKHR(m_vulkanInstance, info.surface, nullptr);
|
||||
return KR_ERROR_VULKAN_SWAP_CHAIN;
|
||||
}
|
||||
@@ -1069,6 +1090,8 @@ KrResult KRContext::createWindowSurface(const KrCreateWindowSurfaceInfo* createW
|
||||
for (size_t j = 0; j < i; j++) {
|
||||
vkDestroyImageView(deviceInfo->logicalDevice, info.swapChainImageViews[j], nullptr);
|
||||
}
|
||||
vkDestroySemaphore(deviceInfo->logicalDevice, info.renderFinishedSemaphore, nullptr);
|
||||
vkDestroySemaphore(deviceInfo->logicalDevice, info.imageAvailableSemaphore, nullptr);
|
||||
vkDestroySurfaceKHR(m_vulkanInstance, info.surface, nullptr);
|
||||
return KR_ERROR_VULKAN_SWAP_CHAIN;
|
||||
}
|
||||
@@ -1094,7 +1117,7 @@ KrResult KRContext::createWindowSurface(const KrCreateWindowSurfaceInfo* createW
|
||||
|
||||
VkFramebufferCreateInfo framebufferInfo{};
|
||||
framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
|
||||
framebufferInfo.renderPass = testPipeline->GetRenderPass();
|
||||
framebufferInfo.renderPass = testPipeline->getRenderPass();
|
||||
framebufferInfo.attachmentCount = 1;
|
||||
framebufferInfo.pAttachments = attachments;
|
||||
framebufferInfo.width = surface.swapChainExtent.width;
|
||||
@@ -1140,6 +1163,8 @@ KrResult KRContext::deleteWindowSurface(const KrDeleteWindowSurfaceInfo* deleteW
|
||||
vkDestroyImageView(deviceInfo.logicalDevice, imageView, nullptr);
|
||||
}
|
||||
vkDestroySwapchainKHR(deviceInfo.logicalDevice, surfaceInfo->swapChain, nullptr);
|
||||
vkDestroySemaphore(deviceInfo.logicalDevice, surfaceInfo->renderFinishedSemaphore, nullptr);
|
||||
vkDestroySemaphore(deviceInfo.logicalDevice, surfaceInfo->imageAvailableSemaphore, nullptr);
|
||||
vkDestroySurfaceKHR(m_vulkanInstance, surfaceInfo->surface, nullptr);
|
||||
m_surfaces.erase(itr);
|
||||
return KR_SUCCESS;
|
||||
@@ -1166,7 +1191,49 @@ void KRContext::presentationThreadFunc()
|
||||
|
||||
void KRContext::renderFrame()
|
||||
{
|
||||
// TODO - Eliminate this and use system wide index once Vulkan path is working
|
||||
static uint64_t frameIndex = 0;
|
||||
|
||||
// TODO - We should use fences to eliminate this mutex
|
||||
const std::lock_guard<std::mutex> surfaceLock(KRContext::g_SurfaceInfoMutex);
|
||||
|
||||
for (auto surfaceItr = m_surfaces.begin(); surfaceItr != m_surfaces.end(); surfaceItr++) {
|
||||
SurfaceInfo& surface = (*surfaceItr).second;
|
||||
DeviceInfo& device = GetDeviceInfo(surface.deviceHandle);
|
||||
// TODO - this will break with more than one surface... Expect to refactor this out
|
||||
VkCommandBuffer commandBuffer = device.graphicsCommandBuffers[frameIndex % device.graphicsCommandBuffers.size()];
|
||||
KRPipeline* testPipeline = m_pPipelineManager->get("simple_blit");
|
||||
|
||||
VkCommandBufferBeginInfo beginInfo{};
|
||||
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
||||
beginInfo.flags = 0;
|
||||
beginInfo.pInheritanceInfo = nullptr;
|
||||
|
||||
if (vkBeginCommandBuffer(commandBuffer, &beginInfo) != VK_SUCCESS) {
|
||||
// TODO - Add error handling...
|
||||
}
|
||||
|
||||
VkClearValue clearColor = { {{0.0f, 0.0f, 0.0f, 1.0f}} };
|
||||
|
||||
VkRenderPassBeginInfo renderPassInfo{};
|
||||
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
||||
renderPassInfo.renderPass = testPipeline->getRenderPass();
|
||||
renderPassInfo.framebuffer = surface.swapChainFramebuffers[frameIndex % surface.swapChainFramebuffers.size()];
|
||||
renderPassInfo.renderArea.offset = { 0, 0 };
|
||||
renderPassInfo.renderArea.extent = surface.swapChainExtent;
|
||||
renderPassInfo.clearValueCount = 1;
|
||||
renderPassInfo.pClearValues = &clearColor;
|
||||
|
||||
vkCmdBeginRenderPass(commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
|
||||
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, testPipeline->getPipeline());
|
||||
vkCmdDraw(commandBuffer, 3, 1, 0, 0);
|
||||
vkCmdEndRenderPass(commandBuffer);
|
||||
if (vkEndCommandBuffer(commandBuffer) != VK_SUCCESS) {
|
||||
// TODO - Add error handling...
|
||||
}
|
||||
}
|
||||
|
||||
frameIndex++;
|
||||
}
|
||||
|
||||
KRContext::SurfaceInfo& KRContext::GetSurfaceInfo(KrSurfaceHandle handle)
|
||||
@@ -1185,6 +1252,7 @@ KRContext::DeviceInfo& KRContext::GetDeviceInfo(KrDeviceHandle handle)
|
||||
|
||||
void KRContext::createDevices()
|
||||
{
|
||||
const std::lock_guard<std::mutex> deviceLock(KRContext::g_DeviceInfoMutex);
|
||||
if (m_devices.size() > 0) {
|
||||
return;
|
||||
}
|
||||
@@ -1355,6 +1423,8 @@ void KRContext::createDevices()
|
||||
allocInfo.commandPool = info.computeCommandPool;
|
||||
allocInfo.commandBufferCount = (uint32_t)info.computeCommandBuffers.size();
|
||||
if (vkAllocateCommandBuffers(info.logicalDevice, &allocInfo, info.computeCommandBuffers.data()) != VK_SUCCESS) {
|
||||
// Note - this repeated cleanup will likely be eliminated with later refactoring to split vulkan
|
||||
// object generation out of KRContext
|
||||
vkDestroyCommandPool(info.logicalDevice, info.computeCommandPool, nullptr);
|
||||
vkDestroyCommandPool(info.logicalDevice, info.graphicsCommandPool, nullptr);
|
||||
vkDestroyDevice(info.logicalDevice, nullptr);
|
||||
|
||||
Reference in New Issue
Block a user