Create Vulkan semaphores for swapchain synchronization

This commit is contained in:
2021-08-12 22:40:40 -07:00
parent 0285e734bc
commit 1114210039
4 changed files with 86 additions and 7 deletions

View File

@@ -47,6 +47,8 @@ int KRContext::KRENGINE_SYS_PAGE_SIZE;
#endif #endif
std::mutex KRContext::g_SurfaceInfoMutex;
std::mutex KRContext::g_DeviceInfoMutex;
const char *KRContext::extension_names[KRENGINE_NUM_EXTENSIONS] = { const char *KRContext::extension_names[KRENGINE_NUM_EXTENSIONS] = {
"GL_EXT_texture_storage" "GL_EXT_texture_storage"
@@ -783,6 +785,7 @@ KRContext::createDeviceContexts()
void void
KRContext::destroyDeviceContexts() KRContext::destroyDeviceContexts()
{ {
const std::lock_guard<std::mutex> lock(KRContext::g_DeviceInfoMutex);
for (auto itr = m_devices.begin(); itr != m_devices.end(); itr++) { for (auto itr = m_devices.begin(); itr != m_devices.end(); itr++) {
DeviceInfo* deviceInfo = &(*itr).second; DeviceInfo* deviceInfo = &(*itr).second;
vkDestroyCommandPool(deviceInfo->logicalDevice, deviceInfo->graphicsCommandPool, nullptr); vkDestroyCommandPool(deviceInfo->logicalDevice, deviceInfo->graphicsCommandPool, nullptr);
@@ -803,6 +806,7 @@ KRContext::destroySurfaces()
if (m_vulkanInstance == VK_NULL_HANDLE) { if (m_vulkanInstance == VK_NULL_HANDLE) {
return; return;
} }
const std::lock_guard<std::mutex> surfaceLock(KRContext::g_SurfaceInfoMutex);
for (auto itr = m_surfaces.begin(); itr != m_surfaces.end(); itr++) { for (auto itr = m_surfaces.begin(); itr != m_surfaces.end(); itr++) {
SurfaceInfo& surfaceInfo = (*itr).second; SurfaceInfo& surfaceInfo = (*itr).second;
DeviceInfo& deviceInfo = GetDeviceInfo(surfaceInfo.deviceHandle); DeviceInfo& deviceInfo = GetDeviceInfo(surfaceInfo.deviceHandle);
@@ -810,8 +814,9 @@ KRContext::destroySurfaces()
vkDestroyFramebuffer(deviceInfo.logicalDevice, framebuffer, nullptr); vkDestroyFramebuffer(deviceInfo.logicalDevice, framebuffer, nullptr);
} }
vkDestroySwapchainKHR(deviceInfo.logicalDevice, surfaceInfo.swapChain, 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); vkDestroySurfaceKHR(m_vulkanInstance, surfaceInfo.surface, nullptr);
} }
m_surfaces.clear(); m_surfaces.clear();
m_surfaceHandleMap.clear(); m_surfaceHandleMap.clear();
@@ -918,13 +923,15 @@ KrResult KRContext::createWindowSurface(const KrCreateWindowSurfaceInfo* createW
return KR_ERROR_NO_DEVICE; 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; DeviceInfo* deviceInfo = nullptr;
#ifdef WIN32 #ifdef WIN32
HWND hWnd = static_cast<HWND>(createWindowSurfaceInfo->hWnd); HWND hWnd = static_cast<HWND>(createWindowSurfaceInfo->hWnd);
SurfaceInfo info{}; SurfaceInfo info{};
info.surfaceHandle = createWindowSurfaceInfo->surfaceHandle;
info.hWnd = hWnd; info.hWnd = hWnd;
VkWin32SurfaceCreateInfoKHR createInfo{}; VkWin32SurfaceCreateInfoKHR createInfo{};
@@ -951,6 +958,18 @@ KrResult KRContext::createWindowSurface(const KrCreateWindowSurfaceInfo* createW
return KR_ERROR_NO_DEVICE; 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{}; VkSurfaceCapabilitiesKHR surfaceCapabilities{};
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(deviceInfo->device, info.surface, &surfaceCapabilities); vkGetPhysicalDeviceSurfaceCapabilitiesKHR(deviceInfo->device, info.surface, &surfaceCapabilities);
@@ -1039,6 +1058,8 @@ KrResult KRContext::createWindowSurface(const KrCreateWindowSurfaceInfo* createW
swapChainCreateInfo.oldSwapchain = VK_NULL_HANDLE; swapChainCreateInfo.oldSwapchain = VK_NULL_HANDLE;
if (vkCreateSwapchainKHR(deviceInfo->logicalDevice, &swapChainCreateInfo, nullptr, &info.swapChain) != VK_SUCCESS) { 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); vkDestroySurfaceKHR(m_vulkanInstance, info.surface, nullptr);
return KR_ERROR_VULKAN_SWAP_CHAIN; return KR_ERROR_VULKAN_SWAP_CHAIN;
} }
@@ -1069,6 +1090,8 @@ KrResult KRContext::createWindowSurface(const KrCreateWindowSurfaceInfo* createW
for (size_t j = 0; j < i; j++) { for (size_t j = 0; j < i; j++) {
vkDestroyImageView(deviceInfo->logicalDevice, info.swapChainImageViews[j], nullptr); 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); vkDestroySurfaceKHR(m_vulkanInstance, info.surface, nullptr);
return KR_ERROR_VULKAN_SWAP_CHAIN; return KR_ERROR_VULKAN_SWAP_CHAIN;
} }
@@ -1094,7 +1117,7 @@ KrResult KRContext::createWindowSurface(const KrCreateWindowSurfaceInfo* createW
VkFramebufferCreateInfo framebufferInfo{}; VkFramebufferCreateInfo framebufferInfo{};
framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
framebufferInfo.renderPass = testPipeline->GetRenderPass(); framebufferInfo.renderPass = testPipeline->getRenderPass();
framebufferInfo.attachmentCount = 1; framebufferInfo.attachmentCount = 1;
framebufferInfo.pAttachments = attachments; framebufferInfo.pAttachments = attachments;
framebufferInfo.width = surface.swapChainExtent.width; framebufferInfo.width = surface.swapChainExtent.width;
@@ -1140,6 +1163,8 @@ KrResult KRContext::deleteWindowSurface(const KrDeleteWindowSurfaceInfo* deleteW
vkDestroyImageView(deviceInfo.logicalDevice, imageView, nullptr); vkDestroyImageView(deviceInfo.logicalDevice, imageView, nullptr);
} }
vkDestroySwapchainKHR(deviceInfo.logicalDevice, surfaceInfo->swapChain, 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); vkDestroySurfaceKHR(m_vulkanInstance, surfaceInfo->surface, nullptr);
m_surfaces.erase(itr); m_surfaces.erase(itr);
return KR_SUCCESS; return KR_SUCCESS;
@@ -1166,7 +1191,49 @@ void KRContext::presentationThreadFunc()
void KRContext::renderFrame() 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) KRContext::SurfaceInfo& KRContext::GetSurfaceInfo(KrSurfaceHandle handle)
@@ -1185,6 +1252,7 @@ KRContext::DeviceInfo& KRContext::GetDeviceInfo(KrDeviceHandle handle)
void KRContext::createDevices() void KRContext::createDevices()
{ {
const std::lock_guard<std::mutex> deviceLock(KRContext::g_DeviceInfoMutex);
if (m_devices.size() > 0) { if (m_devices.size() > 0) {
return; return;
} }
@@ -1355,6 +1423,8 @@ void KRContext::createDevices()
allocInfo.commandPool = info.computeCommandPool; allocInfo.commandPool = info.computeCommandPool;
allocInfo.commandBufferCount = (uint32_t)info.computeCommandBuffers.size(); allocInfo.commandBufferCount = (uint32_t)info.computeCommandBuffers.size();
if (vkAllocateCommandBuffers(info.logicalDevice, &allocInfo, info.computeCommandBuffers.data()) != VK_SUCCESS) { 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.computeCommandPool, nullptr);
vkDestroyCommandPool(info.logicalDevice, info.graphicsCommandPool, nullptr); vkDestroyCommandPool(info.logicalDevice, info.graphicsCommandPool, nullptr);
vkDestroyDevice(info.logicalDevice, nullptr); vkDestroyDevice(info.logicalDevice, nullptr);

View File

@@ -128,7 +128,6 @@ public:
static void activateStreamerContext(); static void activateStreamerContext();
static void activateRenderContext(); static void activateRenderContext();
typedef struct { typedef struct {
VkPhysicalDevice device; VkPhysicalDevice device;
@@ -146,7 +145,6 @@ public:
} DeviceInfo; } DeviceInfo;
typedef struct { typedef struct {
KrSurfaceHandle surfaceHandle;
KrDeviceHandle deviceHandle; KrDeviceHandle deviceHandle;
VkSurfaceKHR surface; VkSurfaceKHR surface;
VkSwapchainKHR swapChain; VkSwapchainKHR swapChain;
@@ -155,11 +153,16 @@ public:
VkExtent2D swapChainExtent; VkExtent2D swapChainExtent;
std::vector<VkImageView> swapChainImageViews; std::vector<VkImageView> swapChainImageViews;
std::vector<VkFramebuffer> swapChainFramebuffers; std::vector<VkFramebuffer> swapChainFramebuffers;
VkSemaphore imageAvailableSemaphore;
VkSemaphore renderFinishedSemaphore;
#ifdef WIN32 #ifdef WIN32
HWND hWnd; HWND hWnd;
#endif #endif
} SurfaceInfo; } SurfaceInfo;
static std::mutex g_SurfaceInfoMutex;
static std::mutex g_DeviceInfoMutex;
DeviceInfo& GetDeviceInfo(KrDeviceHandle handle); DeviceInfo& GetDeviceInfo(KrDeviceHandle handle);
SurfaceInfo& GetSurfaceInfo(KrSurfaceHandle handle); SurfaceInfo& GetSurfaceInfo(KrSurfaceHandle handle);

View File

@@ -764,7 +764,12 @@ const char *KRPipeline::getKey() const {
return m_szKey; return m_szKey;
} }
VkRenderPass& KRPipeline::GetRenderPass() VkRenderPass& KRPipeline::getRenderPass()
{ {
return m_renderPass; return m_renderPass;
}
VkPipeline& KRPipeline::getPipeline()
{
return m_graphicsPipeline;
} }

View File

@@ -145,7 +145,8 @@ public:
void setUniform(int location, const Vector4 &value); void setUniform(int location, const Vector4 &value);
void setUniform(int location, const Matrix4 &value); void setUniform(int location, const Matrix4 &value);
VkRenderPass& GetRenderPass(); VkRenderPass& getRenderPass();
VkPipeline& getPipeline();
private: private:
GLuint m_iProgram; GLuint m_iProgram;