Repository: google/filament
File: filament/backend/src/vulkan/platform/VulkanPlatform.cpp (C++)

Code before:
        VulkanSharedContext const* scontext = (VulkanSharedContext const*) sharedContext;
        // All fields of VulkanSharedContext should be present.
        FILAMENT_CHECK_PRECONDITION(scontext->instance != VK_NULL_HANDLE)
                << "Client needs to provide VkInstance";
        FILAMENT_CHECK_PRECONDITION(scontext->physicalDevice != VK_NULL_HANDLE)
                << "Client needs to provide VkPhysicalDevice";
        FILAMENT_CHECK_PRECONDITION(scontext->logicalDevice != VK_NULL_HANDLE)
                << "Client needs to provide VkDevice";
        FILAMENT_CHECK_PRECONDITION(scontext->graphicsQueueFamilyIndex != INVALID_VK_INDEX)
                << "Client needs to provide graphics queue family index";
        FILAMENT_CHECK_PRECONDITION(scontext->graphicsQueueIndex != INVALID_VK_INDEX)
                << "Client needs to provide graphics queue index";

        mImpl->mInstance = scontext->instance;
        mImpl->mPhysicalDevice = scontext->physicalDevice;
        mImpl->mDevice = scontext->logicalDevice;
        mImpl->mGraphicsQueueFamilyIndex = scontext->graphicsQueueFamilyIndex;
        mImpl->mGraphicsQueueIndex = scontext->graphicsQueueIndex;

        mImpl->mSharedContext = true;
    }

    VulkanContext& context = mImpl->mContext;

    // Pass along relevant driver config (feature flags)
    context.mAsyncPipelineCachePrewarmingEnabled = driverConfig.vulkanEnableAsyncPipelineCachePrewarming;
    context.mStagingBufferBypassEnabled = driverConfig.vulkanEnableStagingBufferBypass;

    ExtensionSet instExts;
    // If using a shared context, we do not assume any extensions.
    if (!mImpl->mSharedContext) {
        // This constains instance extensions that are required for the platform, which includes
        // swapchain surface extensions.
        auto const& swapchainExts = getSwapchainInstanceExtensions();
        instExts = getInstanceExtensions(swapchainExts);

#if defined(FILAMENT_SUPPORTS_XCB) && defined(FILAMENT_SUPPORTS_XLIB)
        // For the special case where we're on linux and both xcb and xlib are "required", then we
        // check if the set of supported extensions contain both of them.  If only xcb is supported,
        // we force XCB surface creation.  This workaround is needed for the default swiftshader
        // build where only XCB is available.
        if (setContains(swapchainExts, VK_KHR_XCB_SURFACE_EXTENSION_NAME) &&
                setContains(swapchainExts, VK_KHR_XLIB_SURFACE_EXTENSION_NAME)) {
            // Assume only XCB is left, then we force the XCB path in the swapchain creation.
            mImpl->mForceXCBSwapchain = !setContains(instExts, VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
            assert_invariant(!mImpl->mForceXCBSwapchain ||
                             setContains(instExts, VK_KHR_XCB_SURFACE_EXTENSION_NAME));
        }
#endif

        instExts.merge(getRequiredInstanceExtensions());

Review comment (suggestion):
The driverConfig in this case should be taken as a hint and then better say, if the prewarm is supported or not.

This should be true only if using a QC gpu, maybe we can also specify the deviceID and if we have the other 2 extensions.

Code after:

bool VulkanPlatform::hasResized(SwapChainPtr handle) {
    return static_cast<VulkanPlatformSwapChainBase*>(handle)->hasResized();
}

bool VulkanPlatform::isProtected(SwapChainPtr handle) {
    return static_cast<VulkanPlatformSwapChainBase*>(handle)->isProtected();
}

VkResult VulkanPlatform::recreate(SwapChainPtr handle) {
    return static_cast<VulkanPlatformSwapChainBase*>(handle)->recreate();
}

void VulkanPlatform::destroy(SwapChainPtr handle) {
    delete static_cast<VulkanPlatformSwapChainBase*>(handle);
}

SwapChainPtr VulkanPlatform::createSwapChain(void* nativeWindow, uint64_t flags,
        VkExtent2D extent) {
    assert_invariant(nativeWindow || (extent.width != 0 && extent.height != 0));
    bool const headless = extent.width != 0 && extent.height != 0;
    if (headless) {
        VulkanPlatformHeadlessSwapChain* swapchain = new VulkanPlatformHeadlessSwapChain(
                mImpl->mContext, mImpl->mDevice, mImpl->mGraphicsQueue, extent, flags);
        return swapchain;
    }

    if (mImpl->mForceXCBSwapchain) {
        flags |= SWAP_CHAIN_CONFIG_ENABLE_XCB;
    }

    if (flags & backend::SWAP_CHAIN_CONFIG_PROTECTED_CONTENT) {
        if (!mImpl->mContext.mProtectedMemorySupported) {
            LOG(WARNING) << "protected swapchain requested, but VulkanPlatform does not support it";
        }
    }

    auto [surface, fallbackExtent] = createVkSurfaceKHR(nativeWindow, mImpl->mInstance, flags);
    // The VulkanPlatformSurfaceSwapChain now `owns` the surface.
    VulkanPlatformSurfaceSwapChain* swapchain = new VulkanPlatformSurfaceSwapChain(mImpl->mContext,
            mImpl->mPhysicalDevice, mImpl->mDevice, mImpl->mGraphicsQueue, mImpl->mInstance,
            surface, fallbackExtent, nativeWindow, flags);
    return swapchain;
}

Platform::Sync* VulkanPlatform::createSync(VkFence fence,
        std::shared_ptr<VulkanCmdFence> fenceStatus) noexcept {
    return new VulkanSync{.fence = fence, .fenceStatus = fenceStatus};
}

void VulkanPlatform::destroySync(Platform::Sync* sync) noexcept {