GrVkGpu.cpp revision 4bcd62e3313da60c3aa96ccd12b7ea440c7266d4
1164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel/*
2164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel * Copyright 2015 Google Inc.
3164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel *
4164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel * Use of this source code is governed by a BSD-style license that can be
5164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel * found in the LICENSE file.
6164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel */
7164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
8164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkGpu.h"
9164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
10164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrContextOptions.h"
11164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrGeometryProcessor.h"
12164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrGpuResourceCacheAccess.h"
130e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel#include "GrMesh.h"
14164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrPipeline.h"
15164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrRenderTargetPriv.h"
16164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrSurfacePriv.h"
17164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrTexturePriv.h"
18164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
19164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkCommandBuffer.h"
20066df7ca911b65d416783f3bec6f4f1662948ad5egdaniel#include "GrVkGpuCommandBuffer.h"
21164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkImage.h"
22164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkIndexBuffer.h"
23164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkMemory.h"
24164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkPipeline.h"
2522281c13a13c4b4e275516e9fe02185a53a7e5aaegdaniel#include "GrVkPipelineState.h"
26164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkRenderPass.h"
27164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkResourceProvider.h"
28164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkTexture.h"
29164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkTextureRenderTarget.h"
30164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkTransferBuffer.h"
31164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkVertexBuffer.h"
32164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
33164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "SkConfig8888.h"
34900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth#include "SkMipMap.h"
35164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
36164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "vk/GrVkInterface.h"
37fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth#include "vk/GrVkTypes.h"
38164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
39b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#if USE_SKSL
40b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "SkSLCompiler.h"
41b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#endif
42b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
43164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#define VK_CALL(X) GR_VK_CALL(this->vkInterface(), X)
44164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#define VK_CALL_RET(RET, X) GR_VK_CALL_RET(this->vkInterface(), RET, X)
45164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#define VK_CALL_ERRCHECK(X) GR_VK_CALL_ERRCHECK(this->vkInterface(), X)
46164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
47735109c24892a95290974c9665527b57b01e5440egdaniel#ifdef SK_ENABLE_VK_LAYERS
48d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverthVKAPI_ATTR VkBool32 VKAPI_CALL DebugReportCallback(
49d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    VkDebugReportFlagsEXT       flags,
50d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    VkDebugReportObjectTypeEXT  objectType,
51d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    uint64_t                    object,
52d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    size_t                      location,
53d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    int32_t                     messageCode,
54d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    const char*                 pLayerPrefix,
55d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    const char*                 pMessage,
56d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    void*                       pUserData) {
57d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    if (flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
58d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        SkDebugf("Vulkan error [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
59d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    } else if (flags & VK_DEBUG_REPORT_WARNING_BIT_EXT) {
60d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        SkDebugf("Vulkan warning [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
61d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    } else if (flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) {
62d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        SkDebugf("Vulkan perf warning [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
63d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    } else {
64d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        SkDebugf("Vulkan info/debug [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
65d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    }
66d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    return VK_FALSE;
67d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth}
68d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth#endif
69d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth
70633b35657c964c32e7010b14bb2d396b4a764c52jvanverthGrGpu* GrVkGpu::Create(GrBackendContext backendContext, const GrContextOptions& options,
71633b35657c964c32e7010b14bb2d396b4a764c52jvanverth                       GrContext* context) {
72dc0fcd41e75682a8bfd5e285d684461475226330bsalomon    const GrVkBackendContext* vkBackendContext =
73dc0fcd41e75682a8bfd5e285d684461475226330bsalomon        reinterpret_cast<const GrVkBackendContext*>(backendContext);
74633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    if (!vkBackendContext) {
75dc0fcd41e75682a8bfd5e285d684461475226330bsalomon        vkBackendContext = GrVkBackendContext::Create();
76633b35657c964c32e7010b14bb2d396b4a764c52jvanverth        if (!vkBackendContext) {
77633b35657c964c32e7010b14bb2d396b4a764c52jvanverth            return nullptr;
78164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
79633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    } else {
80633b35657c964c32e7010b14bb2d396b4a764c52jvanverth        vkBackendContext->ref();
81164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
82164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
83633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    return new GrVkGpu(context, options, vkBackendContext);
84164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
85164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
86164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
87164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
889d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanaryGrVkGpu::GrVkGpu(GrContext* context, const GrContextOptions& options,
89633b35657c964c32e7010b14bb2d396b4a764c52jvanverth                 const GrVkBackendContext* backendCtx)
90164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    : INHERITED(context)
91633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    , fDevice(backendCtx->fDevice)
92633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    , fQueue(backendCtx->fQueue)
93633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    , fResourceProvider(this) {
94633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    fBackendContext.reset(backendCtx);
95164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
96735109c24892a95290974c9665527b57b01e5440egdaniel#ifdef SK_ENABLE_VK_LAYERS
97419ca64f0f800dc098369b5aa5a604acd017b240brianosman    fCallback = VK_NULL_HANDLE;
98fd7bd45ac2178ce6b4a390f517f605750aaef6c8jvanverth    if (backendCtx->fExtensions & kEXT_debug_report_GrVkExtensionFlag) {
99fd7bd45ac2178ce6b4a390f517f605750aaef6c8jvanverth        // Setup callback creation information
100d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        VkDebugReportCallbackCreateInfoEXT callbackCreateInfo;
101d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        callbackCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
102d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        callbackCreateInfo.pNext = nullptr;
103d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        callbackCreateInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT |
104ef0c10cffefef90646ff2e238d7c2d82247a0370egdaniel                                   VK_DEBUG_REPORT_WARNING_BIT_EXT |
105d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth                                   //VK_DEBUG_REPORT_INFORMATION_BIT_EXT |
106d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth                                   //VK_DEBUG_REPORT_DEBUG_BIT_EXT |
107b4aa36211ca66ef127ac2954108742af1ead5082egdaniel                                   VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
108d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        callbackCreateInfo.pfnCallback = &DebugReportCallback;
109d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        callbackCreateInfo.pUserData = nullptr;
110d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth
111fd7bd45ac2178ce6b4a390f517f605750aaef6c8jvanverth        // Register the callback
112a00980e58037fa36d066be80d7fcc0f73b2dfd40jvanverth        GR_VK_CALL_ERRCHECK(this->vkInterface(), CreateDebugReportCallbackEXT(
113a00980e58037fa36d066be80d7fcc0f73b2dfd40jvanverth                            backendCtx->fInstance, &callbackCreateInfo, nullptr, &fCallback));
114d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    }
115d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth#endif
116633b35657c964c32e7010b14bb2d396b4a764c52jvanverth
117b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#if USE_SKSL
118b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    fCompiler = new SkSL::Compiler();
119b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#else
120633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    fCompiler = shaderc_compiler_initialize();
121b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#endif
122633b35657c964c32e7010b14bb2d396b4a764c52jvanverth
123fd7bd45ac2178ce6b4a390f517f605750aaef6c8jvanverth    fVkCaps.reset(new GrVkCaps(options, this->vkInterface(), backendCtx->fPhysicalDevice,
124c5ec1408298510410270ea67e895570ccfa76e54egdaniel                               backendCtx->fFeatures, backendCtx->fExtensions));
125633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    fCaps.reset(SkRef(fVkCaps.get()));
126633b35657c964c32e7010b14bb2d396b4a764c52jvanverth
127633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    VK_CALL(GetPhysicalDeviceMemoryProperties(backendCtx->fPhysicalDevice, &fPhysDevMemProps));
128633b35657c964c32e7010b14bb2d396b4a764c52jvanverth
129633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    const VkCommandPoolCreateInfo cmdPoolInfo = {
1307ec92413307c9da43c013d1e4e15716a44059810jvanverth        VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // sType
1317ec92413307c9da43c013d1e4e15716a44059810jvanverth        nullptr,                                         // pNext
1327ec92413307c9da43c013d1e4e15716a44059810jvanverth        VK_COMMAND_POOL_CREATE_TRANSIENT_BIT |
1337ec92413307c9da43c013d1e4e15716a44059810jvanverth        VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // CmdPoolCreateFlags
1347ec92413307c9da43c013d1e4e15716a44059810jvanverth        backendCtx->fGraphicsQueueIndex,                 // queueFamilyIndex
135633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    };
1369d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary    GR_VK_CALL_ERRCHECK(this->vkInterface(), CreateCommandPool(fDevice, &cmdPoolInfo, nullptr,
137633b35657c964c32e7010b14bb2d396b4a764c52jvanverth                                                               &fCmdPool));
138633b35657c964c32e7010b14bb2d396b4a764c52jvanverth
139633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    // must call this after creating the CommandPool
140633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    fResourceProvider.init();
1417ec92413307c9da43c013d1e4e15716a44059810jvanverth    fCurrentCmdBuffer = fResourceProvider.findOrCreatePrimaryCommandBuffer();
142633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    SkASSERT(fCurrentCmdBuffer);
143633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    fCurrentCmdBuffer->begin(this);
1446b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth
1456b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    // set up our heaps
1466b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    fHeaps[kLinearImage_Heap].reset(new GrVkHeap(this, GrVkHeap::kSubAlloc_Strategy, 16*1024*1024));
14705dceabf3422b785b52439378aa5527c42c6ca18egdaniel    // We want the OptimalImage_Heap to use a SubAlloc_strategy but it occasionally causes the
14805dceabf3422b785b52439378aa5527c42c6ca18egdaniel    // device to run out of memory. Most likely this is caused by fragmentation in the device heap
14905dceabf3422b785b52439378aa5527c42c6ca18egdaniel    // and we can't allocate more. Until we get a fix moving this to SingleAlloc.
15005dceabf3422b785b52439378aa5527c42c6ca18egdaniel    fHeaps[kOptimalImage_Heap].reset(new GrVkHeap(this, GrVkHeap::kSingleAlloc_Strategy, 64*1024*1024));
1516b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    fHeaps[kSmallOptimalImage_Heap].reset(new GrVkHeap(this, GrVkHeap::kSubAlloc_Strategy, 2*1024*1024));
1526b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    fHeaps[kVertexBuffer_Heap].reset(new GrVkHeap(this, GrVkHeap::kSingleAlloc_Strategy, 0));
1536b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    fHeaps[kIndexBuffer_Heap].reset(new GrVkHeap(this, GrVkHeap::kSingleAlloc_Strategy, 0));
1544c6e47a8a827077e36fa5feb4ab5ac7435d8276bjvanverth    fHeaps[kUniformBuffer_Heap].reset(new GrVkHeap(this, GrVkHeap::kSubAlloc_Strategy, 256*1024));
1556b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    fHeaps[kCopyReadBuffer_Heap].reset(new GrVkHeap(this, GrVkHeap::kSingleAlloc_Strategy, 0));
1566b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    fHeaps[kCopyWriteBuffer_Heap].reset(new GrVkHeap(this, GrVkHeap::kSubAlloc_Strategy, 16*1024*1024));
157164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
158164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
159164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielGrVkGpu::~GrVkGpu() {
160164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->end(this);
161164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->unref(this);
162164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
163164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // wait for all commands to finish
164ddf9835e9cdf512b1d5172d014f00ceb6dacd039jvanverth    fResourceProvider.checkCommandBuffers();
165a00980e58037fa36d066be80d7fcc0f73b2dfd40jvanverth    SkDEBUGCODE(VkResult res = ) VK_CALL(QueueWaitIdle(fQueue));
166f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel
167f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel    // On windows, sometimes calls to QueueWaitIdle return before actually signalling the fences
168f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel    // on the command buffers even though they have completed. This causes an assert to fire when
169f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel    // destroying the command buffers. Currently this ony seems to happen on windows, so we add a
170f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel    // sleep to make sure the fence singals.
171f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel#ifdef SK_DEBUG
172f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel#if defined(SK_BUILD_FOR_WIN)
173f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel    Sleep(10); // In milliseconds
174f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel#else
175f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel    // Uncomment if above bug happens on non windows build.
176f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel    // sleep(1);        // In seconds
177f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel#endif
178f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel#endif
179f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel
180ddf9835e9cdf512b1d5172d014f00ceb6dacd039jvanverth    // VK_ERROR_DEVICE_LOST is acceptable when tearing down (see 4.2.4 in spec)
181ddf9835e9cdf512b1d5172d014f00ceb6dacd039jvanverth    SkASSERT(VK_SUCCESS == res || VK_ERROR_DEVICE_LOST == res);
1829d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
183164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // must call this just before we destroy the VkDevice
184164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fResourceProvider.destroyResources();
185164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
186633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    VK_CALL(DestroyCommandPool(fDevice, fCmdPool, nullptr));
187633b35657c964c32e7010b14bb2d396b4a764c52jvanverth
188b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#if USE_SKSL
189b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    delete fCompiler;
190b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#else
191633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    shaderc_compiler_release(fCompiler);
192b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#endif
193633b35657c964c32e7010b14bb2d396b4a764c52jvanverth
194735109c24892a95290974c9665527b57b01e5440egdaniel#ifdef SK_ENABLE_VK_LAYERS
195a00980e58037fa36d066be80d7fcc0f73b2dfd40jvanverth    if (fCallback) {
196a00980e58037fa36d066be80d7fcc0f73b2dfd40jvanverth        VK_CALL(DestroyDebugReportCallbackEXT(fBackendContext->fInstance, fCallback, nullptr));
197419ca64f0f800dc098369b5aa5a604acd017b240brianosman        fCallback = VK_NULL_HANDLE;
198a00980e58037fa36d066be80d7fcc0f73b2dfd40jvanverth    }
199d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth#endif
200164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
201164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
202164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel///////////////////////////////////////////////////////////////////////////////
203164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
2049cb6340a62a5d748e4189d50e51fa527c8c80c03egdanielGrGpuCommandBuffer* GrVkGpu::createCommandBuffer(
2059cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel            GrRenderTarget* target,
2069cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel            const GrGpuCommandBuffer::LoadAndStoreInfo& colorInfo,
2079cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel            const GrGpuCommandBuffer::LoadAndStoreInfo& stencilInfo) {
2089cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel    GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(target);
2099cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel    return new GrVkGpuCommandBuffer(this, vkRT, colorInfo, stencilInfo);
210066df7ca911b65d416783f3bec6f4f1662948ad5egdaniel}
211066df7ca911b65d416783f3bec6f4f1662948ad5egdaniel
212164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::submitCommandBuffer(SyncQueue sync) {
213164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(fCurrentCmdBuffer);
214164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->end(this);
215164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
216164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->submitToQueue(this, fQueue, sync);
217164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fResourceProvider.checkCommandBuffers();
218164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
219164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Release old command buffer and create a new one
220164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->unref(this);
2217ec92413307c9da43c013d1e4e15716a44059810jvanverth    fCurrentCmdBuffer = fResourceProvider.findOrCreatePrimaryCommandBuffer();
222164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(fCurrentCmdBuffer);
223164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
224164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->begin(this);
225164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
226164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
227164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel///////////////////////////////////////////////////////////////////////////////
2281bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdaltonGrBuffer* GrVkGpu::onCreateBuffer(size_t size, GrBufferType type, GrAccessPattern accessPattern,
2291bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton                                  const void* data) {
2301bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton    GrBuffer* buff;
231397536cabe12a9936659870dd220c869789424bacdalton    switch (type) {
232397536cabe12a9936659870dd220c869789424bacdalton        case kVertex_GrBufferType:
233397536cabe12a9936659870dd220c869789424bacdalton            SkASSERT(kDynamic_GrAccessPattern == accessPattern ||
234397536cabe12a9936659870dd220c869789424bacdalton                     kStatic_GrAccessPattern == accessPattern);
2351bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton            buff = GrVkVertexBuffer::Create(this, size, kDynamic_GrAccessPattern == accessPattern);
236e05bbbba79c569c1d32fa6475feecd1477fd3beeegdaniel            break;
237397536cabe12a9936659870dd220c869789424bacdalton        case kIndex_GrBufferType:
238397536cabe12a9936659870dd220c869789424bacdalton            SkASSERT(kDynamic_GrAccessPattern == accessPattern ||
239397536cabe12a9936659870dd220c869789424bacdalton                     kStatic_GrAccessPattern == accessPattern);
2401bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton            buff = GrVkIndexBuffer::Create(this, size, kDynamic_GrAccessPattern == accessPattern);
241e05bbbba79c569c1d32fa6475feecd1477fd3beeegdaniel            break;
242397536cabe12a9936659870dd220c869789424bacdalton        case kXferCpuToGpu_GrBufferType:
243c3d706f7ce87cdd94158d2266ab2fe2f18f5020ajvanverth            SkASSERT(kStream_GrAccessPattern == accessPattern);
2441bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton            buff = GrVkTransferBuffer::Create(this, size, GrVkBuffer::kCopyRead_Type);
245e05bbbba79c569c1d32fa6475feecd1477fd3beeegdaniel            break;
246397536cabe12a9936659870dd220c869789424bacdalton        case kXferGpuToCpu_GrBufferType:
247c3d706f7ce87cdd94158d2266ab2fe2f18f5020ajvanverth            SkASSERT(kStream_GrAccessPattern == accessPattern);
2481bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton            buff = GrVkTransferBuffer::Create(this, size, GrVkBuffer::kCopyWrite_Type);
249e05bbbba79c569c1d32fa6475feecd1477fd3beeegdaniel            break;
250397536cabe12a9936659870dd220c869789424bacdalton        default:
251397536cabe12a9936659870dd220c869789424bacdalton            SkFAIL("Unknown buffer type.");
252397536cabe12a9936659870dd220c869789424bacdalton            return nullptr;
253397536cabe12a9936659870dd220c869789424bacdalton    }
2541bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton    if (data && buff) {
2551bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton        buff->updateData(data, size);
2561bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton    }
2571bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton    return buff;
258164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
259164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
260164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
261164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::onGetWritePixelsInfo(GrSurface* dstSurface, int width, int height,
262164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                   GrPixelConfig srcConfig, DrawPreference* drawPreference,
263164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                   WritePixelTempDrawInfo* tempDrawInfo) {
264164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (kIndex_8_GrPixelConfig == srcConfig || GrPixelConfigIsCompressed(dstSurface->config())) {
265164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
266164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
267164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
2684583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    GrRenderTarget* renderTarget = dstSurface->asRenderTarget();
2694583ec51d9ddc830eeb854db068235be96ce59c4egdaniel
2704583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    // Start off assuming no swizzling
2714583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    tempDrawInfo->fSwizzle = GrSwizzle::RGBA();
2724583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    tempDrawInfo->fWriteConfig = srcConfig;
2734583ec51d9ddc830eeb854db068235be96ce59c4egdaniel
2744583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    // These settings we will always want if a temp draw is performed. Initially set the config
2754583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    // to srcConfig, though that may be modified if we decide to do a R/B swap
2764583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    tempDrawInfo->fTempSurfaceDesc.fFlags = kNone_GrSurfaceFlags;
2774583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    tempDrawInfo->fTempSurfaceDesc.fConfig = srcConfig;
2784583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    tempDrawInfo->fTempSurfaceDesc.fWidth = width;
2794583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    tempDrawInfo->fTempSurfaceDesc.fHeight = height;
2804583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    tempDrawInfo->fTempSurfaceDesc.fSampleCnt = 0;
2814583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    tempDrawInfo->fTempSurfaceDesc.fOrigin = kTopLeft_GrSurfaceOrigin;
2824583ec51d9ddc830eeb854db068235be96ce59c4egdaniel
283d66110f5972169dbcda8932c3a9a001adff23df4egdaniel    if (dstSurface->config() == srcConfig) {
284d66110f5972169dbcda8932c3a9a001adff23df4egdaniel        return true;
285d66110f5972169dbcda8932c3a9a001adff23df4egdaniel    }
286d66110f5972169dbcda8932c3a9a001adff23df4egdaniel
28766933552f1723c4a2b248711ab3d43921401e8e6egdaniel    if (renderTarget && this->vkCaps().isConfigRenderable(renderTarget->config(),
28866933552f1723c4a2b248711ab3d43921401e8e6egdaniel                                                          renderTarget->numColorSamples() > 1)) {
2894583ec51d9ddc830eeb854db068235be96ce59c4egdaniel        ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
2904583ec51d9ddc830eeb854db068235be96ce59c4egdaniel
2914583ec51d9ddc830eeb854db068235be96ce59c4egdaniel        bool configsAreRBSwaps = GrPixelConfigSwapRAndB(srcConfig) == dstSurface->config();
2924583ec51d9ddc830eeb854db068235be96ce59c4egdaniel
2934583ec51d9ddc830eeb854db068235be96ce59c4egdaniel        if (!this->vkCaps().isConfigTexturable(srcConfig) && configsAreRBSwaps) {
2944583ec51d9ddc830eeb854db068235be96ce59c4egdaniel            if (!this->vkCaps().isConfigTexturable(dstSurface->config())) {
2954583ec51d9ddc830eeb854db068235be96ce59c4egdaniel                return false;
2964583ec51d9ddc830eeb854db068235be96ce59c4egdaniel            }
2974583ec51d9ddc830eeb854db068235be96ce59c4egdaniel            tempDrawInfo->fTempSurfaceDesc.fConfig = dstSurface->config();
2984583ec51d9ddc830eeb854db068235be96ce59c4egdaniel            tempDrawInfo->fSwizzle = GrSwizzle::BGRA();
2994583ec51d9ddc830eeb854db068235be96ce59c4egdaniel            tempDrawInfo->fWriteConfig = dstSurface->config();
3004583ec51d9ddc830eeb854db068235be96ce59c4egdaniel        }
3014583ec51d9ddc830eeb854db068235be96ce59c4egdaniel        return true;
302164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
303164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
3044583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    return false;
305164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
306164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
307164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::onWritePixels(GrSurface* surface,
308164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                            int left, int top, int width, int height,
309a1e6b3be8124cef85f2e39e3cb85000ad9526d48bsalomon                            GrPixelConfig config,
310a1e6b3be8124cef85f2e39e3cb85000ad9526d48bsalomon                            const SkTArray<GrMipLevel>& texels) {
311164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkTexture* vkTex = static_cast<GrVkTexture*>(surface->asTexture());
312164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!vkTex) {
313164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
314164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
315164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
316900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // Make sure we have at least the base level
31703509eafa3e25819ff69f4d4f339d46264820c38jvanverth    if (texels.empty() || !texels.begin()->fPixels) {
31803509eafa3e25819ff69f4d4f339d46264820c38jvanverth        return false;
31903509eafa3e25819ff69f4d4f339d46264820c38jvanverth    }
320a1e6b3be8124cef85f2e39e3cb85000ad9526d48bsalomon
321164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // We assume Vulkan doesn't do sRGB <-> linear conversions when reading and writing pixels.
322164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (GrPixelConfigIsSRGB(surface->config()) != GrPixelConfigIsSRGB(config)) {
323164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
324164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
325164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
326164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    bool success = false;
327164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (GrPixelConfigIsCompressed(vkTex->desc().fConfig)) {
328164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // We check that config == desc.fConfig in GrGpu::getWritePixelsInfo()
329164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        SkASSERT(config == vkTex->desc().fConfig);
330164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // TODO: add compressed texture support
331164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // delete the following two lines and uncomment the two after that when ready
332164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        vkTex->unref();
333164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
334164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        //success = this->uploadCompressedTexData(vkTex->desc(), buffer, false, left, top, width,
335164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        //                                       height);
336164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    } else {
337164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        bool linearTiling = vkTex->isLinearTiled();
338900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        if (linearTiling) {
339900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            if (texels.count() > 1) {
340900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                SkDebugf("Can't upload mipmap data to linear tiled texture");
341900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                return false;
342900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            }
343900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            if (VK_IMAGE_LAYOUT_PREINITIALIZED != vkTex->currentLayout()) {
344900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                // Need to change the layout to general in order to perform a host write
345900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                vkTex->setImageLayout(this,
346900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                      VK_IMAGE_LAYOUT_GENERAL,
34750c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                                      VK_ACCESS_HOST_WRITE_BIT,
34850c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                                      VK_PIPELINE_STAGE_HOST_BIT,
349900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                      false);
350bdf8811b3126ab08ccff08b5e647b80cae5bd087egdaniel                this->submitCommandBuffer(kForce_SyncQueue);
351900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            }
352900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            success = this->uploadTexDataLinear(vkTex, left, top, width, height, config,
353900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                                texels.begin()->fPixels, texels.begin()->fRowBytes);
354900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        } else {
355c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth            int newMipLevels = texels.count();
35682c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth            int currentMipLevels = vkTex->texturePriv().maxMipMapLevel() + 1;
35782c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth            if (newMipLevels != currentMipLevels) {
358c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth                if (!vkTex->reallocForMipmap(this, newMipLevels)) {
359900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                    return false;
360900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                }
361900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            }
362900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            success = this->uploadTexDataOptimal(vkTex, left, top, width, height, config, texels);
363164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
364164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
3654583ec51d9ddc830eeb854db068235be96ce59c4egdaniel
366900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    return success;
367164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
368164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
3694bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdanielvoid GrVkGpu::resolveImage(GrVkRenderTarget* dst, GrVkRenderTarget* src, const SkIRect& srcRect,
3704bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel                           const SkIPoint& dstPoint) {
3714bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    SkASSERT(dst);
3724bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    SkASSERT(src && src->numColorSamples() > 1 && src->msaaImage());
3734bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel
3744bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    // Flip rect if necessary
3754bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    SkIRect srcVkRect = srcRect;
3764bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    int32_t dstY = dstPoint.fY;
3774bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel
3784bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    if (kBottomLeft_GrSurfaceOrigin == src->origin()) {
3794bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        SkASSERT(kBottomLeft_GrSurfaceOrigin == dst->origin());
3804bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        srcVkRect.fTop = src->height() - srcRect.fBottom;
3814bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        srcVkRect.fBottom = src->height() - srcRect.fTop;
3824bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        dstY = dst->height() - dstPoint.fY - srcVkRect.height();
3834bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    }
3844bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel
3854bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    VkImageResolve resolveInfo;
3864bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    resolveInfo.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
3874bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    resolveInfo.srcOffset = { srcVkRect.fLeft, srcVkRect.fTop, 0 };
3884bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    resolveInfo.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
3894bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    resolveInfo.dstOffset = { dstPoint.fX, dstY, 0 };
3904bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    // By the spec the depth of the extent should be ignored for 2D images, but certain devices
3914bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    // (e.g. nexus 5x) currently fail if it is not 1
3924bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    resolveInfo.extent = { (uint32_t)srcVkRect.width(), (uint32_t)srcVkRect.height(), 1 };
3934bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel
3944bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    dst->setImageLayout(this,
3954bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel                        VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
3964bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel                        VK_ACCESS_TRANSFER_WRITE_BIT,
3974bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel                        VK_PIPELINE_STAGE_TRANSFER_BIT,
3984bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel                        false);
3994bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel
4004bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    src->msaaImage()->setImageLayout(this,
4014bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel                                     VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
4024bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel                                     VK_ACCESS_TRANSFER_READ_BIT,
4034bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel                                     VK_PIPELINE_STAGE_TRANSFER_BIT,
4044bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel                                     false);
4054bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel
4064bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    fCurrentCmdBuffer->resolveImage(this, *src->msaaImage(), *dst, 1, &resolveInfo);
4074bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel}
4084bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel
40952ad25151a1c7d1ac3872971f56adf15200c437eegdanielvoid GrVkGpu::onResolveRenderTarget(GrRenderTarget* target) {
41066933552f1723c4a2b248711ab3d43921401e8e6egdaniel    if (target->needsResolve()) {
41166933552f1723c4a2b248711ab3d43921401e8e6egdaniel        SkASSERT(target->numColorSamples() > 1);
41252ad25151a1c7d1ac3872971f56adf15200c437eegdaniel        GrVkRenderTarget* rt = static_cast<GrVkRenderTarget*>(target);
41352ad25151a1c7d1ac3872971f56adf15200c437eegdaniel        SkASSERT(rt->msaaImage());
4144bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel
4154bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        const SkIRect& srcRect = rt->getResolveRect();
41652ad25151a1c7d1ac3872971f56adf15200c437eegdaniel
4174bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        this->resolveImage(rt, rt, srcRect, SkIPoint::Make(srcRect.fLeft, srcRect.fTop));
41852ad25151a1c7d1ac3872971f56adf15200c437eegdaniel
41952ad25151a1c7d1ac3872971f56adf15200c437eegdaniel        rt->flagAsResolved();
42052ad25151a1c7d1ac3872971f56adf15200c437eegdaniel    }
42152ad25151a1c7d1ac3872971f56adf15200c437eegdaniel}
42252ad25151a1c7d1ac3872971f56adf15200c437eegdaniel
423900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverthbool GrVkGpu::uploadTexDataLinear(GrVkTexture* tex,
424900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                  int left, int top, int width, int height,
425900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                  GrPixelConfig dataConfig,
426900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                  const void* data,
427900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                  size_t rowBytes) {
428164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(data);
429900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    SkASSERT(tex->isLinearTiled());
430164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
431164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // If we're uploading compressed data then we should be using uploadCompressedTexData
432164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(!GrPixelConfigIsCompressed(dataConfig));
433164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
434164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    size_t bpp = GrBytesPerPixel(dataConfig);
435164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
436164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    const GrSurfaceDesc& desc = tex->desc();
437164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
438164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!GrSurfacePriv::AdjustWritePixelParams(desc.fWidth, desc.fHeight, bpp, &left, &top,
439164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                               &width, &height, &data, &rowBytes)) {
440164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
441164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
442164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    size_t trimRowBytes = width * bpp;
443164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
444900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    SkASSERT(VK_IMAGE_LAYOUT_PREINITIALIZED == tex->currentLayout() ||
445900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth             VK_IMAGE_LAYOUT_GENERAL == tex->currentLayout());
446900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    const VkImageSubresource subres = {
447900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        VK_IMAGE_ASPECT_COLOR_BIT,
448900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        0,  // mipLevel
449900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        0,  // arraySlice
450900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    };
451900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    VkSubresourceLayout layout;
452900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    VkResult err;
453900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
454900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    const GrVkInterface* interface = this->vkInterface();
455900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
456900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    GR_VK_CALL(interface, GetImageSubresourceLayout(fDevice,
457b2df0c2702329be6380a943d548e7377a51d8565egdaniel                                                    tex->image(),
458900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                                    &subres,
459900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                                    &layout));
460900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
461900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    int texTop = kBottomLeft_GrSurfaceOrigin == desc.fOrigin ? tex->height() - top - height : top;
4621e305ba0d6a4237020d36234e9e286d3b0489401jvanverth    const GrVkAlloc& alloc = tex->alloc();
4631e305ba0d6a4237020d36234e9e286d3b0489401jvanverth    VkDeviceSize offset = alloc.fOffset + texTop*layout.rowPitch + left*bpp;
464900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    VkDeviceSize size = height*layout.rowPitch;
465900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    void* mapPtr;
4661e305ba0d6a4237020d36234e9e286d3b0489401jvanverth    err = GR_VK_CALL(interface, MapMemory(fDevice, alloc.fMemory, offset, size, 0, &mapPtr));
467900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    if (err) {
468900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        return false;
469900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    }
470164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
471900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    if (kBottomLeft_GrSurfaceOrigin == desc.fOrigin) {
472900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        // copy into buffer by rows
473900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        const char* srcRow = reinterpret_cast<const char*>(data);
474900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        char* dstRow = reinterpret_cast<char*>(mapPtr)+(height - 1)*layout.rowPitch;
475900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        for (int y = 0; y < height; y++) {
476900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            memcpy(dstRow, srcRow, trimRowBytes);
477900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            srcRow += rowBytes;
478900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            dstRow -= layout.rowPitch;
479900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        }
480900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    } else {
481900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        // If there is no padding on the src (rowBytes) or dst (layout.rowPitch) we can memcpy
482900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        if (trimRowBytes == rowBytes && trimRowBytes == layout.rowPitch) {
483900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            memcpy(mapPtr, data, trimRowBytes * height);
484164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        } else {
48588e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel            SkRectMemcpy(mapPtr, static_cast<size_t>(layout.rowPitch), data, rowBytes, trimRowBytes,
48688e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel                         height);
487164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
488900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    }
489164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
4901e305ba0d6a4237020d36234e9e286d3b0489401jvanverth    GR_VK_CALL(interface, UnmapMemory(fDevice, alloc.fMemory));
491900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
492900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    return true;
493900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth}
494900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
495900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverthbool GrVkGpu::uploadTexDataOptimal(GrVkTexture* tex,
496a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth                                   int left, int top, int width, int height,
497a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth                                   GrPixelConfig dataConfig,
498a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth                                   const SkTArray<GrMipLevel>& texels) {
499900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    SkASSERT(!tex->isLinearTiled());
500900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // The assumption is either that we have no mipmaps, or that our rect is the entire texture
501900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    SkASSERT(1 == texels.count() ||
502900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth             (0 == left && 0 == top && width == tex->width() && height == tex->height()));
503900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
504900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // If we're uploading compressed data then we should be using uploadCompressedTexData
505900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    SkASSERT(!GrPixelConfigIsCompressed(dataConfig));
506900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
507900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    if (width == 0 || height == 0) {
508900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        return false;
509900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    }
510900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
511900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    const GrSurfaceDesc& desc = tex->desc();
512900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    SkASSERT(this->caps()->isConfigTexturable(desc.fConfig));
513900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    size_t bpp = GrBytesPerPixel(dataConfig);
514900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
515900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // texels is const.
516c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    // But we may need to adjust the fPixels ptr based on the copyRect, or fRowBytes.
517c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    // Because of this we need to make a non-const shallow copy of texels.
518c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    SkTArray<GrMipLevel> texelsShallowCopy(texels);
519900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
520c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    for (int currentMipLevel = texelsShallowCopy.count() - 1; currentMipLevel >= 0;
521c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth         currentMipLevel--) {
522c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        SkASSERT(texelsShallowCopy[currentMipLevel].fPixels);
523900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    }
524900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
525900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // Determine whether we need to flip when we copy into the buffer
526c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    bool flipY = (kBottomLeft_GrSurfaceOrigin == desc.fOrigin && !texelsShallowCopy.empty());
527900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
528c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    // adjust any params (left, top, currentWidth, currentHeight
529900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // find the combined size of all the mip levels and the relative offset of
530900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // each into the collective buffer
531c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    // Do the first level separately because we may need to adjust width and height
532c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    // (for the non-mipped case).
533c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    if (!GrSurfacePriv::AdjustWritePixelParams(desc.fWidth, desc.fHeight, bpp, &left, &top,
534c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth                                               &width,
535c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth                                               &height,
536c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth                                               &texelsShallowCopy[0].fPixels,
537c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth                                               &texelsShallowCopy[0].fRowBytes)) {
538c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        return false;
539c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    }
540c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    SkTArray<size_t> individualMipOffsets(texelsShallowCopy.count());
541c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    individualMipOffsets.push_back(0);
542c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    size_t combinedBufferSize = width * bpp * height;
543c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    int currentWidth = width;
544c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    int currentHeight = height;
545c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    for (int currentMipLevel = 1; currentMipLevel < texelsShallowCopy.count(); currentMipLevel++) {
546c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        currentWidth = SkTMax(1, currentWidth/2);
547c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        currentHeight = SkTMax(1, currentHeight/2);
548c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        if (!GrSurfacePriv::AdjustWritePixelParams(desc.fWidth, desc.fHeight, bpp, &left, &top,
549c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth                                                   &currentWidth,
550c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth                                                   &currentHeight,
551c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth                                                   &texelsShallowCopy[currentMipLevel].fPixels,
552c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth                                                   &texelsShallowCopy[currentMipLevel].fRowBytes)) {
553c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth            return false;
554c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        }
555900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        const size_t trimmedSize = currentWidth * bpp * currentHeight;
556900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        individualMipOffsets.push_back(combinedBufferSize);
557900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        combinedBufferSize += trimmedSize;
558900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    }
559900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
560900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // allocate buffer to hold our mip data
561900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    GrVkTransferBuffer* transferBuffer =
562900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                   GrVkTransferBuffer::Create(this, combinedBufferSize, GrVkBuffer::kCopyRead_Type);
563900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
564900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    char* buffer = (char*) transferBuffer->map();
565c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    SkTArray<VkBufferImageCopy> regions(texelsShallowCopy.count());
566900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
567c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    currentWidth = width;
568c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    currentHeight = height;
569c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    for (int currentMipLevel = 0; currentMipLevel < texelsShallowCopy.count(); currentMipLevel++) {
570900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        const size_t trimRowBytes = currentWidth * bpp;
571c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        const size_t rowBytes = texelsShallowCopy[currentMipLevel].fRowBytes;
572900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
573900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        // copy data into the buffer, skipping the trailing bytes
574900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        char* dst = buffer + individualMipOffsets[currentMipLevel];
575c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        const char* src = (const char*)texelsShallowCopy[currentMipLevel].fPixels;
576900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        if (flipY) {
577900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            src += (currentHeight - 1) * rowBytes;
578900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            for (int y = 0; y < currentHeight; y++) {
579900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                memcpy(dst, src, trimRowBytes);
580900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                src -= rowBytes;
581900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                dst += trimRowBytes;
582164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            }
583900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        } else if (trimRowBytes == rowBytes) {
584900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            memcpy(dst, src, trimRowBytes * currentHeight);
585164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        } else {
586900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            SkRectMemcpy(dst, trimRowBytes, src, rowBytes, trimRowBytes, currentHeight);
587164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
588164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
589900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        VkBufferImageCopy& region = regions.push_back();
590164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        memset(&region, 0, sizeof(VkBufferImageCopy));
591db37909347d034943bd6b0922710a94c6c6ea572jvanverth        region.bufferOffset = transferBuffer->offset() + individualMipOffsets[currentMipLevel];
592900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        region.bufferRowLength = currentWidth;
593900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        region.bufferImageHeight = currentHeight;
594cf942c4ef750712b624867cbb2217c14857db3c6bsalomon        region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, SkToU32(currentMipLevel), 0, 1 };
595c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        region.imageOffset = { left, flipY ? tex->height() - top - currentHeight : top, 0 };
596900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        region.imageExtent = { (uint32_t)currentWidth, (uint32_t)currentHeight, 1 };
5974583ec51d9ddc830eeb854db068235be96ce59c4egdaniel
598c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        currentWidth = SkTMax(1, currentWidth/2);
599c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        currentHeight = SkTMax(1, currentHeight/2);
600900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    }
601164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
602900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    transferBuffer->unmap();
603164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
604900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // make sure the unmap has finished
605900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    transferBuffer->addMemoryBarrier(this,
606900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                     VK_ACCESS_HOST_WRITE_BIT,
607900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                     VK_ACCESS_TRANSFER_READ_BIT,
608900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                     VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
609900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                     VK_PIPELINE_STAGE_TRANSFER_BIT,
610900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                     false);
611164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
612900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // Change layout of our target so it can be copied to
613900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    tex->setImageLayout(this,
614900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                        VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
61550c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                        VK_ACCESS_TRANSFER_WRITE_BIT,
61650c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                        VK_PIPELINE_STAGE_TRANSFER_BIT,
617900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                        false);
618900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
619900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // Copy the buffer to the image
620900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    fCurrentCmdBuffer->copyBufferToImage(this,
621900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                         transferBuffer,
622900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                         tex,
623900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
624900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                         regions.count(),
625900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                         regions.begin());
626900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    transferBuffer->unref();
627164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
628164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return true;
629164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
630164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
631164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
6322e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunenGrTexture* GrVkGpu::onCreateTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted,
633a1e6b3be8124cef85f2e39e3cb85000ad9526d48bsalomon                                    const SkTArray<GrMipLevel>& texels) {
634164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag);
635164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
636164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkFormat pixelFormat;
637164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!GrPixelConfigToVkFormat(desc.fConfig, &pixelFormat)) {
638164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return nullptr;
639164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
640164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
641164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!fVkCaps->isConfigTexturable(desc.fConfig)) {
642164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return nullptr;
643164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
644164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
6450a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel    if (renderTarget && !fVkCaps->isConfigRenderable(desc.fConfig, false)) {
6460a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel        return nullptr;
6470a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel    }
6480a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel
649164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    bool linearTiling = false;
650164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (SkToBool(desc.fFlags & kZeroCopy_GrSurfaceFlag)) {
651900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        // we can't have a linear texture with a mipmap
652900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        if (texels.count() > 1) {
653900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            SkDebugf("Trying to create linear tiled texture with mipmap");
654900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            return nullptr;
655900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        }
656a95d46b4ac8e41c9beb2b750cd389b1c6ebaf0a7egdaniel        if (fVkCaps->isConfigTexturableLinearly(desc.fConfig) &&
657164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            (!renderTarget || fVkCaps->isConfigRenderableLinearly(desc.fConfig, false))) {
658164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            linearTiling = true;
659164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        } else {
660164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            return nullptr;
661164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
662164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
663164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
664164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT;
665164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (renderTarget) {
666164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        usageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
667164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
668164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
669164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // For now we will set the VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT and
670164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // VK_IMAGE_USAGE_TRANSFER_SOURCE_BIT on every texture since we do not know whether or not we
671164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // will be using this texture in some copy or not. Also this assumes, as is the current case,
67262340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    // that all render targets in vulkan are also textures. If we change this practice of setting
673164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // both bits, we must make sure to set the destination bit if we are uploading srcData to the
674164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // texture.
675164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    usageFlags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
676164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
677a1e6b3be8124cef85f2e39e3cb85000ad9526d48bsalomon    VkFlags memProps = (!texels.empty() && linearTiling) ? VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT :
678a1e6b3be8124cef85f2e39e3cb85000ad9526d48bsalomon                                                           VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
679164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
680164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // This ImageDesc refers to the texture that will be read by the client. Thus even if msaa is
68162340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    // requested, this ImageDesc describes the resolved texture. Therefore we always have samples set
682164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // to 1.
683c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    int mipLevels = texels.empty() ? 1 : texels.count();
684164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkImage::ImageDesc imageDesc;
685164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fImageType = VK_IMAGE_TYPE_2D;
686164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fFormat = pixelFormat;
687164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fWidth = desc.fWidth;
688164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fHeight = desc.fHeight;
689c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    imageDesc.fLevels = linearTiling ? 1 : mipLevels;
690164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fSamples = 1;
691164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fImageTiling = linearTiling ? VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL;
692164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fUsageFlags = usageFlags;
693164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fMemProps = memProps;
694164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
695164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkTexture* tex;
696164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (renderTarget) {
6972e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        tex = GrVkTextureRenderTarget::CreateNewTextureRenderTarget(this, budgeted, desc,
698164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                    imageDesc);
699164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    } else {
7002e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        tex = GrVkTexture::CreateNewTexture(this, budgeted, desc, imageDesc);
701164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
702164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
703164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!tex) {
704164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return nullptr;
705164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
706164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
707e699d0cd25fd059e3f0c4949e613e50c83a52179bsalomon    if (!texels.empty()) {
708e699d0cd25fd059e3f0c4949e613e50c83a52179bsalomon        SkASSERT(texels.begin()->fPixels);
709900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        bool success;
710900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        if (linearTiling) {
711900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            success = this->uploadTexDataLinear(tex, 0, 0, desc.fWidth, desc.fHeight, desc.fConfig,
712900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                                texels.begin()->fPixels, texels.begin()->fRowBytes);
713900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        } else {
714900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            success = this->uploadTexDataOptimal(tex, 0, 0, desc.fWidth, desc.fHeight, desc.fConfig,
715900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                                 texels);
716900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        }
717900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        if (!success) {
718164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            tex->unref();
719164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            return nullptr;
720164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
721164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
722164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
723164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return tex;
724164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
725164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
726164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
727164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
728db37909347d034943bd6b0922710a94c6c6ea572jvanverthbool GrVkGpu::updateBuffer(GrVkBuffer* buffer, const void* src,
729db37909347d034943bd6b0922710a94c6c6ea572jvanverth                           VkDeviceSize offset, VkDeviceSize size) {
730a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth
731a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth    // Update the buffer
732db37909347d034943bd6b0922710a94c6c6ea572jvanverth    fCurrentCmdBuffer->updateBuffer(this, buffer, offset, size, src);
733a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth
734a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth    return true;
735a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth}
736a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth
737a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth////////////////////////////////////////////////////////////////////////////////
738a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth
739164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielstatic GrSurfaceOrigin resolve_origin(GrSurfaceOrigin origin) {
740164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // By default, all textures in Vk use TopLeft
741164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (kDefault_GrSurfaceOrigin == origin) {
742164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return kTopLeft_GrSurfaceOrigin;
743164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    } else {
744164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return origin;
745164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
746164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
747164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
748164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielGrTexture* GrVkGpu::onWrapBackendTexture(const GrBackendTextureDesc& desc,
749164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                         GrWrapOwnership ownership) {
750164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (0 == desc.fTextureHandle) {
751164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return nullptr;
752164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
753164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
754164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    int maxSize = this->caps()->maxTextureSize();
755164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (desc.fWidth > maxSize || desc.fHeight > maxSize) {
756164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return nullptr;
757164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
758164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
759b2df0c2702329be6380a943d548e7377a51d8565egdaniel    const GrVkImageInfo* info = reinterpret_cast<const GrVkImageInfo*>(desc.fTextureHandle);
7601e305ba0d6a4237020d36234e9e286d3b0489401jvanverth    if (VK_NULL_HANDLE == info->fImage || VK_NULL_HANDLE == info->fAlloc.fMemory) {
761fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        return nullptr;
762fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    }
763b2df0c2702329be6380a943d548e7377a51d8565egdaniel#ifdef SK_DEBUG
764b2df0c2702329be6380a943d548e7377a51d8565egdaniel    VkFormat format;
765b2df0c2702329be6380a943d548e7377a51d8565egdaniel    if (!GrPixelConfigToVkFormat(desc.fConfig, &format)) {
766b2df0c2702329be6380a943d548e7377a51d8565egdaniel        return nullptr;
767b2df0c2702329be6380a943d548e7377a51d8565egdaniel    }
768b2df0c2702329be6380a943d548e7377a51d8565egdaniel    SkASSERT(format == info->fFormat);
769b2df0c2702329be6380a943d548e7377a51d8565egdaniel#endif
770164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
771164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrSurfaceDesc surfDesc;
772164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // next line relies on GrBackendTextureDesc's flags matching GrTexture's
773164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    surfDesc.fFlags = (GrSurfaceFlags)desc.fFlags;
774164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    surfDesc.fWidth = desc.fWidth;
775164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    surfDesc.fHeight = desc.fHeight;
776164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    surfDesc.fConfig = desc.fConfig;
777164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    surfDesc.fSampleCnt = SkTMin(desc.fSampleCnt, this->caps()->maxSampleCount());
778164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrBackendTextureFlag);
779164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // In GL, Chrome assumes all textures are BottomLeft
780164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // In VK, we don't have this restriction
781164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    surfDesc.fOrigin = resolve_origin(desc.fOrigin);
782164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
783164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkTexture* texture = nullptr;
784164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (renderTarget) {
7859d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary        texture = GrVkTextureRenderTarget::CreateWrappedTextureRenderTarget(this, surfDesc,
786b2df0c2702329be6380a943d548e7377a51d8565egdaniel                                                                            ownership, info);
787164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    } else {
788b2df0c2702329be6380a943d548e7377a51d8565egdaniel        texture = GrVkTexture::CreateWrappedTexture(this, surfDesc, ownership, info);
789164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
790164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!texture) {
791164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return nullptr;
792164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
793164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
794164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return texture;
795164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
796164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
797164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielGrRenderTarget* GrVkGpu::onWrapBackendRenderTarget(const GrBackendRenderTargetDesc& wrapDesc,
798164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                   GrWrapOwnership ownership) {
7999d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
800b2df0c2702329be6380a943d548e7377a51d8565egdaniel    const GrVkImageInfo* info =
801b2df0c2702329be6380a943d548e7377a51d8565egdaniel        reinterpret_cast<const GrVkImageInfo*>(wrapDesc.fRenderTargetHandle);
802fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    if (VK_NULL_HANDLE == info->fImage ||
8031e305ba0d6a4237020d36234e9e286d3b0489401jvanverth        (VK_NULL_HANDLE == info->fAlloc.fMemory && kAdopt_GrWrapOwnership == ownership)) {
804fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        return nullptr;
805fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    }
806164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
807164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrSurfaceDesc desc;
808164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    desc.fConfig = wrapDesc.fConfig;
809164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    desc.fFlags = kCheckAllocation_GrSurfaceFlag;
810164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    desc.fWidth = wrapDesc.fWidth;
811164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    desc.fHeight = wrapDesc.fHeight;
812164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    desc.fSampleCnt = SkTMin(wrapDesc.fSampleCnt, this->caps()->maxSampleCount());
813164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
814164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    desc.fOrigin = resolve_origin(wrapDesc.fOrigin);
815164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
816164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkRenderTarget* tgt = GrVkRenderTarget::CreateWrappedRenderTarget(this, desc,
8172e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen                                                                        ownership,
818fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth                                                                        info);
819164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (tgt && wrapDesc.fStencilBits) {
820164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        if (!createStencilAttachmentForRenderTarget(tgt, desc.fWidth, desc.fHeight)) {
821164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            tgt->unref();
822164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            return nullptr;
823164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
824164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
825164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return tgt;
826164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
827164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
82850ead53ac97deb23310916e3736c3f5e2d8f7f4begdanielvoid GrVkGpu::generateMipmap(GrVkTexture* tex) {
829900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // don't do anything for linearly tiled textures (can't have mipmaps)
83062340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    if (tex->isLinearTiled()) {
831900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        SkDebugf("Trying to create mipmap for linear tiled texture");
83262340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth        return;
83362340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    }
83462340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth
83562340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    // determine if we can blit to and from this format
83662340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    const GrVkCaps& caps = this->vkCaps();
83762340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    if (!caps.configCanBeDstofBlit(tex->config(), false) ||
8382f5792a06c87efd5f9295b7b7bb714aac118bd2aegdaniel        !caps.configCanBeSrcofBlit(tex->config(), false) ||
8392f5792a06c87efd5f9295b7b7bb714aac118bd2aegdaniel        !caps.mipMapSupport()) {
84062340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth        return;
84162340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    }
84262340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth
84366933552f1723c4a2b248711ab3d43921401e8e6egdaniel    // We may need to resolve the texture first if it is also a render target
84466933552f1723c4a2b248711ab3d43921401e8e6egdaniel    GrVkRenderTarget* texRT = static_cast<GrVkRenderTarget*>(tex->asRenderTarget());
84566933552f1723c4a2b248711ab3d43921401e8e6egdaniel    if (texRT) {
84666933552f1723c4a2b248711ab3d43921401e8e6egdaniel        this->onResolveRenderTarget(texRT);
84766933552f1723c4a2b248711ab3d43921401e8e6egdaniel    }
84866933552f1723c4a2b248711ab3d43921401e8e6egdaniel
8497ac5da853457b032781cf865ba018de78508edb7egdaniel    int width = tex->width();
8507ac5da853457b032781cf865ba018de78508edb7egdaniel    int height = tex->height();
8517ac5da853457b032781cf865ba018de78508edb7egdaniel    VkImageBlit blitRegion;
8527ac5da853457b032781cf865ba018de78508edb7egdaniel    memset(&blitRegion, 0, sizeof(VkImageBlit));
85362340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth
85482c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth    // SkMipMap doesn't include the base level in the level count so we have to add 1
85582c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth    uint32_t levelCount = SkMipMap::ComputeLevelCount(tex->width(), tex->height()) + 1;
8567ac5da853457b032781cf865ba018de78508edb7egdaniel    if (levelCount != tex->mipLevels()) {
8577ac5da853457b032781cf865ba018de78508edb7egdaniel        const GrVkResource* oldResource = tex->resource();
8587ac5da853457b032781cf865ba018de78508edb7egdaniel        oldResource->ref();
8597ac5da853457b032781cf865ba018de78508edb7egdaniel        // grab handle to the original image resource
8607ac5da853457b032781cf865ba018de78508edb7egdaniel        VkImage oldImage = tex->image();
8617ac5da853457b032781cf865ba018de78508edb7egdaniel
8627ac5da853457b032781cf865ba018de78508edb7egdaniel        // change the original image's layout so we can copy from it
8637ac5da853457b032781cf865ba018de78508edb7egdaniel        tex->setImageLayout(this, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
8647ac5da853457b032781cf865ba018de78508edb7egdaniel                            VK_ACCESS_TRANSFER_READ_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, false);
8657ac5da853457b032781cf865ba018de78508edb7egdaniel
8667ac5da853457b032781cf865ba018de78508edb7egdaniel        if (!tex->reallocForMipmap(this, levelCount)) {
8677ac5da853457b032781cf865ba018de78508edb7egdaniel            oldResource->unref(this);
8687ac5da853457b032781cf865ba018de78508edb7egdaniel            return;
8697ac5da853457b032781cf865ba018de78508edb7egdaniel        }
8707ac5da853457b032781cf865ba018de78508edb7egdaniel        // change the new image's layout so we can blit to it
8717ac5da853457b032781cf865ba018de78508edb7egdaniel        tex->setImageLayout(this, VK_IMAGE_LAYOUT_GENERAL,
8727ac5da853457b032781cf865ba018de78508edb7egdaniel                            VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, false);
87362340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth
8747ac5da853457b032781cf865ba018de78508edb7egdaniel        // Blit original image to top level of new image
8757ac5da853457b032781cf865ba018de78508edb7egdaniel        blitRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
8767ac5da853457b032781cf865ba018de78508edb7egdaniel        blitRegion.srcOffsets[0] = { 0, 0, 0 };
8777ac5da853457b032781cf865ba018de78508edb7egdaniel        blitRegion.srcOffsets[1] = { width, height, 1 };
8787ac5da853457b032781cf865ba018de78508edb7egdaniel        blitRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
8797ac5da853457b032781cf865ba018de78508edb7egdaniel        blitRegion.dstOffsets[0] = { 0, 0, 0 };
8807ac5da853457b032781cf865ba018de78508edb7egdaniel        blitRegion.dstOffsets[1] = { width, height, 1 };
88162340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth
8827ac5da853457b032781cf865ba018de78508edb7egdaniel        fCurrentCmdBuffer->blitImage(this,
8837ac5da853457b032781cf865ba018de78508edb7egdaniel                                     oldResource,
8847ac5da853457b032781cf865ba018de78508edb7egdaniel                                     oldImage,
8857ac5da853457b032781cf865ba018de78508edb7egdaniel                                     VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
8867ac5da853457b032781cf865ba018de78508edb7egdaniel                                     tex->resource(),
8877ac5da853457b032781cf865ba018de78508edb7egdaniel                                     tex->image(),
8887ac5da853457b032781cf865ba018de78508edb7egdaniel                                     VK_IMAGE_LAYOUT_GENERAL,
8897ac5da853457b032781cf865ba018de78508edb7egdaniel                                     1,
8907ac5da853457b032781cf865ba018de78508edb7egdaniel                                     &blitRegion,
8917ac5da853457b032781cf865ba018de78508edb7egdaniel                                     VK_FILTER_LINEAR);
89262340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth
8937ac5da853457b032781cf865ba018de78508edb7egdaniel        oldResource->unref(this);
8947ac5da853457b032781cf865ba018de78508edb7egdaniel    } else {
8957ac5da853457b032781cf865ba018de78508edb7egdaniel        // change layout of the layers so we can write to them.
8967ac5da853457b032781cf865ba018de78508edb7egdaniel        tex->setImageLayout(this, VK_IMAGE_LAYOUT_GENERAL,
8977ac5da853457b032781cf865ba018de78508edb7egdaniel                            VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, false);
8987ac5da853457b032781cf865ba018de78508edb7egdaniel    }
89950c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth
90050c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth    // setup memory barrier
901b2df0c2702329be6380a943d548e7377a51d8565egdaniel    SkASSERT(GrVkFormatToPixelConfig(tex->imageFormat(), nullptr));
90250c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth    VkImageAspectFlags aspectFlags = VK_IMAGE_ASPECT_COLOR_BIT;
90350c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth    VkImageMemoryBarrier imageMemoryBarrier = {
90450c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth        VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,          // sType
90550c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth        NULL,                                            // pNext
9067ac5da853457b032781cf865ba018de78508edb7egdaniel        VK_ACCESS_TRANSFER_WRITE_BIT,                    // srcAccessMask
9077ac5da853457b032781cf865ba018de78508edb7egdaniel        VK_ACCESS_TRANSFER_READ_BIT,                     // dstAccessMask
90850c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth        VK_IMAGE_LAYOUT_GENERAL,                         // oldLayout
90950c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth        VK_IMAGE_LAYOUT_GENERAL,                         // newLayout
91050c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth        VK_QUEUE_FAMILY_IGNORED,                         // srcQueueFamilyIndex
91150c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth        VK_QUEUE_FAMILY_IGNORED,                         // dstQueueFamilyIndex
912b2df0c2702329be6380a943d548e7377a51d8565egdaniel        tex->image(),                                    // image
91350c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth        { aspectFlags, 0, 1, 0, 1 }                      // subresourceRange
91450c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth    };
91550c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth
91662340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    // Blit the miplevels
91782c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth    uint32_t mipLevel = 1;
91882c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth    while (mipLevel < levelCount) {
91982c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth        int prevWidth = width;
92082c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth        int prevHeight = height;
92182c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth        width = SkTMax(1, width / 2);
92282c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth        height = SkTMax(1, height / 2);
92382c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth
92450c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth        imageMemoryBarrier.subresourceRange.baseMipLevel = mipLevel - 1;
92550c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth        this->addImageMemoryBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
92650c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                                    false, &imageMemoryBarrier);
92750c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth
92850c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth        blitRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, mipLevel - 1, 0, 1 };
92962340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth        blitRegion.srcOffsets[0] = { 0, 0, 0 };
930e9906e71fbc29968ea10680f0fcd53a4153c7568brianosman        blitRegion.srcOffsets[1] = { prevWidth, prevHeight, 1 };
93182c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth        blitRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, mipLevel, 0, 1 };
93262340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth        blitRegion.dstOffsets[0] = { 0, 0, 0 };
933e9906e71fbc29968ea10680f0fcd53a4153c7568brianosman        blitRegion.dstOffsets[1] = { width, height, 1 };
93462340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth        fCurrentCmdBuffer->blitImage(this,
935b2df0c2702329be6380a943d548e7377a51d8565egdaniel                                     *tex,
936b2df0c2702329be6380a943d548e7377a51d8565egdaniel                                     *tex,
93762340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth                                     1,
93862340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth                                     &blitRegion,
93962340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth                                     VK_FILTER_LINEAR);
94082c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth        ++mipLevel;
94162340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    }
94262340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth}
94362340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth
944164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
945164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
946164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielGrStencilAttachment* GrVkGpu::createStencilAttachmentForRenderTarget(const GrRenderTarget* rt,
947164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                     int width,
948164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                     int height) {
949164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(width >= rt->width());
950164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(height >= rt->height());
951164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
952164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    int samples = rt->numStencilSamples();
953164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
9548f1dcaa6f3cc098bd5efd2595ca20e0bc1847d10egdaniel    const GrVkCaps::StencilFormat& sFmt = this->vkCaps().preferedStencilFormat();
955164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
956164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkStencilAttachment* stencil(GrVkStencilAttachment::Create(this,
957164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                 width,
958164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                 height,
959164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                 samples,
960164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                 sFmt));
961164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fStats.incStencilAttachmentCreates();
962164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return stencil;
963164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
964164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
965164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
966164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
9673602d4f16a01da860d16eb36fb52eb62487495ccegdanielbool copy_testing_data(GrVkGpu* gpu, void* srcData, GrVkAlloc* alloc,
9683602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                       size_t srcRowBytes, size_t dstRowBytes, int h) {
9693602d4f16a01da860d16eb36fb52eb62487495ccegdaniel    void* mapPtr;
9703602d4f16a01da860d16eb36fb52eb62487495ccegdaniel    VkResult err = GR_VK_CALL(gpu->vkInterface(), MapMemory(gpu->device(),
9713602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                                                            alloc->fMemory,
9723602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                                                            alloc->fOffset,
9733602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                                                            dstRowBytes * h,
9743602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                                                            0,
9753602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                                                            &mapPtr));
9763602d4f16a01da860d16eb36fb52eb62487495ccegdaniel    if (err) {
9773602d4f16a01da860d16eb36fb52eb62487495ccegdaniel        return false;
9783602d4f16a01da860d16eb36fb52eb62487495ccegdaniel    }
9793602d4f16a01da860d16eb36fb52eb62487495ccegdaniel
9803602d4f16a01da860d16eb36fb52eb62487495ccegdaniel    // If there is no padding on dst we can do a single memcopy.
9813602d4f16a01da860d16eb36fb52eb62487495ccegdaniel    // This assumes the srcData comes in with no padding.
9823602d4f16a01da860d16eb36fb52eb62487495ccegdaniel    if (srcRowBytes == dstRowBytes) {
9833602d4f16a01da860d16eb36fb52eb62487495ccegdaniel        memcpy(mapPtr, srcData, srcRowBytes * h);
9843602d4f16a01da860d16eb36fb52eb62487495ccegdaniel    } else {
9853602d4f16a01da860d16eb36fb52eb62487495ccegdaniel        SkRectMemcpy(mapPtr, static_cast<size_t>(dstRowBytes), srcData, srcRowBytes,
9863602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                     srcRowBytes, h);
9873602d4f16a01da860d16eb36fb52eb62487495ccegdaniel    }
9883602d4f16a01da860d16eb36fb52eb62487495ccegdaniel    GR_VK_CALL(gpu->vkInterface(), UnmapMemory(gpu->device(), alloc->fMemory));
9893602d4f16a01da860d16eb36fb52eb62487495ccegdaniel    return true;
9903602d4f16a01da860d16eb36fb52eb62487495ccegdaniel}
9913602d4f16a01da860d16eb36fb52eb62487495ccegdaniel
992164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielGrBackendObject GrVkGpu::createTestingOnlyBackendTexture(void* srcData, int w, int h,
9930a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel                                                         GrPixelConfig config,
9940a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel                                                         bool isRenderTarget) {
995164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
996164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkFormat pixelFormat;
997164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!GrPixelConfigToVkFormat(config, &pixelFormat)) {
998164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return 0;
999164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1000164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1001164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    bool linearTiling = false;
1002164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!fVkCaps->isConfigTexturable(config)) {
1003164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return 0;
1004164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1005164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
10060a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel    if (isRenderTarget && !fVkCaps->isConfigRenderable(config, false)) {
10070a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel        return 0;
10080a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel    }
10090a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel
1010a95d46b4ac8e41c9beb2b750cd389b1c6ebaf0a7egdaniel    if (fVkCaps->isConfigTexturableLinearly(config) &&
10110a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel        (!isRenderTarget || fVkCaps->isConfigRenderableLinearly(config, false))) {
1012164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        linearTiling = true;
1013164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1014164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1015164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT;
1016164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    usageFlags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1017164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    usageFlags |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
10180a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel    if (isRenderTarget) {
10190a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel        usageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
10200a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel    }
1021164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1022fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    VkImage image = VK_NULL_HANDLE;
10236b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    GrVkAlloc alloc = { VK_NULL_HANDLE, 0, 0 };
1024164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1025fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    VkImageTiling imageTiling = linearTiling ? VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL;
1026fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    VkImageLayout initialLayout = (VK_IMAGE_TILING_LINEAR == imageTiling)
1027fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth                                ? VK_IMAGE_LAYOUT_PREINITIALIZED
1028fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth                                : VK_IMAGE_LAYOUT_UNDEFINED;
1029fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth
1030fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    // Create Image
1031fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    VkSampleCountFlagBits vkSamples;
1032fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    if (!GrSampleCountToVkSampleCount(1, &vkSamples)) {
1033fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        return 0;
1034fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    }
1035fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth
1036fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    const VkImageCreateInfo imageCreateInfo = {
1037fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,         // sType
1038fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        NULL,                                        // pNext
1039fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        0,                                           // VkImageCreateFlags
1040fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        VK_IMAGE_TYPE_2D,                            // VkImageType
1041fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        pixelFormat,                                 // VkFormat
1042384b5e9cd36e443437de8df3b0f78ef4150efbacethannicholas        { (uint32_t) w, (uint32_t) h, 1 },           // VkExtent3D
1043fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        1,                                           // mipLevels
1044fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        1,                                           // arrayLayers
1045fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        vkSamples,                                   // samples
1046fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        imageTiling,                                 // VkImageTiling
1047fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        usageFlags,                                  // VkImageUsageFlags
1048fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        VK_SHARING_MODE_EXCLUSIVE,                   // VkSharingMode
1049fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        0,                                           // queueFamilyCount
1050fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        0,                                           // pQueueFamilyIndices
1051fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        initialLayout                                // initialLayout
1052fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    };
1053fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth
1054fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    GR_VK_CALL_ERRCHECK(this->vkInterface(), CreateImage(this->device(), &imageCreateInfo, nullptr, &image));
1055fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth
10566b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    if (!GrVkMemory::AllocAndBindImageMemory(this, image, linearTiling, &alloc)) {
1057fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        VK_CALL(DestroyImage(this->device(), image, nullptr));
1058164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return 0;
1059164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1060164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1061164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (srcData) {
10623602d4f16a01da860d16eb36fb52eb62487495ccegdaniel        size_t bpp = GrBytesPerPixel(config);
10633602d4f16a01da860d16eb36fb52eb62487495ccegdaniel        size_t rowCopyBytes = bpp * w;
1064164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        if (linearTiling) {
1065164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            const VkImageSubresource subres = {
1066164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                VK_IMAGE_ASPECT_COLOR_BIT,
1067164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                0,  // mipLevel
1068164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                0,  // arraySlice
1069164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            };
1070164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            VkSubresourceLayout layout;
1071164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1072fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth            VK_CALL(GetImageSubresourceLayout(fDevice, image, &subres, &layout));
1073164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1074583bc2e98d8105fc799897daea28eea03c23fbbcbrianosman            if (!copy_testing_data(this, srcData, &alloc, rowCopyBytes,
1075583bc2e98d8105fc799897daea28eea03c23fbbcbrianosman                                   static_cast<size_t>(layout.rowPitch), h)) {
10763602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                GrVkMemory::FreeImageMemory(this, linearTiling, alloc);
10773602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                VK_CALL(DestroyImage(fDevice, image, nullptr));
10783602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                return 0;
10793602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            }
10803602d4f16a01da860d16eb36fb52eb62487495ccegdaniel        } else {
10813602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            SkASSERT(w && h);
10823602d4f16a01da860d16eb36fb52eb62487495ccegdaniel
10833602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            VkBuffer buffer;
10843602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            VkBufferCreateInfo bufInfo;
10853602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            memset(&bufInfo, 0, sizeof(VkBufferCreateInfo));
10863602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            bufInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
10873602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            bufInfo.flags = 0;
10883602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            bufInfo.size = rowCopyBytes * h;
10893602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            bufInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
10903602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            bufInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
10913602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            bufInfo.queueFamilyIndexCount = 0;
10923602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            bufInfo.pQueueFamilyIndices = nullptr;
10933602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            VkResult err;
10943602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            err = VK_CALL(CreateBuffer(fDevice, &bufInfo, nullptr, &buffer));
10953602d4f16a01da860d16eb36fb52eb62487495ccegdaniel
1096164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            if (err) {
10976b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth                GrVkMemory::FreeImageMemory(this, linearTiling, alloc);
10983602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                VK_CALL(DestroyImage(fDevice, image, nullptr));
1099164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                return 0;
1100164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            }
1101164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
11023602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            GrVkAlloc bufferAlloc = { VK_NULL_HANDLE, 0, 0 };
11033602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            if (!GrVkMemory::AllocAndBindBufferMemory(this, buffer, GrVkBuffer::kCopyRead_Type,
11043602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                                                      true, &bufferAlloc)) {
11053602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                GrVkMemory::FreeImageMemory(this, linearTiling, alloc);
11063602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                VK_CALL(DestroyImage(fDevice, image, nullptr));
11073602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                VK_CALL(DestroyBuffer(fDevice, buffer, nullptr));
11083602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                return 0;
1109164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            }
11103602d4f16a01da860d16eb36fb52eb62487495ccegdaniel
11113602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            if (!copy_testing_data(this, srcData, &bufferAlloc, rowCopyBytes, rowCopyBytes, h)) {
11123602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                GrVkMemory::FreeImageMemory(this, linearTiling, alloc);
11133602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                VK_CALL(DestroyImage(fDevice, image, nullptr));
11143602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                GrVkMemory::FreeBufferMemory(this, GrVkBuffer::kCopyRead_Type, bufferAlloc);
11153602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                VK_CALL(DestroyBuffer(fDevice, buffer, nullptr));
11163602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                return 0;
11173602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            }
11183602d4f16a01da860d16eb36fb52eb62487495ccegdaniel
11193602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            const VkCommandBufferAllocateInfo cmdInfo = {
11203602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,   // sType
11213602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                NULL,                                             // pNext
11223602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                fCmdPool,                                         // commandPool
11233602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                VK_COMMAND_BUFFER_LEVEL_PRIMARY,                  // level
11243602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                1                                                 // bufferCount
11253602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            };
11263602d4f16a01da860d16eb36fb52eb62487495ccegdaniel
11273602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            VkCommandBuffer cmdBuffer;
11283602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            err = VK_CALL(AllocateCommandBuffers(fDevice, &cmdInfo, &cmdBuffer));
11293602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            if (err) {
11303602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                GrVkMemory::FreeImageMemory(this, linearTiling, alloc);
11313602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                VK_CALL(DestroyImage(fDevice, image, nullptr));
11323602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                GrVkMemory::FreeBufferMemory(this, GrVkBuffer::kCopyRead_Type, bufferAlloc);
11333602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                VK_CALL(DestroyBuffer(fDevice, buffer, nullptr));
11343602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                return 0;
11353602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            }
11363602d4f16a01da860d16eb36fb52eb62487495ccegdaniel
11373602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            VkCommandBufferBeginInfo cmdBufferBeginInfo;
11383602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            memset(&cmdBufferBeginInfo, 0, sizeof(VkCommandBufferBeginInfo));
11393602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            cmdBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
11403602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            cmdBufferBeginInfo.pNext = nullptr;
11413602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            cmdBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
11423602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            cmdBufferBeginInfo.pInheritanceInfo = nullptr;
11433602d4f16a01da860d16eb36fb52eb62487495ccegdaniel
11443602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            err = VK_CALL(BeginCommandBuffer(cmdBuffer, &cmdBufferBeginInfo));
11453602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            SkASSERT(!err);
11463602d4f16a01da860d16eb36fb52eb62487495ccegdaniel
11473602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            // Set image layout and add barrier
11483602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            VkImageMemoryBarrier barrier;
11493602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            memset(&barrier, 0, sizeof(VkImageMemoryBarrier));
11503602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
11513602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            barrier.pNext = nullptr;
11523602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            barrier.srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(initialLayout);
11533602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
11543602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
11553602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
11563602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
11573602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            barrier.image = image;
11583602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            barrier.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0 , 1};
11593602d4f16a01da860d16eb36fb52eb62487495ccegdaniel
11603602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            VK_CALL(CmdPipelineBarrier(cmdBuffer,
11613602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                                       GrVkMemory::LayoutToPipelineStageFlags(initialLayout),
11623602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                                       VK_PIPELINE_STAGE_TRANSFER_BIT,
11633602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                                       0,
11643602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                                       0, nullptr,
11653602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                                       0, nullptr,
11663602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                                       1, &barrier));
11673602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            initialLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
11683602d4f16a01da860d16eb36fb52eb62487495ccegdaniel
11693602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            // Submit copy command
11703602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            VkBufferImageCopy region;
11713602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            memset(&region, 0, sizeof(VkBufferImageCopy));
11723602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            region.bufferOffset = 0;
1173a95d46b4ac8e41c9beb2b750cd389b1c6ebaf0a7egdaniel            region.bufferRowLength = w;
11743602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            region.bufferImageHeight = h;
11753602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
11763602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            region.imageOffset = { 0, 0, 0 };
11773602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            region.imageExtent = { (uint32_t)w, (uint32_t)h, 1 };
11783602d4f16a01da860d16eb36fb52eb62487495ccegdaniel
11793602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            VK_CALL(CmdCopyBufferToImage(cmdBuffer, buffer, image, initialLayout, 1, &region));
11803602d4f16a01da860d16eb36fb52eb62487495ccegdaniel
11813602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            // End CommandBuffer
11823602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            err = VK_CALL(EndCommandBuffer(cmdBuffer));
11833602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            SkASSERT(!err);
11843602d4f16a01da860d16eb36fb52eb62487495ccegdaniel
11853602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            // Create Fence for queue
11863602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            VkFence fence;
11873602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            VkFenceCreateInfo fenceInfo;
11883602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            memset(&fenceInfo, 0, sizeof(VkFenceCreateInfo));
11893602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
11903602d4f16a01da860d16eb36fb52eb62487495ccegdaniel
11913602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            err = VK_CALL(CreateFence(fDevice, &fenceInfo, nullptr, &fence));
11923602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            SkASSERT(!err);
11933602d4f16a01da860d16eb36fb52eb62487495ccegdaniel
11943602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            VkSubmitInfo submitInfo;
11953602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            memset(&submitInfo, 0, sizeof(VkSubmitInfo));
11963602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
11973602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            submitInfo.pNext = nullptr;
11983602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            submitInfo.waitSemaphoreCount = 0;
11993602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            submitInfo.pWaitSemaphores = nullptr;
12003602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            submitInfo.pWaitDstStageMask = 0;
12013602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            submitInfo.commandBufferCount = 1;
12023602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            submitInfo.pCommandBuffers = &cmdBuffer;
12033602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            submitInfo.signalSemaphoreCount = 0;
12043602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            submitInfo.pSignalSemaphores = nullptr;
12053602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            err = VK_CALL(QueueSubmit(this->queue(), 1, &submitInfo, fence));
12063602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            SkASSERT(!err);
12073602d4f16a01da860d16eb36fb52eb62487495ccegdaniel
12083602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            err = VK_CALL(WaitForFences(fDevice, 1, &fence, true, UINT64_MAX));
12093602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            if (VK_TIMEOUT == err) {
12103602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                GrVkMemory::FreeImageMemory(this, linearTiling, alloc);
12113602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                VK_CALL(DestroyImage(fDevice, image, nullptr));
12123602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                GrVkMemory::FreeBufferMemory(this, GrVkBuffer::kCopyRead_Type, bufferAlloc);
12133602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                VK_CALL(DestroyBuffer(fDevice, buffer, nullptr));
12143602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                VK_CALL(FreeCommandBuffers(fDevice, fCmdPool, 1, &cmdBuffer));
12153602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                VK_CALL(DestroyFence(fDevice, fence, nullptr));
12163602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                SkDebugf("Fence failed to signal: %d\n", err);
12173602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                SkFAIL("failing");
12183602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            }
12193602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            SkASSERT(!err);
12203602d4f16a01da860d16eb36fb52eb62487495ccegdaniel
12213602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            // Clean up transfer resources
12223602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            GrVkMemory::FreeBufferMemory(this, GrVkBuffer::kCopyRead_Type, bufferAlloc);
12233602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            VK_CALL(DestroyBuffer(fDevice, buffer, nullptr));
12243602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            VK_CALL(FreeCommandBuffers(fDevice, fCmdPool, 1, &cmdBuffer));
12253602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            VK_CALL(DestroyFence(fDevice, fence, nullptr));
1226164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
1227164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1228164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1229b2df0c2702329be6380a943d548e7377a51d8565egdaniel    GrVkImageInfo* info = new GrVkImageInfo;
1230fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    info->fImage = image;
1231fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    info->fAlloc = alloc;
1232fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    info->fImageTiling = imageTiling;
1233fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    info->fImageLayout = initialLayout;
123458a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel    info->fFormat = pixelFormat;
12352af0f1b014b9aabb6119bf66fac20e4cd3a8279bjvanverth    info->fLevelCount = 1;
1236fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth
1237fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    return (GrBackendObject)info;
1238164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1239164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1240164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::isTestingOnlyBackendTexture(GrBackendObject id) const {
1241b2df0c2702329be6380a943d548e7377a51d8565egdaniel    const GrVkImageInfo* backend = reinterpret_cast<const GrVkImageInfo*>(id);
1242164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
12431e305ba0d6a4237020d36234e9e286d3b0489401jvanverth    if (backend && backend->fImage && backend->fAlloc.fMemory) {
1244164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkMemoryRequirements req;
1245164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        memset(&req, 0, sizeof(req));
1246164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        GR_VK_CALL(this->vkInterface(), GetImageMemoryRequirements(fDevice,
1247164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                   backend->fImage,
1248164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                   &req));
1249164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // TODO: find a better check
1250164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // This will probably fail with a different driver
1251164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return (req.size > 0) && (req.size <= 8192 * 8192);
1252164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1253164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1254164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return false;
1255164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1256164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1257164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::deleteTestingOnlyBackendTexture(GrBackendObject id, bool abandon) {
12586b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    GrVkImageInfo* backend = reinterpret_cast<GrVkImageInfo*>(id);
1259164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (backend) {
1260164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        if (!abandon) {
1261fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth            // something in the command buffer may still be using this, so force submit
1262fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth            this->submitCommandBuffer(kForce_SyncQueue);
12636b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth            GrVkImage::DestroyImageInfo(this, backend);
1264164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
1265fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        delete backend;
1266164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1267164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1268164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1269164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
1270164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1271164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::addMemoryBarrier(VkPipelineStageFlags srcStageMask,
1272164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                               VkPipelineStageFlags dstStageMask,
1273164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                               bool byRegion,
1274164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                               VkMemoryBarrier* barrier) const {
1275164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(fCurrentCmdBuffer);
1276164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->pipelineBarrier(this,
1277164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       srcStageMask,
1278164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       dstStageMask,
1279164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       byRegion,
1280164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       GrVkCommandBuffer::kMemory_BarrierType,
1281164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       barrier);
1282164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1283164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1284164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::addBufferMemoryBarrier(VkPipelineStageFlags srcStageMask,
1285164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     VkPipelineStageFlags dstStageMask,
1286164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     bool byRegion,
1287164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     VkBufferMemoryBarrier* barrier) const {
1288164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(fCurrentCmdBuffer);
1289164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->pipelineBarrier(this,
1290164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       srcStageMask,
1291164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       dstStageMask,
1292164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       byRegion,
1293164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       GrVkCommandBuffer::kBufferMemory_BarrierType,
1294164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       barrier);
1295164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1296164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1297164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::addImageMemoryBarrier(VkPipelineStageFlags srcStageMask,
1298164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                    VkPipelineStageFlags dstStageMask,
1299164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                    bool byRegion,
1300164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                    VkImageMemoryBarrier* barrier) const {
1301164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(fCurrentCmdBuffer);
1302164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->pipelineBarrier(this,
1303164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       srcStageMask,
1304164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       dstStageMask,
1305164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       byRegion,
1306164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       GrVkCommandBuffer::kImageMemory_BarrierType,
1307164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       barrier);
1308164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1309164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1310164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::finishDrawTarget() {
1311164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Submit the current command buffer to the Queue
1312164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    this->submitCommandBuffer(kSkip_SyncQueue);
1313164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1314164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
13153d5d9ac426ea926f37eaa47e13acf7492068667begdanielvoid GrVkGpu::clearStencil(GrRenderTarget* target) {
13163d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    if (nullptr == target) {
13173d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        return;
13183d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    }
13193d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    GrStencilAttachment* stencil = target->renderTargetPriv().getStencilAttachment();
13203d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    GrVkStencilAttachment* vkStencil = (GrVkStencilAttachment*)stencil;
13213d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
13223d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
13233d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    VkClearDepthStencilValue vkStencilColor;
13243d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    memset(&vkStencilColor, 0, sizeof(VkClearDepthStencilValue));
13253d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
13263d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    vkStencil->setImageLayout(this,
13273d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                              VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
132850c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                              VK_ACCESS_TRANSFER_WRITE_BIT,
132950c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                              VK_PIPELINE_STAGE_TRANSFER_BIT,
13303d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                              false);
13313d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
13323d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    VkImageSubresourceRange subRange;
13333d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    memset(&subRange, 0, sizeof(VkImageSubresourceRange));
13343d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    subRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
13353d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    subRange.baseMipLevel = 0;
13363d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    subRange.levelCount = 1;
13373d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    subRange.baseArrayLayer = 0;
13383d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    subRange.layerCount = 1;
13393d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
13403d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    // TODO: I imagine that most times we want to clear a stencil it will be at the beginning of a
13413d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    // draw. Thus we should look into using the load op functions on the render pass to clear out
13423d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    // the stencil there.
13433d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    fCurrentCmdBuffer->clearDepthStencilImage(this, vkStencil, &vkStencilColor, 1, &subRange);
13443d5d9ac426ea926f37eaa47e13acf7492068667begdaniel}
13453d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
1346164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielinline bool can_copy_image(const GrSurface* dst,
1347164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           const GrSurface* src,
1348164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           const GrVkGpu* gpu) {
13494bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    const GrRenderTarget* dstRT = dst->asRenderTarget();
13504bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    const GrRenderTarget* srcRT = src->asRenderTarget();
13514bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    if (dstRT && srcRT) {
13524bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        if (srcRT->numColorSamples() != dstRT->numColorSamples()) {
13534bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel            return false;
13544bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        }
13554bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    } else if (dstRT) {
13564bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        if (dstRT->numColorSamples() > 1) {
13574bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel            return false;
13584bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        }
13594bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    } else if (srcRT) {
13604bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        if (srcRT->numColorSamples() > 1) {
13614bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel            return false;
13624bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        }
136317b892551465e5a44560a06e4b34dc3592b49622egdaniel    }
136417b892551465e5a44560a06e4b34dc3592b49622egdaniel
136517b892551465e5a44560a06e4b34dc3592b49622egdaniel    // We require that all vulkan GrSurfaces have been created with transfer_dst and transfer_src
136617b892551465e5a44560a06e4b34dc3592b49622egdaniel    // as image usage flags.
136717b892551465e5a44560a06e4b34dc3592b49622egdaniel    if (src->origin() == dst->origin() &&
136817b892551465e5a44560a06e4b34dc3592b49622egdaniel        GrBytesPerPixel(src->config()) == GrBytesPerPixel(dst->config())) {
1369164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return true;
1370164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1371164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1372164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return false;
1373164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1374164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1375164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::copySurfaceAsCopyImage(GrSurface* dst,
1376164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     GrSurface* src,
137717b892551465e5a44560a06e4b34dc3592b49622egdaniel                                     GrVkImage* dstImage,
137817b892551465e5a44560a06e4b34dc3592b49622egdaniel                                     GrVkImage* srcImage,
1379164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     const SkIRect& srcRect,
1380164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     const SkIPoint& dstPoint) {
1381164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(can_copy_image(dst, src, this));
1382164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1383164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // These flags are for flushing/invalidating caches and for the dst image it doesn't matter if
1384164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // the cache is flushed since it is only being written to.
138517b892551465e5a44560a06e4b34dc3592b49622egdaniel    dstImage->setImageLayout(this,
138650c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                             VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
138750c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                             VK_ACCESS_TRANSFER_WRITE_BIT,
138850c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                             VK_PIPELINE_STAGE_TRANSFER_BIT,
138950c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                             false);
1390164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
139117b892551465e5a44560a06e4b34dc3592b49622egdaniel    srcImage->setImageLayout(this,
139217b892551465e5a44560a06e4b34dc3592b49622egdaniel                             VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
139350c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                             VK_ACCESS_TRANSFER_READ_BIT,
139450c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                             VK_PIPELINE_STAGE_TRANSFER_BIT,
139517b892551465e5a44560a06e4b34dc3592b49622egdaniel                             false);
1396164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1397164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Flip rect if necessary
1398164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkIRect srcVkRect = srcRect;
1399164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    int32_t dstY = dstPoint.fY;
1400164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1401164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (kBottomLeft_GrSurfaceOrigin == src->origin()) {
1402164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        SkASSERT(kBottomLeft_GrSurfaceOrigin == dst->origin());
1403164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        srcVkRect.fTop = src->height() - srcRect.fBottom;
1404164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        srcVkRect.fBottom =  src->height() - srcRect.fTop;
1405164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        dstY = dst->height() - dstPoint.fY - srcVkRect.height();
1406164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1407164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1408164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkImageCopy copyRegion;
1409164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    memset(&copyRegion, 0, sizeof(VkImageCopy));
1410164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    copyRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
1411164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    copyRegion.srcOffset = { srcVkRect.fLeft, srcVkRect.fTop, 0 };
1412164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    copyRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
1413164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    copyRegion.dstOffset = { dstPoint.fX, dstY, 0 };
1414c355bc8dd117291b63ee7b7b39ec37a0e768eec5egdaniel    // The depth value of the extent is ignored according the vulkan spec for 2D images. However, on
1415c355bc8dd117291b63ee7b7b39ec37a0e768eec5egdaniel    // at least the nexus 5X it seems to be checking it. Thus as a working around we must have the
1416c355bc8dd117291b63ee7b7b39ec37a0e768eec5egdaniel    // depth value be 1.
1417c355bc8dd117291b63ee7b7b39ec37a0e768eec5egdaniel    copyRegion.extent = { (uint32_t)srcVkRect.width(), (uint32_t)srcVkRect.height(), 1 };
1418164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1419164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->copyImage(this,
142017b892551465e5a44560a06e4b34dc3592b49622egdaniel                                 srcImage,
1421164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
142217b892551465e5a44560a06e4b34dc3592b49622egdaniel                                 dstImage,
1423164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1424164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                 1,
1425164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                 &copyRegion);
1426900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
1427900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY,
1428900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                        srcRect.width(), srcRect.height());
1429900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    this->didWriteToSurface(dst, &dstRect);
1430164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1431164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
143217b892551465e5a44560a06e4b34dc3592b49622egdanielinline bool can_copy_as_blit(const GrSurface* dst,
143317b892551465e5a44560a06e4b34dc3592b49622egdaniel                             const GrSurface* src,
143417b892551465e5a44560a06e4b34dc3592b49622egdaniel                             const GrVkImage* dstImage,
143517b892551465e5a44560a06e4b34dc3592b49622egdaniel                             const GrVkImage* srcImage,
143617b892551465e5a44560a06e4b34dc3592b49622egdaniel                             const GrVkGpu* gpu) {
143766933552f1723c4a2b248711ab3d43921401e8e6egdaniel    // We require that all vulkan GrSurfaces have been created with transfer_dst and transfer_src
143817b892551465e5a44560a06e4b34dc3592b49622egdaniel    // as image usage flags.
143917b892551465e5a44560a06e4b34dc3592b49622egdaniel    const GrVkCaps& caps = gpu->vkCaps();
144017b892551465e5a44560a06e4b34dc3592b49622egdaniel    if (!caps.configCanBeDstofBlit(dst->config(), dstImage->isLinearTiled()) ||
144117b892551465e5a44560a06e4b34dc3592b49622egdaniel        !caps.configCanBeSrcofBlit(src->config(), srcImage->isLinearTiled())) {
144217b892551465e5a44560a06e4b34dc3592b49622egdaniel        return false;
144317b892551465e5a44560a06e4b34dc3592b49622egdaniel    }
144417b892551465e5a44560a06e4b34dc3592b49622egdaniel
144517b892551465e5a44560a06e4b34dc3592b49622egdaniel    // We cannot blit images that are multisampled. Will need to figure out if we can blit the
144617b892551465e5a44560a06e4b34dc3592b49622egdaniel    // resolved msaa though.
144717b892551465e5a44560a06e4b34dc3592b49622egdaniel    if ((dst->asRenderTarget() && dst->asRenderTarget()->numColorSamples() > 1) ||
144817b892551465e5a44560a06e4b34dc3592b49622egdaniel        (src->asRenderTarget() && src->asRenderTarget()->numColorSamples() > 1)) {
144917b892551465e5a44560a06e4b34dc3592b49622egdaniel        return false;
145017b892551465e5a44560a06e4b34dc3592b49622egdaniel    }
145117b892551465e5a44560a06e4b34dc3592b49622egdaniel
145217b892551465e5a44560a06e4b34dc3592b49622egdaniel    return true;
145317b892551465e5a44560a06e4b34dc3592b49622egdaniel}
145417b892551465e5a44560a06e4b34dc3592b49622egdaniel
145517b892551465e5a44560a06e4b34dc3592b49622egdanielvoid GrVkGpu::copySurfaceAsBlit(GrSurface* dst,
145617b892551465e5a44560a06e4b34dc3592b49622egdaniel                                GrSurface* src,
145717b892551465e5a44560a06e4b34dc3592b49622egdaniel                                GrVkImage* dstImage,
145817b892551465e5a44560a06e4b34dc3592b49622egdaniel                                GrVkImage* srcImage,
145917b892551465e5a44560a06e4b34dc3592b49622egdaniel                                const SkIRect& srcRect,
146017b892551465e5a44560a06e4b34dc3592b49622egdaniel                                const SkIPoint& dstPoint) {
146117b892551465e5a44560a06e4b34dc3592b49622egdaniel    SkASSERT(can_copy_as_blit(dst, src, dstImage, srcImage, this));
146217b892551465e5a44560a06e4b34dc3592b49622egdaniel
146317b892551465e5a44560a06e4b34dc3592b49622egdaniel    dstImage->setImageLayout(this,
146417b892551465e5a44560a06e4b34dc3592b49622egdaniel                             VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
146550c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                             VK_ACCESS_TRANSFER_WRITE_BIT,
146650c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                             VK_PIPELINE_STAGE_TRANSFER_BIT,
146717b892551465e5a44560a06e4b34dc3592b49622egdaniel                             false);
146817b892551465e5a44560a06e4b34dc3592b49622egdaniel
146917b892551465e5a44560a06e4b34dc3592b49622egdaniel    srcImage->setImageLayout(this,
147017b892551465e5a44560a06e4b34dc3592b49622egdaniel                             VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
147150c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                             VK_ACCESS_TRANSFER_READ_BIT,
147250c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                             VK_PIPELINE_STAGE_TRANSFER_BIT,
147317b892551465e5a44560a06e4b34dc3592b49622egdaniel                             false);
147417b892551465e5a44560a06e4b34dc3592b49622egdaniel
147517b892551465e5a44560a06e4b34dc3592b49622egdaniel    // Flip rect if necessary
147617b892551465e5a44560a06e4b34dc3592b49622egdaniel    SkIRect srcVkRect;
14778af936d3047208def585b7bc824f013b994f6312egdaniel    srcVkRect.fLeft = srcRect.fLeft;
14788af936d3047208def585b7bc824f013b994f6312egdaniel    srcVkRect.fRight = srcRect.fRight;
147917b892551465e5a44560a06e4b34dc3592b49622egdaniel    SkIRect dstRect;
148017b892551465e5a44560a06e4b34dc3592b49622egdaniel    dstRect.fLeft = dstPoint.fX;
14818af936d3047208def585b7bc824f013b994f6312egdaniel    dstRect.fRight = dstPoint.fX + srcRect.width();
148217b892551465e5a44560a06e4b34dc3592b49622egdaniel
148317b892551465e5a44560a06e4b34dc3592b49622egdaniel    if (kBottomLeft_GrSurfaceOrigin == src->origin()) {
148417b892551465e5a44560a06e4b34dc3592b49622egdaniel        srcVkRect.fTop = src->height() - srcRect.fBottom;
148517b892551465e5a44560a06e4b34dc3592b49622egdaniel        srcVkRect.fBottom = src->height() - srcRect.fTop;
148617b892551465e5a44560a06e4b34dc3592b49622egdaniel    } else {
14878af936d3047208def585b7bc824f013b994f6312egdaniel        srcVkRect.fTop = srcRect.fTop;
14888af936d3047208def585b7bc824f013b994f6312egdaniel        srcVkRect.fBottom = srcRect.fBottom;
148917b892551465e5a44560a06e4b34dc3592b49622egdaniel    }
149017b892551465e5a44560a06e4b34dc3592b49622egdaniel
149117b892551465e5a44560a06e4b34dc3592b49622egdaniel    if (kBottomLeft_GrSurfaceOrigin == dst->origin()) {
149217b892551465e5a44560a06e4b34dc3592b49622egdaniel        dstRect.fTop = dst->height() - dstPoint.fY - srcVkRect.height();
149317b892551465e5a44560a06e4b34dc3592b49622egdaniel    } else {
149417b892551465e5a44560a06e4b34dc3592b49622egdaniel        dstRect.fTop = dstPoint.fY;
149517b892551465e5a44560a06e4b34dc3592b49622egdaniel    }
149617b892551465e5a44560a06e4b34dc3592b49622egdaniel    dstRect.fBottom = dstRect.fTop + srcVkRect.height();
149717b892551465e5a44560a06e4b34dc3592b49622egdaniel
149817b892551465e5a44560a06e4b34dc3592b49622egdaniel    // If we have different origins, we need to flip the top and bottom of the dst rect so that we
149917b892551465e5a44560a06e4b34dc3592b49622egdaniel    // get the correct origintation of the copied data.
150017b892551465e5a44560a06e4b34dc3592b49622egdaniel    if (src->origin() != dst->origin()) {
150117b892551465e5a44560a06e4b34dc3592b49622egdaniel        SkTSwap(dstRect.fTop, dstRect.fBottom);
150217b892551465e5a44560a06e4b34dc3592b49622egdaniel    }
150317b892551465e5a44560a06e4b34dc3592b49622egdaniel
150417b892551465e5a44560a06e4b34dc3592b49622egdaniel    VkImageBlit blitRegion;
150517b892551465e5a44560a06e4b34dc3592b49622egdaniel    memset(&blitRegion, 0, sizeof(VkImageBlit));
150617b892551465e5a44560a06e4b34dc3592b49622egdaniel    blitRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
150717b892551465e5a44560a06e4b34dc3592b49622egdaniel    blitRegion.srcOffsets[0] = { srcVkRect.fLeft, srcVkRect.fTop, 0 };
150817b892551465e5a44560a06e4b34dc3592b49622egdaniel    blitRegion.srcOffsets[1] = { srcVkRect.fRight, srcVkRect.fBottom, 0 };
150917b892551465e5a44560a06e4b34dc3592b49622egdaniel    blitRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
151017b892551465e5a44560a06e4b34dc3592b49622egdaniel    blitRegion.dstOffsets[0] = { dstRect.fLeft, dstRect.fTop, 0 };
151117b892551465e5a44560a06e4b34dc3592b49622egdaniel    blitRegion.dstOffsets[1] = { dstRect.fRight, dstRect.fBottom, 0 };
151217b892551465e5a44560a06e4b34dc3592b49622egdaniel
151317b892551465e5a44560a06e4b34dc3592b49622egdaniel    fCurrentCmdBuffer->blitImage(this,
1514b2df0c2702329be6380a943d548e7377a51d8565egdaniel                                 *srcImage,
1515b2df0c2702329be6380a943d548e7377a51d8565egdaniel                                 *dstImage,
151617b892551465e5a44560a06e4b34dc3592b49622egdaniel                                 1,
151717b892551465e5a44560a06e4b34dc3592b49622egdaniel                                 &blitRegion,
151817b892551465e5a44560a06e4b34dc3592b49622egdaniel                                 VK_FILTER_NEAREST); // We never scale so any filter works here
1519900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
1520900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    this->didWriteToSurface(dst, &dstRect);
152117b892551465e5a44560a06e4b34dc3592b49622egdaniel}
152217b892551465e5a44560a06e4b34dc3592b49622egdaniel
15234bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdanielinline bool can_copy_as_resolve(const GrSurface* dst,
15244bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel                                const GrSurface* src,
15254bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel                                const GrVkGpu* gpu) {
15264bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    // Our src must be a multisampled render target
15274bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    if (!src->asRenderTarget() || src->asRenderTarget()->numColorSamples() <= 1) {
15284bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        return false;
15294bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    }
15304bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel
15314bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    // The dst must be a render target but not multisampled
15324bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    if (!dst->asRenderTarget() || dst->asRenderTarget()->numColorSamples() > 1) {
15334bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        return false;
15344bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    }
15354bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel
15364bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    // Surfaces must have the same origin.
15374bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    if (src->origin() != dst->origin()) {
15384bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        return false;
15394bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    }
15404bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel
15414bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    return true;
15424bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel}
15434bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel
15444bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdanielvoid GrVkGpu::copySurfaceAsResolve(GrSurface* dst,
15454bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel                                   GrSurface* src,
15464bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel                                   const SkIRect& srcRect,
15474bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel                                   const SkIPoint& dstPoint) {
15484bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    GrVkRenderTarget* dstRT = static_cast<GrVkRenderTarget*>(dst->asRenderTarget());
15494bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    GrVkRenderTarget* srcRT = static_cast<GrVkRenderTarget*>(src->asRenderTarget());
15504bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    SkASSERT(dstRT && dstRT->numColorSamples() <= 1);
15514bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    this->resolveImage(dstRT, srcRT, srcRect, dstPoint);
15524bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel}
15534bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel
1554164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielinline bool can_copy_as_draw(const GrSurface* dst,
1555164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                             const GrSurface* src,
1556164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                             const GrVkGpu* gpu) {
1557164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return false;
1558164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1559164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1560164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::copySurfaceAsDraw(GrSurface* dst,
1561164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                GrSurface* src,
1562164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                const SkIRect& srcRect,
1563164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                const SkIPoint& dstPoint) {
1564164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(false);
1565164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1566164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1567164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::onCopySurface(GrSurface* dst,
1568164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                            GrSurface* src,
1569164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                            const SkIRect& srcRect,
1570164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                            const SkIPoint& dstPoint) {
15714bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    if (can_copy_as_resolve(dst, src, this)) {
15724bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        this->copySurfaceAsResolve(dst, src, srcRect, dstPoint);
15734bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    }
15744bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel
157517b892551465e5a44560a06e4b34dc3592b49622egdaniel    GrVkImage* dstImage;
157617b892551465e5a44560a06e4b34dc3592b49622egdaniel    GrVkImage* srcImage;
15774bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    GrRenderTarget* dstRT = dst->asRenderTarget();
15784bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    if (dstRT) {
15794bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(dstRT);
15804bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        dstImage = vkRT->numColorSamples() > 1 ? vkRT->msaaImage() : vkRT;
158117b892551465e5a44560a06e4b34dc3592b49622egdaniel    } else {
15824bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        SkASSERT(dst->asTexture());
15834bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        dstImage = static_cast<GrVkTexture*>(dst->asTexture());
158417b892551465e5a44560a06e4b34dc3592b49622egdaniel    }
15854bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    GrRenderTarget* srcRT = src->asRenderTarget();
15864bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    if (srcRT) {
15874bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(srcRT);
15884bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        srcImage = vkRT->numColorSamples() > 1 ? vkRT->msaaImage() : vkRT;
158917b892551465e5a44560a06e4b34dc3592b49622egdaniel    } else {
15904bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        SkASSERT(src->asTexture());
15914bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        srcImage = static_cast<GrVkTexture*>(src->asTexture());
159217b892551465e5a44560a06e4b34dc3592b49622egdaniel    }
159317b892551465e5a44560a06e4b34dc3592b49622egdaniel
1594164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (can_copy_image(dst, src, this)) {
159517b892551465e5a44560a06e4b34dc3592b49622egdaniel        this->copySurfaceAsCopyImage(dst, src, dstImage, srcImage, srcRect, dstPoint);
159617b892551465e5a44560a06e4b34dc3592b49622egdaniel        return true;
159717b892551465e5a44560a06e4b34dc3592b49622egdaniel    }
159817b892551465e5a44560a06e4b34dc3592b49622egdaniel
159917b892551465e5a44560a06e4b34dc3592b49622egdaniel    if (can_copy_as_blit(dst, src, dstImage, srcImage, this)) {
160017b892551465e5a44560a06e4b34dc3592b49622egdaniel        this->copySurfaceAsBlit(dst, src, dstImage, srcImage, srcRect, dstPoint);
1601164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return true;
1602164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1603164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1604164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (can_copy_as_draw(dst, src, this)) {
1605164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        this->copySurfaceAsDraw(dst, src, srcRect, dstPoint);
1606164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return true;
1607164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1608164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1609164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return false;
1610164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1611164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
16124bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdanielbool GrVkGpu::initDescForDstCopy(const GrRenderTarget* src, GrSurfaceDesc* desc) const {
16134bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    // We can always succeed here with either a CopyImage (none msaa src) or ResolveImage (msaa).
16144bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    // For CopyImage we can make a simple texture, for ResolveImage we require the dst to be a
16154bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    // render target as well.
161637798fbd82a7d064c5cc1516f120546a3408044begdaniel    desc->fOrigin = src->origin();
161737798fbd82a7d064c5cc1516f120546a3408044begdaniel    desc->fConfig = src->config();
16184bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    desc->fFlags = src->numColorSamples() > 1 ? kRenderTarget_GrSurfaceFlag : kNone_GrSurfaceFlags;
161937798fbd82a7d064c5cc1516f120546a3408044begdaniel    return true;
162037798fbd82a7d064c5cc1516f120546a3408044begdaniel}
162137798fbd82a7d064c5cc1516f120546a3408044begdaniel
162228f45b949acc746849100fbe112ee5280f0594c9cdaltonvoid GrVkGpu::onGetMultisampleSpecs(GrRenderTarget* rt, const GrStencilSettings&,
16230d28e574ac73fef8bf75cab083ffe23f2d8860a1csmartdalton                                    int* effectiveSampleCnt, SamplePattern*) {
162428f45b949acc746849100fbe112ee5280f0594c9cdalton    // TODO: stub.
162528f45b949acc746849100fbe112ee5280f0594c9cdalton    SkASSERT(!this->caps()->sampleLocationsSupport());
162628f45b949acc746849100fbe112ee5280f0594c9cdalton    *effectiveSampleCnt = rt->desc().fSampleCnt;
162728f45b949acc746849100fbe112ee5280f0594c9cdalton}
162828f45b949acc746849100fbe112ee5280f0594c9cdalton
1629164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::onGetReadPixelsInfo(GrSurface* srcSurface, int width, int height, size_t rowBytes,
1630164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                  GrPixelConfig readConfig, DrawPreference* drawPreference,
1631164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                  ReadPixelTempDrawInfo* tempDrawInfo) {
163288e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    // These settings we will always want if a temp draw is performed.
163388e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    tempDrawInfo->fTempSurfaceDesc.fFlags = kRenderTarget_GrSurfaceFlag;
163488e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    tempDrawInfo->fTempSurfaceDesc.fWidth = width;
163588e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    tempDrawInfo->fTempSurfaceDesc.fHeight = height;
163688e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    tempDrawInfo->fTempSurfaceDesc.fSampleCnt = 0;
163788e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    tempDrawInfo->fTempSurfaceDesc.fOrigin = kTopLeft_GrSurfaceOrigin; // no CPU y-flip for TL.
1638b117ff194ff888ef9107a4797aad053b0d76be30bsalomon    tempDrawInfo->fTempSurfaceFit = SkBackingFit::kApprox;
163988e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel
164088e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    // For now assume no swizzling, we may change that below.
164188e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    tempDrawInfo->fSwizzle = GrSwizzle::RGBA();
164288e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel
164388e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    // Depends on why we need/want a temp draw. Start off assuming no change, the surface we read
164488e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    // from will be srcConfig and we will read readConfig pixels from it.
164588e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    // Not that if we require a draw and return a non-renderable format for the temp surface the
164688e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    // base class will fail for us.
164788e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    tempDrawInfo->fTempSurfaceDesc.fConfig = srcSurface->config();
164888e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    tempDrawInfo->fReadConfig = readConfig;
164988e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel
16504583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    if (srcSurface->config() == readConfig) {
16514583ec51d9ddc830eeb854db068235be96ce59c4egdaniel        return true;
1652164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1653164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
165466933552f1723c4a2b248711ab3d43921401e8e6egdaniel    if (this->vkCaps().isConfigRenderable(readConfig, srcSurface->desc().fSampleCnt > 1)) {
16554583ec51d9ddc830eeb854db068235be96ce59c4egdaniel        ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
16564583ec51d9ddc830eeb854db068235be96ce59c4egdaniel        tempDrawInfo->fTempSurfaceDesc.fConfig = readConfig;
16574583ec51d9ddc830eeb854db068235be96ce59c4egdaniel        tempDrawInfo->fReadConfig = readConfig;
16584583ec51d9ddc830eeb854db068235be96ce59c4egdaniel        return true;
1659164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1660164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
16614583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    return false;
1662164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1663164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1664164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::onReadPixels(GrSurface* surface,
1665164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           int left, int top, int width, int height,
1666164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           GrPixelConfig config,
1667164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           void* buffer,
1668164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           size_t rowBytes) {
1669164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkFormat pixelFormat;
1670164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!GrPixelConfigToVkFormat(config, &pixelFormat)) {
1671164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
1672164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1673164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
167466933552f1723c4a2b248711ab3d43921401e8e6egdaniel    GrVkImage* image = nullptr;
167566933552f1723c4a2b248711ab3d43921401e8e6egdaniel    GrVkRenderTarget* rt = static_cast<GrVkRenderTarget*>(surface->asRenderTarget());
167666933552f1723c4a2b248711ab3d43921401e8e6egdaniel    if (rt) {
167766933552f1723c4a2b248711ab3d43921401e8e6egdaniel        // resolve the render target if necessary
167866933552f1723c4a2b248711ab3d43921401e8e6egdaniel        switch (rt->getResolveType()) {
167966933552f1723c4a2b248711ab3d43921401e8e6egdaniel            case GrVkRenderTarget::kCantResolve_ResolveType:
168066933552f1723c4a2b248711ab3d43921401e8e6egdaniel                return false;
168166933552f1723c4a2b248711ab3d43921401e8e6egdaniel            case GrVkRenderTarget::kAutoResolves_ResolveType:
168266933552f1723c4a2b248711ab3d43921401e8e6egdaniel                break;
168366933552f1723c4a2b248711ab3d43921401e8e6egdaniel            case GrVkRenderTarget::kCanResolve_ResolveType:
168466933552f1723c4a2b248711ab3d43921401e8e6egdaniel                this->onResolveRenderTarget(rt);
168566933552f1723c4a2b248711ab3d43921401e8e6egdaniel                break;
168666933552f1723c4a2b248711ab3d43921401e8e6egdaniel            default:
168766933552f1723c4a2b248711ab3d43921401e8e6egdaniel                SkFAIL("Unknown resolve type");
168866933552f1723c4a2b248711ab3d43921401e8e6egdaniel        }
168966933552f1723c4a2b248711ab3d43921401e8e6egdaniel        image = rt;
169066933552f1723c4a2b248711ab3d43921401e8e6egdaniel    } else {
169166933552f1723c4a2b248711ab3d43921401e8e6egdaniel        image = static_cast<GrVkTexture*>(surface->asTexture());
169266933552f1723c4a2b248711ab3d43921401e8e6egdaniel    }
169366933552f1723c4a2b248711ab3d43921401e8e6egdaniel
169466933552f1723c4a2b248711ab3d43921401e8e6egdaniel    if (!image) {
1695164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
1696164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1697164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1698164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Change layout of our target so it can be used as copy
169966933552f1723c4a2b248711ab3d43921401e8e6egdaniel    image->setImageLayout(this,
170066933552f1723c4a2b248711ab3d43921401e8e6egdaniel                          VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
170166933552f1723c4a2b248711ab3d43921401e8e6egdaniel                          VK_ACCESS_TRANSFER_READ_BIT,
170266933552f1723c4a2b248711ab3d43921401e8e6egdaniel                          VK_PIPELINE_STAGE_TRANSFER_BIT,
170366933552f1723c4a2b248711ab3d43921401e8e6egdaniel                          false);
1704164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
17059d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary    GrVkTransferBuffer* transferBuffer =
1706e2e71c2df4e72e897bbe745752be0444aee5c29fcdalton        static_cast<GrVkTransferBuffer*>(this->createBuffer(rowBytes * height,
1707e2e71c2df4e72e897bbe745752be0444aee5c29fcdalton                                                            kXferGpuToCpu_GrBufferType,
1708397536cabe12a9936659870dd220c869789424bacdalton                                                            kStream_GrAccessPattern));
1709164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1710164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    bool flipY = kBottomLeft_GrSurfaceOrigin == surface->origin();
1711164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkOffset3D offset = {
1712164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        left,
1713164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        flipY ? surface->height() - top - height : top,
1714164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        0
1715164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    };
1716164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1717164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Copy the image to a buffer so we can map it to cpu memory
1718164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkBufferImageCopy region;
1719164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    memset(&region, 0, sizeof(VkBufferImageCopy));
1720db37909347d034943bd6b0922710a94c6c6ea572jvanverth    region.bufferOffset = transferBuffer->offset();
172188e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    region.bufferRowLength = 0; // Forces RowLength to be width. We handle the rowBytes below.
1722164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    region.bufferImageHeight = 0; // Forces height to be tightly packed. Only useful for 3d images.
1723164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
1724164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    region.imageOffset = offset;
1725164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    region.imageExtent = { (uint32_t)width, (uint32_t)height, 1 };
1726164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1727164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->copyImageToBuffer(this,
172866933552f1723c4a2b248711ab3d43921401e8e6egdaniel                                         image,
1729164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1730164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                         transferBuffer,
1731164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                         1,
1732164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                         &region);
1733164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1734164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // make sure the copy to buffer has finished
1735164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    transferBuffer->addMemoryBarrier(this,
1736164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     VK_ACCESS_TRANSFER_WRITE_BIT,
1737164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     VK_ACCESS_HOST_READ_BIT,
1738164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     VK_PIPELINE_STAGE_TRANSFER_BIT,
1739164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     VK_PIPELINE_STAGE_HOST_BIT,
1740164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     false);
1741164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1742164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // We need to submit the current command buffer to the Queue and make sure it finishes before
1743164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // we can copy the data out of the buffer.
1744164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    this->submitCommandBuffer(kForce_SyncQueue);
1745164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1746164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    void* mappedMemory = transferBuffer->map();
1747164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
174888e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    size_t tightRowBytes = GrBytesPerPixel(config) * width;
1749164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (flipY) {
175088e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel        const char* srcRow = reinterpret_cast<const char*>(mappedMemory);
175188e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel        char* dstRow = reinterpret_cast<char*>(buffer)+(height - 1) * rowBytes;
175288e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel        for (int y = 0; y < height; y++) {
175388e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel            memcpy(dstRow, srcRow, tightRowBytes);
175488e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel            srcRow += tightRowBytes;
175588e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel            dstRow -= rowBytes;
175688e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel        }
175788e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    } else {
175888e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel        if (tightRowBytes == rowBytes) {
175988e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel            memcpy(buffer, mappedMemory, rowBytes*height);
176088e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel        } else {
176188e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel            SkRectMemcpy(buffer, rowBytes, mappedMemory, tightRowBytes, tightRowBytes, height);
1762164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
1763164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1764164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
176588e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    transferBuffer->unmap();
176688e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    transferBuffer->unref();
176788e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel
1768164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return true;
1769164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1770066df7ca911b65d416783f3bec6f4f1662948ad5egdaniel
177127bb28473912181cf9a838e9282e86cb62e2d44begdaniel// The RenderArea bounds we pass into BeginRenderPass must have a start x value that is a multiple
177227bb28473912181cf9a838e9282e86cb62e2d44begdaniel// of the granularity. The width must also be a multiple of the granularity or eaqual to the width
177327bb28473912181cf9a838e9282e86cb62e2d44begdaniel// the the entire attachment. Similar requirements for the y and height components.
177427bb28473912181cf9a838e9282e86cb62e2d44begdanielvoid adjust_bounds_to_granularity(SkIRect* dstBounds, const SkIRect& srcBounds,
177527bb28473912181cf9a838e9282e86cb62e2d44begdaniel                                  const VkExtent2D& granularity, int maxWidth, int maxHeight) {
177627bb28473912181cf9a838e9282e86cb62e2d44begdaniel    // Adjust Width
177727bb28473912181cf9a838e9282e86cb62e2d44begdaniel    // Start with the right side of rect so we know if we end up going pass the maxWidth.
177827bb28473912181cf9a838e9282e86cb62e2d44begdaniel    int rightAdj = srcBounds.fRight % granularity.width;
177927bb28473912181cf9a838e9282e86cb62e2d44begdaniel    if (rightAdj != 0) {
178027bb28473912181cf9a838e9282e86cb62e2d44begdaniel        rightAdj = granularity.width - rightAdj;
178127bb28473912181cf9a838e9282e86cb62e2d44begdaniel    }
178227bb28473912181cf9a838e9282e86cb62e2d44begdaniel    dstBounds->fRight = srcBounds.fRight + rightAdj;
178327bb28473912181cf9a838e9282e86cb62e2d44begdaniel    if (dstBounds->fRight > maxWidth) {
178427bb28473912181cf9a838e9282e86cb62e2d44begdaniel        dstBounds->fRight = maxWidth;
178527bb28473912181cf9a838e9282e86cb62e2d44begdaniel        dstBounds->fLeft = 0;
178627bb28473912181cf9a838e9282e86cb62e2d44begdaniel    } else {
178727bb28473912181cf9a838e9282e86cb62e2d44begdaniel       dstBounds->fLeft = srcBounds.fLeft - srcBounds.fLeft % granularity.width;
178827bb28473912181cf9a838e9282e86cb62e2d44begdaniel    }
178927bb28473912181cf9a838e9282e86cb62e2d44begdaniel
179027bb28473912181cf9a838e9282e86cb62e2d44begdaniel    // Adjust height
179127bb28473912181cf9a838e9282e86cb62e2d44begdaniel    // Start with the bottom side of rect so we know if we end up going pass the maxHeight.
179227bb28473912181cf9a838e9282e86cb62e2d44begdaniel    int bottomAdj = srcBounds.fBottom % granularity.height;
179327bb28473912181cf9a838e9282e86cb62e2d44begdaniel    if (bottomAdj != 0) {
179427bb28473912181cf9a838e9282e86cb62e2d44begdaniel        bottomAdj = granularity.height - bottomAdj;
179527bb28473912181cf9a838e9282e86cb62e2d44begdaniel    }
179627bb28473912181cf9a838e9282e86cb62e2d44begdaniel    dstBounds->fBottom = srcBounds.fBottom + bottomAdj;
179727bb28473912181cf9a838e9282e86cb62e2d44begdaniel    if (dstBounds->fBottom > maxHeight) {
179827bb28473912181cf9a838e9282e86cb62e2d44begdaniel        dstBounds->fBottom = maxHeight;
179927bb28473912181cf9a838e9282e86cb62e2d44begdaniel        dstBounds->fTop = 0;
180027bb28473912181cf9a838e9282e86cb62e2d44begdaniel    } else {
180127bb28473912181cf9a838e9282e86cb62e2d44begdaniel       dstBounds->fTop = srcBounds.fTop - srcBounds.fTop % granularity.height;
180227bb28473912181cf9a838e9282e86cb62e2d44begdaniel    }
180327bb28473912181cf9a838e9282e86cb62e2d44begdaniel}
180427bb28473912181cf9a838e9282e86cb62e2d44begdaniel
18057ec92413307c9da43c013d1e4e15716a44059810jvanverthvoid GrVkGpu::submitSecondaryCommandBuffer(GrVkSecondaryCommandBuffer* buffer,
18069cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel                                           const GrVkRenderPass* renderPass,
18079cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel                                           const VkClearValue* colorClear,
18089cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel                                           GrVkRenderTarget* target,
18099cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel                                           const SkIRect& bounds) {
1810e7d1b24ff0a04686aef54fcb9feaca7a03e19891egdaniel    const SkIRect* pBounds = &bounds;
1811e7d1b24ff0a04686aef54fcb9feaca7a03e19891egdaniel    SkIRect flippedBounds;
1812e7d1b24ff0a04686aef54fcb9feaca7a03e19891egdaniel    if (kBottomLeft_GrSurfaceOrigin == target->origin()) {
1813e7d1b24ff0a04686aef54fcb9feaca7a03e19891egdaniel        flippedBounds = bounds;
1814e7d1b24ff0a04686aef54fcb9feaca7a03e19891egdaniel        flippedBounds.fTop = target->height() - bounds.fBottom;
1815e7d1b24ff0a04686aef54fcb9feaca7a03e19891egdaniel        flippedBounds.fBottom = target->height() - bounds.fTop;
1816e7d1b24ff0a04686aef54fcb9feaca7a03e19891egdaniel        pBounds = &flippedBounds;
1817e7d1b24ff0a04686aef54fcb9feaca7a03e19891egdaniel    }
1818e7d1b24ff0a04686aef54fcb9feaca7a03e19891egdaniel
181927bb28473912181cf9a838e9282e86cb62e2d44begdaniel    // The bounds we use for the render pass should be of the granularity supported
182027bb28473912181cf9a838e9282e86cb62e2d44begdaniel    // by the device.
182127bb28473912181cf9a838e9282e86cb62e2d44begdaniel    const VkExtent2D& granularity = renderPass->granularity();
182227bb28473912181cf9a838e9282e86cb62e2d44begdaniel    SkIRect adjustedBounds;
182327bb28473912181cf9a838e9282e86cb62e2d44begdaniel    if ((0 != granularity.width && 1 != granularity.width) ||
182427bb28473912181cf9a838e9282e86cb62e2d44begdaniel        (0 != granularity.height && 1 != granularity.height)) {
182527bb28473912181cf9a838e9282e86cb62e2d44begdaniel        adjust_bounds_to_granularity(&adjustedBounds, *pBounds, granularity,
182627bb28473912181cf9a838e9282e86cb62e2d44begdaniel                                     target->width(), target->height());
182727bb28473912181cf9a838e9282e86cb62e2d44begdaniel        pBounds = &adjustedBounds;
182827bb28473912181cf9a838e9282e86cb62e2d44begdaniel    }
182927bb28473912181cf9a838e9282e86cb62e2d44begdaniel
18309cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel    // Currently it is fine for us to always pass in 1 for the clear count even if no attachment
18319cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel    // uses it. In the current state, we also only use the LOAD_OP_CLEAR for the color attachment
18329cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel    // which is always at the first attachment.
1833e7d1b24ff0a04686aef54fcb9feaca7a03e19891egdaniel    fCurrentCmdBuffer->beginRenderPass(this, renderPass, 1, colorClear, *target, *pBounds, true);
1834066df7ca911b65d416783f3bec6f4f1662948ad5egdaniel    fCurrentCmdBuffer->executeCommands(this, buffer);
1835164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->endRenderPass(this);
183666933552f1723c4a2b248711ab3d43921401e8e6egdaniel
1837ce3bfb1ed155880585b2d0bb0a8d3e43306e23f2egdaniel    this->didWriteToSurface(target, &bounds);
1838164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
18399cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel
1840