diff --git a/kraken/KRContext.cpp b/kraken/KRContext.cpp index 58d7b75..dc1d8c0 100755 --- a/kraken/KRContext.cpp +++ b/kraken/KRContext.cpp @@ -819,21 +819,7 @@ KRContext::destroyDeviceContexts() void KRContext::destroySurfaces() { - if (m_vulkanInstance == VK_NULL_HANDLE) { - return; - } const std::lock_guard surfaceLock(KRContext::g_SurfaceInfoMutex); - for (auto itr = m_surfaces.begin(); itr != m_surfaces.end(); itr++) { - KRSurface& surfaceInfo = (*itr).second; - KRDevice& deviceInfo = GetDeviceInfo(surfaceInfo.deviceHandle); - for (auto framebuffer : surfaceInfo.swapChainFramebuffers) { - vkDestroyFramebuffer(deviceInfo.m_logicalDevice, framebuffer, nullptr); - } - vkDestroySwapchainKHR(deviceInfo.m_logicalDevice, surfaceInfo.swapChain, nullptr); - vkDestroySemaphore(deviceInfo.m_logicalDevice, surfaceInfo.renderFinishedSemaphore, nullptr); - vkDestroySemaphore(deviceInfo.m_logicalDevice, surfaceInfo.imageAvailableSemaphore, nullptr); - vkDestroySurfaceKHR(m_vulkanInstance, surfaceInfo.surface, nullptr); - } m_surfaces.clear(); m_surfaceHandleMap.clear(); } @@ -923,6 +909,21 @@ void KRContext::removeResource(KRResource* resource) } } +KrSurfaceHandle KRContext::GetBestDeviceForSurface(const VkSurfaceKHR& surface) +{ + KrDeviceHandle deviceHandle = 0; + for (auto itr = m_devices.begin(); itr != m_devices.end(); itr++) { + KRDevice& device = *(*itr).second; + VkBool32 canPresent = false; + vkGetPhysicalDeviceSurfaceSupportKHR(device.m_device, device.m_graphicsFamilyQueueIndex, surface, &canPresent); + if (canPresent) { + deviceHandle = (*itr).first; + break; + } + } + return deviceHandle; +} + KrResult KRContext::createWindowSurface(const KrCreateWindowSurfaceInfo* createWindowSurfaceInfo) { if (createWindowSurfaceInfo->surfaceHandle < 0) { @@ -942,193 +943,32 @@ KrResult KRContext::createWindowSurface(const KrCreateWindowSurfaceInfo* createW const std::lock_guard surfaceLock(KRContext::g_SurfaceInfoMutex); const std::lock_guard deviceLock(KRContext::g_DeviceInfoMutex); - KRDevice* deviceInfo = nullptr; - #ifdef WIN32 HWND hWnd = static_cast(createWindowSurfaceInfo->hWnd); + std::unique_ptr info = std::make_unique(*this, hWnd); - KRSurface info{}; - info.hWnd = hWnd; - - VkWin32SurfaceCreateInfoKHR createInfo{}; - createInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR; - createInfo.hinstance = GetModuleHandle(nullptr); - createInfo.hwnd = hWnd; - if (vkCreateWin32SurfaceKHR(m_vulkanInstance, &createInfo, nullptr, &info.surface) != VK_SUCCESS) { - return KR_ERROR_VULKAN; + KrResult initialize_result = info->initialize(); + if (initialize_result != KR_SUCCESS) { + return initialize_result; } - for (auto itr = m_devices.begin(); itr != m_devices.end(); itr++) { - KRDevice& device = *(*itr).second; - VkBool32 canPresent = false; - vkGetPhysicalDeviceSurfaceSupportKHR(device.m_device, device.m_graphicsFamilyQueueIndex, info.surface, &canPresent); - if (canPresent) { - info.deviceHandle = (*itr).first; - deviceInfo = &device; - break; - } - } - - if (deviceInfo == nullptr) { - vkDestroySurfaceKHR(m_vulkanInstance, info.surface, nullptr); - return KR_ERROR_NO_DEVICE; - } - - VkSemaphoreCreateInfo semaphoreInfo{}; - semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; - if (vkCreateSemaphore(deviceInfo->m_logicalDevice, &semaphoreInfo, nullptr, &info.imageAvailableSemaphore) != VK_SUCCESS) { - vkDestroySurfaceKHR(m_vulkanInstance, info.surface, nullptr); - return KR_ERROR_VULKAN; - } - if (vkCreateSemaphore(deviceInfo->m_logicalDevice, &semaphoreInfo, nullptr, &info.renderFinishedSemaphore) != VK_SUCCESS) { - vkDestroySemaphore(deviceInfo->m_logicalDevice, info.imageAvailableSemaphore, nullptr); - vkDestroySurfaceKHR(m_vulkanInstance, info.surface, nullptr); - return KR_ERROR_VULKAN; - } - - VkSurfaceCapabilitiesKHR surfaceCapabilities{}; - vkGetPhysicalDeviceSurfaceCapabilitiesKHR(deviceInfo->m_device, info.surface, &surfaceCapabilities); - - std::vector surfaceFormats; - uint32_t formatCount = 0; - vkGetPhysicalDeviceSurfaceFormatsKHR(deviceInfo->m_device, info.surface, &formatCount, nullptr); - - - if (formatCount != 0) { - surfaceFormats.resize(formatCount); - vkGetPhysicalDeviceSurfaceFormatsKHR(deviceInfo->m_device, info.surface, &formatCount, surfaceFormats.data()); - } - - std::vector surfacePresentModes; - - uint32_t presentModeCount = 0; - vkGetPhysicalDeviceSurfacePresentModesKHR(deviceInfo->m_device, info.surface, &presentModeCount, nullptr); - - if (presentModeCount != 0) { - surfacePresentModes.resize(presentModeCount); - vkGetPhysicalDeviceSurfacePresentModesKHR(deviceInfo->m_device, info.surface, &presentModeCount, surfacePresentModes.data()); - } - - VkSurfaceFormatKHR selectedSurfaceFormat = surfaceFormats[0]; - for (const auto& availableFormat : surfaceFormats) { - if (availableFormat.format == VK_FORMAT_B8G8R8A8_SRGB && availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) { - selectedSurfaceFormat = availableFormat; - break; - } - } - - // VK_PRESENT_MODE_FIFO_KHR is always available - VkPresentModeKHR selectedPresentMode = VK_PRESENT_MODE_FIFO_KHR; - - // Try to find a better mode - for (const auto& availablePresentMode : surfacePresentModes) { - if (availablePresentMode == VK_PRESENT_MODE_MAILBOX_KHR) { - selectedPresentMode = availablePresentMode; - } - } - - VkExtent2D swapExtent; - if (surfaceCapabilities.currentExtent.width != UINT32_MAX) { - swapExtent = surfaceCapabilities.currentExtent; - } else { - const uint32_t MAX_WIDTH = 8192; - const uint32_t MAX_HEIGHT = 8192; - swapExtent.width = std::max(surfaceCapabilities.minImageExtent.width, std::min(surfaceCapabilities.maxImageExtent.width, MAX_WIDTH)); - swapExtent.height = std::max(surfaceCapabilities.minImageExtent.height, std::min(surfaceCapabilities.maxImageExtent.height, MAX_HEIGHT)); - } - info.swapChainExtent = swapExtent; - - uint32_t imageCount = surfaceCapabilities.minImageCount + 1; - if (surfaceCapabilities.maxImageCount > 0 && imageCount > surfaceCapabilities.maxImageCount) { - imageCount = surfaceCapabilities.maxImageCount; - } - - VkSwapchainCreateInfoKHR swapChainCreateInfo{}; - swapChainCreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; - swapChainCreateInfo.surface = info.surface; - swapChainCreateInfo.minImageCount = imageCount; - swapChainCreateInfo.imageFormat = selectedSurfaceFormat.format; - swapChainCreateInfo.imageColorSpace = selectedSurfaceFormat.colorSpace; - swapChainCreateInfo.imageExtent = swapExtent; - swapChainCreateInfo.imageArrayLayers = 1; - swapChainCreateInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - - uint32_t queueFamilyIndices[] = { - deviceInfo->m_graphicsFamilyQueueIndex, - deviceInfo->m_computeFamilyQueueIndex - }; - if (deviceInfo->m_graphicsFamilyQueueIndex == deviceInfo->m_computeFamilyQueueIndex) { - swapChainCreateInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; - swapChainCreateInfo.queueFamilyIndexCount = 0; - swapChainCreateInfo.pQueueFamilyIndices = nullptr; - } else { - swapChainCreateInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT; - swapChainCreateInfo.queueFamilyIndexCount = 2; - swapChainCreateInfo.pQueueFamilyIndices = queueFamilyIndices; - } - - swapChainCreateInfo.preTransform = surfaceCapabilities.currentTransform; - swapChainCreateInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; - swapChainCreateInfo.presentMode = selectedPresentMode; - swapChainCreateInfo.clipped = VK_TRUE; - swapChainCreateInfo.oldSwapchain = VK_NULL_HANDLE; - - if (vkCreateSwapchainKHR(deviceInfo->m_logicalDevice, &swapChainCreateInfo, nullptr, &info.swapChain) != VK_SUCCESS) { - vkDestroySemaphore(deviceInfo->m_logicalDevice, info.renderFinishedSemaphore, nullptr); - vkDestroySemaphore(deviceInfo->m_logicalDevice, info.imageAvailableSemaphore, nullptr); - vkDestroySurfaceKHR(m_vulkanInstance, info.surface, nullptr); - return KR_ERROR_VULKAN_SWAP_CHAIN; - } - - vkGetSwapchainImagesKHR(deviceInfo->m_logicalDevice, info.swapChain, &imageCount, nullptr); - info.swapChainImages.resize(imageCount); - vkGetSwapchainImagesKHR(deviceInfo->m_logicalDevice, info.swapChain, &imageCount, info.swapChainImages.data()); - - info.swapChainImageFormat = selectedSurfaceFormat.format; - - info.swapChainImageViews.resize(info.swapChainImages.size()); - for (size_t i = 0; i < info.swapChainImages.size(); i++) { - VkImageViewCreateInfo createInfo{}; - createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - createInfo.image = info.swapChainImages[i]; - createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; - createInfo.format = info.swapChainImageFormat; - createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; - createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; - createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; - createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; - createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - createInfo.subresourceRange.baseMipLevel = 0; - createInfo.subresourceRange.levelCount = 1; - createInfo.subresourceRange.baseArrayLayer = 0; - createInfo.subresourceRange.layerCount = 1; - if (vkCreateImageView(deviceInfo->m_logicalDevice, &createInfo, nullptr, &info.swapChainImageViews[i]) != VK_SUCCESS) { - for (size_t j = 0; j < i; j++) { - vkDestroyImageView(deviceInfo->m_logicalDevice, info.swapChainImageViews[j], nullptr); - } - vkDestroySemaphore(deviceInfo->m_logicalDevice, info.renderFinishedSemaphore, nullptr); - vkDestroySemaphore(deviceInfo->m_logicalDevice, info.imageAvailableSemaphore, nullptr); - vkDestroySurfaceKHR(m_vulkanInstance, info.surface, nullptr); - return KR_ERROR_VULKAN_SWAP_CHAIN; - } - } + KRDevice* deviceInfo = &GetDeviceInfo(info->m_deviceHandle); KrSurfaceHandle surfaceHandle = ++m_topSurfaceHandle; - m_surfaces.insert(std::pair(surfaceHandle, info)); + m_surfaces.insert(std::pair>(surfaceHandle, std::move(info))); - m_surfaceHandleMap.insert(std::pair(createWindowSurfaceInfo->surfaceHandle, surfaceHandle)); m_pPipelineManager->createPipelines(surfaceHandle); { KRPipeline* testPipeline = m_pPipelineManager->get("vulkan_test"); - KRSurface& surface = m_surfaces[surfaceHandle]; - surface.swapChainFramebuffers.resize(surface.swapChainImageViews.size()); + KRSurface& surface = *m_surfaces[surfaceHandle]; + surface.m_swapChainFramebuffers.resize(surface.m_swapChainImageViews.size()); - for (size_t i = 0; i < surface.swapChainImageViews.size(); i++) { + for (size_t i = 0; i < surface.m_swapChainImageViews.size(); i++) { VkImageView attachments[] = { - surface.swapChainImageViews[i] + surface.m_swapChainImageViews[i] }; VkFramebufferCreateInfo framebufferInfo{}; @@ -1136,11 +976,11 @@ KrResult KRContext::createWindowSurface(const KrCreateWindowSurfaceInfo* createW framebufferInfo.renderPass = testPipeline->getRenderPass(); framebufferInfo.attachmentCount = 1; framebufferInfo.pAttachments = attachments; - framebufferInfo.width = surface.swapChainExtent.width; - framebufferInfo.height = surface.swapChainExtent.height; + framebufferInfo.width = surface.m_swapChainExtent.width; + framebufferInfo.height = surface.m_swapChainExtent.height; framebufferInfo.layers = 1; - if (vkCreateFramebuffer(deviceInfo->m_logicalDevice, &framebufferInfo, nullptr, &surface.swapChainFramebuffers[i]) != VK_SUCCESS) { + if (vkCreateFramebuffer(deviceInfo->m_logicalDevice, &framebufferInfo, nullptr, &surface.m_swapChainFramebuffers[i]) != VK_SUCCESS) { // TODO - Error Handling } } @@ -1173,15 +1013,6 @@ KrResult KRContext::deleteWindowSurface(const KrDeleteWindowSurfaceInfo* deleteW if (itr == m_surfaces.end()) { return KR_ERROR_NOT_FOUND; } - KRSurface* surfaceInfo = &(*itr).second; - KRDevice& deviceInfo = GetDeviceInfo(surfaceInfo->deviceHandle); - for (auto imageView : surfaceInfo->swapChainImageViews) { - vkDestroyImageView(deviceInfo.m_logicalDevice, imageView, nullptr); - } - vkDestroySwapchainKHR(deviceInfo.m_logicalDevice, surfaceInfo->swapChain, nullptr); - vkDestroySemaphore(deviceInfo.m_logicalDevice, surfaceInfo->renderFinishedSemaphore, nullptr); - vkDestroySemaphore(deviceInfo.m_logicalDevice, surfaceInfo->imageAvailableSemaphore, nullptr); - vkDestroySurfaceKHR(m_vulkanInstance, surfaceInfo->surface, nullptr); m_surfaces.erase(itr); return KR_SUCCESS; } @@ -1214,11 +1045,11 @@ void KRContext::renderFrame() const std::lock_guard surfaceLock(KRContext::g_SurfaceInfoMutex); for (auto surfaceItr = m_surfaces.begin(); surfaceItr != m_surfaces.end(); surfaceItr++) { - KRSurface& surface = (*surfaceItr).second; - KRDevice& device = GetDeviceInfo(surface.deviceHandle); + KRSurface& surface = *(*surfaceItr).second; + KRDevice& device = GetDeviceInfo(surface.m_deviceHandle); uint32_t imageIndex = 0; - vkAcquireNextImageKHR(device.m_logicalDevice, surface.swapChain, UINT64_MAX, surface.imageAvailableSemaphore, VK_NULL_HANDLE, &imageIndex); + vkAcquireNextImageKHR(device.m_logicalDevice, surface.m_swapChain, UINT64_MAX, surface.m_imageAvailableSemaphore, VK_NULL_HANDLE, &imageIndex); // TODO - this will break with more than one surface... Expect to refactor this out VkCommandBuffer commandBuffer = device.m_graphicsCommandBuffers[imageIndex]; @@ -1238,9 +1069,9 @@ void KRContext::renderFrame() VkRenderPassBeginInfo renderPassInfo{}; renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; renderPassInfo.renderPass = testPipeline->getRenderPass(); - renderPassInfo.framebuffer = surface.swapChainFramebuffers[frameIndex % surface.swapChainFramebuffers.size()]; + renderPassInfo.framebuffer = surface.m_swapChainFramebuffers[frameIndex % surface.m_swapChainFramebuffers.size()]; renderPassInfo.renderArea.offset = { 0, 0 }; - renderPassInfo.renderArea.extent = surface.swapChainExtent; + renderPassInfo.renderArea.extent = surface.m_swapChainExtent; renderPassInfo.clearValueCount = 1; renderPassInfo.pClearValues = &clearColor; @@ -1255,7 +1086,7 @@ void KRContext::renderFrame() VkSubmitInfo submitInfo{}; submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - VkSemaphore waitSemaphores[] = { surface.imageAvailableSemaphore }; + VkSemaphore waitSemaphores[] = { surface.m_imageAvailableSemaphore }; VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }; submitInfo.waitSemaphoreCount = 1; submitInfo.pWaitSemaphores = waitSemaphores; @@ -1263,7 +1094,7 @@ void KRContext::renderFrame() submitInfo.commandBufferCount = 1; submitInfo.pCommandBuffers = &commandBuffer; - VkSemaphore signalSemaphores[] = { surface.renderFinishedSemaphore }; + VkSemaphore signalSemaphores[] = { surface.m_renderFinishedSemaphore }; submitInfo.signalSemaphoreCount = 1; submitInfo.pSignalSemaphores = signalSemaphores; @@ -1276,7 +1107,7 @@ void KRContext::renderFrame() presentInfo.waitSemaphoreCount = 1; presentInfo.pWaitSemaphores = signalSemaphores; presentInfo.swapchainCount = 1; - presentInfo.pSwapchains = &surface.swapChain; + presentInfo.pSwapchains = &surface.m_swapChain; presentInfo.pImageIndices = &imageIndex; presentInfo.pResults = nullptr; vkQueuePresentKHR(device.m_graphicsQueue, &presentInfo); @@ -1291,7 +1122,7 @@ KRSurface& KRContext::GetSurfaceInfo(KrSurfaceHandle handle) if (itr == m_surfaces.end()) { assert(false); } - return m_surfaces[handle]; + return *m_surfaces[handle]; } KRDevice& KRContext::GetDeviceInfo(KrDeviceHandle handle) @@ -1357,3 +1188,8 @@ void KRContext::createDevices() m_devices[++m_topDeviceHandle] = std::move(device); } } + +VkInstance& KRContext::GetVulkanInstance() +{ + return m_vulkanInstance; +} diff --git a/kraken/KRContext.h b/kraken/KRContext.h index 7c90f45..d04eae5 100755 --- a/kraken/KRContext.h +++ b/kraken/KRContext.h @@ -159,6 +159,8 @@ public: KRDevice& GetDeviceInfo(KrDeviceHandle handle); KRSurface& GetSurfaceInfo(KrSurfaceHandle handle); + VkInstance& GetVulkanInstance(); + KrSurfaceHandle GetBestDeviceForSurface(const VkSurfaceKHR& surface); #if TARGET_OS_MAC static void attachToView(void *view); @@ -218,7 +220,7 @@ private: unordered_map> m_devices; KrDeviceHandle m_topDeviceHandle; - unordered_map m_surfaces; + unordered_map> m_surfaces; KrDeviceHandle m_topSurfaceHandle; unordered_map m_surfaceHandleMap; diff --git a/kraken/KRPipeline.cpp b/kraken/KRPipeline.cpp index 023b6d8..52762ef 100644 --- a/kraken/KRPipeline.cpp +++ b/kraken/KRPipeline.cpp @@ -117,7 +117,7 @@ KRPipeline::KRPipeline(KRContext& context, KrSurfaceHandle surfaceHandle, const m_graphicsPipeline = nullptr; m_renderPass = nullptr; KRSurface& surface = m_pContext->GetSurfaceInfo(surfaceHandle); - KRDevice& device = m_pContext->GetDeviceInfo(surface.deviceHandle); + KRDevice& device = m_pContext->GetDeviceInfo(surface.m_deviceHandle); strcpy(m_szKey, szKey); @@ -145,7 +145,7 @@ KRPipeline::KRPipeline(KRContext& context, KrSurfaceHandle surfaceHandle, const } VkAttachmentDescription colorAttachment{}; - colorAttachment.format = surface.swapChainImageFormat; + colorAttachment.format = surface.m_swapChainImageFormat; colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT; colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; @@ -199,14 +199,14 @@ KRPipeline::KRPipeline(KRContext& context, KrSurfaceHandle surfaceHandle, const VkViewport viewport{}; viewport.x = 0.0f; viewport.y = 0.0f; - viewport.width = (float)surface.swapChainExtent.width; - viewport.height = (float)surface.swapChainExtent.height; + viewport.width = (float)surface.m_swapChainExtent.width; + viewport.height = (float)surface.m_swapChainExtent.height; viewport.minDepth = 0.0f; viewport.maxDepth = 1.0f; VkRect2D scissor{}; scissor.offset = { 0, 0 }; - scissor.extent = surface.swapChainExtent; + scissor.extent = surface.m_swapChainExtent; VkPipelineViewportStateCreateInfo viewportState{}; viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; diff --git a/kraken/KRSurface.cpp b/kraken/KRSurface.cpp index 4d1b93d..6991214 100644 --- a/kraken/KRSurface.cpp +++ b/kraken/KRSurface.cpp @@ -31,3 +31,212 @@ #include "KRSurface.h" +#ifdef WIN32 +KRSurface::KRSurface(KRContext& context, HWND hWnd) +#else +KRSurface::KRSurface(KRContext& context) +#endif + : KRContextObject(context) +#ifdef WIN32 + , m_hWnd(hWnd) +#endif + , m_deviceHandle(VK_NULL_HANDLE) + , m_surface(VK_NULL_HANDLE) + , m_swapChain(VK_NULL_HANDLE) + , m_swapChainImageFormat(VK_FORMAT_UNDEFINED) + , m_swapChainExtent({ 0, 0 }) + , m_imageAvailableSemaphore(VK_NULL_HANDLE) + , m_renderFinishedSemaphore(VK_NULL_HANDLE) +{ + +} + +KRSurface::~KRSurface() +{ + destroy(); +} + +KrResult KRSurface::initialize() +{ + VkWin32SurfaceCreateInfoKHR createInfo{}; + createInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR; + createInfo.hinstance = GetModuleHandle(nullptr); + createInfo.hwnd = m_hWnd; + if (vkCreateWin32SurfaceKHR(m_pContext->GetVulkanInstance(), &createInfo, nullptr, &m_surface) != VK_SUCCESS) { + return KR_ERROR_VULKAN; + } + + m_deviceHandle = m_pContext->GetBestDeviceForSurface(m_surface); + if (m_deviceHandle == 0) { + return KR_ERROR_NO_DEVICE; + } + + KRDevice* deviceInfo = &m_pContext->GetDeviceInfo(m_deviceHandle); + + VkSemaphoreCreateInfo semaphoreInfo{}; + semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; + if (vkCreateSemaphore(deviceInfo->m_logicalDevice, &semaphoreInfo, nullptr, &m_imageAvailableSemaphore) != VK_SUCCESS) { + return KR_ERROR_VULKAN; + } + if (vkCreateSemaphore(deviceInfo->m_logicalDevice, &semaphoreInfo, nullptr, &m_renderFinishedSemaphore) != VK_SUCCESS) { + return KR_ERROR_VULKAN; + } + + VkSurfaceCapabilitiesKHR surfaceCapabilities{}; + vkGetPhysicalDeviceSurfaceCapabilitiesKHR(deviceInfo->m_device, m_surface, &surfaceCapabilities); + + std::vector surfaceFormats; + uint32_t formatCount = 0; + vkGetPhysicalDeviceSurfaceFormatsKHR(deviceInfo->m_device, m_surface, &formatCount, nullptr); + + + if (formatCount != 0) { + surfaceFormats.resize(formatCount); + vkGetPhysicalDeviceSurfaceFormatsKHR(deviceInfo->m_device, m_surface, &formatCount, surfaceFormats.data()); + } + + std::vector surfacePresentModes; + + uint32_t presentModeCount = 0; + vkGetPhysicalDeviceSurfacePresentModesKHR(deviceInfo->m_device, m_surface, &presentModeCount, nullptr); + + if (presentModeCount != 0) { + surfacePresentModes.resize(presentModeCount); + vkGetPhysicalDeviceSurfacePresentModesKHR(deviceInfo->m_device, m_surface, &presentModeCount, surfacePresentModes.data()); + } + + VkSurfaceFormatKHR selectedSurfaceFormat = surfaceFormats[0]; + for (const auto& availableFormat : surfaceFormats) { + if (availableFormat.format == VK_FORMAT_B8G8R8A8_SRGB && availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) { + selectedSurfaceFormat = availableFormat; + break; + } + } + + // VK_PRESENT_MODE_FIFO_KHR is always available + VkPresentModeKHR selectedPresentMode = VK_PRESENT_MODE_FIFO_KHR; + + // Try to find a better mode + for (const auto& availablePresentMode : surfacePresentModes) { + if (availablePresentMode == VK_PRESENT_MODE_MAILBOX_KHR) { + selectedPresentMode = availablePresentMode; + } + } + + VkExtent2D swapExtent; + if (surfaceCapabilities.currentExtent.width != UINT32_MAX) { + swapExtent = surfaceCapabilities.currentExtent; + } + else { + const uint32_t MAX_WIDTH = 8192; + const uint32_t MAX_HEIGHT = 8192; + swapExtent.width = std::max(surfaceCapabilities.minImageExtent.width, std::min(surfaceCapabilities.maxImageExtent.width, MAX_WIDTH)); + swapExtent.height = std::max(surfaceCapabilities.minImageExtent.height, std::min(surfaceCapabilities.maxImageExtent.height, MAX_HEIGHT)); + } + m_swapChainExtent = swapExtent; + + uint32_t imageCount = surfaceCapabilities.minImageCount + 1; + if (surfaceCapabilities.maxImageCount > 0 && imageCount > surfaceCapabilities.maxImageCount) { + imageCount = surfaceCapabilities.maxImageCount; + } + + VkSwapchainCreateInfoKHR swapChainCreateInfo{}; + swapChainCreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; + swapChainCreateInfo.surface = m_surface; + swapChainCreateInfo.minImageCount = imageCount; + swapChainCreateInfo.imageFormat = selectedSurfaceFormat.format; + swapChainCreateInfo.imageColorSpace = selectedSurfaceFormat.colorSpace; + swapChainCreateInfo.imageExtent = swapExtent; + swapChainCreateInfo.imageArrayLayers = 1; + swapChainCreateInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + + uint32_t queueFamilyIndices[] = { + deviceInfo->m_graphicsFamilyQueueIndex, + deviceInfo->m_computeFamilyQueueIndex + }; + if (deviceInfo->m_graphicsFamilyQueueIndex == deviceInfo->m_computeFamilyQueueIndex) { + swapChainCreateInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; + swapChainCreateInfo.queueFamilyIndexCount = 0; + swapChainCreateInfo.pQueueFamilyIndices = nullptr; + } + else { + swapChainCreateInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT; + swapChainCreateInfo.queueFamilyIndexCount = 2; + swapChainCreateInfo.pQueueFamilyIndices = queueFamilyIndices; + } + + swapChainCreateInfo.preTransform = surfaceCapabilities.currentTransform; + swapChainCreateInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; + swapChainCreateInfo.presentMode = selectedPresentMode; + swapChainCreateInfo.clipped = VK_TRUE; + swapChainCreateInfo.oldSwapchain = VK_NULL_HANDLE; + + if (vkCreateSwapchainKHR(deviceInfo->m_logicalDevice, &swapChainCreateInfo, nullptr, &m_swapChain) != VK_SUCCESS) { + return KR_ERROR_VULKAN_SWAP_CHAIN; + } + + vkGetSwapchainImagesKHR(deviceInfo->m_logicalDevice, m_swapChain, &imageCount, nullptr); + m_swapChainImages.resize(imageCount); + vkGetSwapchainImagesKHR(deviceInfo->m_logicalDevice, m_swapChain, &imageCount, m_swapChainImages.data()); + + m_swapChainImageFormat = selectedSurfaceFormat.format; + + m_swapChainImageViews.resize(m_swapChainImages.size()); + for (size_t i = 0; i < m_swapChainImages.size(); i++) { + VkImageViewCreateInfo createInfo{}; + createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + createInfo.image = m_swapChainImages[i]; + createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; + createInfo.format = m_swapChainImageFormat; + createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; + createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; + createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; + createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; + createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + createInfo.subresourceRange.baseMipLevel = 0; + createInfo.subresourceRange.levelCount = 1; + createInfo.subresourceRange.baseArrayLayer = 0; + createInfo.subresourceRange.layerCount = 1; + if (vkCreateImageView(deviceInfo->m_logicalDevice, &createInfo, nullptr, &m_swapChainImageViews[i]) != VK_SUCCESS) { + return KR_ERROR_VULKAN_SWAP_CHAIN; + } + } + + return KR_SUCCESS; +} + +void KRSurface::destroy() +{ + KRDevice& deviceInfo = m_pContext->GetDeviceInfo(m_deviceHandle); + + for (auto framebuffer : m_swapChainFramebuffers) { + vkDestroyFramebuffer(deviceInfo.m_logicalDevice, framebuffer, nullptr); + } + m_swapChainFramebuffers.clear(); + + for (auto imageView : m_swapChainImageViews) { + vkDestroyImageView(deviceInfo.m_logicalDevice, imageView, nullptr); + } + m_swapChainImageViews.clear(); + + if (m_swapChain != VK_NULL_HANDLE) { + vkDestroySwapchainKHR(deviceInfo.m_logicalDevice, m_swapChain, nullptr); + m_swapChain = VK_NULL_HANDLE; + } + + if (m_renderFinishedSemaphore != VK_NULL_HANDLE) { + vkDestroySemaphore(deviceInfo.m_logicalDevice, m_renderFinishedSemaphore, nullptr); + m_renderFinishedSemaphore = VK_NULL_HANDLE; + } + + if (m_imageAvailableSemaphore != VK_NULL_HANDLE) { + vkDestroySemaphore(deviceInfo.m_logicalDevice, m_imageAvailableSemaphore, nullptr); + m_imageAvailableSemaphore = VK_NULL_HANDLE; + } + + if (m_surface != VK_NULL_HANDLE) { + vkDestroySurfaceKHR(m_pContext->GetVulkanInstance(), m_surface, nullptr); + m_surface = VK_NULL_HANDLE; + } + +} diff --git a/kraken/KRSurface.h b/kraken/KRSurface.h index 633eaaf..a3e2584 100644 --- a/kraken/KRSurface.h +++ b/kraken/KRSurface.h @@ -30,26 +30,41 @@ // #include "KREngine-common.h" +#include "KRContext.h" #ifndef KRSURFACE_H #define KRSURFACE_H -class KRSurface +class KRSurface : public KRContextObject { public: - KrDeviceHandle deviceHandle; - VkSurfaceKHR surface; - VkSwapchainKHR swapChain; - std::vector swapChainImages; - VkFormat swapChainImageFormat; - VkExtent2D swapChainExtent; - std::vector swapChainImageViews; - std::vector swapChainFramebuffers; - VkSemaphore imageAvailableSemaphore; - VkSemaphore renderFinishedSemaphore; #ifdef WIN32 - HWND hWnd; + KRSurface(KRContext& context, HWND hWnd); +#else + KRSurface(KRContext& context); #endif + ~KRSurface(); + void destroy(); + + KRSurface(const KRSurface&) = delete; + KRSurface& operator=(const KRSurface&) = delete; + + KrResult initialize(); + +#ifdef WIN32 + HWND m_hWnd; +#endif + KrDeviceHandle m_deviceHandle; + VkSurfaceKHR m_surface; + VkSwapchainKHR m_swapChain; + std::vector m_swapChainImages; + VkFormat m_swapChainImageFormat; + VkExtent2D m_swapChainExtent; + std::vector m_swapChainImageViews; + std::vector m_swapChainFramebuffers; + VkSemaphore m_imageAvailableSemaphore; + VkSemaphore m_renderFinishedSemaphore; + private: };