diff --git a/FastCG/include/FastCG/Graphics/Vulkan/VulkanGraphicsSystem.h b/FastCG/include/FastCG/Graphics/Vulkan/VulkanGraphicsSystem.h index 29c44f65..c5b8f0c8 100644 --- a/FastCG/include/FastCG/Graphics/Vulkan/VulkanGraphicsSystem.h +++ b/FastCG/include/FastCG/Graphics/Vulkan/VulkanGraphicsSystem.h @@ -154,6 +154,7 @@ namespace FastCG std::unique_ptr mAllocationCallbacks{nullptr}; VkDevice mDevice{VK_NULL_HANDLE}; uint32_t mQueueFamilyIdx{~0u}; + bool mQueueSupportsPresentation{false}; bool mQueueSupportsCompute{false}; // support only one queue at the moment VkQueue mQueue{VK_NULL_HANDLE}; diff --git a/FastCG/src/Graphics/Vulkan/VulkanGraphicsSystem.cpp b/FastCG/src/Graphics/Vulkan/VulkanGraphicsSystem.cpp index 32306e5d..f6337f23 100644 --- a/FastCG/src/Graphics/Vulkan/VulkanGraphicsSystem.cpp +++ b/FastCG/src/Graphics/Vulkan/VulkanGraphicsSystem.cpp @@ -55,6 +55,33 @@ namespace }) != vector.end(); } + bool SupportsPresentation(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIdx) + { +#if defined FASTCG_WINDOWS + return vkGetPhysicalDeviceWin32PresentationSupportKHR(physicalDevice, queueFamilyIdx); +#elif defined FASTCG_LINUX + auto *pDisplay = FastCG::X11Application::GetInstance()->GetDisplay(); + assert(pDisplay != nullptr); + // uses visual ID from default visual. Only works because we're using a "simple window". + auto visualId = XVisualIDFromVisual(DefaultVisual(pDisplay, DefaultScreen(pDisplay))); + return vkGetPhysicalDeviceXlibPresentationSupportKHR(physicalDevice, queueFamilyIdx, pDisplay, visualId); +#elif defined FASTCG_ANDROID + // TODO: apparently, there's no need for checking whether a queue family supports presentation on Android + return true; +#else +#error "FastCG::SupportsPresentation(): Don't know how to check presentation support" +#endif + return false; + } + + bool SupportsPresentationToSurface(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIdx, VkSurfaceKHR surface) + { + VkBool32 supportsPresentationToSurface; + FASTCG_CHECK_VK_RESULT(vkGetPhysicalDeviceSurfaceSupportKHR(physicalDevice, queueFamilyIdx, surface, + &supportsPresentationToSurface)); + return supportsPresentationToSurface; + } + #if _DEBUG static VKAPI_ATTR VkBool32 VKAPI_CALL VulkanDebugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, @@ -416,8 +443,13 @@ namespace FastCG FASTCG_CHECK_VK_RESULT( vkCreateAndroidSurfaceKHR(mInstance, &surfaceCreateInfo, mAllocationCallbacks.get(), &mSurface)); #else -#error "FastCG::VulkanGraphicsSystem::CreateHeadedSurface(): Don't know how to create a headed surface" +#error "FastCG::VulkanGraphicsSystem::CreateSurface(): Don't know how to create a surface" #endif + + if (!SupportsPresentationToSurface(mPhysicalDevice, mQueueFamilyIdx, mSurface)) + { + FASTCG_THROW_EXCEPTION(Exception, "Vulkan: Cannot present to surface"); + } } void VulkanGraphicsSystem::SelectPhysicalDevice() @@ -461,6 +493,7 @@ namespace FastCG // FIXME: checking invariants assert((rQueueFamilyProperties.queueFlags & VK_QUEUE_TRANSFER_BIT) != 0); + mQueueSupportsPresentation = SupportsPresentation(rPhysicalDevice, queueFamilyIdx); mQueueSupportsCompute = (rQueueFamilyProperties.queueFlags & VK_QUEUE_COMPUTE_BIT) != 0; mQueueFamilyIdx = queueFamilyIdx; mPhysicalDevice = rPhysicalDevice;