GrVkGpu.cpp revision 13dddce65fd87a8175a209a49f35615735a2886a
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
107ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel#include "GrBackendSurface.h"
11164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrContextOptions.h"
12164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrGeometryProcessor.h"
13164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrGpuResourceCacheAccess.h"
140e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel#include "GrMesh.h"
15164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrPipeline.h"
16164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrRenderTargetPriv.h"
17164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrSurfacePriv.h"
18164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrTexturePriv.h"
19164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
20164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkCommandBuffer.h"
21066df7ca911b65d416783f3bec6f4f1662948ad5egdaniel#include "GrVkGpuCommandBuffer.h"
22164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkImage.h"
23164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkIndexBuffer.h"
24164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkMemory.h"
25164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkPipeline.h"
2622281c13a13c4b4e275516e9fe02185a53a7e5aaegdaniel#include "GrVkPipelineState.h"
27164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkRenderPass.h"
28164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkResourceProvider.h"
296be35238855dbbc7575e78d6723936293a4b38e6Greg Daniel#include "GrVkSemaphore.h"
30c2dd5ed93753dc54619fb713ebcf38bd1af08592Greg Daniel#include "GrVkTexelBuffer.h"
31164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkTexture.h"
32164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkTextureRenderTarget.h"
33164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkTransferBuffer.h"
34164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkVertexBuffer.h"
35164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
36485c499a2797c1eb0e750fa4aaec57192799b424Matt Sarett#include "SkConvertPixels.h"
37900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth#include "SkMipMap.h"
38164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
39164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "vk/GrVkInterface.h"
40fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth#include "vk/GrVkTypes.h"
41164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
42b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "SkSLCompiler.h"
43b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
4444f85712f47f68645bb292df70f807f67aaf6d05Forrest Reiling#if !defined(SK_BUILD_FOR_WIN)
4544f85712f47f68645bb292df70f807f67aaf6d05Forrest Reiling#include <unistd.h>
4644f85712f47f68645bb292df70f807f67aaf6d05Forrest Reiling#endif // !defined(SK_BUILD_FOR_WIN)
4744f85712f47f68645bb292df70f807f67aaf6d05Forrest Reiling
48164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#define VK_CALL(X) GR_VK_CALL(this->vkInterface(), X)
49164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#define VK_CALL_RET(RET, X) GR_VK_CALL_RET(this->vkInterface(), RET, X)
50164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#define VK_CALL_ERRCHECK(X) GR_VK_CALL_ERRCHECK(this->vkInterface(), X)
51164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
52735109c24892a95290974c9665527b57b01e5440egdaniel#ifdef SK_ENABLE_VK_LAYERS
53d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverthVKAPI_ATTR VkBool32 VKAPI_CALL DebugReportCallback(
54d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    VkDebugReportFlagsEXT       flags,
55d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    VkDebugReportObjectTypeEXT  objectType,
56d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    uint64_t                    object,
57d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    size_t                      location,
58d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    int32_t                     messageCode,
59d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    const char*                 pLayerPrefix,
60d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    const char*                 pMessage,
61d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    void*                       pUserData) {
62d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    if (flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
63d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        SkDebugf("Vulkan error [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
64ce3fe23c04e93d2aa8d4c09c0c99088207edd509Jim Van Verth        return VK_TRUE; // skip further layers
65d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    } else if (flags & VK_DEBUG_REPORT_WARNING_BIT_EXT) {
66d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        SkDebugf("Vulkan warning [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
67d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    } else if (flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) {
68d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        SkDebugf("Vulkan perf warning [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
69d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    } else {
70d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        SkDebugf("Vulkan info/debug [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
71d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    }
72d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    return VK_FALSE;
73d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth}
74d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth#endif
75d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth
76633b35657c964c32e7010b14bb2d396b4a764c52jvanverthGrGpu* GrVkGpu::Create(GrBackendContext backendContext, const GrContextOptions& options,
77633b35657c964c32e7010b14bb2d396b4a764c52jvanverth                       GrContext* context) {
78dc0fcd41e75682a8bfd5e285d684461475226330bsalomon    const GrVkBackendContext* vkBackendContext =
79dc0fcd41e75682a8bfd5e285d684461475226330bsalomon        reinterpret_cast<const GrVkBackendContext*>(backendContext);
80633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    if (!vkBackendContext) {
81c1889823de68ffd2ef08b5c1969d41c98034ec6aBrian Salomon        return nullptr;
82633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    } else {
83633b35657c964c32e7010b14bb2d396b4a764c52jvanverth        vkBackendContext->ref();
84164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
85164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
86fe2965af79d70c7f3fe30204846e430c3db56a4eGreg Daniel    if (!vkBackendContext->fInterface->validate(vkBackendContext->fExtensions)) {
87fe2965af79d70c7f3fe30204846e430c3db56a4eGreg Daniel        return nullptr;
88fe2965af79d70c7f3fe30204846e430c3db56a4eGreg Daniel    }
89fe2965af79d70c7f3fe30204846e430c3db56a4eGreg Daniel
90633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    return new GrVkGpu(context, options, vkBackendContext);
91164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
92164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
93164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
94164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
959d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanaryGrVkGpu::GrVkGpu(GrContext* context, const GrContextOptions& options,
96633b35657c964c32e7010b14bb2d396b4a764c52jvanverth                 const GrVkBackendContext* backendCtx)
97164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    : INHERITED(context)
98633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    , fDevice(backendCtx->fDevice)
99633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    , fQueue(backendCtx->fQueue)
1008606cf836e2cdbabe7fd917b7cba88b6673c9175Greg Daniel    , fResourceProvider(this)
1018606cf836e2cdbabe7fd917b7cba88b6673c9175Greg Daniel    , fDisconnected(false) {
102633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    fBackendContext.reset(backendCtx);
103164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
104735109c24892a95290974c9665527b57b01e5440egdaniel#ifdef SK_ENABLE_VK_LAYERS
105419ca64f0f800dc098369b5aa5a604acd017b240brianosman    fCallback = VK_NULL_HANDLE;
106fd7bd45ac2178ce6b4a390f517f605750aaef6c8jvanverth    if (backendCtx->fExtensions & kEXT_debug_report_GrVkExtensionFlag) {
107fd7bd45ac2178ce6b4a390f517f605750aaef6c8jvanverth        // Setup callback creation information
108d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        VkDebugReportCallbackCreateInfoEXT callbackCreateInfo;
109d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        callbackCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
110d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        callbackCreateInfo.pNext = nullptr;
111d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        callbackCreateInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT |
112ef0c10cffefef90646ff2e238d7c2d82247a0370egdaniel                                   VK_DEBUG_REPORT_WARNING_BIT_EXT |
113d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth                                   //VK_DEBUG_REPORT_INFORMATION_BIT_EXT |
114d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth                                   //VK_DEBUG_REPORT_DEBUG_BIT_EXT |
115b4aa36211ca66ef127ac2954108742af1ead5082egdaniel                                   VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
116d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        callbackCreateInfo.pfnCallback = &DebugReportCallback;
117d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        callbackCreateInfo.pUserData = nullptr;
118d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth
119fd7bd45ac2178ce6b4a390f517f605750aaef6c8jvanverth        // Register the callback
120a00980e58037fa36d066be80d7fcc0f73b2dfd40jvanverth        GR_VK_CALL_ERRCHECK(this->vkInterface(), CreateDebugReportCallbackEXT(
121a00980e58037fa36d066be80d7fcc0f73b2dfd40jvanverth                            backendCtx->fInstance, &callbackCreateInfo, nullptr, &fCallback));
122d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    }
123d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth#endif
124633b35657c964c32e7010b14bb2d396b4a764c52jvanverth
125b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    fCompiler = new SkSL::Compiler();
126633b35657c964c32e7010b14bb2d396b4a764c52jvanverth
127fd7bd45ac2178ce6b4a390f517f605750aaef6c8jvanverth    fVkCaps.reset(new GrVkCaps(options, this->vkInterface(), backendCtx->fPhysicalDevice,
128c5ec1408298510410270ea67e895570ccfa76e54egdaniel                               backendCtx->fFeatures, backendCtx->fExtensions));
129633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    fCaps.reset(SkRef(fVkCaps.get()));
130633b35657c964c32e7010b14bb2d396b4a764c52jvanverth
131633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    VK_CALL(GetPhysicalDeviceMemoryProperties(backendCtx->fPhysicalDevice, &fPhysDevMemProps));
132633b35657c964c32e7010b14bb2d396b4a764c52jvanverth
133633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    const VkCommandPoolCreateInfo cmdPoolInfo = {
1347ec92413307c9da43c013d1e4e15716a44059810jvanverth        VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // sType
1357ec92413307c9da43c013d1e4e15716a44059810jvanverth        nullptr,                                         // pNext
1367ec92413307c9da43c013d1e4e15716a44059810jvanverth        VK_COMMAND_POOL_CREATE_TRANSIENT_BIT |
1377ec92413307c9da43c013d1e4e15716a44059810jvanverth        VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // CmdPoolCreateFlags
1387ec92413307c9da43c013d1e4e15716a44059810jvanverth        backendCtx->fGraphicsQueueIndex,                 // queueFamilyIndex
139633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    };
1409d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary    GR_VK_CALL_ERRCHECK(this->vkInterface(), CreateCommandPool(fDevice, &cmdPoolInfo, nullptr,
141633b35657c964c32e7010b14bb2d396b4a764c52jvanverth                                                               &fCmdPool));
142633b35657c964c32e7010b14bb2d396b4a764c52jvanverth
143633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    // must call this after creating the CommandPool
144633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    fResourceProvider.init();
1457ec92413307c9da43c013d1e4e15716a44059810jvanverth    fCurrentCmdBuffer = fResourceProvider.findOrCreatePrimaryCommandBuffer();
146633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    SkASSERT(fCurrentCmdBuffer);
147633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    fCurrentCmdBuffer->begin(this);
1486b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth
1496b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    // set up our heaps
1506b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    fHeaps[kLinearImage_Heap].reset(new GrVkHeap(this, GrVkHeap::kSubAlloc_Strategy, 16*1024*1024));
1514f7d97c16fd159f72d2ad9c105542e2c6c097ad6Greg Daniel    fHeaps[kOptimalImage_Heap].reset(new GrVkHeap(this, GrVkHeap::kSubAlloc_Strategy, 64*1024*1024));
1526b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    fHeaps[kSmallOptimalImage_Heap].reset(new GrVkHeap(this, GrVkHeap::kSubAlloc_Strategy, 2*1024*1024));
1536b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    fHeaps[kVertexBuffer_Heap].reset(new GrVkHeap(this, GrVkHeap::kSingleAlloc_Strategy, 0));
1546b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    fHeaps[kIndexBuffer_Heap].reset(new GrVkHeap(this, GrVkHeap::kSingleAlloc_Strategy, 0));
1554c6e47a8a827077e36fa5feb4ab5ac7435d8276bjvanverth    fHeaps[kUniformBuffer_Heap].reset(new GrVkHeap(this, GrVkHeap::kSubAlloc_Strategy, 256*1024));
156c2dd5ed93753dc54619fb713ebcf38bd1af08592Greg Daniel    fHeaps[kTexelBuffer_Heap].reset(new GrVkHeap(this, GrVkHeap::kSingleAlloc_Strategy, 0));
1576b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    fHeaps[kCopyReadBuffer_Heap].reset(new GrVkHeap(this, GrVkHeap::kSingleAlloc_Strategy, 0));
1586b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    fHeaps[kCopyWriteBuffer_Heap].reset(new GrVkHeap(this, GrVkHeap::kSubAlloc_Strategy, 16*1024*1024));
159164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
160164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1618606cf836e2cdbabe7fd917b7cba88b6673c9175Greg Danielvoid GrVkGpu::destroyResources() {
1628606cf836e2cdbabe7fd917b7cba88b6673c9175Greg Daniel    if (fCurrentCmdBuffer) {
1638606cf836e2cdbabe7fd917b7cba88b6673c9175Greg Daniel        fCurrentCmdBuffer->end(this);
1648606cf836e2cdbabe7fd917b7cba88b6673c9175Greg Daniel        fCurrentCmdBuffer->unref(this);
1658606cf836e2cdbabe7fd917b7cba88b6673c9175Greg Daniel    }
166164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
167164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // wait for all commands to finish
168ddf9835e9cdf512b1d5172d014f00ceb6dacd039jvanverth    fResourceProvider.checkCommandBuffers();
16909557d7c0409ca1194d06d9dd9664fb5530c3f46Jim Van Verth    VkResult res = VK_CALL(QueueWaitIdle(fQueue));
170f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel
171f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel    // On windows, sometimes calls to QueueWaitIdle return before actually signalling the fences
172f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel    // on the command buffers even though they have completed. This causes an assert to fire when
173f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel    // destroying the command buffers. Currently this ony seems to happen on windows, so we add a
17409557d7c0409ca1194d06d9dd9664fb5530c3f46Jim Van Verth    // sleep to make sure the fence signals.
175f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel#ifdef SK_DEBUG
17680a08dd2e5cc379100ae944b3f3fadf887d518f0Greg Daniel    if (this->vkCaps().mustSleepOnTearDown()) {
177f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel#if defined(SK_BUILD_FOR_WIN)
17880a08dd2e5cc379100ae944b3f3fadf887d518f0Greg Daniel        Sleep(10); // In milliseconds
179f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel#else
18080a08dd2e5cc379100ae944b3f3fadf887d518f0Greg Daniel        sleep(1);  // In seconds
181f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel#endif
18280a08dd2e5cc379100ae944b3f3fadf887d518f0Greg Daniel    }
183f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel#endif
184f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel
185be9d82161d8347929a66ef942dabbe56abf592a4egdaniel#ifdef SK_DEBUG
1868a8668b4721097de657ad8b30d45f60f62433c6fGreg Daniel    SkASSERT(VK_SUCCESS == res || VK_ERROR_DEVICE_LOST == res);
187be9d82161d8347929a66ef942dabbe56abf592a4egdaniel#endif
1889d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
1896be35238855dbbc7575e78d6723936293a4b38e6Greg Daniel    for (int i = 0; i < fSemaphoresToWaitOn.count(); ++i) {
1906be35238855dbbc7575e78d6723936293a4b38e6Greg Daniel        fSemaphoresToWaitOn[i]->unref(this);
1916be35238855dbbc7575e78d6723936293a4b38e6Greg Daniel    }
1926be35238855dbbc7575e78d6723936293a4b38e6Greg Daniel    fSemaphoresToWaitOn.reset();
1936be35238855dbbc7575e78d6723936293a4b38e6Greg Daniel
194bc9b2963bf9e39c47ae5c3ab94b8503b476f4f0eegdaniel    fCopyManager.destroyResources(this);
195bc9b2963bf9e39c47ae5c3ab94b8503b476f4f0eegdaniel
19609557d7c0409ca1194d06d9dd9664fb5530c3f46Jim Van Verth    // must call this just before we destroy the command pool and VkDevice
19709557d7c0409ca1194d06d9dd9664fb5530c3f46Jim Van Verth    fResourceProvider.destroyResources(VK_ERROR_DEVICE_LOST == res);
198164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1998606cf836e2cdbabe7fd917b7cba88b6673c9175Greg Daniel    if (fCmdPool != VK_NULL_HANDLE) {
2008606cf836e2cdbabe7fd917b7cba88b6673c9175Greg Daniel        VK_CALL(DestroyCommandPool(fDevice, fCmdPool, nullptr));
2018606cf836e2cdbabe7fd917b7cba88b6673c9175Greg Daniel    }
202633b35657c964c32e7010b14bb2d396b4a764c52jvanverth
203735109c24892a95290974c9665527b57b01e5440egdaniel#ifdef SK_ENABLE_VK_LAYERS
204a00980e58037fa36d066be80d7fcc0f73b2dfd40jvanverth    if (fCallback) {
205a00980e58037fa36d066be80d7fcc0f73b2dfd40jvanverth        VK_CALL(DestroyDebugReportCallbackEXT(fBackendContext->fInstance, fCallback, nullptr));
206a00980e58037fa36d066be80d7fcc0f73b2dfd40jvanverth    }
207d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth#endif
2088606cf836e2cdbabe7fd917b7cba88b6673c9175Greg Daniel
2098606cf836e2cdbabe7fd917b7cba88b6673c9175Greg Daniel}
2108606cf836e2cdbabe7fd917b7cba88b6673c9175Greg Daniel
2118606cf836e2cdbabe7fd917b7cba88b6673c9175Greg DanielGrVkGpu::~GrVkGpu() {
2128606cf836e2cdbabe7fd917b7cba88b6673c9175Greg Daniel    if (!fDisconnected) {
2138606cf836e2cdbabe7fd917b7cba88b6673c9175Greg Daniel        this->destroyResources();
2148606cf836e2cdbabe7fd917b7cba88b6673c9175Greg Daniel    }
2158606cf836e2cdbabe7fd917b7cba88b6673c9175Greg Daniel    delete fCompiler;
2168606cf836e2cdbabe7fd917b7cba88b6673c9175Greg Daniel}
2178606cf836e2cdbabe7fd917b7cba88b6673c9175Greg Daniel
2188606cf836e2cdbabe7fd917b7cba88b6673c9175Greg Daniel
2198606cf836e2cdbabe7fd917b7cba88b6673c9175Greg Danielvoid GrVkGpu::disconnect(DisconnectType type) {
2208606cf836e2cdbabe7fd917b7cba88b6673c9175Greg Daniel    INHERITED::disconnect(type);
2218606cf836e2cdbabe7fd917b7cba88b6673c9175Greg Daniel    if (!fDisconnected) {
2228606cf836e2cdbabe7fd917b7cba88b6673c9175Greg Daniel        if (DisconnectType::kCleanup == type) {
2238606cf836e2cdbabe7fd917b7cba88b6673c9175Greg Daniel            this->destroyResources();
2248606cf836e2cdbabe7fd917b7cba88b6673c9175Greg Daniel        } else {
2258606cf836e2cdbabe7fd917b7cba88b6673c9175Greg Daniel            fCurrentCmdBuffer->unrefAndAbandon();
2268606cf836e2cdbabe7fd917b7cba88b6673c9175Greg Daniel            for (int i = 0; i < fSemaphoresToWaitOn.count(); ++i) {
2278606cf836e2cdbabe7fd917b7cba88b6673c9175Greg Daniel                fSemaphoresToWaitOn[i]->unrefAndAbandon();
2288606cf836e2cdbabe7fd917b7cba88b6673c9175Greg Daniel            }
2298606cf836e2cdbabe7fd917b7cba88b6673c9175Greg Daniel            fCopyManager.abandonResources();
2308606cf836e2cdbabe7fd917b7cba88b6673c9175Greg Daniel
2318606cf836e2cdbabe7fd917b7cba88b6673c9175Greg Daniel            // must call this just before we destroy the command pool and VkDevice
2328606cf836e2cdbabe7fd917b7cba88b6673c9175Greg Daniel            fResourceProvider.abandonResources();
2338606cf836e2cdbabe7fd917b7cba88b6673c9175Greg Daniel        }
2348606cf836e2cdbabe7fd917b7cba88b6673c9175Greg Daniel        fSemaphoresToWaitOn.reset();
2358606cf836e2cdbabe7fd917b7cba88b6673c9175Greg Daniel#ifdef SK_ENABLE_VK_LAYERS
2368606cf836e2cdbabe7fd917b7cba88b6673c9175Greg Daniel        fCallback = VK_NULL_HANDLE;
2378606cf836e2cdbabe7fd917b7cba88b6673c9175Greg Daniel#endif
2388606cf836e2cdbabe7fd917b7cba88b6673c9175Greg Daniel        fCurrentCmdBuffer = nullptr;
2398606cf836e2cdbabe7fd917b7cba88b6673c9175Greg Daniel        fCmdPool = VK_NULL_HANDLE;
2408606cf836e2cdbabe7fd917b7cba88b6673c9175Greg Daniel        fDisconnected = true;
2418606cf836e2cdbabe7fd917b7cba88b6673c9175Greg Daniel    }
242164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
243164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
244164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel///////////////////////////////////////////////////////////////////////////////
245164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
2469cb6340a62a5d748e4189d50e51fa527c8c80c03egdanielGrGpuCommandBuffer* GrVkGpu::createCommandBuffer(
2479cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel            const GrGpuCommandBuffer::LoadAndStoreInfo& colorInfo,
2489cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel            const GrGpuCommandBuffer::LoadAndStoreInfo& stencilInfo) {
249c293a29bc2fced15ac44a66efa813d42cb3f2e0bBrian Salomon    return new GrVkGpuCommandBuffer(this, colorInfo, stencilInfo);
250066df7ca911b65d416783f3bec6f4f1662948ad5egdaniel}
251066df7ca911b65d416783f3bec6f4f1662948ad5egdaniel
2526be35238855dbbc7575e78d6723936293a4b38e6Greg Danielvoid GrVkGpu::submitCommandBuffer(SyncQueue sync,
2536be35238855dbbc7575e78d6723936293a4b38e6Greg Daniel                                  const GrVkSemaphore::Resource* signalSemaphore) {
254164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(fCurrentCmdBuffer);
255164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->end(this);
256164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
2576be35238855dbbc7575e78d6723936293a4b38e6Greg Daniel    fCurrentCmdBuffer->submitToQueue(this, fQueue, sync, signalSemaphore, fSemaphoresToWaitOn);
2586be35238855dbbc7575e78d6723936293a4b38e6Greg Daniel
2596be35238855dbbc7575e78d6723936293a4b38e6Greg Daniel    for (int i = 0; i < fSemaphoresToWaitOn.count(); ++i) {
2606be35238855dbbc7575e78d6723936293a4b38e6Greg Daniel        fSemaphoresToWaitOn[i]->unref(this);
2616be35238855dbbc7575e78d6723936293a4b38e6Greg Daniel    }
2626be35238855dbbc7575e78d6723936293a4b38e6Greg Daniel    fSemaphoresToWaitOn.reset();
2636be35238855dbbc7575e78d6723936293a4b38e6Greg Daniel
264164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fResourceProvider.checkCommandBuffers();
265164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
266164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Release old command buffer and create a new one
267164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->unref(this);
2687ec92413307c9da43c013d1e4e15716a44059810jvanverth    fCurrentCmdBuffer = fResourceProvider.findOrCreatePrimaryCommandBuffer();
269164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(fCurrentCmdBuffer);
270164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
271164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->begin(this);
272164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
273164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
274164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel///////////////////////////////////////////////////////////////////////////////
2751bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdaltonGrBuffer* GrVkGpu::onCreateBuffer(size_t size, GrBufferType type, GrAccessPattern accessPattern,
2761bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton                                  const void* data) {
2771bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton    GrBuffer* buff;
278397536cabe12a9936659870dd220c869789424bacdalton    switch (type) {
279397536cabe12a9936659870dd220c869789424bacdalton        case kVertex_GrBufferType:
280397536cabe12a9936659870dd220c869789424bacdalton            SkASSERT(kDynamic_GrAccessPattern == accessPattern ||
281397536cabe12a9936659870dd220c869789424bacdalton                     kStatic_GrAccessPattern == accessPattern);
2821bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton            buff = GrVkVertexBuffer::Create(this, size, kDynamic_GrAccessPattern == accessPattern);
283e05bbbba79c569c1d32fa6475feecd1477fd3beeegdaniel            break;
284397536cabe12a9936659870dd220c869789424bacdalton        case kIndex_GrBufferType:
285397536cabe12a9936659870dd220c869789424bacdalton            SkASSERT(kDynamic_GrAccessPattern == accessPattern ||
286397536cabe12a9936659870dd220c869789424bacdalton                     kStatic_GrAccessPattern == accessPattern);
2871bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton            buff = GrVkIndexBuffer::Create(this, size, kDynamic_GrAccessPattern == accessPattern);
288e05bbbba79c569c1d32fa6475feecd1477fd3beeegdaniel            break;
289397536cabe12a9936659870dd220c869789424bacdalton        case kXferCpuToGpu_GrBufferType:
290c3d706f7ce87cdd94158d2266ab2fe2f18f5020ajvanverth            SkASSERT(kStream_GrAccessPattern == accessPattern);
2911bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton            buff = GrVkTransferBuffer::Create(this, size, GrVkBuffer::kCopyRead_Type);
292e05bbbba79c569c1d32fa6475feecd1477fd3beeegdaniel            break;
293397536cabe12a9936659870dd220c869789424bacdalton        case kXferGpuToCpu_GrBufferType:
294c3d706f7ce87cdd94158d2266ab2fe2f18f5020ajvanverth            SkASSERT(kStream_GrAccessPattern == accessPattern);
2951bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton            buff = GrVkTransferBuffer::Create(this, size, GrVkBuffer::kCopyWrite_Type);
296e05bbbba79c569c1d32fa6475feecd1477fd3beeegdaniel            break;
297c2dd5ed93753dc54619fb713ebcf38bd1af08592Greg Daniel        case kTexel_GrBufferType:
298c2dd5ed93753dc54619fb713ebcf38bd1af08592Greg Daniel            SkASSERT(kDynamic_GrAccessPattern == accessPattern);
299c2dd5ed93753dc54619fb713ebcf38bd1af08592Greg Daniel            buff = GrVkTexelBuffer::Create(this, size);
300c2dd5ed93753dc54619fb713ebcf38bd1af08592Greg Daniel            break;
301c2dd5ed93753dc54619fb713ebcf38bd1af08592Greg Daniel        case kDrawIndirect_GrBufferType:
302c2dd5ed93753dc54619fb713ebcf38bd1af08592Greg Daniel            SkFAIL("DrawIndirect Buffers not supported  in vulkan backend.");
303c2dd5ed93753dc54619fb713ebcf38bd1af08592Greg Daniel            return nullptr;
304397536cabe12a9936659870dd220c869789424bacdalton        default:
305397536cabe12a9936659870dd220c869789424bacdalton            SkFAIL("Unknown buffer type.");
306397536cabe12a9936659870dd220c869789424bacdalton            return nullptr;
307397536cabe12a9936659870dd220c869789424bacdalton    }
3081bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton    if (data && buff) {
3091bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton        buff->updateData(data, size);
3101bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton    }
3111bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton    return buff;
312164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
313164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
314164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
315164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::onGetWritePixelsInfo(GrSurface* dstSurface, int width, int height,
316164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                   GrPixelConfig srcConfig, DrawPreference* drawPreference,
317164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                   WritePixelTempDrawInfo* tempDrawInfo) {
318d0be1ef36c64c2a420cbd82f4c033704d4c54a07Brian Osman    if (GrPixelConfigIsCompressed(dstSurface->config())) {
319164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
320164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
321164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
3224583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    GrRenderTarget* renderTarget = dstSurface->asRenderTarget();
3234583ec51d9ddc830eeb854db068235be96ce59c4egdaniel
3244583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    // Start off assuming no swizzling
3254583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    tempDrawInfo->fSwizzle = GrSwizzle::RGBA();
3264583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    tempDrawInfo->fWriteConfig = srcConfig;
3274583ec51d9ddc830eeb854db068235be96ce59c4egdaniel
3284583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    // These settings we will always want if a temp draw is performed. Initially set the config
3294583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    // to srcConfig, though that may be modified if we decide to do a R/B swap
3304583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    tempDrawInfo->fTempSurfaceDesc.fFlags = kNone_GrSurfaceFlags;
3314583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    tempDrawInfo->fTempSurfaceDesc.fConfig = srcConfig;
3324583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    tempDrawInfo->fTempSurfaceDesc.fWidth = width;
3334583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    tempDrawInfo->fTempSurfaceDesc.fHeight = height;
3344583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    tempDrawInfo->fTempSurfaceDesc.fSampleCnt = 0;
3354583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    tempDrawInfo->fTempSurfaceDesc.fOrigin = kTopLeft_GrSurfaceOrigin;
3364583ec51d9ddc830eeb854db068235be96ce59c4egdaniel
337d66110f5972169dbcda8932c3a9a001adff23df4egdaniel    if (dstSurface->config() == srcConfig) {
33833910297e032b9af4336bc146c7fbb0f35918de9Brian Osman        // We only support writing pixels to textures. Forcing a draw lets us write to pure RTs.
33933910297e032b9af4336bc146c7fbb0f35918de9Brian Osman        if (!dstSurface->asTexture()) {
34033910297e032b9af4336bc146c7fbb0f35918de9Brian Osman            ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
34133910297e032b9af4336bc146c7fbb0f35918de9Brian Osman        }
34233910297e032b9af4336bc146c7fbb0f35918de9Brian Osman        // If the dst is MSAA, we have to draw, or we'll just be writing to the resolve target.
34333910297e032b9af4336bc146c7fbb0f35918de9Brian Osman        if (renderTarget && renderTarget->numColorSamples() > 1) {
34433910297e032b9af4336bc146c7fbb0f35918de9Brian Osman            ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
34533910297e032b9af4336bc146c7fbb0f35918de9Brian Osman        }
346d66110f5972169dbcda8932c3a9a001adff23df4egdaniel        return true;
347d66110f5972169dbcda8932c3a9a001adff23df4egdaniel    }
348d66110f5972169dbcda8932c3a9a001adff23df4egdaniel
34933910297e032b9af4336bc146c7fbb0f35918de9Brian Osman    // Any config change requires a draw
35033910297e032b9af4336bc146c7fbb0f35918de9Brian Osman    ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
3514583ec51d9ddc830eeb854db068235be96ce59c4egdaniel
35233910297e032b9af4336bc146c7fbb0f35918de9Brian Osman    bool configsAreRBSwaps = GrPixelConfigSwapRAndB(srcConfig) == dstSurface->config();
3534583ec51d9ddc830eeb854db068235be96ce59c4egdaniel
35433910297e032b9af4336bc146c7fbb0f35918de9Brian Osman    if (!this->vkCaps().isConfigTexturable(srcConfig) && configsAreRBSwaps) {
35533910297e032b9af4336bc146c7fbb0f35918de9Brian Osman        tempDrawInfo->fTempSurfaceDesc.fConfig = dstSurface->config();
35633910297e032b9af4336bc146c7fbb0f35918de9Brian Osman        tempDrawInfo->fSwizzle = GrSwizzle::BGRA();
35733910297e032b9af4336bc146c7fbb0f35918de9Brian Osman        tempDrawInfo->fWriteConfig = dstSurface->config();
358164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
35933910297e032b9af4336bc146c7fbb0f35918de9Brian Osman    return true;
360164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
361164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
362164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::onWritePixels(GrSurface* surface,
363164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                            int left, int top, int width, int height,
364a1e6b3be8124cef85f2e39e3cb85000ad9526d48bsalomon                            GrPixelConfig config,
365a1e6b3be8124cef85f2e39e3cb85000ad9526d48bsalomon                            const SkTArray<GrMipLevel>& texels) {
366164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkTexture* vkTex = static_cast<GrVkTexture*>(surface->asTexture());
367164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!vkTex) {
368164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
369164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
370164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
371900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // Make sure we have at least the base level
37203509eafa3e25819ff69f4d4f339d46264820c38jvanverth    if (texels.empty() || !texels.begin()->fPixels) {
37303509eafa3e25819ff69f4d4f339d46264820c38jvanverth        return false;
37403509eafa3e25819ff69f4d4f339d46264820c38jvanverth    }
375a1e6b3be8124cef85f2e39e3cb85000ad9526d48bsalomon
376164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // We assume Vulkan doesn't do sRGB <-> linear conversions when reading and writing pixels.
377164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (GrPixelConfigIsSRGB(surface->config()) != GrPixelConfigIsSRGB(config)) {
378164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
379164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
380164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
381164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    bool success = false;
382164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (GrPixelConfigIsCompressed(vkTex->desc().fConfig)) {
383164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // We check that config == desc.fConfig in GrGpu::getWritePixelsInfo()
384164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        SkASSERT(config == vkTex->desc().fConfig);
385164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // TODO: add compressed texture support
386164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // delete the following two lines and uncomment the two after that when ready
387164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        vkTex->unref();
388164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
389164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        //success = this->uploadCompressedTexData(vkTex->desc(), buffer, false, left, top, width,
390164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        //                                       height);
391164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    } else {
392164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        bool linearTiling = vkTex->isLinearTiled();
393900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        if (linearTiling) {
394900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            if (texels.count() > 1) {
395900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                SkDebugf("Can't upload mipmap data to linear tiled texture");
396900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                return false;
397900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            }
398900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            if (VK_IMAGE_LAYOUT_PREINITIALIZED != vkTex->currentLayout()) {
399900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                // Need to change the layout to general in order to perform a host write
400900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                vkTex->setImageLayout(this,
401900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                      VK_IMAGE_LAYOUT_GENERAL,
40250c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                                      VK_ACCESS_HOST_WRITE_BIT,
40350c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                                      VK_PIPELINE_STAGE_HOST_BIT,
404900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                      false);
405bdf8811b3126ab08ccff08b5e647b80cae5bd087egdaniel                this->submitCommandBuffer(kForce_SyncQueue);
406900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            }
407900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            success = this->uploadTexDataLinear(vkTex, left, top, width, height, config,
408900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                                texels.begin()->fPixels, texels.begin()->fRowBytes);
409900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        } else {
410c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth            int newMipLevels = texels.count();
41182c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth            int currentMipLevels = vkTex->texturePriv().maxMipMapLevel() + 1;
412dd20e918bb3c92a7643a8cbd6760ac66c2694017Greg Daniel            if (newMipLevels > currentMipLevels) {
413c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth                if (!vkTex->reallocForMipmap(this, newMipLevels)) {
414900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                    return false;
415900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                }
416900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            }
417900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            success = this->uploadTexDataOptimal(vkTex, left, top, width, height, config, texels);
418164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
419164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
4204583ec51d9ddc830eeb854db068235be96ce59c4egdaniel
421900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    return success;
422164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
423164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
424bc26c392b2f2e27ea554347dfdb5f994b6dc54f2Greg Danielvoid GrVkGpu::resolveImage(GrSurface* dst, GrVkRenderTarget* src, const SkIRect& srcRect,
4254bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel                           const SkIPoint& dstPoint) {
4264bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    SkASSERT(dst);
4274bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    SkASSERT(src && src->numColorSamples() > 1 && src->msaaImage());
4284bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel
429fd016d7a69f0415f2497d25ec3a7b71de1545826egdaniel    if (this->vkCaps().mustSubmitCommandsBeforeCopyOp()) {
430fd016d7a69f0415f2497d25ec3a7b71de1545826egdaniel        this->submitCommandBuffer(GrVkGpu::kSkip_SyncQueue);
431fd016d7a69f0415f2497d25ec3a7b71de1545826egdaniel    }
432fd016d7a69f0415f2497d25ec3a7b71de1545826egdaniel
4334bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    // Flip rect if necessary
4344bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    SkIRect srcVkRect = srcRect;
4354bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    int32_t dstY = dstPoint.fY;
4364bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel
4374bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    if (kBottomLeft_GrSurfaceOrigin == src->origin()) {
4384bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        SkASSERT(kBottomLeft_GrSurfaceOrigin == dst->origin());
4394bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        srcVkRect.fTop = src->height() - srcRect.fBottom;
4404bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        srcVkRect.fBottom = src->height() - srcRect.fTop;
4414bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        dstY = dst->height() - dstPoint.fY - srcVkRect.height();
4424bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    }
4434bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel
4444bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    VkImageResolve resolveInfo;
4454bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    resolveInfo.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
4464bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    resolveInfo.srcOffset = { srcVkRect.fLeft, srcVkRect.fTop, 0 };
4474bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    resolveInfo.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
4484bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    resolveInfo.dstOffset = { dstPoint.fX, dstY, 0 };
4494bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    resolveInfo.extent = { (uint32_t)srcVkRect.width(), (uint32_t)srcVkRect.height(), 1 };
4504bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel
451bc26c392b2f2e27ea554347dfdb5f994b6dc54f2Greg Daniel    GrVkImage* dstImage;
452bc26c392b2f2e27ea554347dfdb5f994b6dc54f2Greg Daniel    GrRenderTarget* dstRT = dst->asRenderTarget();
453bc26c392b2f2e27ea554347dfdb5f994b6dc54f2Greg Daniel    if (dstRT) {
454bc26c392b2f2e27ea554347dfdb5f994b6dc54f2Greg Daniel        GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(dstRT);
455bc26c392b2f2e27ea554347dfdb5f994b6dc54f2Greg Daniel        dstImage = vkRT;
456bc26c392b2f2e27ea554347dfdb5f994b6dc54f2Greg Daniel    } else {
457bc26c392b2f2e27ea554347dfdb5f994b6dc54f2Greg Daniel        SkASSERT(dst->asTexture());
458bc26c392b2f2e27ea554347dfdb5f994b6dc54f2Greg Daniel        dstImage = static_cast<GrVkTexture*>(dst->asTexture());
459bc26c392b2f2e27ea554347dfdb5f994b6dc54f2Greg Daniel    }
460bc26c392b2f2e27ea554347dfdb5f994b6dc54f2Greg Daniel    dstImage->setImageLayout(this,
461bc26c392b2f2e27ea554347dfdb5f994b6dc54f2Greg Daniel                             VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
462bc26c392b2f2e27ea554347dfdb5f994b6dc54f2Greg Daniel                             VK_ACCESS_TRANSFER_WRITE_BIT,
463bc26c392b2f2e27ea554347dfdb5f994b6dc54f2Greg Daniel                             VK_PIPELINE_STAGE_TRANSFER_BIT,
464bc26c392b2f2e27ea554347dfdb5f994b6dc54f2Greg Daniel                             false);
4654bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel
4664bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    src->msaaImage()->setImageLayout(this,
4674bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel                                     VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
4684bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel                                     VK_ACCESS_TRANSFER_READ_BIT,
4694bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel                                     VK_PIPELINE_STAGE_TRANSFER_BIT,
4704bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel                                     false);
4714bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel
472bc26c392b2f2e27ea554347dfdb5f994b6dc54f2Greg Daniel    fCurrentCmdBuffer->resolveImage(this, *src->msaaImage(), *dstImage, 1, &resolveInfo);
4734bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel}
4744bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel
47569d4992e69d7b142450d0ccb587b7b26be7cf1eaGreg Danielvoid GrVkGpu::internalResolveRenderTarget(GrRenderTarget* target, bool requiresSubmit) {
47666933552f1723c4a2b248711ab3d43921401e8e6egdaniel    if (target->needsResolve()) {
47766933552f1723c4a2b248711ab3d43921401e8e6egdaniel        SkASSERT(target->numColorSamples() > 1);
47852ad25151a1c7d1ac3872971f56adf15200c437eegdaniel        GrVkRenderTarget* rt = static_cast<GrVkRenderTarget*>(target);
47952ad25151a1c7d1ac3872971f56adf15200c437eegdaniel        SkASSERT(rt->msaaImage());
48069d4992e69d7b142450d0ccb587b7b26be7cf1eaGreg Daniel
4814bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        const SkIRect& srcRect = rt->getResolveRect();
48252ad25151a1c7d1ac3872971f56adf15200c437eegdaniel
483bc26c392b2f2e27ea554347dfdb5f994b6dc54f2Greg Daniel        this->resolveImage(target, rt, srcRect, SkIPoint::Make(srcRect.fLeft, srcRect.fTop));
48452ad25151a1c7d1ac3872971f56adf15200c437eegdaniel
48552ad25151a1c7d1ac3872971f56adf15200c437eegdaniel        rt->flagAsResolved();
48669d4992e69d7b142450d0ccb587b7b26be7cf1eaGreg Daniel
48769d4992e69d7b142450d0ccb587b7b26be7cf1eaGreg Daniel        if (requiresSubmit) {
48869d4992e69d7b142450d0ccb587b7b26be7cf1eaGreg Daniel            this->submitCommandBuffer(kSkip_SyncQueue);
48969d4992e69d7b142450d0ccb587b7b26be7cf1eaGreg Daniel        }
49052ad25151a1c7d1ac3872971f56adf15200c437eegdaniel    }
49152ad25151a1c7d1ac3872971f56adf15200c437eegdaniel}
49252ad25151a1c7d1ac3872971f56adf15200c437eegdaniel
493900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverthbool GrVkGpu::uploadTexDataLinear(GrVkTexture* tex,
494900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                  int left, int top, int width, int height,
495900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                  GrPixelConfig dataConfig,
496900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                  const void* data,
497900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                  size_t rowBytes) {
498164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(data);
499900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    SkASSERT(tex->isLinearTiled());
500164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
501164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // If we're uploading compressed data then we should be using uploadCompressedTexData
502164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(!GrPixelConfigIsCompressed(dataConfig));
503164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
504164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    size_t bpp = GrBytesPerPixel(dataConfig);
505164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
506164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    const GrSurfaceDesc& desc = tex->desc();
507164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
508164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!GrSurfacePriv::AdjustWritePixelParams(desc.fWidth, desc.fHeight, bpp, &left, &top,
509164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                               &width, &height, &data, &rowBytes)) {
510164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
511164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
512164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    size_t trimRowBytes = width * bpp;
513164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
514900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    SkASSERT(VK_IMAGE_LAYOUT_PREINITIALIZED == tex->currentLayout() ||
515900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth             VK_IMAGE_LAYOUT_GENERAL == tex->currentLayout());
516900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    const VkImageSubresource subres = {
517900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        VK_IMAGE_ASPECT_COLOR_BIT,
518900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        0,  // mipLevel
519900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        0,  // arraySlice
520900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    };
521900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    VkSubresourceLayout layout;
522900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    VkResult err;
523900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
524900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    const GrVkInterface* interface = this->vkInterface();
525900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
526900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    GR_VK_CALL(interface, GetImageSubresourceLayout(fDevice,
527b2df0c2702329be6380a943d548e7377a51d8565egdaniel                                                    tex->image(),
528900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                                    &subres,
529900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                                    &layout));
530900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
531900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    int texTop = kBottomLeft_GrSurfaceOrigin == desc.fOrigin ? tex->height() - top - height : top;
5321e305ba0d6a4237020d36234e9e286d3b0489401jvanverth    const GrVkAlloc& alloc = tex->alloc();
5331e305ba0d6a4237020d36234e9e286d3b0489401jvanverth    VkDeviceSize offset = alloc.fOffset + texTop*layout.rowPitch + left*bpp;
534900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    VkDeviceSize size = height*layout.rowPitch;
535900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    void* mapPtr;
5361e305ba0d6a4237020d36234e9e286d3b0489401jvanverth    err = GR_VK_CALL(interface, MapMemory(fDevice, alloc.fMemory, offset, size, 0, &mapPtr));
537900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    if (err) {
538900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        return false;
539900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    }
540164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
541900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    if (kBottomLeft_GrSurfaceOrigin == desc.fOrigin) {
542900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        // copy into buffer by rows
543900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        const char* srcRow = reinterpret_cast<const char*>(data);
544900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        char* dstRow = reinterpret_cast<char*>(mapPtr)+(height - 1)*layout.rowPitch;
545900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        for (int y = 0; y < height; y++) {
546900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            memcpy(dstRow, srcRow, trimRowBytes);
547900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            srcRow += rowBytes;
548900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            dstRow -= layout.rowPitch;
549900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        }
550900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    } else {
551cf3525a95eea54d00727392463a6fe648914c3eaMatt Sarett        SkRectMemcpy(mapPtr, static_cast<size_t>(layout.rowPitch), data, rowBytes, trimRowBytes,
552cf3525a95eea54d00727392463a6fe648914c3eaMatt Sarett                     height);
553900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    }
554164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
5559d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth    GrVkMemory::FlushMappedAlloc(this, alloc);
5561e305ba0d6a4237020d36234e9e286d3b0489401jvanverth    GR_VK_CALL(interface, UnmapMemory(fDevice, alloc.fMemory));
557900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
558900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    return true;
559900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth}
560900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
561900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverthbool GrVkGpu::uploadTexDataOptimal(GrVkTexture* tex,
562a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth                                   int left, int top, int width, int height,
563a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth                                   GrPixelConfig dataConfig,
564a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth                                   const SkTArray<GrMipLevel>& texels) {
565900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    SkASSERT(!tex->isLinearTiled());
566900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // The assumption is either that we have no mipmaps, or that our rect is the entire texture
567900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    SkASSERT(1 == texels.count() ||
568900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth             (0 == left && 0 == top && width == tex->width() && height == tex->height()));
569900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
570dd20e918bb3c92a7643a8cbd6760ac66c2694017Greg Daniel    // We assume that if the texture has mip levels, we either upload to all the levels or just the
571dd20e918bb3c92a7643a8cbd6760ac66c2694017Greg Daniel    // first.
572dd20e918bb3c92a7643a8cbd6760ac66c2694017Greg Daniel    SkASSERT(1 == texels.count() || texels.count() == (tex->texturePriv().maxMipMapLevel() + 1));
573dd20e918bb3c92a7643a8cbd6760ac66c2694017Greg Daniel
574900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // If we're uploading compressed data then we should be using uploadCompressedTexData
575900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    SkASSERT(!GrPixelConfigIsCompressed(dataConfig));
576900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
577900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    if (width == 0 || height == 0) {
578900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        return false;
579900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    }
580900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
581900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    const GrSurfaceDesc& desc = tex->desc();
582900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    SkASSERT(this->caps()->isConfigTexturable(desc.fConfig));
583900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    size_t bpp = GrBytesPerPixel(dataConfig);
584900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
585900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // texels is const.
586c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    // But we may need to adjust the fPixels ptr based on the copyRect, or fRowBytes.
587c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    // Because of this we need to make a non-const shallow copy of texels.
588c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    SkTArray<GrMipLevel> texelsShallowCopy(texels);
589900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
590c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    for (int currentMipLevel = texelsShallowCopy.count() - 1; currentMipLevel >= 0;
591c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth         currentMipLevel--) {
592c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        SkASSERT(texelsShallowCopy[currentMipLevel].fPixels);
593900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    }
594900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
595900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // Determine whether we need to flip when we copy into the buffer
596c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    bool flipY = (kBottomLeft_GrSurfaceOrigin == desc.fOrigin && !texelsShallowCopy.empty());
597900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
598c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    // adjust any params (left, top, currentWidth, currentHeight
599900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // find the combined size of all the mip levels and the relative offset of
600900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // each into the collective buffer
601c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    // Do the first level separately because we may need to adjust width and height
602c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    // (for the non-mipped case).
603c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    if (!GrSurfacePriv::AdjustWritePixelParams(desc.fWidth, desc.fHeight, bpp, &left, &top,
604c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth                                               &width,
605c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth                                               &height,
606c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth                                               &texelsShallowCopy[0].fPixels,
607c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth                                               &texelsShallowCopy[0].fRowBytes)) {
608c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        return false;
609c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    }
610c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    SkTArray<size_t> individualMipOffsets(texelsShallowCopy.count());
611c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    individualMipOffsets.push_back(0);
612c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    size_t combinedBufferSize = width * bpp * height;
613c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    int currentWidth = width;
614c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    int currentHeight = height;
615468fd63760283c56630d752583b234f44ab03024Greg Daniel    // The alignment must be at least 4 bytes and a multiple of the bytes per pixel of the image
616468fd63760283c56630d752583b234f44ab03024Greg Daniel    // config. This works with the assumption that the bytes in pixel config is always a power of 2.
617468fd63760283c56630d752583b234f44ab03024Greg Daniel    SkASSERT((bpp & (bpp - 1)) == 0);
618468fd63760283c56630d752583b234f44ab03024Greg Daniel    const size_t alignmentMask = 0x3 | (bpp - 1);
619c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    for (int currentMipLevel = 1; currentMipLevel < texelsShallowCopy.count(); currentMipLevel++) {
620c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        currentWidth = SkTMax(1, currentWidth/2);
621c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        currentHeight = SkTMax(1, currentHeight/2);
622c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        if (!GrSurfacePriv::AdjustWritePixelParams(desc.fWidth, desc.fHeight, bpp, &left, &top,
623c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth                                                   &currentWidth,
624c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth                                                   &currentHeight,
625c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth                                                   &texelsShallowCopy[currentMipLevel].fPixels,
626c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth                                                   &texelsShallowCopy[currentMipLevel].fRowBytes)) {
627c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth            return false;
628c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        }
629900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        const size_t trimmedSize = currentWidth * bpp * currentHeight;
630468fd63760283c56630d752583b234f44ab03024Greg Daniel        const size_t alignmentDiff = combinedBufferSize & alignmentMask;
631468fd63760283c56630d752583b234f44ab03024Greg Daniel        if (alignmentDiff != 0) {
632468fd63760283c56630d752583b234f44ab03024Greg Daniel           combinedBufferSize += alignmentMask - alignmentDiff + 1;
633468fd63760283c56630d752583b234f44ab03024Greg Daniel        }
634900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        individualMipOffsets.push_back(combinedBufferSize);
635900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        combinedBufferSize += trimmedSize;
636900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    }
637900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
638900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // allocate buffer to hold our mip data
639900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    GrVkTransferBuffer* transferBuffer =
640900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                   GrVkTransferBuffer::Create(this, combinedBufferSize, GrVkBuffer::kCopyRead_Type);
641c04f8450d4701ea2b4494c3cd12f5f972d6d5b54Forrest Reiling    if(!transferBuffer)
642c04f8450d4701ea2b4494c3cd12f5f972d6d5b54Forrest Reiling        return false;
643900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
644900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    char* buffer = (char*) transferBuffer->map();
645c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    SkTArray<VkBufferImageCopy> regions(texelsShallowCopy.count());
646900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
647c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    currentWidth = width;
648c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    currentHeight = height;
649a1b282be3f93a6713e1bf7e1d0fc0caef5940a40Greg Daniel    int layerHeight = tex->height();
650c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    for (int currentMipLevel = 0; currentMipLevel < texelsShallowCopy.count(); currentMipLevel++) {
651a1b282be3f93a6713e1bf7e1d0fc0caef5940a40Greg Daniel        SkASSERT(1 == texelsShallowCopy.count() || currentHeight == layerHeight);
652900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        const size_t trimRowBytes = currentWidth * bpp;
653c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        const size_t rowBytes = texelsShallowCopy[currentMipLevel].fRowBytes;
654900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
655900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        // copy data into the buffer, skipping the trailing bytes
656900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        char* dst = buffer + individualMipOffsets[currentMipLevel];
657c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        const char* src = (const char*)texelsShallowCopy[currentMipLevel].fPixels;
658900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        if (flipY) {
659900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            src += (currentHeight - 1) * rowBytes;
660900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            for (int y = 0; y < currentHeight; y++) {
661900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                memcpy(dst, src, trimRowBytes);
662900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                src -= rowBytes;
663900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                dst += trimRowBytes;
664164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            }
665164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        } else {
666900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            SkRectMemcpy(dst, trimRowBytes, src, rowBytes, trimRowBytes, currentHeight);
667164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
668164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
669900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        VkBufferImageCopy& region = regions.push_back();
670164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        memset(&region, 0, sizeof(VkBufferImageCopy));
671db37909347d034943bd6b0922710a94c6c6ea572jvanverth        region.bufferOffset = transferBuffer->offset() + individualMipOffsets[currentMipLevel];
672900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        region.bufferRowLength = currentWidth;
673900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        region.bufferImageHeight = currentHeight;
674cf942c4ef750712b624867cbb2217c14857db3c6bsalomon        region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, SkToU32(currentMipLevel), 0, 1 };
675a1b282be3f93a6713e1bf7e1d0fc0caef5940a40Greg Daniel        region.imageOffset = { left, flipY ? layerHeight - top - currentHeight : top, 0 };
676900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        region.imageExtent = { (uint32_t)currentWidth, (uint32_t)currentHeight, 1 };
6774583ec51d9ddc830eeb854db068235be96ce59c4egdaniel
678c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        currentWidth = SkTMax(1, currentWidth/2);
679c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        currentHeight = SkTMax(1, currentHeight/2);
680a1b282be3f93a6713e1bf7e1d0fc0caef5940a40Greg Daniel        layerHeight = currentHeight;
681900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    }
682164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
6839d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth    // no need to flush non-coherent memory, unmap will do that for us
684900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    transferBuffer->unmap();
685164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
686900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // Change layout of our target so it can be copied to
687900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    tex->setImageLayout(this,
688900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                        VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
68950c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                        VK_ACCESS_TRANSFER_WRITE_BIT,
69050c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                        VK_PIPELINE_STAGE_TRANSFER_BIT,
691900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                        false);
692900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
693900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // Copy the buffer to the image
694900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    fCurrentCmdBuffer->copyBufferToImage(this,
695900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                         transferBuffer,
696900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                         tex,
697900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
698900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                         regions.count(),
699900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                         regions.begin());
700900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    transferBuffer->unref();
701dd20e918bb3c92a7643a8cbd6760ac66c2694017Greg Daniel    if (1 == texelsShallowCopy.count()) {
702dd20e918bb3c92a7643a8cbd6760ac66c2694017Greg Daniel       tex->texturePriv().dirtyMipMaps(true);
703dd20e918bb3c92a7643a8cbd6760ac66c2694017Greg Daniel    }
704164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
705164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return true;
706164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
707164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
708164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
7092e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunenGrTexture* GrVkGpu::onCreateTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted,
710a1e6b3be8124cef85f2e39e3cb85000ad9526d48bsalomon                                    const SkTArray<GrMipLevel>& texels) {
711164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag);
712164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
713164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkFormat pixelFormat;
714164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!GrPixelConfigToVkFormat(desc.fConfig, &pixelFormat)) {
715164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return nullptr;
716164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
717164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
718164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!fVkCaps->isConfigTexturable(desc.fConfig)) {
719164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return nullptr;
720164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
721164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
7220a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel    if (renderTarget && !fVkCaps->isConfigRenderable(desc.fConfig, false)) {
7230a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel        return nullptr;
7240a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel    }
7250a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel
726164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    bool linearTiling = false;
727164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (SkToBool(desc.fFlags & kZeroCopy_GrSurfaceFlag)) {
728900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        // we can't have a linear texture with a mipmap
729900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        if (texels.count() > 1) {
730900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            SkDebugf("Trying to create linear tiled texture with mipmap");
731900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            return nullptr;
732900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        }
733a95d46b4ac8e41c9beb2b750cd389b1c6ebaf0a7egdaniel        if (fVkCaps->isConfigTexturableLinearly(desc.fConfig) &&
734164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            (!renderTarget || fVkCaps->isConfigRenderableLinearly(desc.fConfig, false))) {
735164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            linearTiling = true;
736164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        } else {
737164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            return nullptr;
738164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
739164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
740164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
741164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT;
742164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (renderTarget) {
743164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        usageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
744164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
745164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
746164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // For now we will set the VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT and
747164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // VK_IMAGE_USAGE_TRANSFER_SOURCE_BIT on every texture since we do not know whether or not we
748164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // will be using this texture in some copy or not. Also this assumes, as is the current case,
74962340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    // that all render targets in vulkan are also textures. If we change this practice of setting
750164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // both bits, we must make sure to set the destination bit if we are uploading srcData to the
751164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // texture.
752164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    usageFlags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
753164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
754a1e6b3be8124cef85f2e39e3cb85000ad9526d48bsalomon    VkFlags memProps = (!texels.empty() && linearTiling) ? VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT :
755a1e6b3be8124cef85f2e39e3cb85000ad9526d48bsalomon                                                           VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
756164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
757164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // This ImageDesc refers to the texture that will be read by the client. Thus even if msaa is
75862340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    // requested, this ImageDesc describes the resolved texture. Therefore we always have samples set
759164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // to 1.
760c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    int mipLevels = texels.empty() ? 1 : texels.count();
761164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkImage::ImageDesc imageDesc;
762164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fImageType = VK_IMAGE_TYPE_2D;
763164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fFormat = pixelFormat;
764164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fWidth = desc.fWidth;
765164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fHeight = desc.fHeight;
766c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    imageDesc.fLevels = linearTiling ? 1 : mipLevels;
767164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fSamples = 1;
768164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fImageTiling = linearTiling ? VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL;
769164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fUsageFlags = usageFlags;
770164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fMemProps = memProps;
771164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
772164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkTexture* tex;
773164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (renderTarget) {
7742e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        tex = GrVkTextureRenderTarget::CreateNewTextureRenderTarget(this, budgeted, desc,
775164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                    imageDesc);
776164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    } else {
7772e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        tex = GrVkTexture::CreateNewTexture(this, budgeted, desc, imageDesc);
778164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
779164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
780164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!tex) {
781164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return nullptr;
782164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
783164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
784e699d0cd25fd059e3f0c4949e613e50c83a52179bsalomon    if (!texels.empty()) {
785e699d0cd25fd059e3f0c4949e613e50c83a52179bsalomon        SkASSERT(texels.begin()->fPixels);
786900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        bool success;
787900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        if (linearTiling) {
788900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            success = this->uploadTexDataLinear(tex, 0, 0, desc.fWidth, desc.fHeight, desc.fConfig,
789900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                                texels.begin()->fPixels, texels.begin()->fRowBytes);
790900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        } else {
791900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            success = this->uploadTexDataOptimal(tex, 0, 0, desc.fWidth, desc.fHeight, desc.fConfig,
792900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                                 texels);
793900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        }
794900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        if (!success) {
795164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            tex->unref();
796164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            return nullptr;
797164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
798164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
799164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
800164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return tex;
801164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
802164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
803164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
804164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
805db37909347d034943bd6b0922710a94c6c6ea572jvanverthbool GrVkGpu::updateBuffer(GrVkBuffer* buffer, const void* src,
806db37909347d034943bd6b0922710a94c6c6ea572jvanverth                           VkDeviceSize offset, VkDeviceSize size) {
807a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth
808a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth    // Update the buffer
809db37909347d034943bd6b0922710a94c6c6ea572jvanverth    fCurrentCmdBuffer->updateBuffer(this, buffer, offset, size, src);
810a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth
811a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth    return true;
812a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth}
813a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth
814a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth////////////////////////////////////////////////////////////////////////////////
815a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth
816164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielstatic GrSurfaceOrigin resolve_origin(GrSurfaceOrigin origin) {
817164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // By default, all textures in Vk use TopLeft
818164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (kDefault_GrSurfaceOrigin == origin) {
819164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return kTopLeft_GrSurfaceOrigin;
820164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    } else {
821164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return origin;
822164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
823164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
824164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
8257ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Danielsk_sp<GrTexture> GrVkGpu::onWrapBackendTexture(const GrBackendTexture& backendTex,
8267ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel                                               GrSurfaceOrigin origin,
8277ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel                                               GrBackendTextureFlags flags,
8287ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel                                               int sampleCnt,
8296bd5284415bd983b0628c4941dff5def40018f5abungeman                                               GrWrapOwnership ownership) {
8307ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel    const GrVkImageInfo* info = backendTex.getVkImageInfo();
8317ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel    if (!info) {
832164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return nullptr;
833164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
834164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
835164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    int maxSize = this->caps()->maxTextureSize();
8367ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel    if (backendTex.width() > maxSize || backendTex.height() > maxSize) {
837164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return nullptr;
838164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
839164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
8401e305ba0d6a4237020d36234e9e286d3b0489401jvanverth    if (VK_NULL_HANDLE == info->fImage || VK_NULL_HANDLE == info->fAlloc.fMemory) {
841fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        return nullptr;
842fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    }
8437ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel
8447ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel    SkASSERT(backendTex.config() == GrVkFormatToPixelConfig(info->fFormat));
845164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
846164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrSurfaceDesc surfDesc;
8477ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel    // next line relies on GrBackendTextureFlags matching GrTexture's
8487ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel    surfDesc.fFlags = (GrSurfaceFlags)flags;
8497ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel    surfDesc.fWidth = backendTex.width();
8507ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel    surfDesc.fHeight = backendTex.height();
8517ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel    surfDesc.fConfig = backendTex.config();
8527ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel    surfDesc.fSampleCnt = SkTMin(sampleCnt, this->caps()->maxSampleCount());
8537ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel    bool renderTarget = SkToBool(flags & kRenderTarget_GrBackendTextureFlag);
854766fcbb01cece88ad88808581b4ecc5a5cb60e01Brian Osman    SkASSERT(!renderTarget || kAdoptAndCache_GrWrapOwnership != ownership);  // Not supported
855164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // In GL, Chrome assumes all textures are BottomLeft
856164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // In VK, we don't have this restriction
8577ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel    surfDesc.fOrigin = resolve_origin(origin);
858164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
8596bd5284415bd983b0628c4941dff5def40018f5abungeman    if (!renderTarget) {
8606bd5284415bd983b0628c4941dff5def40018f5abungeman        return GrVkTexture::MakeWrappedTexture(this, surfDesc, ownership, info);
861164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
8626bd5284415bd983b0628c4941dff5def40018f5abungeman    return GrVkTextureRenderTarget::MakeWrappedTextureRenderTarget(this, surfDesc, ownership, info);
863164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
864164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
865bcf612b5d0032f09d58c2ea5671de977130395dbGreg Danielsk_sp<GrRenderTarget> GrVkGpu::onWrapBackendRenderTarget(const GrBackendRenderTarget& backendRT,
866bcf612b5d0032f09d58c2ea5671de977130395dbGreg Daniel                                                         GrSurfaceOrigin origin){
867e79b473714866682dea85b66c005c5bb2ff6a397Greg Daniel    // Currently the Vulkan backend does not support wrapping of msaa render targets directly. In
868e79b473714866682dea85b66c005c5bb2ff6a397Greg Daniel    // general this is not an issue since swapchain images in vulkan are never multisampled. Thus if
869e79b473714866682dea85b66c005c5bb2ff6a397Greg Daniel    // you want a multisampled RT it is best to wrap the swapchain images and then let Skia handle
870e79b473714866682dea85b66c005c5bb2ff6a397Greg Daniel    // creating and owning the MSAA images.
871bcf612b5d0032f09d58c2ea5671de977130395dbGreg Daniel    if (backendRT.sampleCnt()) {
872e79b473714866682dea85b66c005c5bb2ff6a397Greg Daniel        return nullptr;
873e79b473714866682dea85b66c005c5bb2ff6a397Greg Daniel    }
8749d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
875bcf612b5d0032f09d58c2ea5671de977130395dbGreg Daniel    const GrVkImageInfo* info = backendRT.getVkImageInfo();
876bcf612b5d0032f09d58c2ea5671de977130395dbGreg Daniel    if (!info) {
877bcf612b5d0032f09d58c2ea5671de977130395dbGreg Daniel        return nullptr;
878bcf612b5d0032f09d58c2ea5671de977130395dbGreg Daniel    }
8790b791f57c4a158fa3cab7250f0955b7f8abd5755Brian Osman    if (VK_NULL_HANDLE == info->fImage) {
880fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        return nullptr;
881fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    }
882164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
883164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrSurfaceDesc desc;
884bcf612b5d0032f09d58c2ea5671de977130395dbGreg Daniel    desc.fConfig = backendRT.config();
8853667b4970d6972675be58a331be7c5ba02f3d39eRobert Phillips    desc.fFlags = kCheckAllocation_GrSurfaceFlag | kRenderTarget_GrSurfaceFlag;
886bcf612b5d0032f09d58c2ea5671de977130395dbGreg Daniel    desc.fWidth = backendRT.width();
887bcf612b5d0032f09d58c2ea5671de977130395dbGreg Daniel    desc.fHeight = backendRT.height();
888e79b473714866682dea85b66c005c5bb2ff6a397Greg Daniel    desc.fSampleCnt = 0;
889164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
890bcf612b5d0032f09d58c2ea5671de977130395dbGreg Daniel    SkASSERT(kDefault_GrSurfaceOrigin != origin);
891bcf612b5d0032f09d58c2ea5671de977130395dbGreg Daniel    desc.fOrigin = origin;
892164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
8930b791f57c4a158fa3cab7250f0955b7f8abd5755Brian Osman    sk_sp<GrVkRenderTarget> tgt = GrVkRenderTarget::MakeWrappedRenderTarget(this, desc, info);
894bcf612b5d0032f09d58c2ea5671de977130395dbGreg Daniel    if (tgt && backendRT.stencilBits()) {
8956bd5284415bd983b0628c4941dff5def40018f5abungeman        if (!createStencilAttachmentForRenderTarget(tgt.get(), desc.fWidth, desc.fHeight)) {
896164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            return nullptr;
897164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
898164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
899164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return tgt;
900164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
901164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
9027ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Danielsk_sp<GrRenderTarget> GrVkGpu::onWrapBackendTextureAsRenderTarget(const GrBackendTexture& tex,
9037ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel                                                                  GrSurfaceOrigin origin,
9047ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel                                                                  int sampleCnt) {
90533910297e032b9af4336bc146c7fbb0f35918de9Brian Osman
9067ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel    const GrVkImageInfo* info = tex.getVkImageInfo();
907bcf612b5d0032f09d58c2ea5671de977130395dbGreg Daniel    if (!info) {
908bcf612b5d0032f09d58c2ea5671de977130395dbGreg Daniel        return nullptr;
909bcf612b5d0032f09d58c2ea5671de977130395dbGreg Daniel    }
91033910297e032b9af4336bc146c7fbb0f35918de9Brian Osman    if (VK_NULL_HANDLE == info->fImage) {
91133910297e032b9af4336bc146c7fbb0f35918de9Brian Osman        return nullptr;
91233910297e032b9af4336bc146c7fbb0f35918de9Brian Osman    }
91333910297e032b9af4336bc146c7fbb0f35918de9Brian Osman
91433910297e032b9af4336bc146c7fbb0f35918de9Brian Osman    GrSurfaceDesc desc;
9157ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel    desc.fFlags = kRenderTarget_GrSurfaceFlag;
9167ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel    desc.fConfig = tex.config();
9177ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel    desc.fWidth = tex.width();
9187ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel    desc.fHeight = tex.height();
9197ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel    desc.fSampleCnt = SkTMin(sampleCnt, this->caps()->maxSampleCount());
92033910297e032b9af4336bc146c7fbb0f35918de9Brian Osman
9217ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel    desc.fOrigin = resolve_origin(origin);
92233910297e032b9af4336bc146c7fbb0f35918de9Brian Osman
92333910297e032b9af4336bc146c7fbb0f35918de9Brian Osman    sk_sp<GrVkRenderTarget> tgt = GrVkRenderTarget::MakeWrappedRenderTarget(this, desc, info);
92433910297e032b9af4336bc146c7fbb0f35918de9Brian Osman    return tgt;
92533910297e032b9af4336bc146c7fbb0f35918de9Brian Osman}
92633910297e032b9af4336bc146c7fbb0f35918de9Brian Osman
92750ead53ac97deb23310916e3736c3f5e2d8f7f4begdanielvoid GrVkGpu::generateMipmap(GrVkTexture* tex) {
928900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // don't do anything for linearly tiled textures (can't have mipmaps)
92962340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    if (tex->isLinearTiled()) {
930900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        SkDebugf("Trying to create mipmap for linear tiled texture");
93162340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth        return;
93262340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    }
93362340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth
93462340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    // determine if we can blit to and from this format
93562340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    const GrVkCaps& caps = this->vkCaps();
93662340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    if (!caps.configCanBeDstofBlit(tex->config(), false) ||
9372f5792a06c87efd5f9295b7b7bb714aac118bd2aegdaniel        !caps.configCanBeSrcofBlit(tex->config(), false) ||
9382f5792a06c87efd5f9295b7b7bb714aac118bd2aegdaniel        !caps.mipMapSupport()) {
93962340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth        return;
94062340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    }
94162340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth
942fd016d7a69f0415f2497d25ec3a7b71de1545826egdaniel    if (this->vkCaps().mustSubmitCommandsBeforeCopyOp()) {
943fd016d7a69f0415f2497d25ec3a7b71de1545826egdaniel        this->submitCommandBuffer(kSkip_SyncQueue);
944fd016d7a69f0415f2497d25ec3a7b71de1545826egdaniel    }
945fd016d7a69f0415f2497d25ec3a7b71de1545826egdaniel
94666933552f1723c4a2b248711ab3d43921401e8e6egdaniel    // We may need to resolve the texture first if it is also a render target
94766933552f1723c4a2b248711ab3d43921401e8e6egdaniel    GrVkRenderTarget* texRT = static_cast<GrVkRenderTarget*>(tex->asRenderTarget());
94866933552f1723c4a2b248711ab3d43921401e8e6egdaniel    if (texRT) {
94969d4992e69d7b142450d0ccb587b7b26be7cf1eaGreg Daniel        this->internalResolveRenderTarget(texRT, false);
95066933552f1723c4a2b248711ab3d43921401e8e6egdaniel    }
95166933552f1723c4a2b248711ab3d43921401e8e6egdaniel
9527ac5da853457b032781cf865ba018de78508edb7egdaniel    int width = tex->width();
9537ac5da853457b032781cf865ba018de78508edb7egdaniel    int height = tex->height();
9547ac5da853457b032781cf865ba018de78508edb7egdaniel    VkImageBlit blitRegion;
9557ac5da853457b032781cf865ba018de78508edb7egdaniel    memset(&blitRegion, 0, sizeof(VkImageBlit));
95662340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth
95782c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth    // SkMipMap doesn't include the base level in the level count so we have to add 1
95882c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth    uint32_t levelCount = SkMipMap::ComputeLevelCount(tex->width(), tex->height()) + 1;
9597ac5da853457b032781cf865ba018de78508edb7egdaniel    if (levelCount != tex->mipLevels()) {
9607ac5da853457b032781cf865ba018de78508edb7egdaniel        const GrVkResource* oldResource = tex->resource();
9617ac5da853457b032781cf865ba018de78508edb7egdaniel        oldResource->ref();
9627ac5da853457b032781cf865ba018de78508edb7egdaniel        // grab handle to the original image resource
9637ac5da853457b032781cf865ba018de78508edb7egdaniel        VkImage oldImage = tex->image();
9647ac5da853457b032781cf865ba018de78508edb7egdaniel
9657ac5da853457b032781cf865ba018de78508edb7egdaniel        // change the original image's layout so we can copy from it
9667ac5da853457b032781cf865ba018de78508edb7egdaniel        tex->setImageLayout(this, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
9677ac5da853457b032781cf865ba018de78508edb7egdaniel                            VK_ACCESS_TRANSFER_READ_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, false);
9687ac5da853457b032781cf865ba018de78508edb7egdaniel
9697ac5da853457b032781cf865ba018de78508edb7egdaniel        if (!tex->reallocForMipmap(this, levelCount)) {
9707ac5da853457b032781cf865ba018de78508edb7egdaniel            oldResource->unref(this);
9717ac5da853457b032781cf865ba018de78508edb7egdaniel            return;
9727ac5da853457b032781cf865ba018de78508edb7egdaniel        }
9737ac5da853457b032781cf865ba018de78508edb7egdaniel        // change the new image's layout so we can blit to it
9747ac5da853457b032781cf865ba018de78508edb7egdaniel        tex->setImageLayout(this, VK_IMAGE_LAYOUT_GENERAL,
9757ac5da853457b032781cf865ba018de78508edb7egdaniel                            VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, false);
97662340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth
9777ac5da853457b032781cf865ba018de78508edb7egdaniel        // Blit original image to top level of new image
9787ac5da853457b032781cf865ba018de78508edb7egdaniel        blitRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
9797ac5da853457b032781cf865ba018de78508edb7egdaniel        blitRegion.srcOffsets[0] = { 0, 0, 0 };
9807ac5da853457b032781cf865ba018de78508edb7egdaniel        blitRegion.srcOffsets[1] = { width, height, 1 };
9817ac5da853457b032781cf865ba018de78508edb7egdaniel        blitRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
9827ac5da853457b032781cf865ba018de78508edb7egdaniel        blitRegion.dstOffsets[0] = { 0, 0, 0 };
9837ac5da853457b032781cf865ba018de78508edb7egdaniel        blitRegion.dstOffsets[1] = { width, height, 1 };
98462340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth
9857ac5da853457b032781cf865ba018de78508edb7egdaniel        fCurrentCmdBuffer->blitImage(this,
9867ac5da853457b032781cf865ba018de78508edb7egdaniel                                     oldResource,
9877ac5da853457b032781cf865ba018de78508edb7egdaniel                                     oldImage,
9887ac5da853457b032781cf865ba018de78508edb7egdaniel                                     VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
9897ac5da853457b032781cf865ba018de78508edb7egdaniel                                     tex->resource(),
9907ac5da853457b032781cf865ba018de78508edb7egdaniel                                     tex->image(),
9917ac5da853457b032781cf865ba018de78508edb7egdaniel                                     VK_IMAGE_LAYOUT_GENERAL,
9927ac5da853457b032781cf865ba018de78508edb7egdaniel                                     1,
9937ac5da853457b032781cf865ba018de78508edb7egdaniel                                     &blitRegion,
9947ac5da853457b032781cf865ba018de78508edb7egdaniel                                     VK_FILTER_LINEAR);
99562340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth
9967ac5da853457b032781cf865ba018de78508edb7egdaniel        oldResource->unref(this);
9977ac5da853457b032781cf865ba018de78508edb7egdaniel    } else {
9987ac5da853457b032781cf865ba018de78508edb7egdaniel        // change layout of the layers so we can write to them.
9997ac5da853457b032781cf865ba018de78508edb7egdaniel        tex->setImageLayout(this, VK_IMAGE_LAYOUT_GENERAL,
10007ac5da853457b032781cf865ba018de78508edb7egdaniel                            VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, false);
10017ac5da853457b032781cf865ba018de78508edb7egdaniel    }
100250c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth
100350c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth    // setup memory barrier
10049440345a81d6c2372ac0aed937080f3da67439ddGreg Daniel    SkASSERT(kUnknown_GrPixelConfig != GrVkFormatToPixelConfig(tex->imageFormat()));
100550c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth    VkImageAspectFlags aspectFlags = VK_IMAGE_ASPECT_COLOR_BIT;
100650c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth    VkImageMemoryBarrier imageMemoryBarrier = {
100750c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth        VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,          // sType
100850c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth        NULL,                                            // pNext
10097ac5da853457b032781cf865ba018de78508edb7egdaniel        VK_ACCESS_TRANSFER_WRITE_BIT,                    // srcAccessMask
10107ac5da853457b032781cf865ba018de78508edb7egdaniel        VK_ACCESS_TRANSFER_READ_BIT,                     // dstAccessMask
101150c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth        VK_IMAGE_LAYOUT_GENERAL,                         // oldLayout
101250c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth        VK_IMAGE_LAYOUT_GENERAL,                         // newLayout
101350c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth        VK_QUEUE_FAMILY_IGNORED,                         // srcQueueFamilyIndex
101450c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth        VK_QUEUE_FAMILY_IGNORED,                         // dstQueueFamilyIndex
1015b2df0c2702329be6380a943d548e7377a51d8565egdaniel        tex->image(),                                    // image
101650c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth        { aspectFlags, 0, 1, 0, 1 }                      // subresourceRange
101750c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth    };
101850c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth
101962340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    // Blit the miplevels
102082c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth    uint32_t mipLevel = 1;
102182c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth    while (mipLevel < levelCount) {
102282c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth        int prevWidth = width;
102382c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth        int prevHeight = height;
102482c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth        width = SkTMax(1, width / 2);
102582c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth        height = SkTMax(1, height / 2);
102682c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth
102750c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth        imageMemoryBarrier.subresourceRange.baseMipLevel = mipLevel - 1;
102850c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth        this->addImageMemoryBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
102950c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                                    false, &imageMemoryBarrier);
103050c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth
103150c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth        blitRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, mipLevel - 1, 0, 1 };
103262340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth        blitRegion.srcOffsets[0] = { 0, 0, 0 };
1033e9906e71fbc29968ea10680f0fcd53a4153c7568brianosman        blitRegion.srcOffsets[1] = { prevWidth, prevHeight, 1 };
103482c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth        blitRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, mipLevel, 0, 1 };
103562340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth        blitRegion.dstOffsets[0] = { 0, 0, 0 };
1036e9906e71fbc29968ea10680f0fcd53a4153c7568brianosman        blitRegion.dstOffsets[1] = { width, height, 1 };
103762340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth        fCurrentCmdBuffer->blitImage(this,
1038b2df0c2702329be6380a943d548e7377a51d8565egdaniel                                     *tex,
1039b2df0c2702329be6380a943d548e7377a51d8565egdaniel                                     *tex,
104062340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth                                     1,
104162340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth                                     &blitRegion,
104262340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth                                     VK_FILTER_LINEAR);
104382c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth        ++mipLevel;
104462340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    }
104562340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth}
104662340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth
1047164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
1048164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1049164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielGrStencilAttachment* GrVkGpu::createStencilAttachmentForRenderTarget(const GrRenderTarget* rt,
1050164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                     int width,
1051164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                     int height) {
1052164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(width >= rt->width());
1053164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(height >= rt->height());
1054164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1055164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    int samples = rt->numStencilSamples();
1056164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
10578f1dcaa6f3cc098bd5efd2595ca20e0bc1847d10egdaniel    const GrVkCaps::StencilFormat& sFmt = this->vkCaps().preferedStencilFormat();
1058164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1059164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkStencilAttachment* stencil(GrVkStencilAttachment::Create(this,
1060164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                 width,
1061164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                 height,
1062164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                 samples,
1063164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                 sFmt));
1064164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fStats.incStencilAttachmentCreates();
1065164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return stencil;
1066164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1067164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1068164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
1069164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
10709d54afc38b171c01a03b34e773d154fcf83d97dcjvanverthbool copy_testing_data(GrVkGpu* gpu, void* srcData, const GrVkAlloc& alloc,
10713602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                       size_t srcRowBytes, size_t dstRowBytes, int h) {
10723602d4f16a01da860d16eb36fb52eb62487495ccegdaniel    void* mapPtr;
10733602d4f16a01da860d16eb36fb52eb62487495ccegdaniel    VkResult err = GR_VK_CALL(gpu->vkInterface(), MapMemory(gpu->device(),
10749d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth                                                            alloc.fMemory,
10759d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth                                                            alloc.fOffset,
10763602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                                                            dstRowBytes * h,
10773602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                                                            0,
10783602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                                                            &mapPtr));
10793602d4f16a01da860d16eb36fb52eb62487495ccegdaniel    if (err) {
10803602d4f16a01da860d16eb36fb52eb62487495ccegdaniel        return false;
10813602d4f16a01da860d16eb36fb52eb62487495ccegdaniel    }
10823602d4f16a01da860d16eb36fb52eb62487495ccegdaniel
108320ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel    if (srcData) {
108420ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        // If there is no padding on dst we can do a single memcopy.
108520ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        // This assumes the srcData comes in with no padding.
108620ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        SkRectMemcpy(mapPtr, static_cast<size_t>(dstRowBytes),
108720ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel                     srcData, srcRowBytes, srcRowBytes, h);
108820ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel    } else {
108920ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        // If there is no srcdata we always copy 0's into the textures so that it is initialized
109020ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        // with some data.
109120ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        if (srcRowBytes == static_cast<size_t>(dstRowBytes)) {
109220ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel            memset(mapPtr, 0, srcRowBytes * h);
109320ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        } else {
109420ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel            for (int i = 0; i < h; ++i) {
109520ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel                memset(mapPtr, 0, srcRowBytes);
109620ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel                mapPtr = SkTAddOffset<void>(mapPtr, static_cast<size_t>(dstRowBytes));
109720ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel            }
109820ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        }
109920ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel    }
11009d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth    GrVkMemory::FlushMappedAlloc(gpu, alloc);
11019d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth    GR_VK_CALL(gpu->vkInterface(), UnmapMemory(gpu->device(), alloc.fMemory));
11023602d4f16a01da860d16eb36fb52eb62487495ccegdaniel    return true;
11033602d4f16a01da860d16eb36fb52eb62487495ccegdaniel}
11043602d4f16a01da860d16eb36fb52eb62487495ccegdaniel
1105164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielGrBackendObject GrVkGpu::createTestingOnlyBackendTexture(void* srcData, int w, int h,
11060a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel                                                         GrPixelConfig config,
11070a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel                                                         bool isRenderTarget) {
1108164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1109164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkFormat pixelFormat;
1110164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!GrPixelConfigToVkFormat(config, &pixelFormat)) {
1111164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return 0;
1112164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1113164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1114164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    bool linearTiling = false;
1115164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!fVkCaps->isConfigTexturable(config)) {
1116164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return 0;
1117164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1118164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
11190a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel    if (isRenderTarget && !fVkCaps->isConfigRenderable(config, false)) {
11200a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel        return 0;
11210a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel    }
11220a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel
1123a95d46b4ac8e41c9beb2b750cd389b1c6ebaf0a7egdaniel    if (fVkCaps->isConfigTexturableLinearly(config) &&
11240a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel        (!isRenderTarget || fVkCaps->isConfigRenderableLinearly(config, false))) {
1125164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        linearTiling = true;
1126164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1127164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1128164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT;
1129164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    usageFlags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1130164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    usageFlags |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
11310a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel    if (isRenderTarget) {
11320a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel        usageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
11330a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel    }
1134164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1135fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    VkImage image = VK_NULL_HANDLE;
11369d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth    GrVkAlloc alloc = { VK_NULL_HANDLE, 0, 0, 0 };
1137164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1138fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    VkImageTiling imageTiling = linearTiling ? VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL;
1139fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    VkImageLayout initialLayout = (VK_IMAGE_TILING_LINEAR == imageTiling)
1140fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth                                ? VK_IMAGE_LAYOUT_PREINITIALIZED
1141fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth                                : VK_IMAGE_LAYOUT_UNDEFINED;
1142fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth
1143fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    // Create Image
1144fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    VkSampleCountFlagBits vkSamples;
1145fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    if (!GrSampleCountToVkSampleCount(1, &vkSamples)) {
1146fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        return 0;
1147fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    }
1148fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth
1149fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    const VkImageCreateInfo imageCreateInfo = {
1150fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,         // sType
1151fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        NULL,                                        // pNext
1152fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        0,                                           // VkImageCreateFlags
1153fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        VK_IMAGE_TYPE_2D,                            // VkImageType
1154fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        pixelFormat,                                 // VkFormat
1155384b5e9cd36e443437de8df3b0f78ef4150efbacethannicholas        { (uint32_t) w, (uint32_t) h, 1 },           // VkExtent3D
1156fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        1,                                           // mipLevels
1157fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        1,                                           // arrayLayers
1158fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        vkSamples,                                   // samples
1159fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        imageTiling,                                 // VkImageTiling
1160fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        usageFlags,                                  // VkImageUsageFlags
1161fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        VK_SHARING_MODE_EXCLUSIVE,                   // VkSharingMode
1162fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        0,                                           // queueFamilyCount
1163fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        0,                                           // pQueueFamilyIndices
1164fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        initialLayout                                // initialLayout
1165fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    };
1166fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth
1167fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    GR_VK_CALL_ERRCHECK(this->vkInterface(), CreateImage(this->device(), &imageCreateInfo, nullptr, &image));
1168fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth
11696b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    if (!GrVkMemory::AllocAndBindImageMemory(this, image, linearTiling, &alloc)) {
1170fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        VK_CALL(DestroyImage(this->device(), image, nullptr));
1171164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return 0;
1172164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1173164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
117420ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel    size_t bpp = GrBytesPerPixel(config);
117520ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel    size_t rowCopyBytes = bpp * w;
117620ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel    if (linearTiling) {
117720ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        const VkImageSubresource subres = {
117820ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel            VK_IMAGE_ASPECT_COLOR_BIT,
117920ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel            0,  // mipLevel
118020ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel            0,  // arraySlice
118120ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        };
118220ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        VkSubresourceLayout layout;
118320ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel
118420ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        VK_CALL(GetImageSubresourceLayout(fDevice, image, &subres, &layout));
118520ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel
118620ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        if (!copy_testing_data(this, srcData, alloc, rowCopyBytes,
118720ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel                               static_cast<size_t>(layout.rowPitch), h)) {
118820ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel            GrVkMemory::FreeImageMemory(this, linearTiling, alloc);
118920ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel            VK_CALL(DestroyImage(fDevice, image, nullptr));
119020ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel            return 0;
119120ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        }
119220ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel    } else {
119320ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        SkASSERT(w && h);
119420ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel
119520ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        VkBuffer buffer;
119620ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        VkBufferCreateInfo bufInfo;
119720ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        memset(&bufInfo, 0, sizeof(VkBufferCreateInfo));
119820ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        bufInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
119920ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        bufInfo.flags = 0;
120020ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        bufInfo.size = rowCopyBytes * h;
120120ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        bufInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
120220ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        bufInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
120320ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        bufInfo.queueFamilyIndexCount = 0;
120420ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        bufInfo.pQueueFamilyIndices = nullptr;
120520ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        VkResult err;
120620ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        err = VK_CALL(CreateBuffer(fDevice, &bufInfo, nullptr, &buffer));
120720ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel
120820ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        if (err) {
120920ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel            GrVkMemory::FreeImageMemory(this, linearTiling, alloc);
121020ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel            VK_CALL(DestroyImage(fDevice, image, nullptr));
121120ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel            return 0;
121220ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        }
12133602d4f16a01da860d16eb36fb52eb62487495ccegdaniel
121420ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        GrVkAlloc bufferAlloc = { VK_NULL_HANDLE, 0, 0, 0 };
121520ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        if (!GrVkMemory::AllocAndBindBufferMemory(this, buffer, GrVkBuffer::kCopyRead_Type,
121620ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel                                                  true, &bufferAlloc)) {
121720ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel            GrVkMemory::FreeImageMemory(this, linearTiling, alloc);
121820ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel            VK_CALL(DestroyImage(fDevice, image, nullptr));
121920ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel            VK_CALL(DestroyBuffer(fDevice, buffer, nullptr));
122020ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel            return 0;
122120ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        }
12223602d4f16a01da860d16eb36fb52eb62487495ccegdaniel
122320ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        if (!copy_testing_data(this, srcData, bufferAlloc, rowCopyBytes, rowCopyBytes, h)) {
122420ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel            GrVkMemory::FreeImageMemory(this, linearTiling, alloc);
122520ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel            VK_CALL(DestroyImage(fDevice, image, nullptr));
122620ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel            GrVkMemory::FreeBufferMemory(this, GrVkBuffer::kCopyRead_Type, bufferAlloc);
122720ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel            VK_CALL(DestroyBuffer(fDevice, buffer, nullptr));
122820ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel            return 0;
122920ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        }
12303602d4f16a01da860d16eb36fb52eb62487495ccegdaniel
123120ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        const VkCommandBufferAllocateInfo cmdInfo = {
123220ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel            VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,   // sType
123320ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel            NULL,                                             // pNext
123420ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel            fCmdPool,                                         // commandPool
123520ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel            VK_COMMAND_BUFFER_LEVEL_PRIMARY,                  // level
123620ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel            1                                                 // bufferCount
123720ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        };
123820ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel
123920ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        VkCommandBuffer cmdBuffer;
124020ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        err = VK_CALL(AllocateCommandBuffers(fDevice, &cmdInfo, &cmdBuffer));
124120ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        if (err) {
124220ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel            GrVkMemory::FreeImageMemory(this, linearTiling, alloc);
124320ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel            VK_CALL(DestroyImage(fDevice, image, nullptr));
124420ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel            GrVkMemory::FreeBufferMemory(this, GrVkBuffer::kCopyRead_Type, bufferAlloc);
124520ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel            VK_CALL(DestroyBuffer(fDevice, buffer, nullptr));
124620ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel            return 0;
124720ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        }
12483602d4f16a01da860d16eb36fb52eb62487495ccegdaniel
124920ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        VkCommandBufferBeginInfo cmdBufferBeginInfo;
125020ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        memset(&cmdBufferBeginInfo, 0, sizeof(VkCommandBufferBeginInfo));
125120ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        cmdBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
125220ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        cmdBufferBeginInfo.pNext = nullptr;
125320ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        cmdBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
125420ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        cmdBufferBeginInfo.pInheritanceInfo = nullptr;
125520ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel
125620ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        err = VK_CALL(BeginCommandBuffer(cmdBuffer, &cmdBufferBeginInfo));
125720ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        SkASSERT(!err);
125820ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel
125920ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        // Set image layout and add barrier
126020ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        VkImageMemoryBarrier barrier;
126120ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        memset(&barrier, 0, sizeof(VkImageMemoryBarrier));
126220ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
126320ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        barrier.pNext = nullptr;
126420ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        barrier.srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(initialLayout);
126520ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
126620ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
126720ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
126820ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
126920ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        barrier.image = image;
127020ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        barrier.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0 , 1};
127120ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel
127220ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        VK_CALL(CmdPipelineBarrier(cmdBuffer,
127320ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel                                   GrVkMemory::LayoutToPipelineStageFlags(initialLayout),
127420ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel                                   VK_PIPELINE_STAGE_TRANSFER_BIT,
127520ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel                                   0,
127620ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel                                   0, nullptr,
127720ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel                                   0, nullptr,
127820ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel                                   1, &barrier));
127920ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        initialLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
128020ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel
128120ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        // Submit copy command
128220ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        VkBufferImageCopy region;
128320ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        memset(&region, 0, sizeof(VkBufferImageCopy));
128420ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        region.bufferOffset = 0;
128520ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        region.bufferRowLength = w;
128620ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        region.bufferImageHeight = h;
128720ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
128820ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        region.imageOffset = { 0, 0, 0 };
128920ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        region.imageExtent = { (uint32_t)w, (uint32_t)h, 1 };
129020ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel
129120ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        VK_CALL(CmdCopyBufferToImage(cmdBuffer, buffer, image, initialLayout, 1, &region));
129220ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel
129320ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        // End CommandBuffer
129420ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        err = VK_CALL(EndCommandBuffer(cmdBuffer));
129520ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        SkASSERT(!err);
129620ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel
129720ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        // Create Fence for queue
129820ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        VkFence fence;
129920ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        VkFenceCreateInfo fenceInfo;
130020ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        memset(&fenceInfo, 0, sizeof(VkFenceCreateInfo));
130120ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
130220ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel
130320ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        err = VK_CALL(CreateFence(fDevice, &fenceInfo, nullptr, &fence));
130420ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        SkASSERT(!err);
130520ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel
130620ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        VkSubmitInfo submitInfo;
130720ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        memset(&submitInfo, 0, sizeof(VkSubmitInfo));
130820ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
130920ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        submitInfo.pNext = nullptr;
131020ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        submitInfo.waitSemaphoreCount = 0;
131120ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        submitInfo.pWaitSemaphores = nullptr;
131220ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        submitInfo.pWaitDstStageMask = 0;
131320ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        submitInfo.commandBufferCount = 1;
131420ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        submitInfo.pCommandBuffers = &cmdBuffer;
131520ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        submitInfo.signalSemaphoreCount = 0;
131620ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        submitInfo.pSignalSemaphores = nullptr;
131720ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        err = VK_CALL(QueueSubmit(this->queue(), 1, &submitInfo, fence));
131820ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        SkASSERT(!err);
131920ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel
132020ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        err = VK_CALL(WaitForFences(fDevice, 1, &fence, true, UINT64_MAX));
132120ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        if (VK_TIMEOUT == err) {
132220ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel            GrVkMemory::FreeImageMemory(this, linearTiling, alloc);
132320ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel            VK_CALL(DestroyImage(fDevice, image, nullptr));
13243602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            GrVkMemory::FreeBufferMemory(this, GrVkBuffer::kCopyRead_Type, bufferAlloc);
13253602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            VK_CALL(DestroyBuffer(fDevice, buffer, nullptr));
13263602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            VK_CALL(FreeCommandBuffers(fDevice, fCmdPool, 1, &cmdBuffer));
13273602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            VK_CALL(DestroyFence(fDevice, fence, nullptr));
132820ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel            SkDebugf("Fence failed to signal: %d\n", err);
132920ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel            SkFAIL("failing");
1330164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
133120ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        SkASSERT(!err);
133220ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel
133320ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        // Clean up transfer resources
133420ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        GrVkMemory::FreeBufferMemory(this, GrVkBuffer::kCopyRead_Type, bufferAlloc);
133520ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        VK_CALL(DestroyBuffer(fDevice, buffer, nullptr));
133620ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        VK_CALL(FreeCommandBuffers(fDevice, fCmdPool, 1, &cmdBuffer));
133720ece3a966708bf2886034cda15aea7f4946f4b1Greg Daniel        VK_CALL(DestroyFence(fDevice, fence, nullptr));
1338164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1339164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1340b2df0c2702329be6380a943d548e7377a51d8565egdaniel    GrVkImageInfo* info = new GrVkImageInfo;
1341fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    info->fImage = image;
1342fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    info->fAlloc = alloc;
1343fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    info->fImageTiling = imageTiling;
1344fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    info->fImageLayout = initialLayout;
134558a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel    info->fFormat = pixelFormat;
13462af0f1b014b9aabb6119bf66fac20e4cd3a8279bjvanverth    info->fLevelCount = 1;
1347fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth
1348fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    return (GrBackendObject)info;
1349164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1350164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1351164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::isTestingOnlyBackendTexture(GrBackendObject id) const {
1352b2df0c2702329be6380a943d548e7377a51d8565egdaniel    const GrVkImageInfo* backend = reinterpret_cast<const GrVkImageInfo*>(id);
1353164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
13541e305ba0d6a4237020d36234e9e286d3b0489401jvanverth    if (backend && backend->fImage && backend->fAlloc.fMemory) {
1355164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkMemoryRequirements req;
1356164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        memset(&req, 0, sizeof(req));
1357164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        GR_VK_CALL(this->vkInterface(), GetImageMemoryRequirements(fDevice,
1358164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                   backend->fImage,
1359164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                   &req));
1360164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // TODO: find a better check
1361164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // This will probably fail with a different driver
1362164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return (req.size > 0) && (req.size <= 8192 * 8192);
1363164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1364164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1365164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return false;
1366164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1367164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1368164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::deleteTestingOnlyBackendTexture(GrBackendObject id, bool abandon) {
13696b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    GrVkImageInfo* backend = reinterpret_cast<GrVkImageInfo*>(id);
1370164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (backend) {
1371164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        if (!abandon) {
1372fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth            // something in the command buffer may still be using this, so force submit
1373fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth            this->submitCommandBuffer(kForce_SyncQueue);
13746b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth            GrVkImage::DestroyImageInfo(this, backend);
1375164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
1376fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        delete backend;
1377164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1378164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1379164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1380164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
1381164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1382164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::addMemoryBarrier(VkPipelineStageFlags srcStageMask,
1383164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                               VkPipelineStageFlags dstStageMask,
1384164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                               bool byRegion,
1385164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                               VkMemoryBarrier* barrier) const {
1386164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(fCurrentCmdBuffer);
1387164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->pipelineBarrier(this,
1388164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       srcStageMask,
1389164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       dstStageMask,
1390164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       byRegion,
1391164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       GrVkCommandBuffer::kMemory_BarrierType,
1392164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       barrier);
1393164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1394164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1395164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::addBufferMemoryBarrier(VkPipelineStageFlags srcStageMask,
1396164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     VkPipelineStageFlags dstStageMask,
1397164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     bool byRegion,
1398164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     VkBufferMemoryBarrier* barrier) const {
1399164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(fCurrentCmdBuffer);
1400164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->pipelineBarrier(this,
1401164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       srcStageMask,
1402164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       dstStageMask,
1403164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       byRegion,
1404164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       GrVkCommandBuffer::kBufferMemory_BarrierType,
1405164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       barrier);
1406164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1407164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1408164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::addImageMemoryBarrier(VkPipelineStageFlags srcStageMask,
1409164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                    VkPipelineStageFlags dstStageMask,
1410164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                    bool byRegion,
1411164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                    VkImageMemoryBarrier* barrier) const {
1412164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(fCurrentCmdBuffer);
1413164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->pipelineBarrier(this,
1414164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       srcStageMask,
1415164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       dstStageMask,
1416164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       byRegion,
1417164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       GrVkCommandBuffer::kImageMemory_BarrierType,
1418164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       barrier);
1419164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1420164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1421f2361d2d93c200cd4555b5e8ecea4531801abaaaRobert Phillipsvoid GrVkGpu::finishOpList() {
1422164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Submit the current command buffer to the Queue
1423164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    this->submitCommandBuffer(kSkip_SyncQueue);
1424164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1425164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
14263d5d9ac426ea926f37eaa47e13acf7492068667begdanielvoid GrVkGpu::clearStencil(GrRenderTarget* target) {
14273d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    if (nullptr == target) {
14283d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        return;
14293d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    }
14303d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    GrStencilAttachment* stencil = target->renderTargetPriv().getStencilAttachment();
14313d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    GrVkStencilAttachment* vkStencil = (GrVkStencilAttachment*)stencil;
14323d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
14333d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
14343d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    VkClearDepthStencilValue vkStencilColor;
14353d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    memset(&vkStencilColor, 0, sizeof(VkClearDepthStencilValue));
14363d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
14373d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    vkStencil->setImageLayout(this,
14383d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                              VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
143950c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                              VK_ACCESS_TRANSFER_WRITE_BIT,
144050c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                              VK_PIPELINE_STAGE_TRANSFER_BIT,
14413d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                              false);
14423d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
14433d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    VkImageSubresourceRange subRange;
14443d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    memset(&subRange, 0, sizeof(VkImageSubresourceRange));
14453d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    subRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
14463d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    subRange.baseMipLevel = 0;
14473d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    subRange.levelCount = 1;
14483d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    subRange.baseArrayLayer = 0;
14493d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    subRange.layerCount = 1;
14503d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
14513d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    // TODO: I imagine that most times we want to clear a stencil it will be at the beginning of a
14523d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    // draw. Thus we should look into using the load op functions on the render pass to clear out
14533d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    // the stencil there.
14543d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    fCurrentCmdBuffer->clearDepthStencilImage(this, vkStencil, &vkStencilColor, 1, &subRange);
14553d5d9ac426ea926f37eaa47e13acf7492068667begdaniel}
14563d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
1457164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielinline bool can_copy_image(const GrSurface* dst,
1458164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           const GrSurface* src,
1459164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           const GrVkGpu* gpu) {
14604bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    const GrRenderTarget* dstRT = dst->asRenderTarget();
14614bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    const GrRenderTarget* srcRT = src->asRenderTarget();
14624bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    if (dstRT && srcRT) {
14634bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        if (srcRT->numColorSamples() != dstRT->numColorSamples()) {
14644bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel            return false;
14654bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        }
14664bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    } else if (dstRT) {
14674bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        if (dstRT->numColorSamples() > 1) {
14684bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel            return false;
14694bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        }
14704bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    } else if (srcRT) {
14714bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        if (srcRT->numColorSamples() > 1) {
14724bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel            return false;
14734bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        }
147417b892551465e5a44560a06e4b34dc3592b49622egdaniel    }
147517b892551465e5a44560a06e4b34dc3592b49622egdaniel
14763251ed84052ced22d1e4c285524a835a82f7dd12Michael Jurka    // We require that all vulkan GrSurfaces have been created with transfer_dst and transfer_src
147717b892551465e5a44560a06e4b34dc3592b49622egdaniel    // as image usage flags.
147817b892551465e5a44560a06e4b34dc3592b49622egdaniel    if (src->origin() == dst->origin() &&
147917b892551465e5a44560a06e4b34dc3592b49622egdaniel        GrBytesPerPixel(src->config()) == GrBytesPerPixel(dst->config())) {
1480164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return true;
1481164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1482164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1483164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return false;
1484164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1485164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1486164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::copySurfaceAsCopyImage(GrSurface* dst,
1487164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     GrSurface* src,
148817b892551465e5a44560a06e4b34dc3592b49622egdaniel                                     GrVkImage* dstImage,
148917b892551465e5a44560a06e4b34dc3592b49622egdaniel                                     GrVkImage* srcImage,
1490164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     const SkIRect& srcRect,
1491164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     const SkIPoint& dstPoint) {
1492164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(can_copy_image(dst, src, this));
1493164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1494164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // These flags are for flushing/invalidating caches and for the dst image it doesn't matter if
1495164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // the cache is flushed since it is only being written to.
149617b892551465e5a44560a06e4b34dc3592b49622egdaniel    dstImage->setImageLayout(this,
149750c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                             VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
149850c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                             VK_ACCESS_TRANSFER_WRITE_BIT,
149950c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                             VK_PIPELINE_STAGE_TRANSFER_BIT,
150050c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                             false);
1501164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
150217b892551465e5a44560a06e4b34dc3592b49622egdaniel    srcImage->setImageLayout(this,
150317b892551465e5a44560a06e4b34dc3592b49622egdaniel                             VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
150450c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                             VK_ACCESS_TRANSFER_READ_BIT,
150550c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                             VK_PIPELINE_STAGE_TRANSFER_BIT,
150617b892551465e5a44560a06e4b34dc3592b49622egdaniel                             false);
1507164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1508164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Flip rect if necessary
1509164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkIRect srcVkRect = srcRect;
1510164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    int32_t dstY = dstPoint.fY;
1511164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1512164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (kBottomLeft_GrSurfaceOrigin == src->origin()) {
1513164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        SkASSERT(kBottomLeft_GrSurfaceOrigin == dst->origin());
1514164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        srcVkRect.fTop = src->height() - srcRect.fBottom;
1515164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        srcVkRect.fBottom =  src->height() - srcRect.fTop;
1516164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        dstY = dst->height() - dstPoint.fY - srcVkRect.height();
1517164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1518164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1519164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkImageCopy copyRegion;
1520164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    memset(&copyRegion, 0, sizeof(VkImageCopy));
1521164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    copyRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
1522164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    copyRegion.srcOffset = { srcVkRect.fLeft, srcVkRect.fTop, 0 };
1523164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    copyRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
1524164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    copyRegion.dstOffset = { dstPoint.fX, dstY, 0 };
1525c355bc8dd117291b63ee7b7b39ec37a0e768eec5egdaniel    copyRegion.extent = { (uint32_t)srcVkRect.width(), (uint32_t)srcVkRect.height(), 1 };
1526164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1527164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->copyImage(this,
152817b892551465e5a44560a06e4b34dc3592b49622egdaniel                                 srcImage,
1529164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
153017b892551465e5a44560a06e4b34dc3592b49622egdaniel                                 dstImage,
1531164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1532164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                 1,
1533164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                 &copyRegion);
1534900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
1535900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY,
1536900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                        srcRect.width(), srcRect.height());
1537900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    this->didWriteToSurface(dst, &dstRect);
1538164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1539164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
154017b892551465e5a44560a06e4b34dc3592b49622egdanielinline bool can_copy_as_blit(const GrSurface* dst,
154117b892551465e5a44560a06e4b34dc3592b49622egdaniel                             const GrSurface* src,
154217b892551465e5a44560a06e4b34dc3592b49622egdaniel                             const GrVkImage* dstImage,
154317b892551465e5a44560a06e4b34dc3592b49622egdaniel                             const GrVkImage* srcImage,
154417b892551465e5a44560a06e4b34dc3592b49622egdaniel                             const GrVkGpu* gpu) {
154566933552f1723c4a2b248711ab3d43921401e8e6egdaniel    // We require that all vulkan GrSurfaces have been created with transfer_dst and transfer_src
154617b892551465e5a44560a06e4b34dc3592b49622egdaniel    // as image usage flags.
154717b892551465e5a44560a06e4b34dc3592b49622egdaniel    const GrVkCaps& caps = gpu->vkCaps();
154817b892551465e5a44560a06e4b34dc3592b49622egdaniel    if (!caps.configCanBeDstofBlit(dst->config(), dstImage->isLinearTiled()) ||
154917b892551465e5a44560a06e4b34dc3592b49622egdaniel        !caps.configCanBeSrcofBlit(src->config(), srcImage->isLinearTiled())) {
155017b892551465e5a44560a06e4b34dc3592b49622egdaniel        return false;
155117b892551465e5a44560a06e4b34dc3592b49622egdaniel    }
155217b892551465e5a44560a06e4b34dc3592b49622egdaniel
155317b892551465e5a44560a06e4b34dc3592b49622egdaniel    // We cannot blit images that are multisampled. Will need to figure out if we can blit the
155417b892551465e5a44560a06e4b34dc3592b49622egdaniel    // resolved msaa though.
155517b892551465e5a44560a06e4b34dc3592b49622egdaniel    if ((dst->asRenderTarget() && dst->asRenderTarget()->numColorSamples() > 1) ||
155617b892551465e5a44560a06e4b34dc3592b49622egdaniel        (src->asRenderTarget() && src->asRenderTarget()->numColorSamples() > 1)) {
155717b892551465e5a44560a06e4b34dc3592b49622egdaniel        return false;
155817b892551465e5a44560a06e4b34dc3592b49622egdaniel    }
155917b892551465e5a44560a06e4b34dc3592b49622egdaniel
156017b892551465e5a44560a06e4b34dc3592b49622egdaniel    return true;
156117b892551465e5a44560a06e4b34dc3592b49622egdaniel}
156217b892551465e5a44560a06e4b34dc3592b49622egdaniel
156317b892551465e5a44560a06e4b34dc3592b49622egdanielvoid GrVkGpu::copySurfaceAsBlit(GrSurface* dst,
156417b892551465e5a44560a06e4b34dc3592b49622egdaniel                                GrSurface* src,
156517b892551465e5a44560a06e4b34dc3592b49622egdaniel                                GrVkImage* dstImage,
156617b892551465e5a44560a06e4b34dc3592b49622egdaniel                                GrVkImage* srcImage,
156717b892551465e5a44560a06e4b34dc3592b49622egdaniel                                const SkIRect& srcRect,
156817b892551465e5a44560a06e4b34dc3592b49622egdaniel                                const SkIPoint& dstPoint) {
156917b892551465e5a44560a06e4b34dc3592b49622egdaniel    SkASSERT(can_copy_as_blit(dst, src, dstImage, srcImage, this));
157017b892551465e5a44560a06e4b34dc3592b49622egdaniel
157117b892551465e5a44560a06e4b34dc3592b49622egdaniel    dstImage->setImageLayout(this,
157217b892551465e5a44560a06e4b34dc3592b49622egdaniel                             VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
157350c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                             VK_ACCESS_TRANSFER_WRITE_BIT,
157450c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                             VK_PIPELINE_STAGE_TRANSFER_BIT,
157517b892551465e5a44560a06e4b34dc3592b49622egdaniel                             false);
157617b892551465e5a44560a06e4b34dc3592b49622egdaniel
157717b892551465e5a44560a06e4b34dc3592b49622egdaniel    srcImage->setImageLayout(this,
157817b892551465e5a44560a06e4b34dc3592b49622egdaniel                             VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
157950c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                             VK_ACCESS_TRANSFER_READ_BIT,
158050c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                             VK_PIPELINE_STAGE_TRANSFER_BIT,
158117b892551465e5a44560a06e4b34dc3592b49622egdaniel                             false);
158217b892551465e5a44560a06e4b34dc3592b49622egdaniel
158317b892551465e5a44560a06e4b34dc3592b49622egdaniel    // Flip rect if necessary
158417b892551465e5a44560a06e4b34dc3592b49622egdaniel    SkIRect srcVkRect;
15858af936d3047208def585b7bc824f013b994f6312egdaniel    srcVkRect.fLeft = srcRect.fLeft;
15868af936d3047208def585b7bc824f013b994f6312egdaniel    srcVkRect.fRight = srcRect.fRight;
158717b892551465e5a44560a06e4b34dc3592b49622egdaniel    SkIRect dstRect;
158817b892551465e5a44560a06e4b34dc3592b49622egdaniel    dstRect.fLeft = dstPoint.fX;
15898af936d3047208def585b7bc824f013b994f6312egdaniel    dstRect.fRight = dstPoint.fX + srcRect.width();
159017b892551465e5a44560a06e4b34dc3592b49622egdaniel
159117b892551465e5a44560a06e4b34dc3592b49622egdaniel    if (kBottomLeft_GrSurfaceOrigin == src->origin()) {
159217b892551465e5a44560a06e4b34dc3592b49622egdaniel        srcVkRect.fTop = src->height() - srcRect.fBottom;
159317b892551465e5a44560a06e4b34dc3592b49622egdaniel        srcVkRect.fBottom = src->height() - srcRect.fTop;
159417b892551465e5a44560a06e4b34dc3592b49622egdaniel    } else {
15958af936d3047208def585b7bc824f013b994f6312egdaniel        srcVkRect.fTop = srcRect.fTop;
15968af936d3047208def585b7bc824f013b994f6312egdaniel        srcVkRect.fBottom = srcRect.fBottom;
159717b892551465e5a44560a06e4b34dc3592b49622egdaniel    }
159817b892551465e5a44560a06e4b34dc3592b49622egdaniel
159917b892551465e5a44560a06e4b34dc3592b49622egdaniel    if (kBottomLeft_GrSurfaceOrigin == dst->origin()) {
160017b892551465e5a44560a06e4b34dc3592b49622egdaniel        dstRect.fTop = dst->height() - dstPoint.fY - srcVkRect.height();
160117b892551465e5a44560a06e4b34dc3592b49622egdaniel    } else {
160217b892551465e5a44560a06e4b34dc3592b49622egdaniel        dstRect.fTop = dstPoint.fY;
160317b892551465e5a44560a06e4b34dc3592b49622egdaniel    }
160417b892551465e5a44560a06e4b34dc3592b49622egdaniel    dstRect.fBottom = dstRect.fTop + srcVkRect.height();
160517b892551465e5a44560a06e4b34dc3592b49622egdaniel
160617b892551465e5a44560a06e4b34dc3592b49622egdaniel    // If we have different origins, we need to flip the top and bottom of the dst rect so that we
160717b892551465e5a44560a06e4b34dc3592b49622egdaniel    // get the correct origintation of the copied data.
160817b892551465e5a44560a06e4b34dc3592b49622egdaniel    if (src->origin() != dst->origin()) {
160917b892551465e5a44560a06e4b34dc3592b49622egdaniel        SkTSwap(dstRect.fTop, dstRect.fBottom);
161017b892551465e5a44560a06e4b34dc3592b49622egdaniel    }
161117b892551465e5a44560a06e4b34dc3592b49622egdaniel
161217b892551465e5a44560a06e4b34dc3592b49622egdaniel    VkImageBlit blitRegion;
161317b892551465e5a44560a06e4b34dc3592b49622egdaniel    memset(&blitRegion, 0, sizeof(VkImageBlit));
161417b892551465e5a44560a06e4b34dc3592b49622egdaniel    blitRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
161517b892551465e5a44560a06e4b34dc3592b49622egdaniel    blitRegion.srcOffsets[0] = { srcVkRect.fLeft, srcVkRect.fTop, 0 };
1616e76071ca0f98cb4d7e2d1789c46aa3037637b309Greg Daniel    blitRegion.srcOffsets[1] = { srcVkRect.fRight, srcVkRect.fBottom, 1 };
161717b892551465e5a44560a06e4b34dc3592b49622egdaniel    blitRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
161817b892551465e5a44560a06e4b34dc3592b49622egdaniel    blitRegion.dstOffsets[0] = { dstRect.fLeft, dstRect.fTop, 0 };
1619e76071ca0f98cb4d7e2d1789c46aa3037637b309Greg Daniel    blitRegion.dstOffsets[1] = { dstRect.fRight, dstRect.fBottom, 1 };
162017b892551465e5a44560a06e4b34dc3592b49622egdaniel
162117b892551465e5a44560a06e4b34dc3592b49622egdaniel    fCurrentCmdBuffer->blitImage(this,
1622b2df0c2702329be6380a943d548e7377a51d8565egdaniel                                 *srcImage,
1623b2df0c2702329be6380a943d548e7377a51d8565egdaniel                                 *dstImage,
162417b892551465e5a44560a06e4b34dc3592b49622egdaniel                                 1,
162517b892551465e5a44560a06e4b34dc3592b49622egdaniel                                 &blitRegion,
162617b892551465e5a44560a06e4b34dc3592b49622egdaniel                                 VK_FILTER_NEAREST); // We never scale so any filter works here
1627900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
1628900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    this->didWriteToSurface(dst, &dstRect);
162917b892551465e5a44560a06e4b34dc3592b49622egdaniel}
163017b892551465e5a44560a06e4b34dc3592b49622egdaniel
16314bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdanielinline bool can_copy_as_resolve(const GrSurface* dst,
16324bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel                                const GrSurface* src,
16334bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel                                const GrVkGpu* gpu) {
16344bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    // Our src must be a multisampled render target
16354bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    if (!src->asRenderTarget() || src->asRenderTarget()->numColorSamples() <= 1) {
16364bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        return false;
16374bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    }
16384bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel
16397d6f6666fe8f3b45734f9dd1a9d1d34b7bdd6b60Greg Daniel    // The dst must not be a multisampled render target, expect in the case where the dst is the
16407d6f6666fe8f3b45734f9dd1a9d1d34b7bdd6b60Greg Daniel    // resolve texture connected to the msaa src. We check for this in case we are copying a part of
16417d6f6666fe8f3b45734f9dd1a9d1d34b7bdd6b60Greg Daniel    // a surface to a different region in the same surface.
16427d6f6666fe8f3b45734f9dd1a9d1d34b7bdd6b60Greg Daniel    if (dst->asRenderTarget() && dst->asRenderTarget()->numColorSamples() > 1 && dst != src) {
16434bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        return false;
16444bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    }
16454bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel
16464bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    // Surfaces must have the same origin.
16474bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    if (src->origin() != dst->origin()) {
16484bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        return false;
16494bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    }
16504bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel
16514bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    return true;
16524bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel}
16534bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel
16544bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdanielvoid GrVkGpu::copySurfaceAsResolve(GrSurface* dst,
16554bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel                                   GrSurface* src,
16564bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel                                   const SkIRect& srcRect,
16574bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel                                   const SkIPoint& dstPoint) {
16584bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    GrVkRenderTarget* srcRT = static_cast<GrVkRenderTarget*>(src->asRenderTarget());
1659bc26c392b2f2e27ea554347dfdb5f994b6dc54f2Greg Daniel    this->resolveImage(dst, srcRT, srcRect, dstPoint);
16604bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel}
16614bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel
1662164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::onCopySurface(GrSurface* dst,
1663164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                            GrSurface* src,
1664164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                            const SkIRect& srcRect,
1665164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                            const SkIPoint& dstPoint) {
16664bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    if (can_copy_as_resolve(dst, src, this)) {
16674bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        this->copySurfaceAsResolve(dst, src, srcRect, dstPoint);
1668ec44099979acd3e83ad93a15dbd9301856a90572egdaniel        return true;
16694bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    }
16704bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel
1671fd016d7a69f0415f2497d25ec3a7b71de1545826egdaniel    if (this->vkCaps().mustSubmitCommandsBeforeCopyOp()) {
1672fd016d7a69f0415f2497d25ec3a7b71de1545826egdaniel        this->submitCommandBuffer(GrVkGpu::kSkip_SyncQueue);
1673fd016d7a69f0415f2497d25ec3a7b71de1545826egdaniel    }
1674fd016d7a69f0415f2497d25ec3a7b71de1545826egdaniel
1675bc9b2963bf9e39c47ae5c3ab94b8503b476f4f0eegdaniel    if (fCopyManager.copySurfaceAsDraw(this, dst, src, srcRect, dstPoint)) {
1676bc9b2963bf9e39c47ae5c3ab94b8503b476f4f0eegdaniel        return true;
1677bc9b2963bf9e39c47ae5c3ab94b8503b476f4f0eegdaniel    }
1678bc9b2963bf9e39c47ae5c3ab94b8503b476f4f0eegdaniel
167917b892551465e5a44560a06e4b34dc3592b49622egdaniel    GrVkImage* dstImage;
168017b892551465e5a44560a06e4b34dc3592b49622egdaniel    GrVkImage* srcImage;
16814bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    GrRenderTarget* dstRT = dst->asRenderTarget();
16824bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    if (dstRT) {
16834bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(dstRT);
16844bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        dstImage = vkRT->numColorSamples() > 1 ? vkRT->msaaImage() : vkRT;
168517b892551465e5a44560a06e4b34dc3592b49622egdaniel    } else {
16864bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        SkASSERT(dst->asTexture());
16874bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        dstImage = static_cast<GrVkTexture*>(dst->asTexture());
168817b892551465e5a44560a06e4b34dc3592b49622egdaniel    }
16894bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    GrRenderTarget* srcRT = src->asRenderTarget();
16904bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    if (srcRT) {
16914bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(srcRT);
16924bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        srcImage = vkRT->numColorSamples() > 1 ? vkRT->msaaImage() : vkRT;
169317b892551465e5a44560a06e4b34dc3592b49622egdaniel    } else {
16944bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        SkASSERT(src->asTexture());
16954bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        srcImage = static_cast<GrVkTexture*>(src->asTexture());
169617b892551465e5a44560a06e4b34dc3592b49622egdaniel    }
169717b892551465e5a44560a06e4b34dc3592b49622egdaniel
169813dddce65fd87a8175a209a49f35615735a2886aBrian Osman    // For borrowed textures, we *only* want to copy using draws (to avoid layout changes)
169913dddce65fd87a8175a209a49f35615735a2886aBrian Osman    if (srcImage->isBorrowed()) {
170013dddce65fd87a8175a209a49f35615735a2886aBrian Osman        return false;
170113dddce65fd87a8175a209a49f35615735a2886aBrian Osman    }
170213dddce65fd87a8175a209a49f35615735a2886aBrian Osman
1703164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (can_copy_image(dst, src, this)) {
170417b892551465e5a44560a06e4b34dc3592b49622egdaniel        this->copySurfaceAsCopyImage(dst, src, dstImage, srcImage, srcRect, dstPoint);
170517b892551465e5a44560a06e4b34dc3592b49622egdaniel        return true;
170617b892551465e5a44560a06e4b34dc3592b49622egdaniel    }
170717b892551465e5a44560a06e4b34dc3592b49622egdaniel
170817b892551465e5a44560a06e4b34dc3592b49622egdaniel    if (can_copy_as_blit(dst, src, dstImage, srcImage, this)) {
170917b892551465e5a44560a06e4b34dc3592b49622egdaniel        this->copySurfaceAsBlit(dst, src, dstImage, srcImage, srcRect, dstPoint);
1710164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return true;
1711164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1712164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1713164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return false;
1714164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1715164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1716c25c5d73e9f4d840dc758c399496d5690709ad58csmartdaltonvoid GrVkGpu::onQueryMultisampleSpecs(GrRenderTarget* rt, const GrStencilSettings&,
1717c25c5d73e9f4d840dc758c399496d5690709ad58csmartdalton                                      int* effectiveSampleCnt, SamplePattern*) {
171828f45b949acc746849100fbe112ee5280f0594c9cdalton    // TODO: stub.
171928f45b949acc746849100fbe112ee5280f0594c9cdalton    SkASSERT(!this->caps()->sampleLocationsSupport());
172028f45b949acc746849100fbe112ee5280f0594c9cdalton    *effectiveSampleCnt = rt->desc().fSampleCnt;
172128f45b949acc746849100fbe112ee5280f0594c9cdalton}
172228f45b949acc746849100fbe112ee5280f0594c9cdalton
1723164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::onGetReadPixelsInfo(GrSurface* srcSurface, int width, int height, size_t rowBytes,
1724164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                  GrPixelConfig readConfig, DrawPreference* drawPreference,
1725164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                  ReadPixelTempDrawInfo* tempDrawInfo) {
172688e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    // These settings we will always want if a temp draw is performed.
172788e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    tempDrawInfo->fTempSurfaceDesc.fFlags = kRenderTarget_GrSurfaceFlag;
172888e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    tempDrawInfo->fTempSurfaceDesc.fWidth = width;
172988e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    tempDrawInfo->fTempSurfaceDesc.fHeight = height;
173088e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    tempDrawInfo->fTempSurfaceDesc.fSampleCnt = 0;
173188e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    tempDrawInfo->fTempSurfaceDesc.fOrigin = kTopLeft_GrSurfaceOrigin; // no CPU y-flip for TL.
1732b117ff194ff888ef9107a4797aad053b0d76be30bsalomon    tempDrawInfo->fTempSurfaceFit = SkBackingFit::kApprox;
173388e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel
173488e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    // For now assume no swizzling, we may change that below.
173588e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    tempDrawInfo->fSwizzle = GrSwizzle::RGBA();
173688e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel
173788e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    // Depends on why we need/want a temp draw. Start off assuming no change, the surface we read
173888e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    // from will be srcConfig and we will read readConfig pixels from it.
173933910297e032b9af4336bc146c7fbb0f35918de9Brian Osman    // Note that if we require a draw and return a non-renderable format for the temp surface the
174088e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    // base class will fail for us.
174188e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    tempDrawInfo->fTempSurfaceDesc.fConfig = srcSurface->config();
174288e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    tempDrawInfo->fReadConfig = readConfig;
174388e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel
17444583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    if (srcSurface->config() == readConfig) {
17454583ec51d9ddc830eeb854db068235be96ce59c4egdaniel        return true;
1746164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1747164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
174833910297e032b9af4336bc146c7fbb0f35918de9Brian Osman    // Any config change requires a draw
174933910297e032b9af4336bc146c7fbb0f35918de9Brian Osman    ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
175033910297e032b9af4336bc146c7fbb0f35918de9Brian Osman    tempDrawInfo->fTempSurfaceDesc.fConfig = readConfig;
175133910297e032b9af4336bc146c7fbb0f35918de9Brian Osman    tempDrawInfo->fReadConfig = readConfig;
1752164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
175333910297e032b9af4336bc146c7fbb0f35918de9Brian Osman    return true;
1754164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1755164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1756164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::onReadPixels(GrSurface* surface,
1757164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           int left, int top, int width, int height,
1758164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           GrPixelConfig config,
1759164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           void* buffer,
1760164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           size_t rowBytes) {
1761164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkFormat pixelFormat;
1762164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!GrPixelConfigToVkFormat(config, &pixelFormat)) {
1763164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
1764164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1765164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
176666933552f1723c4a2b248711ab3d43921401e8e6egdaniel    GrVkImage* image = nullptr;
176766933552f1723c4a2b248711ab3d43921401e8e6egdaniel    GrVkRenderTarget* rt = static_cast<GrVkRenderTarget*>(surface->asRenderTarget());
176866933552f1723c4a2b248711ab3d43921401e8e6egdaniel    if (rt) {
176966933552f1723c4a2b248711ab3d43921401e8e6egdaniel        // resolve the render target if necessary
177066933552f1723c4a2b248711ab3d43921401e8e6egdaniel        switch (rt->getResolveType()) {
177166933552f1723c4a2b248711ab3d43921401e8e6egdaniel            case GrVkRenderTarget::kCantResolve_ResolveType:
177266933552f1723c4a2b248711ab3d43921401e8e6egdaniel                return false;
177366933552f1723c4a2b248711ab3d43921401e8e6egdaniel            case GrVkRenderTarget::kAutoResolves_ResolveType:
177466933552f1723c4a2b248711ab3d43921401e8e6egdaniel                break;
177566933552f1723c4a2b248711ab3d43921401e8e6egdaniel            case GrVkRenderTarget::kCanResolve_ResolveType:
177669d4992e69d7b142450d0ccb587b7b26be7cf1eaGreg Daniel                this->internalResolveRenderTarget(rt, false);
177766933552f1723c4a2b248711ab3d43921401e8e6egdaniel                break;
177866933552f1723c4a2b248711ab3d43921401e8e6egdaniel            default:
177966933552f1723c4a2b248711ab3d43921401e8e6egdaniel                SkFAIL("Unknown resolve type");
178066933552f1723c4a2b248711ab3d43921401e8e6egdaniel        }
178166933552f1723c4a2b248711ab3d43921401e8e6egdaniel        image = rt;
178266933552f1723c4a2b248711ab3d43921401e8e6egdaniel    } else {
178366933552f1723c4a2b248711ab3d43921401e8e6egdaniel        image = static_cast<GrVkTexture*>(surface->asTexture());
178466933552f1723c4a2b248711ab3d43921401e8e6egdaniel    }
178566933552f1723c4a2b248711ab3d43921401e8e6egdaniel
178666933552f1723c4a2b248711ab3d43921401e8e6egdaniel    if (!image) {
1787164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
1788164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1789164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1790164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Change layout of our target so it can be used as copy
179166933552f1723c4a2b248711ab3d43921401e8e6egdaniel    image->setImageLayout(this,
179266933552f1723c4a2b248711ab3d43921401e8e6egdaniel                          VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
179366933552f1723c4a2b248711ab3d43921401e8e6egdaniel                          VK_ACCESS_TRANSFER_READ_BIT,
179466933552f1723c4a2b248711ab3d43921401e8e6egdaniel                          VK_PIPELINE_STAGE_TRANSFER_BIT,
179566933552f1723c4a2b248711ab3d43921401e8e6egdaniel                          false);
1796164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
17976fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel    size_t bpp = GrBytesPerPixel(config);
17986fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel    size_t tightRowBytes = bpp * width;
1799164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    bool flipY = kBottomLeft_GrSurfaceOrigin == surface->origin();
1800164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1801164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkBufferImageCopy region;
1802164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    memset(&region, 0, sizeof(VkBufferImageCopy));
18036fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel
18046fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel    bool copyFromOrigin = this->vkCaps().mustDoCopiesFromOrigin();
18056fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel    if (copyFromOrigin) {
18066fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel        region.imageOffset = { 0, 0, 0 };
18076fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel        region.imageExtent = { (uint32_t)(left + width),
18086fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel                               (uint32_t)(flipY ? surface->height() - top : top + height),
18096fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel                               1
18106fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel                             };
18116fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel    } else {
18126fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel        VkOffset3D offset = {
18136fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel            left,
18146fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel            flipY ? surface->height() - top - height : top,
18156fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel            0
18166fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel        };
18176fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel        region.imageOffset = offset;
18186fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel        region.imageExtent = { (uint32_t)width, (uint32_t)height, 1 };
18196fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel    }
18206fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel
18216fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel    size_t transBufferRowBytes = bpp * region.imageExtent.width;
18226fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel    GrVkTransferBuffer* transferBuffer =
18236fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel            static_cast<GrVkTransferBuffer*>(this->createBuffer(transBufferRowBytes * height,
18246fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel                                                                kXferGpuToCpu_GrBufferType,
18256fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel                                                                kStream_GrAccessPattern));
18266fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel
18276fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel    // Copy the image to a buffer so we can map it to cpu memory
1828db37909347d034943bd6b0922710a94c6c6ea572jvanverth    region.bufferOffset = transferBuffer->offset();
182988e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    region.bufferRowLength = 0; // Forces RowLength to be width. We handle the rowBytes below.
1830164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    region.bufferImageHeight = 0; // Forces height to be tightly packed. Only useful for 3d images.
1831164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
1832164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1833164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->copyImageToBuffer(this,
183466933552f1723c4a2b248711ab3d43921401e8e6egdaniel                                         image,
1835164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1836164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                         transferBuffer,
1837164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                         1,
1838164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                         &region);
1839164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1840164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // make sure the copy to buffer has finished
1841164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    transferBuffer->addMemoryBarrier(this,
1842164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     VK_ACCESS_TRANSFER_WRITE_BIT,
1843164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     VK_ACCESS_HOST_READ_BIT,
1844164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     VK_PIPELINE_STAGE_TRANSFER_BIT,
1845164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     VK_PIPELINE_STAGE_HOST_BIT,
1846164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     false);
1847164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1848164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // We need to submit the current command buffer to the Queue and make sure it finishes before
1849164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // we can copy the data out of the buffer.
1850164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    this->submitCommandBuffer(kForce_SyncQueue);
18519d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth    GrVkMemory::InvalidateMappedAlloc(this, transferBuffer->alloc());
1852164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    void* mappedMemory = transferBuffer->map();
1853164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
18546fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel    if (copyFromOrigin) {
18556fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel        uint32_t skipRows = region.imageExtent.height - height;
18566fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel        mappedMemory = (char*)mappedMemory + transBufferRowBytes * skipRows + bpp * left;
18576fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel    }
18586fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel
1859164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (flipY) {
186088e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel        const char* srcRow = reinterpret_cast<const char*>(mappedMemory);
186188e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel        char* dstRow = reinterpret_cast<char*>(buffer)+(height - 1) * rowBytes;
186288e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel        for (int y = 0; y < height; y++) {
186388e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel            memcpy(dstRow, srcRow, tightRowBytes);
18646fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel            srcRow += transBufferRowBytes;
186588e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel            dstRow -= rowBytes;
186688e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel        }
186788e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    } else {
1868cf3525a95eea54d00727392463a6fe648914c3eaMatt Sarett        SkRectMemcpy(buffer, rowBytes, mappedMemory, transBufferRowBytes, tightRowBytes, height);
1869164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1870164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
187188e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    transferBuffer->unmap();
187288e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    transferBuffer->unref();
1873164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return true;
1874164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1875066df7ca911b65d416783f3bec6f4f1662948ad5egdaniel
187627bb28473912181cf9a838e9282e86cb62e2d44begdaniel// The RenderArea bounds we pass into BeginRenderPass must have a start x value that is a multiple
187727bb28473912181cf9a838e9282e86cb62e2d44begdaniel// of the granularity. The width must also be a multiple of the granularity or eaqual to the width
187827bb28473912181cf9a838e9282e86cb62e2d44begdaniel// the the entire attachment. Similar requirements for the y and height components.
187927bb28473912181cf9a838e9282e86cb62e2d44begdanielvoid adjust_bounds_to_granularity(SkIRect* dstBounds, const SkIRect& srcBounds,
188027bb28473912181cf9a838e9282e86cb62e2d44begdaniel                                  const VkExtent2D& granularity, int maxWidth, int maxHeight) {
188127bb28473912181cf9a838e9282e86cb62e2d44begdaniel    // Adjust Width
1882d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel    if ((0 != granularity.width && 1 != granularity.width)) {
1883d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel        // Start with the right side of rect so we know if we end up going pass the maxWidth.
1884d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel        int rightAdj = srcBounds.fRight % granularity.width;
1885d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel        if (rightAdj != 0) {
1886d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel            rightAdj = granularity.width - rightAdj;
1887d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel        }
1888d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel        dstBounds->fRight = srcBounds.fRight + rightAdj;
1889d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel        if (dstBounds->fRight > maxWidth) {
1890d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel            dstBounds->fRight = maxWidth;
1891d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel            dstBounds->fLeft = 0;
1892d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel        } else {
1893d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel            dstBounds->fLeft = srcBounds.fLeft - srcBounds.fLeft % granularity.width;
1894d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel        }
189527bb28473912181cf9a838e9282e86cb62e2d44begdaniel    } else {
1896d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel        dstBounds->fLeft = srcBounds.fLeft;
1897d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel        dstBounds->fRight = srcBounds.fRight;
189827bb28473912181cf9a838e9282e86cb62e2d44begdaniel    }
189927bb28473912181cf9a838e9282e86cb62e2d44begdaniel
190027bb28473912181cf9a838e9282e86cb62e2d44begdaniel    // Adjust height
1901d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel    if ((0 != granularity.height && 1 != granularity.height)) {
1902d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel        // Start with the bottom side of rect so we know if we end up going pass the maxHeight.
1903d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel        int bottomAdj = srcBounds.fBottom % granularity.height;
1904d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel        if (bottomAdj != 0) {
1905d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel            bottomAdj = granularity.height - bottomAdj;
1906d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel        }
1907d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel        dstBounds->fBottom = srcBounds.fBottom + bottomAdj;
1908d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel        if (dstBounds->fBottom > maxHeight) {
1909d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel            dstBounds->fBottom = maxHeight;
1910d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel            dstBounds->fTop = 0;
1911d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel        } else {
1912d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel            dstBounds->fTop = srcBounds.fTop - srcBounds.fTop % granularity.height;
1913d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel        }
191427bb28473912181cf9a838e9282e86cb62e2d44begdaniel    } else {
1915d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel        dstBounds->fTop = srcBounds.fTop;
1916d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel        dstBounds->fBottom = srcBounds.fBottom;
191727bb28473912181cf9a838e9282e86cb62e2d44begdaniel    }
191827bb28473912181cf9a838e9282e86cb62e2d44begdaniel}
191927bb28473912181cf9a838e9282e86cb62e2d44begdaniel
192022bc8653d704584e13f35844dafb5ddeb9989127Greg Danielvoid GrVkGpu::submitSecondaryCommandBuffer(const SkTArray<GrVkSecondaryCommandBuffer*>& buffers,
19219cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel                                           const GrVkRenderPass* renderPass,
19229cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel                                           const VkClearValue* colorClear,
19239cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel                                           GrVkRenderTarget* target,
19249cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel                                           const SkIRect& bounds) {
1925e7d1b24ff0a04686aef54fcb9feaca7a03e19891egdaniel    const SkIRect* pBounds = &bounds;
1926e7d1b24ff0a04686aef54fcb9feaca7a03e19891egdaniel    SkIRect flippedBounds;
1927e7d1b24ff0a04686aef54fcb9feaca7a03e19891egdaniel    if (kBottomLeft_GrSurfaceOrigin == target->origin()) {
1928e7d1b24ff0a04686aef54fcb9feaca7a03e19891egdaniel        flippedBounds = bounds;
1929e7d1b24ff0a04686aef54fcb9feaca7a03e19891egdaniel        flippedBounds.fTop = target->height() - bounds.fBottom;
1930e7d1b24ff0a04686aef54fcb9feaca7a03e19891egdaniel        flippedBounds.fBottom = target->height() - bounds.fTop;
1931e7d1b24ff0a04686aef54fcb9feaca7a03e19891egdaniel        pBounds = &flippedBounds;
1932e7d1b24ff0a04686aef54fcb9feaca7a03e19891egdaniel    }
1933e7d1b24ff0a04686aef54fcb9feaca7a03e19891egdaniel
193427bb28473912181cf9a838e9282e86cb62e2d44begdaniel    // The bounds we use for the render pass should be of the granularity supported
193527bb28473912181cf9a838e9282e86cb62e2d44begdaniel    // by the device.
193627bb28473912181cf9a838e9282e86cb62e2d44begdaniel    const VkExtent2D& granularity = renderPass->granularity();
193727bb28473912181cf9a838e9282e86cb62e2d44begdaniel    SkIRect adjustedBounds;
193827bb28473912181cf9a838e9282e86cb62e2d44begdaniel    if ((0 != granularity.width && 1 != granularity.width) ||
193927bb28473912181cf9a838e9282e86cb62e2d44begdaniel        (0 != granularity.height && 1 != granularity.height)) {
194027bb28473912181cf9a838e9282e86cb62e2d44begdaniel        adjust_bounds_to_granularity(&adjustedBounds, *pBounds, granularity,
194127bb28473912181cf9a838e9282e86cb62e2d44begdaniel                                     target->width(), target->height());
194227bb28473912181cf9a838e9282e86cb62e2d44begdaniel        pBounds = &adjustedBounds;
194327bb28473912181cf9a838e9282e86cb62e2d44begdaniel    }
194427bb28473912181cf9a838e9282e86cb62e2d44begdaniel
194577a86f81f39227ea53441af2afc647f589a96a0dGreg Daniel    fCurrentCmdBuffer->beginRenderPass(this, renderPass, colorClear, *target, *pBounds, true);
194622bc8653d704584e13f35844dafb5ddeb9989127Greg Daniel    for (int i = 0; i < buffers.count(); ++i) {
194722bc8653d704584e13f35844dafb5ddeb9989127Greg Daniel        fCurrentCmdBuffer->executeCommands(this, buffers[i]);
194822bc8653d704584e13f35844dafb5ddeb9989127Greg Daniel    }
1949164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->endRenderPass(this);
195066933552f1723c4a2b248711ab3d43921401e8e6egdaniel
1951ce3bfb1ed155880585b2d0bb0a8d3e43306e23f2egdaniel    this->didWriteToSurface(target, &bounds);
1952164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
19539cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel
19546be35238855dbbc7575e78d6723936293a4b38e6Greg DanielGrFence SK_WARN_UNUSED_RESULT GrVkGpu::insertFence() {
195584741b308496409f4ff662658167221fc6801bbejvanverth    VkFenceCreateInfo createInfo;
195684741b308496409f4ff662658167221fc6801bbejvanverth    memset(&createInfo, 0, sizeof(VkFenceCreateInfo));
195784741b308496409f4ff662658167221fc6801bbejvanverth    createInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
195884741b308496409f4ff662658167221fc6801bbejvanverth    createInfo.pNext = nullptr;
195984741b308496409f4ff662658167221fc6801bbejvanverth    createInfo.flags = 0;
196084741b308496409f4ff662658167221fc6801bbejvanverth    VkFence fence = VK_NULL_HANDLE;
19616be35238855dbbc7575e78d6723936293a4b38e6Greg Daniel
19626be35238855dbbc7575e78d6723936293a4b38e6Greg Daniel    VK_CALL_ERRCHECK(CreateFence(this->device(), &createInfo, nullptr, &fence));
19636be35238855dbbc7575e78d6723936293a4b38e6Greg Daniel    VK_CALL(QueueSubmit(this->queue(), 0, nullptr, fence));
19646be35238855dbbc7575e78d6723936293a4b38e6Greg Daniel
19656be35238855dbbc7575e78d6723936293a4b38e6Greg Daniel    GR_STATIC_ASSERT(sizeof(GrFence) >= sizeof(VkFence));
196684741b308496409f4ff662658167221fc6801bbejvanverth    return (GrFence)fence;
196784741b308496409f4ff662658167221fc6801bbejvanverth}
196884741b308496409f4ff662658167221fc6801bbejvanverth
19696be35238855dbbc7575e78d6723936293a4b38e6Greg Danielbool GrVkGpu::waitFence(GrFence fence, uint64_t timeout) {
19706be35238855dbbc7575e78d6723936293a4b38e6Greg Daniel    SkASSERT(VK_NULL_HANDLE != (VkFence)fence);
19716be35238855dbbc7575e78d6723936293a4b38e6Greg Daniel
19726be35238855dbbc7575e78d6723936293a4b38e6Greg Daniel    VkResult result = VK_CALL(WaitForFences(this->device(), 1, (VkFence*)&fence, VK_TRUE, timeout));
197384741b308496409f4ff662658167221fc6801bbejvanverth    return (VK_SUCCESS == result);
197484741b308496409f4ff662658167221fc6801bbejvanverth}
197584741b308496409f4ff662658167221fc6801bbejvanverth
197684741b308496409f4ff662658167221fc6801bbejvanverthvoid GrVkGpu::deleteFence(GrFence fence) const {
19776be35238855dbbc7575e78d6723936293a4b38e6Greg Daniel    VK_CALL(DestroyFence(this->device(), (VkFence)fence, nullptr));
19786be35238855dbbc7575e78d6723936293a4b38e6Greg Daniel}
19796be35238855dbbc7575e78d6723936293a4b38e6Greg Daniel
19806be35238855dbbc7575e78d6723936293a4b38e6Greg Danielsk_sp<GrSemaphore> SK_WARN_UNUSED_RESULT GrVkGpu::makeSemaphore() {
19816be35238855dbbc7575e78d6723936293a4b38e6Greg Daniel    return GrVkSemaphore::Make(this);
19826be35238855dbbc7575e78d6723936293a4b38e6Greg Daniel}
19836be35238855dbbc7575e78d6723936293a4b38e6Greg Daniel
1984dc87c95382d5beab7fdae2e654d6de568fbe1671Brian Osmanvoid GrVkGpu::insertSemaphore(sk_sp<GrSemaphore> semaphore, bool /*flush*/) {
19856be35238855dbbc7575e78d6723936293a4b38e6Greg Daniel    GrVkSemaphore* vkSem = static_cast<GrVkSemaphore*>(semaphore.get());
19866be35238855dbbc7575e78d6723936293a4b38e6Greg Daniel
1987dc87c95382d5beab7fdae2e654d6de568fbe1671Brian Osman    // We *always* flush, so ignore that parameter
19886be35238855dbbc7575e78d6723936293a4b38e6Greg Daniel    this->submitCommandBuffer(kSkip_SyncQueue, vkSem->getResource());
19896be35238855dbbc7575e78d6723936293a4b38e6Greg Daniel}
19906be35238855dbbc7575e78d6723936293a4b38e6Greg Daniel
19916be35238855dbbc7575e78d6723936293a4b38e6Greg Danielvoid GrVkGpu::waitSemaphore(sk_sp<GrSemaphore> semaphore) {
19926be35238855dbbc7575e78d6723936293a4b38e6Greg Daniel    GrVkSemaphore* vkSem = static_cast<GrVkSemaphore*>(semaphore.get());
19936be35238855dbbc7575e78d6723936293a4b38e6Greg Daniel
19946be35238855dbbc7575e78d6723936293a4b38e6Greg Daniel    const GrVkSemaphore::Resource* resource = vkSem->getResource();
19956be35238855dbbc7575e78d6723936293a4b38e6Greg Daniel    resource->ref();
19966be35238855dbbc7575e78d6723936293a4b38e6Greg Daniel    fSemaphoresToWaitOn.push_back(resource);
199784741b308496409f4ff662658167221fc6801bbejvanverth}
199813dddce65fd87a8175a209a49f35615735a2886aBrian Osman
199913dddce65fd87a8175a209a49f35615735a2886aBrian Osmansk_sp<GrSemaphore> GrVkGpu::prepareTextureForCrossContextUsage(GrTexture* texture) {
200013dddce65fd87a8175a209a49f35615735a2886aBrian Osman    SkASSERT(texture);
200113dddce65fd87a8175a209a49f35615735a2886aBrian Osman    GrVkTexture* vkTexture = static_cast<GrVkTexture*>(texture);
200213dddce65fd87a8175a209a49f35615735a2886aBrian Osman    vkTexture->setImageLayout(this,
200313dddce65fd87a8175a209a49f35615735a2886aBrian Osman                              VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
200413dddce65fd87a8175a209a49f35615735a2886aBrian Osman                              VK_ACCESS_SHADER_READ_BIT,
200513dddce65fd87a8175a209a49f35615735a2886aBrian Osman                              VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
200613dddce65fd87a8175a209a49f35615735a2886aBrian Osman                              false);
200713dddce65fd87a8175a209a49f35615735a2886aBrian Osman    this->submitCommandBuffer(kSkip_SyncQueue);
200813dddce65fd87a8175a209a49f35615735a2886aBrian Osman
200913dddce65fd87a8175a209a49f35615735a2886aBrian Osman    // The image layout change serves as a barrier, so no semaphore is needed
201013dddce65fd87a8175a209a49f35615735a2886aBrian Osman    return nullptr;
201113dddce65fd87a8175a209a49f35615735a2886aBrian Osman}
2012