VulkanManager.cpp revision 0e3cba31460e0698def0310003b7d291f1174afa
10e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger/*
20e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger * Copyright (C) 2016 The Android Open Source Project
30e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger *
40e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger * Licensed under the Apache License, Version 2.0 (the "License");
50e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger * you may not use this file except in compliance with the License.
60e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger * You may obtain a copy of the License at
70e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger *
80e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger *      http://www.apache.org/licenses/LICENSE-2.0
90e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger *
100e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger * Unless required by applicable law or agreed to in writing, software
110e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger * distributed under the License is distributed on an "AS IS" BASIS,
120e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger * See the License for the specific language governing permissions and
140e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger * limitations under the License.
150e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger */
160e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
170e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger#include "VulkanManager.h"
180e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
190e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger#include "DeviceInfo.h"
200e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger#include "RenderThread.h"
210e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
220e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger#include <GrContext.h>
230e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger#include <GrTypes.h>
240e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger#include <vk/GrVkTypes.h>
250e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
260e3cba31460e0698def0310003b7d291f1174afaDerek Sollenbergernamespace android {
270e3cba31460e0698def0310003b7d291f1174afaDerek Sollenbergernamespace uirenderer {
280e3cba31460e0698def0310003b7d291f1174afaDerek Sollenbergernamespace renderthread {
290e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
300e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger#define GET_PROC(F) m ## F = (PFN_vk ## F) vkGetInstanceProcAddr(instance, "vk" #F)
310e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger#define GET_DEV_PROC(F) m ## F = (PFN_vk ## F) vkGetDeviceProcAddr(device, "vk" #F)
320e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
330e3cba31460e0698def0310003b7d291f1174afaDerek SollenbergerVulkanManager::VulkanManager(RenderThread& thread) : mRenderThread(thread) {
340e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger}
350e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
360e3cba31460e0698def0310003b7d291f1174afaDerek Sollenbergervoid VulkanManager::destroy() {
370e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    if (!hasVkContext()) return;
380e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
390e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    if (VK_NULL_HANDLE != mCommandPool) {
400e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        mDestroyCommandPool(mBackendContext->fDevice, mCommandPool, nullptr);
410e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        mCommandPool = VK_NULL_HANDLE;
420e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    }
430e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger}
440e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
450e3cba31460e0698def0310003b7d291f1174afaDerek Sollenbergervoid VulkanManager::initialize() {
460e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    if (hasVkContext()) { return; }
470e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
480e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    auto canPresent = [](VkInstance, VkPhysicalDevice, uint32_t) { return true; };
490e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
500e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    mBackendContext.reset(GrVkBackendContext::Create(&mPresentQueueIndex, canPresent));
510e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
520e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    // Get all the addresses of needed vulkan functions
530e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    VkInstance instance = mBackendContext->fInstance;
540e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    VkDevice device = mBackendContext->fDevice;
550e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    GET_PROC(CreateAndroidSurfaceKHR);
560e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    GET_PROC(DestroySurfaceKHR);
570e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    GET_PROC(GetPhysicalDeviceSurfaceSupportKHR);
580e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    GET_PROC(GetPhysicalDeviceSurfaceCapabilitiesKHR);
590e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    GET_PROC(GetPhysicalDeviceSurfaceFormatsKHR);
600e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    GET_PROC(GetPhysicalDeviceSurfacePresentModesKHR);
610e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    GET_DEV_PROC(CreateSwapchainKHR);
620e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    GET_DEV_PROC(DestroySwapchainKHR);
630e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    GET_DEV_PROC(GetSwapchainImagesKHR);
640e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    GET_DEV_PROC(AcquireNextImageKHR);
650e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    GET_DEV_PROC(QueuePresentKHR);
660e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    GET_DEV_PROC(CreateCommandPool);
670e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    GET_DEV_PROC(DestroyCommandPool);
680e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    GET_DEV_PROC(AllocateCommandBuffers);
690e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    GET_DEV_PROC(FreeCommandBuffers);
700e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    GET_DEV_PROC(ResetCommandBuffer);
710e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    GET_DEV_PROC(BeginCommandBuffer);
720e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    GET_DEV_PROC(EndCommandBuffer);
730e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    GET_DEV_PROC(CmdPipelineBarrier);
740e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    GET_DEV_PROC(GetDeviceQueue);
750e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    GET_DEV_PROC(QueueSubmit);
760e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    GET_DEV_PROC(QueueWaitIdle);
770e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    GET_DEV_PROC(DeviceWaitIdle);
780e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    GET_DEV_PROC(CreateSemaphore);
790e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    GET_DEV_PROC(DestroySemaphore);
800e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    GET_DEV_PROC(CreateFence);
810e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    GET_DEV_PROC(DestroyFence);
820e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    GET_DEV_PROC(WaitForFences);
830e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    GET_DEV_PROC(ResetFences);
840e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
850e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    // create the command pool for the command buffers
860e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    if (VK_NULL_HANDLE == mCommandPool) {
870e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        VkCommandPoolCreateInfo commandPoolInfo;
880e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        memset(&commandPoolInfo, 0, sizeof(VkCommandPoolCreateInfo));
890e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        commandPoolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
900e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        // this needs to be on the render queue
910e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        commandPoolInfo.queueFamilyIndex = mBackendContext->fGraphicsQueueIndex;
920e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        commandPoolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
930e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        SkDEBUGCODE(VkResult res =) mCreateCommandPool(mBackendContext->fDevice,
940e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger                &commandPoolInfo, nullptr, &mCommandPool);
950e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        SkASSERT(VK_SUCCESS == res);
960e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    }
970e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
980e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    mGetDeviceQueue(mBackendContext->fDevice, mPresentQueueIndex, 0, &mPresentQueue);
990e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
1000e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    mRenderThread.setGrContext(GrContext::Create(kVulkan_GrBackend,
1010e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger            (GrBackendContext) mBackendContext.get()));
1020e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    DeviceInfo::initialize(mRenderThread.getGrContext()->caps()->maxRenderTargetSize());
1030e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger}
1040e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
1050e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger// Returns the next BackbufferInfo to use for the next draw. The function will make sure all
1060e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger// previous uses have finished before returning.
1070e3cba31460e0698def0310003b7d291f1174afaDerek SollenbergerVulkanSurface::BackbufferInfo* VulkanManager::getAvailableBackbuffer(VulkanSurface* surface) {
1080e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    SkASSERT(surface->mBackbuffers);
1090e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
1100e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    ++surface->mCurrentBackbufferIndex;
1110e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    if (surface->mCurrentBackbufferIndex > surface->mImageCount) {
1120e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        surface->mCurrentBackbufferIndex = 0;
1130e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    }
1140e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
1150e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    VulkanSurface::BackbufferInfo* backbuffer = surface->mBackbuffers +
1160e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger            surface->mCurrentBackbufferIndex;
1170e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
1180e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    // Before we reuse a backbuffer, make sure its fences have all signaled so that we can safely
1190e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    // reuse its commands buffers.
1200e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    VkResult res = mWaitForFences(mBackendContext->fDevice, 2, backbuffer->mUsageFences,
1210e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger            true, UINT64_MAX);
1220e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    if (res != VK_SUCCESS) {
1230e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        return nullptr;
1240e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    }
1250e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
1260e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    return backbuffer;
1270e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger}
1280e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
1290e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
1300e3cba31460e0698def0310003b7d291f1174afaDerek SollenbergerSkSurface* VulkanManager::getBackbufferSurface(VulkanSurface* surface) {
1310e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    VulkanSurface::BackbufferInfo* backbuffer = getAvailableBackbuffer(surface);
1320e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    SkASSERT(backbuffer);
1330e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
1340e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    VkResult res;
1350e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
1360e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    res = mResetFences(mBackendContext->fDevice, 2, backbuffer->mUsageFences);
1370e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    SkASSERT(VK_SUCCESS == res);
1380e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
1390e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    // The acquire will signal the attached mAcquireSemaphore. We use this to know the image has
1400e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    // finished presenting and that it is safe to begin sending new commands to the returned image.
1410e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    res = mAcquireNextImageKHR(mBackendContext->fDevice, surface->mSwapchain, UINT64_MAX,
1420e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger            backbuffer->mAcquireSemaphore, VK_NULL_HANDLE, &backbuffer->mImageIndex);
1430e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
1440e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    if (VK_ERROR_SURFACE_LOST_KHR == res) {
1450e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        // need to figure out how to create a new vkSurface without the platformData*
1460e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        // maybe use attach somehow? but need a Window
1470e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        return nullptr;
1480e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    }
1490e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    if (VK_ERROR_OUT_OF_DATE_KHR == res) {
1500e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        // tear swapchain down and try again
1510e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        if (!createSwapchain(surface)) {
1520e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger            return nullptr;
1530e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        }
1540e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
1550e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        // acquire the image
1560e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        res = mAcquireNextImageKHR(mBackendContext->fDevice, surface->mSwapchain, UINT64_MAX,
1570e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger                backbuffer->mAcquireSemaphore, VK_NULL_HANDLE, &backbuffer->mImageIndex);
1580e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
1590e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        if (VK_SUCCESS != res) {
1600e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger            return nullptr;
1610e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        }
1620e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    }
1630e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
1640e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    // set up layout transfer from initial to color attachment
1650e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    VkImageLayout layout = surface->mImageLayouts[backbuffer->mImageIndex];
1660e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    SkASSERT(VK_IMAGE_LAYOUT_UNDEFINED == layout || VK_IMAGE_LAYOUT_PRESENT_SRC_KHR == layout);
1670e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    VkPipelineStageFlags srcStageMask = (VK_IMAGE_LAYOUT_UNDEFINED == layout) ?
1680e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger                                        VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT :
1690e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger                                        VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1700e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1710e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    VkAccessFlags srcAccessMask = (VK_IMAGE_LAYOUT_UNDEFINED == layout) ?
1720e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger                                  0 : VK_ACCESS_MEMORY_READ_BIT;
1730e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    VkAccessFlags dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
1740e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
1750e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    VkImageMemoryBarrier imageMemoryBarrier = {
1760e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,    // sType
1770e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        NULL,                                      // pNext
1780e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        srcAccessMask,                             // outputMask
1790e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        dstAccessMask,                             // inputMask
1800e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        layout,                                    // oldLayout
1810e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,  // newLayout
1820e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        mPresentQueueIndex,                        // srcQueueFamilyIndex
1830e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        mBackendContext->fGraphicsQueueIndex,      // dstQueueFamilyIndex
1840e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        surface->mImages[backbuffer->mImageIndex], // image
1850e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }  // subresourceRange
1860e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    };
1870e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    mResetCommandBuffer(backbuffer->mTransitionCmdBuffers[0], 0);
1880e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
1890e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    VkCommandBufferBeginInfo info;
1900e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    memset(&info, 0, sizeof(VkCommandBufferBeginInfo));
1910e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
1920e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    info.flags = 0;
1930e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    mBeginCommandBuffer(backbuffer->mTransitionCmdBuffers[0], &info);
1940e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
1950e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    mCmdPipelineBarrier(backbuffer->mTransitionCmdBuffers[0], srcStageMask, dstStageMask, 0,
1960e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger            0, nullptr, 0, nullptr, 1, &imageMemoryBarrier);
1970e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
1980e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    mEndCommandBuffer(backbuffer->mTransitionCmdBuffers[0]);
1990e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
2000e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    VkPipelineStageFlags waitDstStageFlags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
2010e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    // insert the layout transfer into the queue and wait on the acquire
2020e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    VkSubmitInfo submitInfo;
2030e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    memset(&submitInfo, 0, sizeof(VkSubmitInfo));
2040e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
2050e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    submitInfo.waitSemaphoreCount = 1;
2060e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    // Wait to make sure aquire semaphore set above has signaled.
2070e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    submitInfo.pWaitSemaphores = &backbuffer->mAcquireSemaphore;
2080e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    submitInfo.pWaitDstStageMask = &waitDstStageFlags;
2090e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    submitInfo.commandBufferCount = 1;
2100e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    submitInfo.pCommandBuffers = &backbuffer->mTransitionCmdBuffers[0];
2110e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    submitInfo.signalSemaphoreCount = 0;
2120e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
2130e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    // Attach first fence to submission here so we can track when the command buffer finishes.
2140e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    mQueueSubmit(mBackendContext->fQueue, 1, &submitInfo, backbuffer->mUsageFences[0]);
2150e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
2160e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    // We need to notify Skia that we changed the layout of the wrapped VkImage
2170e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    GrVkImageInfo* imageInfo;
2180e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    sk_sp<SkSurface> skSurface = surface->mSurfaces[backbuffer->mImageIndex];
2190e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    skSurface->getRenderTargetHandle((GrBackendObject*)&imageInfo,
2200e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger            SkSurface::kFlushRead_BackendHandleAccess);
2210e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    imageInfo->updateImageLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
2220e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
2230e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    surface->mBackbuffer = std::move(skSurface);
2240e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    return surface->mBackbuffer.get();
2250e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger}
2260e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
2270e3cba31460e0698def0310003b7d291f1174afaDerek Sollenbergervoid VulkanManager::destroyBuffers(VulkanSurface* surface) {
2280e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    if (surface->mBackbuffers) {
2290e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        for (uint32_t i = 0; i < surface->mImageCount + 1; ++i) {
2300e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger            mWaitForFences(mBackendContext->fDevice, 2, surface->mBackbuffers[i].mUsageFences, true,
2310e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger                    UINT64_MAX);
2320e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger            surface->mBackbuffers[i].mImageIndex = -1;
2330e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger            mDestroySemaphore(mBackendContext->fDevice, surface->mBackbuffers[i].mAcquireSemaphore,
2340e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger                    nullptr);
2350e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger            mDestroySemaphore(mBackendContext->fDevice, surface->mBackbuffers[i].mRenderSemaphore,
2360e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger                    nullptr);
2370e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger            mFreeCommandBuffers(mBackendContext->fDevice, mCommandPool, 2,
2380e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger                    surface->mBackbuffers[i].mTransitionCmdBuffers);
2390e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger            mDestroyFence(mBackendContext->fDevice, surface->mBackbuffers[i].mUsageFences[0], 0);
2400e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger            mDestroyFence(mBackendContext->fDevice, surface->mBackbuffers[i].mUsageFences[1], 0);
2410e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        }
2420e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    }
2430e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
2440e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    delete[] surface->mBackbuffers;
2450e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    surface->mBackbuffers = nullptr;
2460e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    delete[] surface->mSurfaces;
2470e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    surface->mSurfaces = nullptr;
2480e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    delete[] surface->mImageLayouts;
2490e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    surface->mImageLayouts = nullptr;
2500e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    delete[] surface->mImages;
2510e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    surface->mImages = nullptr;
2520e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger}
2530e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
2540e3cba31460e0698def0310003b7d291f1174afaDerek Sollenbergervoid VulkanManager::destroySurface(VulkanSurface* surface) {
2550e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    // Make sure all submit commands have finished before starting to destroy objects.
2560e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    if (VK_NULL_HANDLE != mPresentQueue) {
2570e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        mQueueWaitIdle(mPresentQueue);
2580e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    }
2590e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    mDeviceWaitIdle(mBackendContext->fDevice);
2600e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
2610e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    destroyBuffers(surface);
2620e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
2630e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    if (VK_NULL_HANDLE != surface->mSwapchain) {
2640e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        mDestroySwapchainKHR(mBackendContext->fDevice, surface->mSwapchain, nullptr);
2650e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        surface->mSwapchain = VK_NULL_HANDLE;
2660e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    }
2670e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
2680e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    if (VK_NULL_HANDLE != surface->mVkSurface) {
2690e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        mDestroySurfaceKHR(mBackendContext->fInstance, surface->mVkSurface, nullptr);
2700e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        surface->mVkSurface = VK_NULL_HANDLE;
2710e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    }
2720e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    delete surface;
2730e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger}
2740e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
2750e3cba31460e0698def0310003b7d291f1174afaDerek Sollenbergervoid VulkanManager::createBuffers(VulkanSurface* surface, VkFormat format, VkExtent2D extent) {
2760e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    mGetSwapchainImagesKHR(mBackendContext->fDevice, surface->mSwapchain, &surface->mImageCount,
2770e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger            nullptr);
2780e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    SkASSERT(surface->mImageCount);
2790e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    surface->mImages = new VkImage[surface->mImageCount];
2800e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    mGetSwapchainImagesKHR(mBackendContext->fDevice, surface->mSwapchain,
2810e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger            &surface->mImageCount, surface->mImages);
2820e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
2830e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
2840e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
2850e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    bool wantSRGB = VK_FORMAT_R8G8B8A8_SRGB == format;
2860e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    GrPixelConfig config = wantSRGB ? kSRGBA_8888_GrPixelConfig : kRGBA_8888_GrPixelConfig;
2870e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
2880e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    // set up initial image layouts and create surfaces
2890e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    surface->mImageLayouts = new VkImageLayout[surface->mImageCount];
2900e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    surface->mSurfaces = new sk_sp<SkSurface>[surface->mImageCount];
2910e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    for (uint32_t i = 0; i < surface->mImageCount; ++i) {
2920e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        GrBackendRenderTargetDesc desc;
2930e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        GrVkImageInfo info;
2940e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        info.fImage = surface->mImages[i];
2950e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        info.fAlloc = { VK_NULL_HANDLE, 0, 0, 0 };
2960e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        info.fImageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
2970e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        info.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
2980e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        info.fFormat = format;
2990e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        info.fLevelCount = 1;
3000e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
3010e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        desc.fWidth = extent.width;
3020e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        desc.fHeight = extent.height;
3030e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        desc.fConfig = config;
3040e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        desc.fOrigin = kTopLeft_GrSurfaceOrigin;
3050e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        desc.fSampleCnt = 0;
3060e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        desc.fStencilBits = 0;
3070e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        desc.fRenderTargetHandle = (GrBackendObject) &info;
3080e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
3090e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        surface->mSurfaces[i] = SkSurface::MakeFromBackendRenderTarget(mRenderThread.getGrContext(),
3100e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger                desc, &props);
3110e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        surface->mImageLayouts[i] = VK_IMAGE_LAYOUT_UNDEFINED;
3120e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    }
3130e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
3140e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    SkASSERT(mCommandPool != VK_NULL_HANDLE);
3150e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
3160e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    // set up the backbuffers
3170e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    VkSemaphoreCreateInfo semaphoreInfo;
3180e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    memset(&semaphoreInfo, 0, sizeof(VkSemaphoreCreateInfo));
3190e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
3200e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    semaphoreInfo.pNext = nullptr;
3210e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    semaphoreInfo.flags = 0;
3220e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    VkCommandBufferAllocateInfo commandBuffersInfo;
3230e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    memset(&commandBuffersInfo, 0, sizeof(VkCommandBufferAllocateInfo));
3240e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    commandBuffersInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
3250e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    commandBuffersInfo.pNext = nullptr;
3260e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    commandBuffersInfo.commandPool = mCommandPool;
3270e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    commandBuffersInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
3280e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    commandBuffersInfo.commandBufferCount = 2;
3290e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    VkFenceCreateInfo fenceInfo;
3300e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    memset(&fenceInfo, 0, sizeof(VkFenceCreateInfo));
3310e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
3320e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    fenceInfo.pNext = nullptr;
3330e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
3340e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
3350e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    // we create one additional backbuffer structure here, because we want to
3360e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    // give the command buffers they contain a chance to finish before we cycle back
3370e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    surface->mBackbuffers = new VulkanSurface::BackbufferInfo[surface->mImageCount + 1];
3380e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    for (uint32_t i = 0; i < surface->mImageCount + 1; ++i) {
3390e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        SkDEBUGCODE(VkResult res);
3400e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        surface->mBackbuffers[i].mImageIndex = -1;
3410e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        SkDEBUGCODE(res = ) mCreateSemaphore(mBackendContext->fDevice, &semaphoreInfo, nullptr,
3420e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger                &surface->mBackbuffers[i].mAcquireSemaphore);
3430e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        SkDEBUGCODE(res = ) mCreateSemaphore(mBackendContext->fDevice, &semaphoreInfo, nullptr,
3440e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger                &surface->mBackbuffers[i].mRenderSemaphore);
3450e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        SkDEBUGCODE(res = ) mAllocateCommandBuffers(mBackendContext->fDevice, &commandBuffersInfo,
3460e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger                surface->mBackbuffers[i].mTransitionCmdBuffers);
3470e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        SkDEBUGCODE(res = ) mCreateFence(mBackendContext->fDevice, &fenceInfo, nullptr,
3480e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger                &surface->mBackbuffers[i].mUsageFences[0]);
3490e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        SkDEBUGCODE(res = ) mCreateFence(mBackendContext->fDevice, &fenceInfo, nullptr,
3500e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger                &surface->mBackbuffers[i].mUsageFences[1]);
3510e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        SkASSERT(VK_SUCCESS == res);
3520e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    }
3530e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    surface->mCurrentBackbufferIndex = surface->mImageCount;
3540e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger}
3550e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
3560e3cba31460e0698def0310003b7d291f1174afaDerek Sollenbergerbool VulkanManager::createSwapchain(VulkanSurface* surface) {
3570e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    // check for capabilities
3580e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    VkSurfaceCapabilitiesKHR caps;
3590e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    VkResult res = mGetPhysicalDeviceSurfaceCapabilitiesKHR(mBackendContext->fPhysicalDevice,
3600e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger            surface->mVkSurface, &caps);
3610e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    if (VK_SUCCESS != res) {
3620e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        return false;
3630e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    }
3640e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
3650e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    uint32_t surfaceFormatCount;
3660e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    res = mGetPhysicalDeviceSurfaceFormatsKHR(mBackendContext->fPhysicalDevice, surface->mVkSurface,
3670e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger            &surfaceFormatCount, nullptr);
3680e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    if (VK_SUCCESS != res) {
3690e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        return false;
3700e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    }
3710e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
3720e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    SkAutoMalloc surfaceFormatAlloc(surfaceFormatCount * sizeof(VkSurfaceFormatKHR));
3730e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    VkSurfaceFormatKHR* surfaceFormats = (VkSurfaceFormatKHR*)surfaceFormatAlloc.get();
3740e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    res = mGetPhysicalDeviceSurfaceFormatsKHR(mBackendContext->fPhysicalDevice, surface->mVkSurface,
3750e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger            &surfaceFormatCount, surfaceFormats);
3760e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    if (VK_SUCCESS != res) {
3770e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        return false;
3780e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    }
3790e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
3800e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    uint32_t presentModeCount;
3810e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    res = mGetPhysicalDeviceSurfacePresentModesKHR(mBackendContext->fPhysicalDevice,
3820e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger            surface->mVkSurface, &presentModeCount, nullptr);
3830e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    if (VK_SUCCESS != res) {
3840e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        return false;
3850e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    }
3860e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
3870e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    SkAutoMalloc presentModeAlloc(presentModeCount * sizeof(VkPresentModeKHR));
3880e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    VkPresentModeKHR* presentModes = (VkPresentModeKHR*)presentModeAlloc.get();
3890e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    res = mGetPhysicalDeviceSurfacePresentModesKHR(mBackendContext->fPhysicalDevice,
3900e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger            surface->mVkSurface, &presentModeCount, presentModes);
3910e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    if (VK_SUCCESS != res) {
3920e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        return false;
3930e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    }
3940e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
3950e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    VkExtent2D extent = caps.currentExtent;
3960e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    // clamp width; to handle currentExtent of -1 and  protect us from broken hints
3970e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    if (extent.width < caps.minImageExtent.width) {
3980e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        extent.width = caps.minImageExtent.width;
3990e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    }
4000e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    SkASSERT(extent.width <= caps.maxImageExtent.width);
4010e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    // clamp height
4020e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    if (extent.height < caps.minImageExtent.height) {
4030e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        extent.height = caps.minImageExtent.height;
4040e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    }
4050e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    SkASSERT(extent.height <= caps.maxImageExtent.height);
4060e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
4070e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    uint32_t imageCount = caps.minImageCount + 2;
4080e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    if (caps.maxImageCount > 0 && imageCount > caps.maxImageCount) {
4090e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        // Application must settle for fewer images than desired:
4100e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        imageCount = caps.maxImageCount;
4110e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    }
4120e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
4130e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    // Currently Skia requires the images to be color attchments and support all transfer
4140e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    // operations.
4150e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
4160e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger                                   VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
4170e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger                                   VK_IMAGE_USAGE_TRANSFER_DST_BIT;
4180e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    SkASSERT((caps.supportedUsageFlags & usageFlags) == usageFlags);
4190e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    SkASSERT(caps.supportedTransforms & caps.currentTransform);
4200e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    SkASSERT(caps.supportedCompositeAlpha & (VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR |
4210e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger                                             VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR));
4220e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    VkCompositeAlphaFlagBitsKHR composite_alpha =
4230e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        (caps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR) ?
4240e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger                                        VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR :
4250e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger                                        VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
4260e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
4270e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    // Pick our surface format. For now, just make sure it matches our sRGB request:
4280e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    VkFormat surfaceFormat = VK_FORMAT_UNDEFINED;
4290e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    VkColorSpaceKHR colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
4300e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
4310e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    bool wantSRGB = false;
4320e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger#ifdef ANDROID_ENABLE_LINEAR_BLENDING
4330e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    wantSRGB = true;
4340e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger#endif
4350e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    for (uint32_t i = 0; i < surfaceFormatCount; ++i) {
4360e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        // We are assuming we can get either R8G8B8A8_UNORM or R8G8B8A8_SRGB
4370e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        VkFormat desiredFormat = wantSRGB ? VK_FORMAT_R8G8B8A8_SRGB : VK_FORMAT_R8G8B8A8_UNORM;
4380e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        if (desiredFormat == surfaceFormats[i].format) {
4390e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger            surfaceFormat = surfaceFormats[i].format;
4400e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger            colorSpace = surfaceFormats[i].colorSpace;
4410e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        }
4420e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    }
4430e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
4440e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    if (VK_FORMAT_UNDEFINED == surfaceFormat) {
4450e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        return false;
4460e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    }
4470e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
4480e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    // If mailbox mode is available, use it, as it is the lowest-latency non-
4490e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    // tearing mode. If not, fall back to FIFO which is always available.
4500e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    VkPresentModeKHR mode = VK_PRESENT_MODE_FIFO_KHR;
4510e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    for (uint32_t i = 0; i < presentModeCount; ++i) {
4520e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        // use mailbox
4530e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        if (VK_PRESENT_MODE_MAILBOX_KHR == presentModes[i]) {
4540e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger            mode = presentModes[i];
4550e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger            break;
4560e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        }
4570e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    }
4580e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
4590e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    VkSwapchainCreateInfoKHR swapchainCreateInfo;
4600e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    memset(&swapchainCreateInfo, 0, sizeof(VkSwapchainCreateInfoKHR));
4610e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    swapchainCreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
4620e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    swapchainCreateInfo.surface = surface->mVkSurface;
4630e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    swapchainCreateInfo.minImageCount = imageCount;
4640e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    swapchainCreateInfo.imageFormat = surfaceFormat;
4650e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    swapchainCreateInfo.imageColorSpace = colorSpace;
4660e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    swapchainCreateInfo.imageExtent = extent;
4670e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    swapchainCreateInfo.imageArrayLayers = 1;
4680e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    swapchainCreateInfo.imageUsage = usageFlags;
4690e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
4700e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    uint32_t queueFamilies[] = { mBackendContext->fGraphicsQueueIndex, mPresentQueueIndex };
4710e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    if (mBackendContext->fGraphicsQueueIndex != mPresentQueueIndex) {
4720e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        swapchainCreateInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
4730e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        swapchainCreateInfo.queueFamilyIndexCount = 2;
4740e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        swapchainCreateInfo.pQueueFamilyIndices = queueFamilies;
4750e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    } else {
4760e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        swapchainCreateInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
4770e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        swapchainCreateInfo.queueFamilyIndexCount = 0;
4780e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        swapchainCreateInfo.pQueueFamilyIndices = nullptr;
4790e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    }
4800e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
4810e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    swapchainCreateInfo.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
4820e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    swapchainCreateInfo.compositeAlpha = composite_alpha;
4830e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    swapchainCreateInfo.presentMode = mode;
4840e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    swapchainCreateInfo.clipped = true;
4850e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    swapchainCreateInfo.oldSwapchain = surface->mSwapchain;
4860e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
4870e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    res = mCreateSwapchainKHR(mBackendContext->fDevice, &swapchainCreateInfo, nullptr,
4880e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger            &surface->mSwapchain);
4890e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    if (VK_SUCCESS != res) {
4900e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        return false;
4910e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    }
4920e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
4930e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    // destroy the old swapchain
4940e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    if (swapchainCreateInfo.oldSwapchain != VK_NULL_HANDLE) {
4950e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        mDeviceWaitIdle(mBackendContext->fDevice);
4960e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
4970e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        destroyBuffers(surface);
4980e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
4990e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        mDestroySwapchainKHR(mBackendContext->fDevice, swapchainCreateInfo.oldSwapchain, nullptr);
5000e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    }
5010e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
5020e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    createBuffers(surface, surfaceFormat, extent);
5030e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
5040e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    return true;
5050e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger}
5060e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
5070e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
5080e3cba31460e0698def0310003b7d291f1174afaDerek SollenbergerVulkanSurface* VulkanManager::createSurface(ANativeWindow* window) {
5090e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    initialize();
5100e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
5110e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    if (!window) {
5120e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        return nullptr;
5130e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    }
5140e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
5150e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    VulkanSurface* surface = new VulkanSurface();
5160e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
5170e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    VkAndroidSurfaceCreateInfoKHR surfaceCreateInfo;
5180e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    memset(&surfaceCreateInfo, 0, sizeof(VkAndroidSurfaceCreateInfoKHR));
5190e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR;
5200e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    surfaceCreateInfo.pNext = nullptr;
5210e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    surfaceCreateInfo.flags = 0;
5220e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    surfaceCreateInfo.window = window;
5230e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
5240e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    VkResult res = mCreateAndroidSurfaceKHR(mBackendContext->fInstance, &surfaceCreateInfo,
5250e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger            nullptr, &surface->mVkSurface);
5260e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    if (VK_SUCCESS != res) {
5270e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        delete surface;
5280e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        return nullptr;
5290e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    }
5300e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
5310e3cba31460e0698def0310003b7d291f1174afaDerek SollenbergerSkDEBUGCODE(
5320e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    VkBool32 supported;
5330e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    res = mGetPhysicalDeviceSurfaceSupportKHR(mBackendContext->fPhysicalDevice,
5340e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger            mPresentQueueIndex, surface->mVkSurface, &supported);
5350e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    // All physical devices and queue families on Android must be capable of presentation with any
5360e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    // native window.
5370e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    SkASSERT(VK_SUCCESS == res && supported);
5380e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger);
5390e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
5400e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    if (!createSwapchain(surface)) {
5410e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        destroySurface(surface);
5420e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        return nullptr;
5430e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    }
5440e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
5450e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    return surface;
5460e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger}
5470e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
5480e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger// Helper to know which src stage flags we need to set when transitioning to the present layout
5490e3cba31460e0698def0310003b7d291f1174afaDerek Sollenbergerstatic VkPipelineStageFlags layoutToPipelineStageFlags(const VkImageLayout layout) {
5500e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    if (VK_IMAGE_LAYOUT_GENERAL == layout) {
5510e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        return VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
5520e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    } else if (VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL == layout ||
5530e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger               VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL == layout) {
5540e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        return VK_PIPELINE_STAGE_TRANSFER_BIT;
5550e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    } else if (VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL == layout ||
5560e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger               VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL == layout ||
5570e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger               VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL == layout ||
5580e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger               VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL == layout) {
5590e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        return VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT;
5600e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    } else if (VK_IMAGE_LAYOUT_PREINITIALIZED == layout) {
5610e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        return VK_PIPELINE_STAGE_HOST_BIT;
5620e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    }
5630e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
5640e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    SkASSERT(VK_IMAGE_LAYOUT_UNDEFINED == layout);
5650e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    return VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
5660e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger}
5670e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
5680e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger// Helper to know which src access mask we need to set when transitioning to the present layout
5690e3cba31460e0698def0310003b7d291f1174afaDerek Sollenbergerstatic VkAccessFlags layoutToSrcAccessMask(const VkImageLayout layout) {
5700e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    VkAccessFlags flags = 0;
5710e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    if (VK_IMAGE_LAYOUT_GENERAL == layout) {
5720e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        flags = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
5730e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger                VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
5740e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger                VK_ACCESS_TRANSFER_WRITE_BIT |
5750e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger                VK_ACCESS_TRANSFER_READ_BIT |
5760e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger                VK_ACCESS_SHADER_READ_BIT |
5770e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger                VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_HOST_READ_BIT;
5780e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    } else if (VK_IMAGE_LAYOUT_PREINITIALIZED == layout) {
5790e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        flags = VK_ACCESS_HOST_WRITE_BIT;
5800e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    } else if (VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL == layout) {
5810e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        flags = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
5820e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    } else if (VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL == layout) {
5830e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        flags = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
5840e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    } else if (VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL == layout) {
5850e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        flags = VK_ACCESS_TRANSFER_WRITE_BIT;
5860e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    } else if (VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL == layout) {
5870e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        flags = VK_ACCESS_TRANSFER_READ_BIT;
5880e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    } else if (VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL == layout) {
5890e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        flags = VK_ACCESS_SHADER_READ_BIT;
5900e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    }
5910e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    return flags;
5920e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger}
5930e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
5940e3cba31460e0698def0310003b7d291f1174afaDerek Sollenbergervoid VulkanManager::swapBuffers(VulkanSurface* surface) {
5950e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    VulkanSurface::BackbufferInfo* backbuffer = surface->mBackbuffers +
5960e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger            surface->mCurrentBackbufferIndex;
5970e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    GrVkImageInfo* imageInfo;
5980e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    SkSurface* skSurface = surface->mSurfaces[backbuffer->mImageIndex].get();
5990e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    skSurface->getRenderTargetHandle((GrBackendObject*)&imageInfo,
6000e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger            SkSurface::kFlushRead_BackendHandleAccess);
6010e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    // Check to make sure we never change the actually wrapped image
6020e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    SkASSERT(imageInfo->fImage == surface->mImages[backbuffer->mImageIndex]);
6030e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
6040e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    // We need to transition the image to VK_IMAGE_LAYOUT_PRESENT_SRC_KHR and make sure that all
6050e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    // previous work is complete for before presenting. So we first add the necessary barrier here.
6060e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    VkImageLayout layout = imageInfo->fImageLayout;
6070e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    VkPipelineStageFlags srcStageMask = layoutToPipelineStageFlags(layout);
6080e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
6090e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    VkAccessFlags srcAccessMask = layoutToSrcAccessMask(layout);
6100e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    VkAccessFlags dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
6110e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
6120e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    VkImageMemoryBarrier imageMemoryBarrier = {
6130e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,    // sType
6140e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        NULL,                                      // pNext
6150e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        srcAccessMask,                             // outputMask
6160e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        dstAccessMask,                             // inputMask
6170e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        layout,                                    // oldLayout
6180e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,           // newLayout
6190e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        mBackendContext->fGraphicsQueueIndex,      // srcQueueFamilyIndex
6200e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        mPresentQueueIndex,                        // dstQueueFamilyIndex
6210e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        surface->mImages[backbuffer->mImageIndex], // image
6220e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }  // subresourceRange
6230e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    };
6240e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
6250e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    mResetCommandBuffer(backbuffer->mTransitionCmdBuffers[1], 0);
6260e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    VkCommandBufferBeginInfo info;
6270e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    memset(&info, 0, sizeof(VkCommandBufferBeginInfo));
6280e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
6290e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    info.flags = 0;
6300e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    mBeginCommandBuffer(backbuffer->mTransitionCmdBuffers[1], &info);
6310e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    mCmdPipelineBarrier(backbuffer->mTransitionCmdBuffers[1], srcStageMask, dstStageMask, 0,
6320e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger            0, nullptr, 0, nullptr, 1, &imageMemoryBarrier);
6330e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    mEndCommandBuffer(backbuffer->mTransitionCmdBuffers[1]);
6340e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
6350e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    surface->mImageLayouts[backbuffer->mImageIndex] = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
6360e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
6370e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    // insert the layout transfer into the queue and wait on the acquire
6380e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    VkSubmitInfo submitInfo;
6390e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    memset(&submitInfo, 0, sizeof(VkSubmitInfo));
6400e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
6410e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    submitInfo.waitSemaphoreCount = 0;
6420e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    submitInfo.pWaitDstStageMask = 0;
6430e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    submitInfo.commandBufferCount = 1;
6440e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    submitInfo.pCommandBuffers = &backbuffer->mTransitionCmdBuffers[1];
6450e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    submitInfo.signalSemaphoreCount = 1;
6460e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    // When this command buffer finishes we will signal this semaphore so that we know it is now
6470e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    // safe to present the image to the screen.
6480e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    submitInfo.pSignalSemaphores = &backbuffer->mRenderSemaphore;
6490e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
6500e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    // Attach second fence to submission here so we can track when the command buffer finishes.
6510e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    mQueueSubmit(mBackendContext->fQueue, 1, &submitInfo, backbuffer->mUsageFences[1]);
6520e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
6530e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    // Submit present operation to present queue. We use a semaphore here to make sure all rendering
6540e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    // to the image is complete and that the layout has been change to present on the graphics
6550e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    // queue.
6560e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    const VkPresentInfoKHR presentInfo =
6570e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    {
6580e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, // sType
6590e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        NULL, // pNext
6600e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        1, // waitSemaphoreCount
6610e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        &backbuffer->mRenderSemaphore, // pWaitSemaphores
6620e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        1, // swapchainCount
6630e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        &surface->mSwapchain, // pSwapchains
6640e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        &backbuffer->mImageIndex, // pImageIndices
6650e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger        NULL // pResults
6660e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    };
6670e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
6680e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    mQueuePresentKHR(mPresentQueue, &presentInfo);
6690e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
6700e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger    surface->mBackbuffer.reset();
6710e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger}
6720e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger
6730e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger} /* namespace renderthread */
6740e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger} /* namespace uirenderer */
6750e3cba31460e0698def0310003b7d291f1174afaDerek Sollenberger} /* namespace android */
676