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