GrVkGpu.cpp revision c293a29bc2fced15ac44a66efa813d42cb3f2e0b
1164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel/*
2164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel * Copyright 2015 Google Inc.
3164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel *
4164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel * Use of this source code is governed by a BSD-style license that can be
5164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel * found in the LICENSE file.
6164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel */
7164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
8164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkGpu.h"
9164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
10164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrContextOptions.h"
11164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrGeometryProcessor.h"
12164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrGpuResourceCacheAccess.h"
130e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel#include "GrMesh.h"
14164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrPipeline.h"
15164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrRenderTargetPriv.h"
16164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrSurfacePriv.h"
17164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrTexturePriv.h"
18164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
19164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkCommandBuffer.h"
20066df7ca911b65d416783f3bec6f4f1662948ad5egdaniel#include "GrVkGpuCommandBuffer.h"
21164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkImage.h"
22164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkIndexBuffer.h"
23164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkMemory.h"
24164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkPipeline.h"
2522281c13a13c4b4e275516e9fe02185a53a7e5aaegdaniel#include "GrVkPipelineState.h"
26164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkRenderPass.h"
27164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkResourceProvider.h"
28164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkTexture.h"
29164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkTextureRenderTarget.h"
30164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkTransferBuffer.h"
31164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkVertexBuffer.h"
32164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
33164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "SkConfig8888.h"
34900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth#include "SkMipMap.h"
35164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
36164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "vk/GrVkInterface.h"
37fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth#include "vk/GrVkTypes.h"
38164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
39b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#if USE_SKSL
40b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "SkSLCompiler.h"
41b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#endif
42b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
43164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#define VK_CALL(X) GR_VK_CALL(this->vkInterface(), X)
44164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#define VK_CALL_RET(RET, X) GR_VK_CALL_RET(this->vkInterface(), RET, X)
45164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#define VK_CALL_ERRCHECK(X) GR_VK_CALL_ERRCHECK(this->vkInterface(), X)
46164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
47735109c24892a95290974c9665527b57b01e5440egdaniel#ifdef SK_ENABLE_VK_LAYERS
48d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverthVKAPI_ATTR VkBool32 VKAPI_CALL DebugReportCallback(
49d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    VkDebugReportFlagsEXT       flags,
50d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    VkDebugReportObjectTypeEXT  objectType,
51d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    uint64_t                    object,
52d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    size_t                      location,
53d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    int32_t                     messageCode,
54d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    const char*                 pLayerPrefix,
55d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    const char*                 pMessage,
56d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    void*                       pUserData) {
57d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    if (flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
58d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        SkDebugf("Vulkan error [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
59ce3fe23c04e93d2aa8d4c09c0c99088207edd509Jim Van Verth        return VK_TRUE; // skip further layers
60d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    } else if (flags & VK_DEBUG_REPORT_WARNING_BIT_EXT) {
61d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        SkDebugf("Vulkan warning [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
62d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    } else if (flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) {
63d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        SkDebugf("Vulkan perf warning [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
64d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    } else {
65d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        SkDebugf("Vulkan info/debug [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
66d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    }
67d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    return VK_FALSE;
68d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth}
69d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth#endif
70d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth
71633b35657c964c32e7010b14bb2d396b4a764c52jvanverthGrGpu* GrVkGpu::Create(GrBackendContext backendContext, const GrContextOptions& options,
72633b35657c964c32e7010b14bb2d396b4a764c52jvanverth                       GrContext* context) {
73dc0fcd41e75682a8bfd5e285d684461475226330bsalomon    const GrVkBackendContext* vkBackendContext =
74dc0fcd41e75682a8bfd5e285d684461475226330bsalomon        reinterpret_cast<const GrVkBackendContext*>(backendContext);
75633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    if (!vkBackendContext) {
76dc0fcd41e75682a8bfd5e285d684461475226330bsalomon        vkBackendContext = GrVkBackendContext::Create();
77633b35657c964c32e7010b14bb2d396b4a764c52jvanverth        if (!vkBackendContext) {
78633b35657c964c32e7010b14bb2d396b4a764c52jvanverth            return nullptr;
79164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
80633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    } else {
81633b35657c964c32e7010b14bb2d396b4a764c52jvanverth        vkBackendContext->ref();
82164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
83164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
84fe2965af79d70c7f3fe30204846e430c3db56a4eGreg Daniel    if (!vkBackendContext->fInterface->validate(vkBackendContext->fExtensions)) {
85fe2965af79d70c7f3fe30204846e430c3db56a4eGreg Daniel        return nullptr;
86fe2965af79d70c7f3fe30204846e430c3db56a4eGreg Daniel    }
87fe2965af79d70c7f3fe30204846e430c3db56a4eGreg Daniel
88633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    return new GrVkGpu(context, options, vkBackendContext);
89164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
90164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
91164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
92164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
939d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanaryGrVkGpu::GrVkGpu(GrContext* context, const GrContextOptions& options,
94633b35657c964c32e7010b14bb2d396b4a764c52jvanverth                 const GrVkBackendContext* backendCtx)
95164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    : INHERITED(context)
96633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    , fDevice(backendCtx->fDevice)
97633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    , fQueue(backendCtx->fQueue)
98633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    , fResourceProvider(this) {
99633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    fBackendContext.reset(backendCtx);
100164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
101735109c24892a95290974c9665527b57b01e5440egdaniel#ifdef SK_ENABLE_VK_LAYERS
102419ca64f0f800dc098369b5aa5a604acd017b240brianosman    fCallback = VK_NULL_HANDLE;
103fd7bd45ac2178ce6b4a390f517f605750aaef6c8jvanverth    if (backendCtx->fExtensions & kEXT_debug_report_GrVkExtensionFlag) {
104fd7bd45ac2178ce6b4a390f517f605750aaef6c8jvanverth        // Setup callback creation information
105d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        VkDebugReportCallbackCreateInfoEXT callbackCreateInfo;
106d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        callbackCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
107d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        callbackCreateInfo.pNext = nullptr;
108d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        callbackCreateInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT |
109ef0c10cffefef90646ff2e238d7c2d82247a0370egdaniel                                   VK_DEBUG_REPORT_WARNING_BIT_EXT |
110d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth                                   //VK_DEBUG_REPORT_INFORMATION_BIT_EXT |
111d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth                                   //VK_DEBUG_REPORT_DEBUG_BIT_EXT |
112b4aa36211ca66ef127ac2954108742af1ead5082egdaniel                                   VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
113d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        callbackCreateInfo.pfnCallback = &DebugReportCallback;
114d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        callbackCreateInfo.pUserData = nullptr;
115d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth
116fd7bd45ac2178ce6b4a390f517f605750aaef6c8jvanverth        // Register the callback
117a00980e58037fa36d066be80d7fcc0f73b2dfd40jvanverth        GR_VK_CALL_ERRCHECK(this->vkInterface(), CreateDebugReportCallbackEXT(
118a00980e58037fa36d066be80d7fcc0f73b2dfd40jvanverth                            backendCtx->fInstance, &callbackCreateInfo, nullptr, &fCallback));
119d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    }
120d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth#endif
121633b35657c964c32e7010b14bb2d396b4a764c52jvanverth
122b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#if USE_SKSL
123b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    fCompiler = new SkSL::Compiler();
124b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#else
125633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    fCompiler = shaderc_compiler_initialize();
126b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#endif
127633b35657c964c32e7010b14bb2d396b4a764c52jvanverth
128fd7bd45ac2178ce6b4a390f517f605750aaef6c8jvanverth    fVkCaps.reset(new GrVkCaps(options, this->vkInterface(), backendCtx->fPhysicalDevice,
129c5ec1408298510410270ea67e895570ccfa76e54egdaniel                               backendCtx->fFeatures, backendCtx->fExtensions));
130633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    fCaps.reset(SkRef(fVkCaps.get()));
131633b35657c964c32e7010b14bb2d396b4a764c52jvanverth
132633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    VK_CALL(GetPhysicalDeviceMemoryProperties(backendCtx->fPhysicalDevice, &fPhysDevMemProps));
133633b35657c964c32e7010b14bb2d396b4a764c52jvanverth
134633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    const VkCommandPoolCreateInfo cmdPoolInfo = {
1357ec92413307c9da43c013d1e4e15716a44059810jvanverth        VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // sType
1367ec92413307c9da43c013d1e4e15716a44059810jvanverth        nullptr,                                         // pNext
1377ec92413307c9da43c013d1e4e15716a44059810jvanverth        VK_COMMAND_POOL_CREATE_TRANSIENT_BIT |
1387ec92413307c9da43c013d1e4e15716a44059810jvanverth        VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // CmdPoolCreateFlags
1397ec92413307c9da43c013d1e4e15716a44059810jvanverth        backendCtx->fGraphicsQueueIndex,                 // queueFamilyIndex
140633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    };
1419d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary    GR_VK_CALL_ERRCHECK(this->vkInterface(), CreateCommandPool(fDevice, &cmdPoolInfo, nullptr,
142633b35657c964c32e7010b14bb2d396b4a764c52jvanverth                                                               &fCmdPool));
143633b35657c964c32e7010b14bb2d396b4a764c52jvanverth
144633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    // must call this after creating the CommandPool
145633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    fResourceProvider.init();
1467ec92413307c9da43c013d1e4e15716a44059810jvanverth    fCurrentCmdBuffer = fResourceProvider.findOrCreatePrimaryCommandBuffer();
147633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    SkASSERT(fCurrentCmdBuffer);
148633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    fCurrentCmdBuffer->begin(this);
1496b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth
1506b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    // set up our heaps
1516b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    fHeaps[kLinearImage_Heap].reset(new GrVkHeap(this, GrVkHeap::kSubAlloc_Strategy, 16*1024*1024));
15205dceabf3422b785b52439378aa5527c42c6ca18egdaniel    // We want the OptimalImage_Heap to use a SubAlloc_strategy but it occasionally causes the
15305dceabf3422b785b52439378aa5527c42c6ca18egdaniel    // device to run out of memory. Most likely this is caused by fragmentation in the device heap
15405dceabf3422b785b52439378aa5527c42c6ca18egdaniel    // and we can't allocate more. Until we get a fix moving this to SingleAlloc.
15505dceabf3422b785b52439378aa5527c42c6ca18egdaniel    fHeaps[kOptimalImage_Heap].reset(new GrVkHeap(this, GrVkHeap::kSingleAlloc_Strategy, 64*1024*1024));
1566b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    fHeaps[kSmallOptimalImage_Heap].reset(new GrVkHeap(this, GrVkHeap::kSubAlloc_Strategy, 2*1024*1024));
1576b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    fHeaps[kVertexBuffer_Heap].reset(new GrVkHeap(this, GrVkHeap::kSingleAlloc_Strategy, 0));
1586b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    fHeaps[kIndexBuffer_Heap].reset(new GrVkHeap(this, GrVkHeap::kSingleAlloc_Strategy, 0));
1594c6e47a8a827077e36fa5feb4ab5ac7435d8276bjvanverth    fHeaps[kUniformBuffer_Heap].reset(new GrVkHeap(this, GrVkHeap::kSubAlloc_Strategy, 256*1024));
1606b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    fHeaps[kCopyReadBuffer_Heap].reset(new GrVkHeap(this, GrVkHeap::kSingleAlloc_Strategy, 0));
1616b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    fHeaps[kCopyWriteBuffer_Heap].reset(new GrVkHeap(this, GrVkHeap::kSubAlloc_Strategy, 16*1024*1024));
162164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
163164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
164164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielGrVkGpu::~GrVkGpu() {
165164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->end(this);
166164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->unref(this);
167164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
168164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // wait for all commands to finish
169ddf9835e9cdf512b1d5172d014f00ceb6dacd039jvanverth    fResourceProvider.checkCommandBuffers();
17009557d7c0409ca1194d06d9dd9664fb5530c3f46Jim Van Verth    VkResult res = VK_CALL(QueueWaitIdle(fQueue));
171f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel
172f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel    // On windows, sometimes calls to QueueWaitIdle return before actually signalling the fences
173f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel    // on the command buffers even though they have completed. This causes an assert to fire when
174f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel    // destroying the command buffers. Currently this ony seems to happen on windows, so we add a
17509557d7c0409ca1194d06d9dd9664fb5530c3f46Jim Van Verth    // sleep to make sure the fence signals.
176f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel#ifdef SK_DEBUG
177f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel#if defined(SK_BUILD_FOR_WIN)
178f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel    Sleep(10); // In milliseconds
179f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel#else
180f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel    // Uncomment if above bug happens on non windows build.
181f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel    // sleep(1);        // In seconds
182f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel#endif
183f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel#endif
184f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel
185be9d82161d8347929a66ef942dabbe56abf592a4egdaniel#ifdef SK_DEBUG
1868a8668b4721097de657ad8b30d45f60f62433c6fGreg Daniel    SkASSERT(VK_SUCCESS == res || VK_ERROR_DEVICE_LOST == res);
187be9d82161d8347929a66ef942dabbe56abf592a4egdaniel#endif
1889d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
189bc9b2963bf9e39c47ae5c3ab94b8503b476f4f0eegdaniel    fCopyManager.destroyResources(this);
190bc9b2963bf9e39c47ae5c3ab94b8503b476f4f0eegdaniel
19109557d7c0409ca1194d06d9dd9664fb5530c3f46Jim Van Verth    // must call this just before we destroy the command pool and VkDevice
19209557d7c0409ca1194d06d9dd9664fb5530c3f46Jim Van Verth    fResourceProvider.destroyResources(VK_ERROR_DEVICE_LOST == res);
193164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
194633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    VK_CALL(DestroyCommandPool(fDevice, fCmdPool, nullptr));
195633b35657c964c32e7010b14bb2d396b4a764c52jvanverth
196b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#if USE_SKSL
197b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    delete fCompiler;
198b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#else
199633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    shaderc_compiler_release(fCompiler);
200b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#endif
201633b35657c964c32e7010b14bb2d396b4a764c52jvanverth
202735109c24892a95290974c9665527b57b01e5440egdaniel#ifdef SK_ENABLE_VK_LAYERS
203a00980e58037fa36d066be80d7fcc0f73b2dfd40jvanverth    if (fCallback) {
204a00980e58037fa36d066be80d7fcc0f73b2dfd40jvanverth        VK_CALL(DestroyDebugReportCallbackEXT(fBackendContext->fInstance, fCallback, nullptr));
205419ca64f0f800dc098369b5aa5a604acd017b240brianosman        fCallback = VK_NULL_HANDLE;
206a00980e58037fa36d066be80d7fcc0f73b2dfd40jvanverth    }
207d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth#endif
208164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
209164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
210164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel///////////////////////////////////////////////////////////////////////////////
211164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
2129cb6340a62a5d748e4189d50e51fa527c8c80c03egdanielGrGpuCommandBuffer* GrVkGpu::createCommandBuffer(
2139cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel            const GrGpuCommandBuffer::LoadAndStoreInfo& colorInfo,
2149cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel            const GrGpuCommandBuffer::LoadAndStoreInfo& stencilInfo) {
215c293a29bc2fced15ac44a66efa813d42cb3f2e0bBrian Salomon    return new GrVkGpuCommandBuffer(this, colorInfo, stencilInfo);
216066df7ca911b65d416783f3bec6f4f1662948ad5egdaniel}
217066df7ca911b65d416783f3bec6f4f1662948ad5egdaniel
218164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::submitCommandBuffer(SyncQueue sync) {
219164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(fCurrentCmdBuffer);
220164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->end(this);
221164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
222164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->submitToQueue(this, fQueue, sync);
223164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fResourceProvider.checkCommandBuffers();
224164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
225164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Release old command buffer and create a new one
226164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->unref(this);
2277ec92413307c9da43c013d1e4e15716a44059810jvanverth    fCurrentCmdBuffer = fResourceProvider.findOrCreatePrimaryCommandBuffer();
228164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(fCurrentCmdBuffer);
229164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
230164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->begin(this);
231164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
232164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
233164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel///////////////////////////////////////////////////////////////////////////////
2341bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdaltonGrBuffer* GrVkGpu::onCreateBuffer(size_t size, GrBufferType type, GrAccessPattern accessPattern,
2351bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton                                  const void* data) {
2361bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton    GrBuffer* buff;
237397536cabe12a9936659870dd220c869789424bacdalton    switch (type) {
238397536cabe12a9936659870dd220c869789424bacdalton        case kVertex_GrBufferType:
239397536cabe12a9936659870dd220c869789424bacdalton            SkASSERT(kDynamic_GrAccessPattern == accessPattern ||
240397536cabe12a9936659870dd220c869789424bacdalton                     kStatic_GrAccessPattern == accessPattern);
2411bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton            buff = GrVkVertexBuffer::Create(this, size, kDynamic_GrAccessPattern == accessPattern);
242e05bbbba79c569c1d32fa6475feecd1477fd3beeegdaniel            break;
243397536cabe12a9936659870dd220c869789424bacdalton        case kIndex_GrBufferType:
244397536cabe12a9936659870dd220c869789424bacdalton            SkASSERT(kDynamic_GrAccessPattern == accessPattern ||
245397536cabe12a9936659870dd220c869789424bacdalton                     kStatic_GrAccessPattern == accessPattern);
2461bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton            buff = GrVkIndexBuffer::Create(this, size, kDynamic_GrAccessPattern == accessPattern);
247e05bbbba79c569c1d32fa6475feecd1477fd3beeegdaniel            break;
248397536cabe12a9936659870dd220c869789424bacdalton        case kXferCpuToGpu_GrBufferType:
249c3d706f7ce87cdd94158d2266ab2fe2f18f5020ajvanverth            SkASSERT(kStream_GrAccessPattern == accessPattern);
2501bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton            buff = GrVkTransferBuffer::Create(this, size, GrVkBuffer::kCopyRead_Type);
251e05bbbba79c569c1d32fa6475feecd1477fd3beeegdaniel            break;
252397536cabe12a9936659870dd220c869789424bacdalton        case kXferGpuToCpu_GrBufferType:
253c3d706f7ce87cdd94158d2266ab2fe2f18f5020ajvanverth            SkASSERT(kStream_GrAccessPattern == accessPattern);
2541bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton            buff = GrVkTransferBuffer::Create(this, size, GrVkBuffer::kCopyWrite_Type);
255e05bbbba79c569c1d32fa6475feecd1477fd3beeegdaniel            break;
256397536cabe12a9936659870dd220c869789424bacdalton        default:
257397536cabe12a9936659870dd220c869789424bacdalton            SkFAIL("Unknown buffer type.");
258397536cabe12a9936659870dd220c869789424bacdalton            return nullptr;
259397536cabe12a9936659870dd220c869789424bacdalton    }
2601bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton    if (data && buff) {
2611bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton        buff->updateData(data, size);
2621bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton    }
2631bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton    return buff;
264164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
265164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
266164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
267164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::onGetWritePixelsInfo(GrSurface* dstSurface, int width, int height,
268164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                   GrPixelConfig srcConfig, DrawPreference* drawPreference,
269164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                   WritePixelTempDrawInfo* tempDrawInfo) {
270164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (kIndex_8_GrPixelConfig == srcConfig || GrPixelConfigIsCompressed(dstSurface->config())) {
271164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
272164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
273164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
2744583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    GrRenderTarget* renderTarget = dstSurface->asRenderTarget();
2754583ec51d9ddc830eeb854db068235be96ce59c4egdaniel
2764583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    // Start off assuming no swizzling
2774583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    tempDrawInfo->fSwizzle = GrSwizzle::RGBA();
2784583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    tempDrawInfo->fWriteConfig = srcConfig;
2794583ec51d9ddc830eeb854db068235be96ce59c4egdaniel
2804583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    // These settings we will always want if a temp draw is performed. Initially set the config
2814583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    // to srcConfig, though that may be modified if we decide to do a R/B swap
2824583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    tempDrawInfo->fTempSurfaceDesc.fFlags = kNone_GrSurfaceFlags;
2834583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    tempDrawInfo->fTempSurfaceDesc.fConfig = srcConfig;
2844583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    tempDrawInfo->fTempSurfaceDesc.fWidth = width;
2854583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    tempDrawInfo->fTempSurfaceDesc.fHeight = height;
2864583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    tempDrawInfo->fTempSurfaceDesc.fSampleCnt = 0;
2874583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    tempDrawInfo->fTempSurfaceDesc.fOrigin = kTopLeft_GrSurfaceOrigin;
2884583ec51d9ddc830eeb854db068235be96ce59c4egdaniel
289d66110f5972169dbcda8932c3a9a001adff23df4egdaniel    if (dstSurface->config() == srcConfig) {
290d66110f5972169dbcda8932c3a9a001adff23df4egdaniel        return true;
291d66110f5972169dbcda8932c3a9a001adff23df4egdaniel    }
292d66110f5972169dbcda8932c3a9a001adff23df4egdaniel
29366933552f1723c4a2b248711ab3d43921401e8e6egdaniel    if (renderTarget && this->vkCaps().isConfigRenderable(renderTarget->config(),
29466933552f1723c4a2b248711ab3d43921401e8e6egdaniel                                                          renderTarget->numColorSamples() > 1)) {
2954583ec51d9ddc830eeb854db068235be96ce59c4egdaniel        ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
2964583ec51d9ddc830eeb854db068235be96ce59c4egdaniel
2974583ec51d9ddc830eeb854db068235be96ce59c4egdaniel        bool configsAreRBSwaps = GrPixelConfigSwapRAndB(srcConfig) == dstSurface->config();
2984583ec51d9ddc830eeb854db068235be96ce59c4egdaniel
2994583ec51d9ddc830eeb854db068235be96ce59c4egdaniel        if (!this->vkCaps().isConfigTexturable(srcConfig) && configsAreRBSwaps) {
3004583ec51d9ddc830eeb854db068235be96ce59c4egdaniel            if (!this->vkCaps().isConfigTexturable(dstSurface->config())) {
3014583ec51d9ddc830eeb854db068235be96ce59c4egdaniel                return false;
3024583ec51d9ddc830eeb854db068235be96ce59c4egdaniel            }
3034583ec51d9ddc830eeb854db068235be96ce59c4egdaniel            tempDrawInfo->fTempSurfaceDesc.fConfig = dstSurface->config();
3044583ec51d9ddc830eeb854db068235be96ce59c4egdaniel            tempDrawInfo->fSwizzle = GrSwizzle::BGRA();
3054583ec51d9ddc830eeb854db068235be96ce59c4egdaniel            tempDrawInfo->fWriteConfig = dstSurface->config();
3064583ec51d9ddc830eeb854db068235be96ce59c4egdaniel        }
3074583ec51d9ddc830eeb854db068235be96ce59c4egdaniel        return true;
308164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
309164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
3104583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    return false;
311164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
312164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
313164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::onWritePixels(GrSurface* surface,
314164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                            int left, int top, int width, int height,
315a1e6b3be8124cef85f2e39e3cb85000ad9526d48bsalomon                            GrPixelConfig config,
316a1e6b3be8124cef85f2e39e3cb85000ad9526d48bsalomon                            const SkTArray<GrMipLevel>& texels) {
317164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkTexture* vkTex = static_cast<GrVkTexture*>(surface->asTexture());
318164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!vkTex) {
319164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
320164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
321164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
322900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // Make sure we have at least the base level
32303509eafa3e25819ff69f4d4f339d46264820c38jvanverth    if (texels.empty() || !texels.begin()->fPixels) {
32403509eafa3e25819ff69f4d4f339d46264820c38jvanverth        return false;
32503509eafa3e25819ff69f4d4f339d46264820c38jvanverth    }
326a1e6b3be8124cef85f2e39e3cb85000ad9526d48bsalomon
327164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // We assume Vulkan doesn't do sRGB <-> linear conversions when reading and writing pixels.
328164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (GrPixelConfigIsSRGB(surface->config()) != GrPixelConfigIsSRGB(config)) {
329164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
330164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
331164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
332164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    bool success = false;
333164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (GrPixelConfigIsCompressed(vkTex->desc().fConfig)) {
334164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // We check that config == desc.fConfig in GrGpu::getWritePixelsInfo()
335164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        SkASSERT(config == vkTex->desc().fConfig);
336164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // TODO: add compressed texture support
337164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // delete the following two lines and uncomment the two after that when ready
338164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        vkTex->unref();
339164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
340164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        //success = this->uploadCompressedTexData(vkTex->desc(), buffer, false, left, top, width,
341164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        //                                       height);
342164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    } else {
343164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        bool linearTiling = vkTex->isLinearTiled();
344900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        if (linearTiling) {
345900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            if (texels.count() > 1) {
346900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                SkDebugf("Can't upload mipmap data to linear tiled texture");
347900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                return false;
348900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            }
349900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            if (VK_IMAGE_LAYOUT_PREINITIALIZED != vkTex->currentLayout()) {
350900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                // Need to change the layout to general in order to perform a host write
351900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                vkTex->setImageLayout(this,
352900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                      VK_IMAGE_LAYOUT_GENERAL,
35350c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                                      VK_ACCESS_HOST_WRITE_BIT,
35450c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                                      VK_PIPELINE_STAGE_HOST_BIT,
355900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                      false);
356bdf8811b3126ab08ccff08b5e647b80cae5bd087egdaniel                this->submitCommandBuffer(kForce_SyncQueue);
357900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            }
358900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            success = this->uploadTexDataLinear(vkTex, left, top, width, height, config,
359900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                                texels.begin()->fPixels, texels.begin()->fRowBytes);
360900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        } else {
361c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth            int newMipLevels = texels.count();
36282c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth            int currentMipLevels = vkTex->texturePriv().maxMipMapLevel() + 1;
36382c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth            if (newMipLevels != currentMipLevels) {
364c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth                if (!vkTex->reallocForMipmap(this, newMipLevels)) {
365900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                    return false;
366900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                }
367900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            }
368900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            success = this->uploadTexDataOptimal(vkTex, left, top, width, height, config, texels);
369164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
370164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
3714583ec51d9ddc830eeb854db068235be96ce59c4egdaniel
372900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    return success;
373164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
374164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
3754bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdanielvoid GrVkGpu::resolveImage(GrVkRenderTarget* dst, GrVkRenderTarget* src, const SkIRect& srcRect,
3764bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel                           const SkIPoint& dstPoint) {
3774bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    SkASSERT(dst);
3784bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    SkASSERT(src && src->numColorSamples() > 1 && src->msaaImage());
3794bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel
380fd016d7a69f0415f2497d25ec3a7b71de1545826egdaniel    if (this->vkCaps().mustSubmitCommandsBeforeCopyOp()) {
381fd016d7a69f0415f2497d25ec3a7b71de1545826egdaniel        this->submitCommandBuffer(GrVkGpu::kSkip_SyncQueue);
382fd016d7a69f0415f2497d25ec3a7b71de1545826egdaniel    }
383fd016d7a69f0415f2497d25ec3a7b71de1545826egdaniel
3844bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    // Flip rect if necessary
3854bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    SkIRect srcVkRect = srcRect;
3864bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    int32_t dstY = dstPoint.fY;
3874bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel
3884bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    if (kBottomLeft_GrSurfaceOrigin == src->origin()) {
3894bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        SkASSERT(kBottomLeft_GrSurfaceOrigin == dst->origin());
3904bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        srcVkRect.fTop = src->height() - srcRect.fBottom;
3914bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        srcVkRect.fBottom = src->height() - srcRect.fTop;
3924bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        dstY = dst->height() - dstPoint.fY - srcVkRect.height();
3934bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    }
3944bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel
3954bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    VkImageResolve resolveInfo;
3964bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    resolveInfo.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
3974bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    resolveInfo.srcOffset = { srcVkRect.fLeft, srcVkRect.fTop, 0 };
3984bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    resolveInfo.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
3994bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    resolveInfo.dstOffset = { dstPoint.fX, dstY, 0 };
4004bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    resolveInfo.extent = { (uint32_t)srcVkRect.width(), (uint32_t)srcVkRect.height(), 1 };
4014bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel
4024bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    dst->setImageLayout(this,
4034bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel                        VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
4044bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel                        VK_ACCESS_TRANSFER_WRITE_BIT,
4054bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel                        VK_PIPELINE_STAGE_TRANSFER_BIT,
4064bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel                        false);
4074bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel
4084bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    src->msaaImage()->setImageLayout(this,
4094bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel                                     VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
4104bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel                                     VK_ACCESS_TRANSFER_READ_BIT,
4114bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel                                     VK_PIPELINE_STAGE_TRANSFER_BIT,
4124bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel                                     false);
4134bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel
4144bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    fCurrentCmdBuffer->resolveImage(this, *src->msaaImage(), *dst, 1, &resolveInfo);
4154bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel}
4164bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel
41752ad25151a1c7d1ac3872971f56adf15200c437eegdanielvoid GrVkGpu::onResolveRenderTarget(GrRenderTarget* target) {
41866933552f1723c4a2b248711ab3d43921401e8e6egdaniel    if (target->needsResolve()) {
41966933552f1723c4a2b248711ab3d43921401e8e6egdaniel        SkASSERT(target->numColorSamples() > 1);
42052ad25151a1c7d1ac3872971f56adf15200c437eegdaniel        GrVkRenderTarget* rt = static_cast<GrVkRenderTarget*>(target);
42152ad25151a1c7d1ac3872971f56adf15200c437eegdaniel        SkASSERT(rt->msaaImage());
4224bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel
4234bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        const SkIRect& srcRect = rt->getResolveRect();
42452ad25151a1c7d1ac3872971f56adf15200c437eegdaniel
4254bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        this->resolveImage(rt, rt, srcRect, SkIPoint::Make(srcRect.fLeft, srcRect.fTop));
42652ad25151a1c7d1ac3872971f56adf15200c437eegdaniel
42752ad25151a1c7d1ac3872971f56adf15200c437eegdaniel        rt->flagAsResolved();
42852ad25151a1c7d1ac3872971f56adf15200c437eegdaniel    }
42952ad25151a1c7d1ac3872971f56adf15200c437eegdaniel}
43052ad25151a1c7d1ac3872971f56adf15200c437eegdaniel
431900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverthbool GrVkGpu::uploadTexDataLinear(GrVkTexture* tex,
432900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                  int left, int top, int width, int height,
433900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                  GrPixelConfig dataConfig,
434900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                  const void* data,
435900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                  size_t rowBytes) {
436164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(data);
437900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    SkASSERT(tex->isLinearTiled());
438164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
439164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // If we're uploading compressed data then we should be using uploadCompressedTexData
440164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(!GrPixelConfigIsCompressed(dataConfig));
441164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
442164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    size_t bpp = GrBytesPerPixel(dataConfig);
443164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
444164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    const GrSurfaceDesc& desc = tex->desc();
445164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
446164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!GrSurfacePriv::AdjustWritePixelParams(desc.fWidth, desc.fHeight, bpp, &left, &top,
447164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                               &width, &height, &data, &rowBytes)) {
448164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
449164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
450164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    size_t trimRowBytes = width * bpp;
451164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
452900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    SkASSERT(VK_IMAGE_LAYOUT_PREINITIALIZED == tex->currentLayout() ||
453900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth             VK_IMAGE_LAYOUT_GENERAL == tex->currentLayout());
454900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    const VkImageSubresource subres = {
455900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        VK_IMAGE_ASPECT_COLOR_BIT,
456900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        0,  // mipLevel
457900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        0,  // arraySlice
458900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    };
459900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    VkSubresourceLayout layout;
460900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    VkResult err;
461900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
462900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    const GrVkInterface* interface = this->vkInterface();
463900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
464900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    GR_VK_CALL(interface, GetImageSubresourceLayout(fDevice,
465b2df0c2702329be6380a943d548e7377a51d8565egdaniel                                                    tex->image(),
466900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                                    &subres,
467900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                                    &layout));
468900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
469900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    int texTop = kBottomLeft_GrSurfaceOrigin == desc.fOrigin ? tex->height() - top - height : top;
4701e305ba0d6a4237020d36234e9e286d3b0489401jvanverth    const GrVkAlloc& alloc = tex->alloc();
4711e305ba0d6a4237020d36234e9e286d3b0489401jvanverth    VkDeviceSize offset = alloc.fOffset + texTop*layout.rowPitch + left*bpp;
472900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    VkDeviceSize size = height*layout.rowPitch;
473900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    void* mapPtr;
4741e305ba0d6a4237020d36234e9e286d3b0489401jvanverth    err = GR_VK_CALL(interface, MapMemory(fDevice, alloc.fMemory, offset, size, 0, &mapPtr));
475900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    if (err) {
476900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        return false;
477900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    }
478164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
479900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    if (kBottomLeft_GrSurfaceOrigin == desc.fOrigin) {
480900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        // copy into buffer by rows
481900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        const char* srcRow = reinterpret_cast<const char*>(data);
482900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        char* dstRow = reinterpret_cast<char*>(mapPtr)+(height - 1)*layout.rowPitch;
483900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        for (int y = 0; y < height; y++) {
484900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            memcpy(dstRow, srcRow, trimRowBytes);
485900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            srcRow += rowBytes;
486900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            dstRow -= layout.rowPitch;
487900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        }
488900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    } else {
489900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        // If there is no padding on the src (rowBytes) or dst (layout.rowPitch) we can memcpy
490900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        if (trimRowBytes == rowBytes && trimRowBytes == layout.rowPitch) {
491900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            memcpy(mapPtr, data, trimRowBytes * height);
492164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        } else {
49388e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel            SkRectMemcpy(mapPtr, static_cast<size_t>(layout.rowPitch), data, rowBytes, trimRowBytes,
49488e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel                         height);
495164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
496900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    }
497164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
4989d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth    GrVkMemory::FlushMappedAlloc(this, alloc);
4991e305ba0d6a4237020d36234e9e286d3b0489401jvanverth    GR_VK_CALL(interface, UnmapMemory(fDevice, alloc.fMemory));
500900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
501900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    return true;
502900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth}
503900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
504900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverthbool GrVkGpu::uploadTexDataOptimal(GrVkTexture* tex,
505a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth                                   int left, int top, int width, int height,
506a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth                                   GrPixelConfig dataConfig,
507a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth                                   const SkTArray<GrMipLevel>& texels) {
508900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    SkASSERT(!tex->isLinearTiled());
509900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // The assumption is either that we have no mipmaps, or that our rect is the entire texture
510900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    SkASSERT(1 == texels.count() ||
511900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth             (0 == left && 0 == top && width == tex->width() && height == tex->height()));
512900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
513900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // If we're uploading compressed data then we should be using uploadCompressedTexData
514900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    SkASSERT(!GrPixelConfigIsCompressed(dataConfig));
515900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
516900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    if (width == 0 || height == 0) {
517900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        return false;
518900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    }
519900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
520900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    const GrSurfaceDesc& desc = tex->desc();
521900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    SkASSERT(this->caps()->isConfigTexturable(desc.fConfig));
522900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    size_t bpp = GrBytesPerPixel(dataConfig);
523900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
524900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // texels is const.
525c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    // But we may need to adjust the fPixels ptr based on the copyRect, or fRowBytes.
526c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    // Because of this we need to make a non-const shallow copy of texels.
527c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    SkTArray<GrMipLevel> texelsShallowCopy(texels);
528900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
529c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    for (int currentMipLevel = texelsShallowCopy.count() - 1; currentMipLevel >= 0;
530c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth         currentMipLevel--) {
531c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        SkASSERT(texelsShallowCopy[currentMipLevel].fPixels);
532900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    }
533900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
534900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // Determine whether we need to flip when we copy into the buffer
535c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    bool flipY = (kBottomLeft_GrSurfaceOrigin == desc.fOrigin && !texelsShallowCopy.empty());
536900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
537c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    // adjust any params (left, top, currentWidth, currentHeight
538900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // find the combined size of all the mip levels and the relative offset of
539900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // each into the collective buffer
540c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    // Do the first level separately because we may need to adjust width and height
541c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    // (for the non-mipped case).
542c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    if (!GrSurfacePriv::AdjustWritePixelParams(desc.fWidth, desc.fHeight, bpp, &left, &top,
543c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth                                               &width,
544c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth                                               &height,
545c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth                                               &texelsShallowCopy[0].fPixels,
546c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth                                               &texelsShallowCopy[0].fRowBytes)) {
547c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        return false;
548c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    }
549c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    SkTArray<size_t> individualMipOffsets(texelsShallowCopy.count());
550c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    individualMipOffsets.push_back(0);
551c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    size_t combinedBufferSize = width * bpp * height;
552c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    int currentWidth = width;
553c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    int currentHeight = height;
554c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    for (int currentMipLevel = 1; currentMipLevel < texelsShallowCopy.count(); currentMipLevel++) {
555c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        currentWidth = SkTMax(1, currentWidth/2);
556c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        currentHeight = SkTMax(1, currentHeight/2);
557c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        if (!GrSurfacePriv::AdjustWritePixelParams(desc.fWidth, desc.fHeight, bpp, &left, &top,
558c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth                                                   &currentWidth,
559c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth                                                   &currentHeight,
560c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth                                                   &texelsShallowCopy[currentMipLevel].fPixels,
561c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth                                                   &texelsShallowCopy[currentMipLevel].fRowBytes)) {
562c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth            return false;
563c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        }
564900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        const size_t trimmedSize = currentWidth * bpp * currentHeight;
565900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        individualMipOffsets.push_back(combinedBufferSize);
566900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        combinedBufferSize += trimmedSize;
567900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    }
568900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
569900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // allocate buffer to hold our mip data
570900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    GrVkTransferBuffer* transferBuffer =
571900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                   GrVkTransferBuffer::Create(this, combinedBufferSize, GrVkBuffer::kCopyRead_Type);
572900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
573900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    char* buffer = (char*) transferBuffer->map();
574c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    SkTArray<VkBufferImageCopy> regions(texelsShallowCopy.count());
575900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
576c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    currentWidth = width;
577c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    currentHeight = height;
578c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    for (int currentMipLevel = 0; currentMipLevel < texelsShallowCopy.count(); currentMipLevel++) {
579900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        const size_t trimRowBytes = currentWidth * bpp;
580c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        const size_t rowBytes = texelsShallowCopy[currentMipLevel].fRowBytes;
581900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
582900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        // copy data into the buffer, skipping the trailing bytes
583900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        char* dst = buffer + individualMipOffsets[currentMipLevel];
584c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        const char* src = (const char*)texelsShallowCopy[currentMipLevel].fPixels;
585900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        if (flipY) {
586900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            src += (currentHeight - 1) * rowBytes;
587900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            for (int y = 0; y < currentHeight; y++) {
588900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                memcpy(dst, src, trimRowBytes);
589900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                src -= rowBytes;
590900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                dst += trimRowBytes;
591164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            }
592900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        } else if (trimRowBytes == rowBytes) {
593900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            memcpy(dst, src, trimRowBytes * currentHeight);
594164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        } else {
595900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            SkRectMemcpy(dst, trimRowBytes, src, rowBytes, trimRowBytes, currentHeight);
596164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
597164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
598900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        VkBufferImageCopy& region = regions.push_back();
599164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        memset(&region, 0, sizeof(VkBufferImageCopy));
600db37909347d034943bd6b0922710a94c6c6ea572jvanverth        region.bufferOffset = transferBuffer->offset() + individualMipOffsets[currentMipLevel];
601900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        region.bufferRowLength = currentWidth;
602900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        region.bufferImageHeight = currentHeight;
603cf942c4ef750712b624867cbb2217c14857db3c6bsalomon        region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, SkToU32(currentMipLevel), 0, 1 };
604c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        region.imageOffset = { left, flipY ? tex->height() - top - currentHeight : top, 0 };
605900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        region.imageExtent = { (uint32_t)currentWidth, (uint32_t)currentHeight, 1 };
6064583ec51d9ddc830eeb854db068235be96ce59c4egdaniel
607c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        currentWidth = SkTMax(1, currentWidth/2);
608c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        currentHeight = SkTMax(1, currentHeight/2);
609900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    }
610164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
6119d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth    // no need to flush non-coherent memory, unmap will do that for us
612900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    transferBuffer->unmap();
613164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
614900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // Change layout of our target so it can be copied to
615900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    tex->setImageLayout(this,
616900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                        VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
61750c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                        VK_ACCESS_TRANSFER_WRITE_BIT,
61850c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                        VK_PIPELINE_STAGE_TRANSFER_BIT,
619900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                        false);
620900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
621900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // Copy the buffer to the image
622900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    fCurrentCmdBuffer->copyBufferToImage(this,
623900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                         transferBuffer,
624900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                         tex,
625900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
626900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                         regions.count(),
627900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                         regions.begin());
628900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    transferBuffer->unref();
629164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
630164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return true;
631164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
632164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
633164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
6342e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunenGrTexture* GrVkGpu::onCreateTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted,
635a1e6b3be8124cef85f2e39e3cb85000ad9526d48bsalomon                                    const SkTArray<GrMipLevel>& texels) {
636164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag);
637164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
638164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkFormat pixelFormat;
639164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!GrPixelConfigToVkFormat(desc.fConfig, &pixelFormat)) {
640164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return nullptr;
641164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
642164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
643164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!fVkCaps->isConfigTexturable(desc.fConfig)) {
644164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return nullptr;
645164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
646164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
6470a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel    if (renderTarget && !fVkCaps->isConfigRenderable(desc.fConfig, false)) {
6480a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel        return nullptr;
6490a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel    }
6500a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel
651164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    bool linearTiling = false;
652164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (SkToBool(desc.fFlags & kZeroCopy_GrSurfaceFlag)) {
653900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        // we can't have a linear texture with a mipmap
654900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        if (texels.count() > 1) {
655900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            SkDebugf("Trying to create linear tiled texture with mipmap");
656900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            return nullptr;
657900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        }
658a95d46b4ac8e41c9beb2b750cd389b1c6ebaf0a7egdaniel        if (fVkCaps->isConfigTexturableLinearly(desc.fConfig) &&
659164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            (!renderTarget || fVkCaps->isConfigRenderableLinearly(desc.fConfig, false))) {
660164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            linearTiling = true;
661164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        } else {
662164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            return nullptr;
663164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
664164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
665164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
666164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT;
667164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (renderTarget) {
668164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        usageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
669164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
670164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
671164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // For now we will set the VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT and
672164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // VK_IMAGE_USAGE_TRANSFER_SOURCE_BIT on every texture since we do not know whether or not we
673164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // will be using this texture in some copy or not. Also this assumes, as is the current case,
67462340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    // that all render targets in vulkan are also textures. If we change this practice of setting
675164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // both bits, we must make sure to set the destination bit if we are uploading srcData to the
676164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // texture.
677164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    usageFlags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
678164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
679a1e6b3be8124cef85f2e39e3cb85000ad9526d48bsalomon    VkFlags memProps = (!texels.empty() && linearTiling) ? VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT :
680a1e6b3be8124cef85f2e39e3cb85000ad9526d48bsalomon                                                           VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
681164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
682164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // This ImageDesc refers to the texture that will be read by the client. Thus even if msaa is
68362340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    // requested, this ImageDesc describes the resolved texture. Therefore we always have samples set
684164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // to 1.
685c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    int mipLevels = texels.empty() ? 1 : texels.count();
686164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkImage::ImageDesc imageDesc;
687164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fImageType = VK_IMAGE_TYPE_2D;
688164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fFormat = pixelFormat;
689164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fWidth = desc.fWidth;
690164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fHeight = desc.fHeight;
691c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    imageDesc.fLevels = linearTiling ? 1 : mipLevels;
692164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fSamples = 1;
693164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fImageTiling = linearTiling ? VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL;
694164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fUsageFlags = usageFlags;
695164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fMemProps = memProps;
696164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
697164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkTexture* tex;
698164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (renderTarget) {
6992e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        tex = GrVkTextureRenderTarget::CreateNewTextureRenderTarget(this, budgeted, desc,
700164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                    imageDesc);
701164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    } else {
7022e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        tex = GrVkTexture::CreateNewTexture(this, budgeted, desc, imageDesc);
703164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
704164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
705164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!tex) {
706164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return nullptr;
707164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
708164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
709e699d0cd25fd059e3f0c4949e613e50c83a52179bsalomon    if (!texels.empty()) {
710e699d0cd25fd059e3f0c4949e613e50c83a52179bsalomon        SkASSERT(texels.begin()->fPixels);
711900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        bool success;
712900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        if (linearTiling) {
713900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            success = this->uploadTexDataLinear(tex, 0, 0, desc.fWidth, desc.fHeight, desc.fConfig,
714900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                                texels.begin()->fPixels, texels.begin()->fRowBytes);
715900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        } else {
716900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            success = this->uploadTexDataOptimal(tex, 0, 0, desc.fWidth, desc.fHeight, desc.fConfig,
717900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                                 texels);
718900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        }
719900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        if (!success) {
720164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            tex->unref();
721164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            return nullptr;
722164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
723164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
724164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
725164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return tex;
726164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
727164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
728164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
729164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
730db37909347d034943bd6b0922710a94c6c6ea572jvanverthbool GrVkGpu::updateBuffer(GrVkBuffer* buffer, const void* src,
731db37909347d034943bd6b0922710a94c6c6ea572jvanverth                           VkDeviceSize offset, VkDeviceSize size) {
732a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth
733a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth    // Update the buffer
734db37909347d034943bd6b0922710a94c6c6ea572jvanverth    fCurrentCmdBuffer->updateBuffer(this, buffer, offset, size, src);
735a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth
736a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth    return true;
737a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth}
738a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth
739a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth////////////////////////////////////////////////////////////////////////////////
740a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth
741164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielstatic GrSurfaceOrigin resolve_origin(GrSurfaceOrigin origin) {
742164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // By default, all textures in Vk use TopLeft
743164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (kDefault_GrSurfaceOrigin == origin) {
744164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return kTopLeft_GrSurfaceOrigin;
745164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    } else {
746164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return origin;
747164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
748164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
749164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
7506bd5284415bd983b0628c4941dff5def40018f5abungemansk_sp<GrTexture> GrVkGpu::onWrapBackendTexture(const GrBackendTextureDesc& desc,
7516bd5284415bd983b0628c4941dff5def40018f5abungeman                                               GrWrapOwnership ownership) {
752164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (0 == desc.fTextureHandle) {
753164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return nullptr;
754164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
755164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
756164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    int maxSize = this->caps()->maxTextureSize();
757164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (desc.fWidth > maxSize || desc.fHeight > maxSize) {
758164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return nullptr;
759164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
760164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
761b2df0c2702329be6380a943d548e7377a51d8565egdaniel    const GrVkImageInfo* info = reinterpret_cast<const GrVkImageInfo*>(desc.fTextureHandle);
7621e305ba0d6a4237020d36234e9e286d3b0489401jvanverth    if (VK_NULL_HANDLE == info->fImage || VK_NULL_HANDLE == info->fAlloc.fMemory) {
763fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        return nullptr;
764fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    }
765b2df0c2702329be6380a943d548e7377a51d8565egdaniel#ifdef SK_DEBUG
766b2df0c2702329be6380a943d548e7377a51d8565egdaniel    VkFormat format;
767b2df0c2702329be6380a943d548e7377a51d8565egdaniel    if (!GrPixelConfigToVkFormat(desc.fConfig, &format)) {
768b2df0c2702329be6380a943d548e7377a51d8565egdaniel        return nullptr;
769b2df0c2702329be6380a943d548e7377a51d8565egdaniel    }
770b2df0c2702329be6380a943d548e7377a51d8565egdaniel    SkASSERT(format == info->fFormat);
771b2df0c2702329be6380a943d548e7377a51d8565egdaniel#endif
772164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
773164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrSurfaceDesc surfDesc;
774164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // next line relies on GrBackendTextureDesc's flags matching GrTexture's
775164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    surfDesc.fFlags = (GrSurfaceFlags)desc.fFlags;
776164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    surfDesc.fWidth = desc.fWidth;
777164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    surfDesc.fHeight = desc.fHeight;
778164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    surfDesc.fConfig = desc.fConfig;
779164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    surfDesc.fSampleCnt = SkTMin(desc.fSampleCnt, this->caps()->maxSampleCount());
780164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrBackendTextureFlag);
781164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // In GL, Chrome assumes all textures are BottomLeft
782164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // In VK, we don't have this restriction
783164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    surfDesc.fOrigin = resolve_origin(desc.fOrigin);
784164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
7856bd5284415bd983b0628c4941dff5def40018f5abungeman    if (!renderTarget) {
7866bd5284415bd983b0628c4941dff5def40018f5abungeman        return GrVkTexture::MakeWrappedTexture(this, surfDesc, ownership, info);
787164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
7886bd5284415bd983b0628c4941dff5def40018f5abungeman    return GrVkTextureRenderTarget::MakeWrappedTextureRenderTarget(this, surfDesc, ownership, info);
789164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
790164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
7916bd5284415bd983b0628c4941dff5def40018f5abungemansk_sp<GrRenderTarget> GrVkGpu::onWrapBackendRenderTarget(const GrBackendRenderTargetDesc& wrapDesc,
7926bd5284415bd983b0628c4941dff5def40018f5abungeman                                                         GrWrapOwnership ownership) {
7939d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
794b2df0c2702329be6380a943d548e7377a51d8565egdaniel    const GrVkImageInfo* info =
795b2df0c2702329be6380a943d548e7377a51d8565egdaniel        reinterpret_cast<const GrVkImageInfo*>(wrapDesc.fRenderTargetHandle);
796fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    if (VK_NULL_HANDLE == info->fImage ||
7971e305ba0d6a4237020d36234e9e286d3b0489401jvanverth        (VK_NULL_HANDLE == info->fAlloc.fMemory && kAdopt_GrWrapOwnership == ownership)) {
798fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        return nullptr;
799fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    }
800164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
801164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrSurfaceDesc desc;
802164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    desc.fConfig = wrapDesc.fConfig;
8033667b4970d6972675be58a331be7c5ba02f3d39eRobert Phillips    desc.fFlags = kCheckAllocation_GrSurfaceFlag | kRenderTarget_GrSurfaceFlag;
804164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    desc.fWidth = wrapDesc.fWidth;
805164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    desc.fHeight = wrapDesc.fHeight;
806164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    desc.fSampleCnt = SkTMin(wrapDesc.fSampleCnt, this->caps()->maxSampleCount());
807164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
808164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    desc.fOrigin = resolve_origin(wrapDesc.fOrigin);
809164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
8106bd5284415bd983b0628c4941dff5def40018f5abungeman    sk_sp<GrVkRenderTarget> tgt = GrVkRenderTarget::MakeWrappedRenderTarget(this, desc,
8116bd5284415bd983b0628c4941dff5def40018f5abungeman                                                                            ownership, info);
812164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (tgt && wrapDesc.fStencilBits) {
8136bd5284415bd983b0628c4941dff5def40018f5abungeman        if (!createStencilAttachmentForRenderTarget(tgt.get(), desc.fWidth, desc.fHeight)) {
814164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            return nullptr;
815164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
816164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
817164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return tgt;
818164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
819164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
82050ead53ac97deb23310916e3736c3f5e2d8f7f4begdanielvoid GrVkGpu::generateMipmap(GrVkTexture* tex) {
821900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // don't do anything for linearly tiled textures (can't have mipmaps)
82262340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    if (tex->isLinearTiled()) {
823900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        SkDebugf("Trying to create mipmap for linear tiled texture");
82462340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth        return;
82562340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    }
82662340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth
82762340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    // determine if we can blit to and from this format
82862340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    const GrVkCaps& caps = this->vkCaps();
82962340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    if (!caps.configCanBeDstofBlit(tex->config(), false) ||
8302f5792a06c87efd5f9295b7b7bb714aac118bd2aegdaniel        !caps.configCanBeSrcofBlit(tex->config(), false) ||
8312f5792a06c87efd5f9295b7b7bb714aac118bd2aegdaniel        !caps.mipMapSupport()) {
83262340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth        return;
83362340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    }
83462340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth
835fd016d7a69f0415f2497d25ec3a7b71de1545826egdaniel    if (this->vkCaps().mustSubmitCommandsBeforeCopyOp()) {
836fd016d7a69f0415f2497d25ec3a7b71de1545826egdaniel        this->submitCommandBuffer(kSkip_SyncQueue);
837fd016d7a69f0415f2497d25ec3a7b71de1545826egdaniel    }
838fd016d7a69f0415f2497d25ec3a7b71de1545826egdaniel
83966933552f1723c4a2b248711ab3d43921401e8e6egdaniel    // We may need to resolve the texture first if it is also a render target
84066933552f1723c4a2b248711ab3d43921401e8e6egdaniel    GrVkRenderTarget* texRT = static_cast<GrVkRenderTarget*>(tex->asRenderTarget());
84166933552f1723c4a2b248711ab3d43921401e8e6egdaniel    if (texRT) {
84266933552f1723c4a2b248711ab3d43921401e8e6egdaniel        this->onResolveRenderTarget(texRT);
84366933552f1723c4a2b248711ab3d43921401e8e6egdaniel    }
84466933552f1723c4a2b248711ab3d43921401e8e6egdaniel
8457ac5da853457b032781cf865ba018de78508edb7egdaniel    int width = tex->width();
8467ac5da853457b032781cf865ba018de78508edb7egdaniel    int height = tex->height();
8477ac5da853457b032781cf865ba018de78508edb7egdaniel    VkImageBlit blitRegion;
8487ac5da853457b032781cf865ba018de78508edb7egdaniel    memset(&blitRegion, 0, sizeof(VkImageBlit));
84962340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth
85082c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth    // SkMipMap doesn't include the base level in the level count so we have to add 1
85182c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth    uint32_t levelCount = SkMipMap::ComputeLevelCount(tex->width(), tex->height()) + 1;
8527ac5da853457b032781cf865ba018de78508edb7egdaniel    if (levelCount != tex->mipLevels()) {
8537ac5da853457b032781cf865ba018de78508edb7egdaniel        const GrVkResource* oldResource = tex->resource();
8547ac5da853457b032781cf865ba018de78508edb7egdaniel        oldResource->ref();
8557ac5da853457b032781cf865ba018de78508edb7egdaniel        // grab handle to the original image resource
8567ac5da853457b032781cf865ba018de78508edb7egdaniel        VkImage oldImage = tex->image();
8577ac5da853457b032781cf865ba018de78508edb7egdaniel
8587ac5da853457b032781cf865ba018de78508edb7egdaniel        // change the original image's layout so we can copy from it
8597ac5da853457b032781cf865ba018de78508edb7egdaniel        tex->setImageLayout(this, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
8607ac5da853457b032781cf865ba018de78508edb7egdaniel                            VK_ACCESS_TRANSFER_READ_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, false);
8617ac5da853457b032781cf865ba018de78508edb7egdaniel
8627ac5da853457b032781cf865ba018de78508edb7egdaniel        if (!tex->reallocForMipmap(this, levelCount)) {
8637ac5da853457b032781cf865ba018de78508edb7egdaniel            oldResource->unref(this);
8647ac5da853457b032781cf865ba018de78508edb7egdaniel            return;
8657ac5da853457b032781cf865ba018de78508edb7egdaniel        }
8667ac5da853457b032781cf865ba018de78508edb7egdaniel        // change the new image's layout so we can blit to it
8677ac5da853457b032781cf865ba018de78508edb7egdaniel        tex->setImageLayout(this, VK_IMAGE_LAYOUT_GENERAL,
8687ac5da853457b032781cf865ba018de78508edb7egdaniel                            VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, false);
86962340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth
8707ac5da853457b032781cf865ba018de78508edb7egdaniel        // Blit original image to top level of new image
8717ac5da853457b032781cf865ba018de78508edb7egdaniel        blitRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
8727ac5da853457b032781cf865ba018de78508edb7egdaniel        blitRegion.srcOffsets[0] = { 0, 0, 0 };
8737ac5da853457b032781cf865ba018de78508edb7egdaniel        blitRegion.srcOffsets[1] = { width, height, 1 };
8747ac5da853457b032781cf865ba018de78508edb7egdaniel        blitRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
8757ac5da853457b032781cf865ba018de78508edb7egdaniel        blitRegion.dstOffsets[0] = { 0, 0, 0 };
8767ac5da853457b032781cf865ba018de78508edb7egdaniel        blitRegion.dstOffsets[1] = { width, height, 1 };
87762340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth
8787ac5da853457b032781cf865ba018de78508edb7egdaniel        fCurrentCmdBuffer->blitImage(this,
8797ac5da853457b032781cf865ba018de78508edb7egdaniel                                     oldResource,
8807ac5da853457b032781cf865ba018de78508edb7egdaniel                                     oldImage,
8817ac5da853457b032781cf865ba018de78508edb7egdaniel                                     VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
8827ac5da853457b032781cf865ba018de78508edb7egdaniel                                     tex->resource(),
8837ac5da853457b032781cf865ba018de78508edb7egdaniel                                     tex->image(),
8847ac5da853457b032781cf865ba018de78508edb7egdaniel                                     VK_IMAGE_LAYOUT_GENERAL,
8857ac5da853457b032781cf865ba018de78508edb7egdaniel                                     1,
8867ac5da853457b032781cf865ba018de78508edb7egdaniel                                     &blitRegion,
8877ac5da853457b032781cf865ba018de78508edb7egdaniel                                     VK_FILTER_LINEAR);
88862340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth
8897ac5da853457b032781cf865ba018de78508edb7egdaniel        oldResource->unref(this);
8907ac5da853457b032781cf865ba018de78508edb7egdaniel    } else {
8917ac5da853457b032781cf865ba018de78508edb7egdaniel        // change layout of the layers so we can write to them.
8927ac5da853457b032781cf865ba018de78508edb7egdaniel        tex->setImageLayout(this, VK_IMAGE_LAYOUT_GENERAL,
8937ac5da853457b032781cf865ba018de78508edb7egdaniel                            VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, false);
8947ac5da853457b032781cf865ba018de78508edb7egdaniel    }
89550c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth
89650c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth    // setup memory barrier
897b2df0c2702329be6380a943d548e7377a51d8565egdaniel    SkASSERT(GrVkFormatToPixelConfig(tex->imageFormat(), nullptr));
89850c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth    VkImageAspectFlags aspectFlags = VK_IMAGE_ASPECT_COLOR_BIT;
89950c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth    VkImageMemoryBarrier imageMemoryBarrier = {
90050c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth        VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,          // sType
90150c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth        NULL,                                            // pNext
9027ac5da853457b032781cf865ba018de78508edb7egdaniel        VK_ACCESS_TRANSFER_WRITE_BIT,                    // srcAccessMask
9037ac5da853457b032781cf865ba018de78508edb7egdaniel        VK_ACCESS_TRANSFER_READ_BIT,                     // dstAccessMask
90450c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth        VK_IMAGE_LAYOUT_GENERAL,                         // oldLayout
90550c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth        VK_IMAGE_LAYOUT_GENERAL,                         // newLayout
90650c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth        VK_QUEUE_FAMILY_IGNORED,                         // srcQueueFamilyIndex
90750c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth        VK_QUEUE_FAMILY_IGNORED,                         // dstQueueFamilyIndex
908b2df0c2702329be6380a943d548e7377a51d8565egdaniel        tex->image(),                                    // image
90950c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth        { aspectFlags, 0, 1, 0, 1 }                      // subresourceRange
91050c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth    };
91150c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth
91262340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    // Blit the miplevels
91382c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth    uint32_t mipLevel = 1;
91482c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth    while (mipLevel < levelCount) {
91582c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth        int prevWidth = width;
91682c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth        int prevHeight = height;
91782c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth        width = SkTMax(1, width / 2);
91882c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth        height = SkTMax(1, height / 2);
91982c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth
92050c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth        imageMemoryBarrier.subresourceRange.baseMipLevel = mipLevel - 1;
92150c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth        this->addImageMemoryBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
92250c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                                    false, &imageMemoryBarrier);
92350c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth
92450c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth        blitRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, mipLevel - 1, 0, 1 };
92562340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth        blitRegion.srcOffsets[0] = { 0, 0, 0 };
926e9906e71fbc29968ea10680f0fcd53a4153c7568brianosman        blitRegion.srcOffsets[1] = { prevWidth, prevHeight, 1 };
92782c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth        blitRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, mipLevel, 0, 1 };
92862340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth        blitRegion.dstOffsets[0] = { 0, 0, 0 };
929e9906e71fbc29968ea10680f0fcd53a4153c7568brianosman        blitRegion.dstOffsets[1] = { width, height, 1 };
93062340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth        fCurrentCmdBuffer->blitImage(this,
931b2df0c2702329be6380a943d548e7377a51d8565egdaniel                                     *tex,
932b2df0c2702329be6380a943d548e7377a51d8565egdaniel                                     *tex,
93362340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth                                     1,
93462340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth                                     &blitRegion,
93562340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth                                     VK_FILTER_LINEAR);
93682c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth        ++mipLevel;
93762340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    }
93862340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth}
93962340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth
940164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
941164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
942164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielGrStencilAttachment* GrVkGpu::createStencilAttachmentForRenderTarget(const GrRenderTarget* rt,
943164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                     int width,
944164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                     int height) {
945164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(width >= rt->width());
946164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(height >= rt->height());
947164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
948164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    int samples = rt->numStencilSamples();
949164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
9508f1dcaa6f3cc098bd5efd2595ca20e0bc1847d10egdaniel    const GrVkCaps::StencilFormat& sFmt = this->vkCaps().preferedStencilFormat();
951164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
952164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkStencilAttachment* stencil(GrVkStencilAttachment::Create(this,
953164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                 width,
954164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                 height,
955164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                 samples,
956164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                 sFmt));
957164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fStats.incStencilAttachmentCreates();
958164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return stencil;
959164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
960164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
961164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
962164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
9639d54afc38b171c01a03b34e773d154fcf83d97dcjvanverthbool copy_testing_data(GrVkGpu* gpu, void* srcData, const GrVkAlloc& alloc,
9643602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                       size_t srcRowBytes, size_t dstRowBytes, int h) {
9653602d4f16a01da860d16eb36fb52eb62487495ccegdaniel    void* mapPtr;
9663602d4f16a01da860d16eb36fb52eb62487495ccegdaniel    VkResult err = GR_VK_CALL(gpu->vkInterface(), MapMemory(gpu->device(),
9679d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth                                                            alloc.fMemory,
9689d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth                                                            alloc.fOffset,
9693602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                                                            dstRowBytes * h,
9703602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                                                            0,
9713602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                                                            &mapPtr));
9723602d4f16a01da860d16eb36fb52eb62487495ccegdaniel    if (err) {
9733602d4f16a01da860d16eb36fb52eb62487495ccegdaniel        return false;
9743602d4f16a01da860d16eb36fb52eb62487495ccegdaniel    }
9753602d4f16a01da860d16eb36fb52eb62487495ccegdaniel
9763602d4f16a01da860d16eb36fb52eb62487495ccegdaniel    // If there is no padding on dst we can do a single memcopy.
9773602d4f16a01da860d16eb36fb52eb62487495ccegdaniel    // This assumes the srcData comes in with no padding.
9783602d4f16a01da860d16eb36fb52eb62487495ccegdaniel    if (srcRowBytes == dstRowBytes) {
9793602d4f16a01da860d16eb36fb52eb62487495ccegdaniel        memcpy(mapPtr, srcData, srcRowBytes * h);
9803602d4f16a01da860d16eb36fb52eb62487495ccegdaniel    } else {
9813602d4f16a01da860d16eb36fb52eb62487495ccegdaniel        SkRectMemcpy(mapPtr, static_cast<size_t>(dstRowBytes), srcData, srcRowBytes,
9823602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                     srcRowBytes, h);
9833602d4f16a01da860d16eb36fb52eb62487495ccegdaniel    }
9849d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth    GrVkMemory::FlushMappedAlloc(gpu, alloc);
9859d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth    GR_VK_CALL(gpu->vkInterface(), UnmapMemory(gpu->device(), alloc.fMemory));
9863602d4f16a01da860d16eb36fb52eb62487495ccegdaniel    return true;
9873602d4f16a01da860d16eb36fb52eb62487495ccegdaniel}
9883602d4f16a01da860d16eb36fb52eb62487495ccegdaniel
989164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielGrBackendObject GrVkGpu::createTestingOnlyBackendTexture(void* srcData, int w, int h,
9900a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel                                                         GrPixelConfig config,
9910a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel                                                         bool isRenderTarget) {
992164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
993164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkFormat pixelFormat;
994164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!GrPixelConfigToVkFormat(config, &pixelFormat)) {
995164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return 0;
996164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
997164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
998164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    bool linearTiling = false;
999164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!fVkCaps->isConfigTexturable(config)) {
1000164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return 0;
1001164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1002164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
10030a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel    if (isRenderTarget && !fVkCaps->isConfigRenderable(config, false)) {
10040a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel        return 0;
10050a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel    }
10060a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel
1007a95d46b4ac8e41c9beb2b750cd389b1c6ebaf0a7egdaniel    if (fVkCaps->isConfigTexturableLinearly(config) &&
10080a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel        (!isRenderTarget || fVkCaps->isConfigRenderableLinearly(config, false))) {
1009164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        linearTiling = true;
1010164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1011164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1012164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT;
1013164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    usageFlags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1014164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    usageFlags |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
10150a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel    if (isRenderTarget) {
10160a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel        usageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
10170a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel    }
1018164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1019fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    VkImage image = VK_NULL_HANDLE;
10209d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth    GrVkAlloc alloc = { VK_NULL_HANDLE, 0, 0, 0 };
1021164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1022fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    VkImageTiling imageTiling = linearTiling ? VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL;
1023fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    VkImageLayout initialLayout = (VK_IMAGE_TILING_LINEAR == imageTiling)
1024fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth                                ? VK_IMAGE_LAYOUT_PREINITIALIZED
1025fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth                                : VK_IMAGE_LAYOUT_UNDEFINED;
1026fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth
1027fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    // Create Image
1028fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    VkSampleCountFlagBits vkSamples;
1029fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    if (!GrSampleCountToVkSampleCount(1, &vkSamples)) {
1030fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        return 0;
1031fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    }
1032fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth
1033fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    const VkImageCreateInfo imageCreateInfo = {
1034fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,         // sType
1035fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        NULL,                                        // pNext
1036fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        0,                                           // VkImageCreateFlags
1037fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        VK_IMAGE_TYPE_2D,                            // VkImageType
1038fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        pixelFormat,                                 // VkFormat
1039384b5e9cd36e443437de8df3b0f78ef4150efbacethannicholas        { (uint32_t) w, (uint32_t) h, 1 },           // VkExtent3D
1040fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        1,                                           // mipLevels
1041fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        1,                                           // arrayLayers
1042fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        vkSamples,                                   // samples
1043fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        imageTiling,                                 // VkImageTiling
1044fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        usageFlags,                                  // VkImageUsageFlags
1045fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        VK_SHARING_MODE_EXCLUSIVE,                   // VkSharingMode
1046fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        0,                                           // queueFamilyCount
1047fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        0,                                           // pQueueFamilyIndices
1048fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        initialLayout                                // initialLayout
1049fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    };
1050fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth
1051fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    GR_VK_CALL_ERRCHECK(this->vkInterface(), CreateImage(this->device(), &imageCreateInfo, nullptr, &image));
1052fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth
10536b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    if (!GrVkMemory::AllocAndBindImageMemory(this, image, linearTiling, &alloc)) {
1054fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        VK_CALL(DestroyImage(this->device(), image, nullptr));
1055164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return 0;
1056164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1057164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1058164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (srcData) {
10593602d4f16a01da860d16eb36fb52eb62487495ccegdaniel        size_t bpp = GrBytesPerPixel(config);
10603602d4f16a01da860d16eb36fb52eb62487495ccegdaniel        size_t rowCopyBytes = bpp * w;
1061164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        if (linearTiling) {
1062164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            const VkImageSubresource subres = {
1063164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                VK_IMAGE_ASPECT_COLOR_BIT,
1064164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                0,  // mipLevel
1065164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                0,  // arraySlice
1066164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            };
1067164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            VkSubresourceLayout layout;
1068164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1069fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth            VK_CALL(GetImageSubresourceLayout(fDevice, image, &subres, &layout));
1070164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
10719d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth            if (!copy_testing_data(this, srcData, alloc, rowCopyBytes,
1072583bc2e98d8105fc799897daea28eea03c23fbbcbrianosman                                   static_cast<size_t>(layout.rowPitch), h)) {
10733602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                GrVkMemory::FreeImageMemory(this, linearTiling, alloc);
10743602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                VK_CALL(DestroyImage(fDevice, image, nullptr));
10753602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                return 0;
10763602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            }
10773602d4f16a01da860d16eb36fb52eb62487495ccegdaniel        } else {
10783602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            SkASSERT(w && h);
10793602d4f16a01da860d16eb36fb52eb62487495ccegdaniel
10803602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            VkBuffer buffer;
10813602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            VkBufferCreateInfo bufInfo;
10823602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            memset(&bufInfo, 0, sizeof(VkBufferCreateInfo));
10833602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            bufInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
10843602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            bufInfo.flags = 0;
10853602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            bufInfo.size = rowCopyBytes * h;
10863602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            bufInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
10873602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            bufInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
10883602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            bufInfo.queueFamilyIndexCount = 0;
10893602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            bufInfo.pQueueFamilyIndices = nullptr;
10903602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            VkResult err;
10913602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            err = VK_CALL(CreateBuffer(fDevice, &bufInfo, nullptr, &buffer));
10923602d4f16a01da860d16eb36fb52eb62487495ccegdaniel
1093164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            if (err) {
10946b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth                GrVkMemory::FreeImageMemory(this, linearTiling, alloc);
10953602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                VK_CALL(DestroyImage(fDevice, image, nullptr));
1096164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                return 0;
1097164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            }
1098164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
10999d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth            GrVkAlloc bufferAlloc = { VK_NULL_HANDLE, 0, 0, 0 };
11003602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            if (!GrVkMemory::AllocAndBindBufferMemory(this, buffer, GrVkBuffer::kCopyRead_Type,
11013602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                                                      true, &bufferAlloc)) {
11023602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                GrVkMemory::FreeImageMemory(this, linearTiling, alloc);
11033602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                VK_CALL(DestroyImage(fDevice, image, nullptr));
11043602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                VK_CALL(DestroyBuffer(fDevice, buffer, nullptr));
11053602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                return 0;
1106164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            }
11073602d4f16a01da860d16eb36fb52eb62487495ccegdaniel
11089d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth            if (!copy_testing_data(this, srcData, bufferAlloc, rowCopyBytes, rowCopyBytes, h)) {
11093602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                GrVkMemory::FreeImageMemory(this, linearTiling, alloc);
11103602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                VK_CALL(DestroyImage(fDevice, image, nullptr));
11113602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                GrVkMemory::FreeBufferMemory(this, GrVkBuffer::kCopyRead_Type, bufferAlloc);
11123602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                VK_CALL(DestroyBuffer(fDevice, buffer, nullptr));
11133602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                return 0;
11143602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            }
11153602d4f16a01da860d16eb36fb52eb62487495ccegdaniel
11163602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            const VkCommandBufferAllocateInfo cmdInfo = {
11173602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,   // sType
11183602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                NULL,                                             // pNext
11193602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                fCmdPool,                                         // commandPool
11203602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                VK_COMMAND_BUFFER_LEVEL_PRIMARY,                  // level
11213602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                1                                                 // bufferCount
11223602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            };
11233602d4f16a01da860d16eb36fb52eb62487495ccegdaniel
11243602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            VkCommandBuffer cmdBuffer;
11253602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            err = VK_CALL(AllocateCommandBuffers(fDevice, &cmdInfo, &cmdBuffer));
11263602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            if (err) {
11273602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                GrVkMemory::FreeImageMemory(this, linearTiling, alloc);
11283602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                VK_CALL(DestroyImage(fDevice, image, nullptr));
11293602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                GrVkMemory::FreeBufferMemory(this, GrVkBuffer::kCopyRead_Type, bufferAlloc);
11303602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                VK_CALL(DestroyBuffer(fDevice, buffer, nullptr));
11313602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                return 0;
11323602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            }
11333602d4f16a01da860d16eb36fb52eb62487495ccegdaniel
11343602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            VkCommandBufferBeginInfo cmdBufferBeginInfo;
11353602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            memset(&cmdBufferBeginInfo, 0, sizeof(VkCommandBufferBeginInfo));
11363602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            cmdBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
11373602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            cmdBufferBeginInfo.pNext = nullptr;
11383602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            cmdBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
11393602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            cmdBufferBeginInfo.pInheritanceInfo = nullptr;
11403602d4f16a01da860d16eb36fb52eb62487495ccegdaniel
11413602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            err = VK_CALL(BeginCommandBuffer(cmdBuffer, &cmdBufferBeginInfo));
11423602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            SkASSERT(!err);
11433602d4f16a01da860d16eb36fb52eb62487495ccegdaniel
11443602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            // Set image layout and add barrier
11453602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            VkImageMemoryBarrier barrier;
11463602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            memset(&barrier, 0, sizeof(VkImageMemoryBarrier));
11473602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
11483602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            barrier.pNext = nullptr;
11493602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            barrier.srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(initialLayout);
11503602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
11513602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
11523602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
11533602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
11543602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            barrier.image = image;
11553602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            barrier.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0 , 1};
11563602d4f16a01da860d16eb36fb52eb62487495ccegdaniel
11573602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            VK_CALL(CmdPipelineBarrier(cmdBuffer,
11583602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                                       GrVkMemory::LayoutToPipelineStageFlags(initialLayout),
11593602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                                       VK_PIPELINE_STAGE_TRANSFER_BIT,
11603602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                                       0,
11613602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                                       0, nullptr,
11623602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                                       0, nullptr,
11633602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                                       1, &barrier));
11643602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            initialLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
11653602d4f16a01da860d16eb36fb52eb62487495ccegdaniel
11663602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            // Submit copy command
11673602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            VkBufferImageCopy region;
11683602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            memset(&region, 0, sizeof(VkBufferImageCopy));
11693602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            region.bufferOffset = 0;
1170a95d46b4ac8e41c9beb2b750cd389b1c6ebaf0a7egdaniel            region.bufferRowLength = w;
11713602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            region.bufferImageHeight = h;
11723602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
11733602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            region.imageOffset = { 0, 0, 0 };
11743602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            region.imageExtent = { (uint32_t)w, (uint32_t)h, 1 };
11753602d4f16a01da860d16eb36fb52eb62487495ccegdaniel
11763602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            VK_CALL(CmdCopyBufferToImage(cmdBuffer, buffer, image, initialLayout, 1, &region));
11773602d4f16a01da860d16eb36fb52eb62487495ccegdaniel
11783602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            // End CommandBuffer
11793602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            err = VK_CALL(EndCommandBuffer(cmdBuffer));
11803602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            SkASSERT(!err);
11813602d4f16a01da860d16eb36fb52eb62487495ccegdaniel
11823602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            // Create Fence for queue
11833602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            VkFence fence;
11843602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            VkFenceCreateInfo fenceInfo;
11853602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            memset(&fenceInfo, 0, sizeof(VkFenceCreateInfo));
11863602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
11873602d4f16a01da860d16eb36fb52eb62487495ccegdaniel
11883602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            err = VK_CALL(CreateFence(fDevice, &fenceInfo, nullptr, &fence));
11893602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            SkASSERT(!err);
11903602d4f16a01da860d16eb36fb52eb62487495ccegdaniel
11913602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            VkSubmitInfo submitInfo;
11923602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            memset(&submitInfo, 0, sizeof(VkSubmitInfo));
11933602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
11943602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            submitInfo.pNext = nullptr;
11953602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            submitInfo.waitSemaphoreCount = 0;
11963602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            submitInfo.pWaitSemaphores = nullptr;
11973602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            submitInfo.pWaitDstStageMask = 0;
11983602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            submitInfo.commandBufferCount = 1;
11993602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            submitInfo.pCommandBuffers = &cmdBuffer;
12003602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            submitInfo.signalSemaphoreCount = 0;
12013602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            submitInfo.pSignalSemaphores = nullptr;
12023602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            err = VK_CALL(QueueSubmit(this->queue(), 1, &submitInfo, fence));
12033602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            SkASSERT(!err);
12043602d4f16a01da860d16eb36fb52eb62487495ccegdaniel
12053602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            err = VK_CALL(WaitForFences(fDevice, 1, &fence, true, UINT64_MAX));
12063602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            if (VK_TIMEOUT == err) {
12073602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                GrVkMemory::FreeImageMemory(this, linearTiling, alloc);
12083602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                VK_CALL(DestroyImage(fDevice, image, nullptr));
12093602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                GrVkMemory::FreeBufferMemory(this, GrVkBuffer::kCopyRead_Type, bufferAlloc);
12103602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                VK_CALL(DestroyBuffer(fDevice, buffer, nullptr));
12113602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                VK_CALL(FreeCommandBuffers(fDevice, fCmdPool, 1, &cmdBuffer));
12123602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                VK_CALL(DestroyFence(fDevice, fence, nullptr));
12133602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                SkDebugf("Fence failed to signal: %d\n", err);
12143602d4f16a01da860d16eb36fb52eb62487495ccegdaniel                SkFAIL("failing");
12153602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            }
12163602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            SkASSERT(!err);
12173602d4f16a01da860d16eb36fb52eb62487495ccegdaniel
12183602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            // Clean up transfer resources
12193602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            GrVkMemory::FreeBufferMemory(this, GrVkBuffer::kCopyRead_Type, bufferAlloc);
12203602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            VK_CALL(DestroyBuffer(fDevice, buffer, nullptr));
12213602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            VK_CALL(FreeCommandBuffers(fDevice, fCmdPool, 1, &cmdBuffer));
12223602d4f16a01da860d16eb36fb52eb62487495ccegdaniel            VK_CALL(DestroyFence(fDevice, fence, nullptr));
1223164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
1224164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1225164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1226b2df0c2702329be6380a943d548e7377a51d8565egdaniel    GrVkImageInfo* info = new GrVkImageInfo;
1227fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    info->fImage = image;
1228fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    info->fAlloc = alloc;
1229fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    info->fImageTiling = imageTiling;
1230fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    info->fImageLayout = initialLayout;
123158a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel    info->fFormat = pixelFormat;
12322af0f1b014b9aabb6119bf66fac20e4cd3a8279bjvanverth    info->fLevelCount = 1;
1233fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth
1234fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    return (GrBackendObject)info;
1235164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1236164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1237164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::isTestingOnlyBackendTexture(GrBackendObject id) const {
1238b2df0c2702329be6380a943d548e7377a51d8565egdaniel    const GrVkImageInfo* backend = reinterpret_cast<const GrVkImageInfo*>(id);
1239164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
12401e305ba0d6a4237020d36234e9e286d3b0489401jvanverth    if (backend && backend->fImage && backend->fAlloc.fMemory) {
1241164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkMemoryRequirements req;
1242164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        memset(&req, 0, sizeof(req));
1243164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        GR_VK_CALL(this->vkInterface(), GetImageMemoryRequirements(fDevice,
1244164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                   backend->fImage,
1245164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                   &req));
1246164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // TODO: find a better check
1247164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // This will probably fail with a different driver
1248164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return (req.size > 0) && (req.size <= 8192 * 8192);
1249164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1250164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1251164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return false;
1252164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1253164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1254164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::deleteTestingOnlyBackendTexture(GrBackendObject id, bool abandon) {
12556b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    GrVkImageInfo* backend = reinterpret_cast<GrVkImageInfo*>(id);
1256164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (backend) {
1257164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        if (!abandon) {
1258fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth            // something in the command buffer may still be using this, so force submit
1259fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth            this->submitCommandBuffer(kForce_SyncQueue);
12606b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth            GrVkImage::DestroyImageInfo(this, backend);
1261164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
1262fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        delete backend;
1263164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1264164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1265164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1266164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
1267164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1268164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::addMemoryBarrier(VkPipelineStageFlags srcStageMask,
1269164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                               VkPipelineStageFlags dstStageMask,
1270164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                               bool byRegion,
1271164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                               VkMemoryBarrier* barrier) const {
1272164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(fCurrentCmdBuffer);
1273164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->pipelineBarrier(this,
1274164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       srcStageMask,
1275164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       dstStageMask,
1276164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       byRegion,
1277164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       GrVkCommandBuffer::kMemory_BarrierType,
1278164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       barrier);
1279164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1280164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1281164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::addBufferMemoryBarrier(VkPipelineStageFlags srcStageMask,
1282164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     VkPipelineStageFlags dstStageMask,
1283164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     bool byRegion,
1284164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     VkBufferMemoryBarrier* barrier) const {
1285164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(fCurrentCmdBuffer);
1286164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->pipelineBarrier(this,
1287164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       srcStageMask,
1288164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       dstStageMask,
1289164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       byRegion,
1290164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       GrVkCommandBuffer::kBufferMemory_BarrierType,
1291164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       barrier);
1292164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1293164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1294164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::addImageMemoryBarrier(VkPipelineStageFlags srcStageMask,
1295164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                    VkPipelineStageFlags dstStageMask,
1296164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                    bool byRegion,
1297164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                    VkImageMemoryBarrier* barrier) const {
1298164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(fCurrentCmdBuffer);
1299164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->pipelineBarrier(this,
1300164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       srcStageMask,
1301164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       dstStageMask,
1302164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       byRegion,
1303164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       GrVkCommandBuffer::kImageMemory_BarrierType,
1304164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       barrier);
1305164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1306164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1307f2361d2d93c200cd4555b5e8ecea4531801abaaaRobert Phillipsvoid GrVkGpu::finishOpList() {
1308164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Submit the current command buffer to the Queue
1309164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    this->submitCommandBuffer(kSkip_SyncQueue);
1310164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1311164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
13123d5d9ac426ea926f37eaa47e13acf7492068667begdanielvoid GrVkGpu::clearStencil(GrRenderTarget* target) {
13133d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    if (nullptr == target) {
13143d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        return;
13153d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    }
13163d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    GrStencilAttachment* stencil = target->renderTargetPriv().getStencilAttachment();
13173d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    GrVkStencilAttachment* vkStencil = (GrVkStencilAttachment*)stencil;
13183d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
13193d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
13203d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    VkClearDepthStencilValue vkStencilColor;
13213d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    memset(&vkStencilColor, 0, sizeof(VkClearDepthStencilValue));
13223d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
13233d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    vkStencil->setImageLayout(this,
13243d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                              VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
132550c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                              VK_ACCESS_TRANSFER_WRITE_BIT,
132650c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                              VK_PIPELINE_STAGE_TRANSFER_BIT,
13273d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                              false);
13283d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
13293d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    VkImageSubresourceRange subRange;
13303d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    memset(&subRange, 0, sizeof(VkImageSubresourceRange));
13313d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    subRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
13323d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    subRange.baseMipLevel = 0;
13333d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    subRange.levelCount = 1;
13343d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    subRange.baseArrayLayer = 0;
13353d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    subRange.layerCount = 1;
13363d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
13373d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    // TODO: I imagine that most times we want to clear a stencil it will be at the beginning of a
13383d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    // draw. Thus we should look into using the load op functions on the render pass to clear out
13393d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    // the stencil there.
13403d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    fCurrentCmdBuffer->clearDepthStencilImage(this, vkStencil, &vkStencilColor, 1, &subRange);
13413d5d9ac426ea926f37eaa47e13acf7492068667begdaniel}
13423d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
1343164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielinline bool can_copy_image(const GrSurface* dst,
1344164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           const GrSurface* src,
1345164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           const GrVkGpu* gpu) {
13464bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    const GrRenderTarget* dstRT = dst->asRenderTarget();
13474bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    const GrRenderTarget* srcRT = src->asRenderTarget();
13484bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    if (dstRT && srcRT) {
13494bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        if (srcRT->numColorSamples() != dstRT->numColorSamples()) {
13504bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel            return false;
13514bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        }
13524bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    } else if (dstRT) {
13534bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        if (dstRT->numColorSamples() > 1) {
13544bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel            return false;
13554bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        }
13564bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    } else if (srcRT) {
13574bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        if (srcRT->numColorSamples() > 1) {
13584bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel            return false;
13594bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        }
136017b892551465e5a44560a06e4b34dc3592b49622egdaniel    }
136117b892551465e5a44560a06e4b34dc3592b49622egdaniel
136217b892551465e5a44560a06e4b34dc3592b49622egdaniel    // We require that all vulkan GrSurfaces have been created with transfer_dst and transfer_src
136317b892551465e5a44560a06e4b34dc3592b49622egdaniel    // as image usage flags.
136417b892551465e5a44560a06e4b34dc3592b49622egdaniel    if (src->origin() == dst->origin() &&
136517b892551465e5a44560a06e4b34dc3592b49622egdaniel        GrBytesPerPixel(src->config()) == GrBytesPerPixel(dst->config())) {
1366164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return true;
1367164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1368164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1369164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return false;
1370164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1371164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1372164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::copySurfaceAsCopyImage(GrSurface* dst,
1373164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     GrSurface* src,
137417b892551465e5a44560a06e4b34dc3592b49622egdaniel                                     GrVkImage* dstImage,
137517b892551465e5a44560a06e4b34dc3592b49622egdaniel                                     GrVkImage* srcImage,
1376164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     const SkIRect& srcRect,
1377164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     const SkIPoint& dstPoint) {
1378164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(can_copy_image(dst, src, this));
1379164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1380164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // These flags are for flushing/invalidating caches and for the dst image it doesn't matter if
1381164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // the cache is flushed since it is only being written to.
138217b892551465e5a44560a06e4b34dc3592b49622egdaniel    dstImage->setImageLayout(this,
138350c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                             VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
138450c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                             VK_ACCESS_TRANSFER_WRITE_BIT,
138550c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                             VK_PIPELINE_STAGE_TRANSFER_BIT,
138650c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                             false);
1387164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
138817b892551465e5a44560a06e4b34dc3592b49622egdaniel    srcImage->setImageLayout(this,
138917b892551465e5a44560a06e4b34dc3592b49622egdaniel                             VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
139050c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                             VK_ACCESS_TRANSFER_READ_BIT,
139150c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                             VK_PIPELINE_STAGE_TRANSFER_BIT,
139217b892551465e5a44560a06e4b34dc3592b49622egdaniel                             false);
1393164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1394164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Flip rect if necessary
1395164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkIRect srcVkRect = srcRect;
1396164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    int32_t dstY = dstPoint.fY;
1397164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1398164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (kBottomLeft_GrSurfaceOrigin == src->origin()) {
1399164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        SkASSERT(kBottomLeft_GrSurfaceOrigin == dst->origin());
1400164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        srcVkRect.fTop = src->height() - srcRect.fBottom;
1401164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        srcVkRect.fBottom =  src->height() - srcRect.fTop;
1402164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        dstY = dst->height() - dstPoint.fY - srcVkRect.height();
1403164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1404164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1405164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkImageCopy copyRegion;
1406164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    memset(&copyRegion, 0, sizeof(VkImageCopy));
1407164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    copyRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
1408164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    copyRegion.srcOffset = { srcVkRect.fLeft, srcVkRect.fTop, 0 };
1409164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    copyRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
1410164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    copyRegion.dstOffset = { dstPoint.fX, dstY, 0 };
1411c355bc8dd117291b63ee7b7b39ec37a0e768eec5egdaniel    copyRegion.extent = { (uint32_t)srcVkRect.width(), (uint32_t)srcVkRect.height(), 1 };
1412164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1413164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->copyImage(this,
141417b892551465e5a44560a06e4b34dc3592b49622egdaniel                                 srcImage,
1415164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
141617b892551465e5a44560a06e4b34dc3592b49622egdaniel                                 dstImage,
1417164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1418164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                 1,
1419164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                 &copyRegion);
1420900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
1421900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY,
1422900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                        srcRect.width(), srcRect.height());
1423900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    this->didWriteToSurface(dst, &dstRect);
1424164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1425164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
142617b892551465e5a44560a06e4b34dc3592b49622egdanielinline bool can_copy_as_blit(const GrSurface* dst,
142717b892551465e5a44560a06e4b34dc3592b49622egdaniel                             const GrSurface* src,
142817b892551465e5a44560a06e4b34dc3592b49622egdaniel                             const GrVkImage* dstImage,
142917b892551465e5a44560a06e4b34dc3592b49622egdaniel                             const GrVkImage* srcImage,
143017b892551465e5a44560a06e4b34dc3592b49622egdaniel                             const GrVkGpu* gpu) {
143166933552f1723c4a2b248711ab3d43921401e8e6egdaniel    // We require that all vulkan GrSurfaces have been created with transfer_dst and transfer_src
143217b892551465e5a44560a06e4b34dc3592b49622egdaniel    // as image usage flags.
143317b892551465e5a44560a06e4b34dc3592b49622egdaniel    const GrVkCaps& caps = gpu->vkCaps();
143417b892551465e5a44560a06e4b34dc3592b49622egdaniel    if (!caps.configCanBeDstofBlit(dst->config(), dstImage->isLinearTiled()) ||
143517b892551465e5a44560a06e4b34dc3592b49622egdaniel        !caps.configCanBeSrcofBlit(src->config(), srcImage->isLinearTiled())) {
143617b892551465e5a44560a06e4b34dc3592b49622egdaniel        return false;
143717b892551465e5a44560a06e4b34dc3592b49622egdaniel    }
143817b892551465e5a44560a06e4b34dc3592b49622egdaniel
143917b892551465e5a44560a06e4b34dc3592b49622egdaniel    // We cannot blit images that are multisampled. Will need to figure out if we can blit the
144017b892551465e5a44560a06e4b34dc3592b49622egdaniel    // resolved msaa though.
144117b892551465e5a44560a06e4b34dc3592b49622egdaniel    if ((dst->asRenderTarget() && dst->asRenderTarget()->numColorSamples() > 1) ||
144217b892551465e5a44560a06e4b34dc3592b49622egdaniel        (src->asRenderTarget() && src->asRenderTarget()->numColorSamples() > 1)) {
144317b892551465e5a44560a06e4b34dc3592b49622egdaniel        return false;
144417b892551465e5a44560a06e4b34dc3592b49622egdaniel    }
144517b892551465e5a44560a06e4b34dc3592b49622egdaniel
144617b892551465e5a44560a06e4b34dc3592b49622egdaniel    return true;
144717b892551465e5a44560a06e4b34dc3592b49622egdaniel}
144817b892551465e5a44560a06e4b34dc3592b49622egdaniel
144917b892551465e5a44560a06e4b34dc3592b49622egdanielvoid GrVkGpu::copySurfaceAsBlit(GrSurface* dst,
145017b892551465e5a44560a06e4b34dc3592b49622egdaniel                                GrSurface* src,
145117b892551465e5a44560a06e4b34dc3592b49622egdaniel                                GrVkImage* dstImage,
145217b892551465e5a44560a06e4b34dc3592b49622egdaniel                                GrVkImage* srcImage,
145317b892551465e5a44560a06e4b34dc3592b49622egdaniel                                const SkIRect& srcRect,
145417b892551465e5a44560a06e4b34dc3592b49622egdaniel                                const SkIPoint& dstPoint) {
145517b892551465e5a44560a06e4b34dc3592b49622egdaniel    SkASSERT(can_copy_as_blit(dst, src, dstImage, srcImage, this));
145617b892551465e5a44560a06e4b34dc3592b49622egdaniel
145717b892551465e5a44560a06e4b34dc3592b49622egdaniel    dstImage->setImageLayout(this,
145817b892551465e5a44560a06e4b34dc3592b49622egdaniel                             VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
145950c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                             VK_ACCESS_TRANSFER_WRITE_BIT,
146050c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                             VK_PIPELINE_STAGE_TRANSFER_BIT,
146117b892551465e5a44560a06e4b34dc3592b49622egdaniel                             false);
146217b892551465e5a44560a06e4b34dc3592b49622egdaniel
146317b892551465e5a44560a06e4b34dc3592b49622egdaniel    srcImage->setImageLayout(this,
146417b892551465e5a44560a06e4b34dc3592b49622egdaniel                             VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
146550c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                             VK_ACCESS_TRANSFER_READ_BIT,
146650c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                             VK_PIPELINE_STAGE_TRANSFER_BIT,
146717b892551465e5a44560a06e4b34dc3592b49622egdaniel                             false);
146817b892551465e5a44560a06e4b34dc3592b49622egdaniel
146917b892551465e5a44560a06e4b34dc3592b49622egdaniel    // Flip rect if necessary
147017b892551465e5a44560a06e4b34dc3592b49622egdaniel    SkIRect srcVkRect;
14718af936d3047208def585b7bc824f013b994f6312egdaniel    srcVkRect.fLeft = srcRect.fLeft;
14728af936d3047208def585b7bc824f013b994f6312egdaniel    srcVkRect.fRight = srcRect.fRight;
147317b892551465e5a44560a06e4b34dc3592b49622egdaniel    SkIRect dstRect;
147417b892551465e5a44560a06e4b34dc3592b49622egdaniel    dstRect.fLeft = dstPoint.fX;
14758af936d3047208def585b7bc824f013b994f6312egdaniel    dstRect.fRight = dstPoint.fX + srcRect.width();
147617b892551465e5a44560a06e4b34dc3592b49622egdaniel
147717b892551465e5a44560a06e4b34dc3592b49622egdaniel    if (kBottomLeft_GrSurfaceOrigin == src->origin()) {
147817b892551465e5a44560a06e4b34dc3592b49622egdaniel        srcVkRect.fTop = src->height() - srcRect.fBottom;
147917b892551465e5a44560a06e4b34dc3592b49622egdaniel        srcVkRect.fBottom = src->height() - srcRect.fTop;
148017b892551465e5a44560a06e4b34dc3592b49622egdaniel    } else {
14818af936d3047208def585b7bc824f013b994f6312egdaniel        srcVkRect.fTop = srcRect.fTop;
14828af936d3047208def585b7bc824f013b994f6312egdaniel        srcVkRect.fBottom = srcRect.fBottom;
148317b892551465e5a44560a06e4b34dc3592b49622egdaniel    }
148417b892551465e5a44560a06e4b34dc3592b49622egdaniel
148517b892551465e5a44560a06e4b34dc3592b49622egdaniel    if (kBottomLeft_GrSurfaceOrigin == dst->origin()) {
148617b892551465e5a44560a06e4b34dc3592b49622egdaniel        dstRect.fTop = dst->height() - dstPoint.fY - srcVkRect.height();
148717b892551465e5a44560a06e4b34dc3592b49622egdaniel    } else {
148817b892551465e5a44560a06e4b34dc3592b49622egdaniel        dstRect.fTop = dstPoint.fY;
148917b892551465e5a44560a06e4b34dc3592b49622egdaniel    }
149017b892551465e5a44560a06e4b34dc3592b49622egdaniel    dstRect.fBottom = dstRect.fTop + srcVkRect.height();
149117b892551465e5a44560a06e4b34dc3592b49622egdaniel
149217b892551465e5a44560a06e4b34dc3592b49622egdaniel    // If we have different origins, we need to flip the top and bottom of the dst rect so that we
149317b892551465e5a44560a06e4b34dc3592b49622egdaniel    // get the correct origintation of the copied data.
149417b892551465e5a44560a06e4b34dc3592b49622egdaniel    if (src->origin() != dst->origin()) {
149517b892551465e5a44560a06e4b34dc3592b49622egdaniel        SkTSwap(dstRect.fTop, dstRect.fBottom);
149617b892551465e5a44560a06e4b34dc3592b49622egdaniel    }
149717b892551465e5a44560a06e4b34dc3592b49622egdaniel
149817b892551465e5a44560a06e4b34dc3592b49622egdaniel    VkImageBlit blitRegion;
149917b892551465e5a44560a06e4b34dc3592b49622egdaniel    memset(&blitRegion, 0, sizeof(VkImageBlit));
150017b892551465e5a44560a06e4b34dc3592b49622egdaniel    blitRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
150117b892551465e5a44560a06e4b34dc3592b49622egdaniel    blitRegion.srcOffsets[0] = { srcVkRect.fLeft, srcVkRect.fTop, 0 };
1502e76071ca0f98cb4d7e2d1789c46aa3037637b309Greg Daniel    blitRegion.srcOffsets[1] = { srcVkRect.fRight, srcVkRect.fBottom, 1 };
150317b892551465e5a44560a06e4b34dc3592b49622egdaniel    blitRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
150417b892551465e5a44560a06e4b34dc3592b49622egdaniel    blitRegion.dstOffsets[0] = { dstRect.fLeft, dstRect.fTop, 0 };
1505e76071ca0f98cb4d7e2d1789c46aa3037637b309Greg Daniel    blitRegion.dstOffsets[1] = { dstRect.fRight, dstRect.fBottom, 1 };
150617b892551465e5a44560a06e4b34dc3592b49622egdaniel
150717b892551465e5a44560a06e4b34dc3592b49622egdaniel    fCurrentCmdBuffer->blitImage(this,
1508b2df0c2702329be6380a943d548e7377a51d8565egdaniel                                 *srcImage,
1509b2df0c2702329be6380a943d548e7377a51d8565egdaniel                                 *dstImage,
151017b892551465e5a44560a06e4b34dc3592b49622egdaniel                                 1,
151117b892551465e5a44560a06e4b34dc3592b49622egdaniel                                 &blitRegion,
151217b892551465e5a44560a06e4b34dc3592b49622egdaniel                                 VK_FILTER_NEAREST); // We never scale so any filter works here
1513900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
1514900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    this->didWriteToSurface(dst, &dstRect);
151517b892551465e5a44560a06e4b34dc3592b49622egdaniel}
151617b892551465e5a44560a06e4b34dc3592b49622egdaniel
15174bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdanielinline bool can_copy_as_resolve(const GrSurface* dst,
15184bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel                                const GrSurface* src,
15194bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel                                const GrVkGpu* gpu) {
15204bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    // Our src must be a multisampled render target
15214bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    if (!src->asRenderTarget() || src->asRenderTarget()->numColorSamples() <= 1) {
15224bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        return false;
15234bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    }
15244bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel
15254bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    // The dst must be a render target but not multisampled
15264bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    if (!dst->asRenderTarget() || dst->asRenderTarget()->numColorSamples() > 1) {
15274bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        return false;
15284bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    }
15294bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel
15304bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    // Surfaces must have the same origin.
15314bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    if (src->origin() != dst->origin()) {
15324bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        return false;
15334bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    }
15344bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel
15354bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    return true;
15364bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel}
15374bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel
15384bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdanielvoid GrVkGpu::copySurfaceAsResolve(GrSurface* dst,
15394bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel                                   GrSurface* src,
15404bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel                                   const SkIRect& srcRect,
15414bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel                                   const SkIPoint& dstPoint) {
15424bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    GrVkRenderTarget* dstRT = static_cast<GrVkRenderTarget*>(dst->asRenderTarget());
15434bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    GrVkRenderTarget* srcRT = static_cast<GrVkRenderTarget*>(src->asRenderTarget());
15444bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    SkASSERT(dstRT && dstRT->numColorSamples() <= 1);
15454bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    this->resolveImage(dstRT, srcRT, srcRect, dstPoint);
15464bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel}
15474bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel
1548164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielinline bool can_copy_as_draw(const GrSurface* dst,
1549164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                             const GrSurface* src,
1550164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                             const GrVkGpu* gpu) {
1551164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return false;
1552164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1553164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1554164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::copySurfaceAsDraw(GrSurface* dst,
1555164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                GrSurface* src,
1556164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                const SkIRect& srcRect,
1557164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                const SkIPoint& dstPoint) {
1558164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(false);
1559164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1560164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1561164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::onCopySurface(GrSurface* dst,
1562164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                            GrSurface* src,
1563164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                            const SkIRect& srcRect,
1564164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                            const SkIPoint& dstPoint) {
15654bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    if (can_copy_as_resolve(dst, src, this)) {
15664bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        this->copySurfaceAsResolve(dst, src, srcRect, dstPoint);
1567ec44099979acd3e83ad93a15dbd9301856a90572egdaniel        return true;
15684bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    }
15694bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel
1570fd016d7a69f0415f2497d25ec3a7b71de1545826egdaniel    if (this->vkCaps().mustSubmitCommandsBeforeCopyOp()) {
1571fd016d7a69f0415f2497d25ec3a7b71de1545826egdaniel        this->submitCommandBuffer(GrVkGpu::kSkip_SyncQueue);
1572fd016d7a69f0415f2497d25ec3a7b71de1545826egdaniel    }
1573fd016d7a69f0415f2497d25ec3a7b71de1545826egdaniel
1574bc9b2963bf9e39c47ae5c3ab94b8503b476f4f0eegdaniel    if (fCopyManager.copySurfaceAsDraw(this, dst, src, srcRect, dstPoint)) {
1575bc9b2963bf9e39c47ae5c3ab94b8503b476f4f0eegdaniel        return true;
1576bc9b2963bf9e39c47ae5c3ab94b8503b476f4f0eegdaniel    }
1577bc9b2963bf9e39c47ae5c3ab94b8503b476f4f0eegdaniel
157817b892551465e5a44560a06e4b34dc3592b49622egdaniel    GrVkImage* dstImage;
157917b892551465e5a44560a06e4b34dc3592b49622egdaniel    GrVkImage* srcImage;
15804bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    GrRenderTarget* dstRT = dst->asRenderTarget();
15814bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    if (dstRT) {
15824bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(dstRT);
15834bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        dstImage = vkRT->numColorSamples() > 1 ? vkRT->msaaImage() : vkRT;
158417b892551465e5a44560a06e4b34dc3592b49622egdaniel    } else {
15854bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        SkASSERT(dst->asTexture());
15864bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        dstImage = static_cast<GrVkTexture*>(dst->asTexture());
158717b892551465e5a44560a06e4b34dc3592b49622egdaniel    }
15884bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    GrRenderTarget* srcRT = src->asRenderTarget();
15894bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    if (srcRT) {
15904bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(srcRT);
15914bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        srcImage = vkRT->numColorSamples() > 1 ? vkRT->msaaImage() : vkRT;
159217b892551465e5a44560a06e4b34dc3592b49622egdaniel    } else {
15934bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        SkASSERT(src->asTexture());
15944bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel        srcImage = static_cast<GrVkTexture*>(src->asTexture());
159517b892551465e5a44560a06e4b34dc3592b49622egdaniel    }
159617b892551465e5a44560a06e4b34dc3592b49622egdaniel
1597164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (can_copy_image(dst, src, this)) {
159817b892551465e5a44560a06e4b34dc3592b49622egdaniel        this->copySurfaceAsCopyImage(dst, src, dstImage, srcImage, srcRect, dstPoint);
159917b892551465e5a44560a06e4b34dc3592b49622egdaniel        return true;
160017b892551465e5a44560a06e4b34dc3592b49622egdaniel    }
160117b892551465e5a44560a06e4b34dc3592b49622egdaniel
160217b892551465e5a44560a06e4b34dc3592b49622egdaniel    if (can_copy_as_blit(dst, src, dstImage, srcImage, this)) {
160317b892551465e5a44560a06e4b34dc3592b49622egdaniel        this->copySurfaceAsBlit(dst, src, dstImage, srcImage, srcRect, dstPoint);
1604164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return true;
1605164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1606164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1607164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return false;
1608164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1609164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
16104bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdanielbool GrVkGpu::initDescForDstCopy(const GrRenderTarget* src, GrSurfaceDesc* desc) const {
16114bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    // We can always succeed here with either a CopyImage (none msaa src) or ResolveImage (msaa).
16124bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    // For CopyImage we can make a simple texture, for ResolveImage we require the dst to be a
16134bcd62e3313da60c3aa96ccd12b7ea440c7266d4egdaniel    // render target as well.
161437798fbd82a7d064c5cc1516f120546a3408044begdaniel    desc->fOrigin = src->origin();
161537798fbd82a7d064c5cc1516f120546a3408044begdaniel    desc->fConfig = src->config();
1616bc9b2963bf9e39c47ae5c3ab94b8503b476f4f0eegdaniel    if (src->numColorSamples() > 1 ||
1617bc9b2963bf9e39c47ae5c3ab94b8503b476f4f0eegdaniel        (src->asTexture() && this->vkCaps().supportsCopiesAsDraws())) {
1618bc9b2963bf9e39c47ae5c3ab94b8503b476f4f0eegdaniel        desc->fFlags = kRenderTarget_GrSurfaceFlag;
1619bc9b2963bf9e39c47ae5c3ab94b8503b476f4f0eegdaniel    } else {
1620bc9b2963bf9e39c47ae5c3ab94b8503b476f4f0eegdaniel        // Just going to use CopyImage here
1621bc9b2963bf9e39c47ae5c3ab94b8503b476f4f0eegdaniel        desc->fFlags = kNone_GrSurfaceFlags;
1622bc9b2963bf9e39c47ae5c3ab94b8503b476f4f0eegdaniel    }
1623bc9b2963bf9e39c47ae5c3ab94b8503b476f4f0eegdaniel
162437798fbd82a7d064c5cc1516f120546a3408044begdaniel    return true;
162537798fbd82a7d064c5cc1516f120546a3408044begdaniel}
162637798fbd82a7d064c5cc1516f120546a3408044begdaniel
1627c25c5d73e9f4d840dc758c399496d5690709ad58csmartdaltonvoid GrVkGpu::onQueryMultisampleSpecs(GrRenderTarget* rt, const GrStencilSettings&,
1628c25c5d73e9f4d840dc758c399496d5690709ad58csmartdalton                                      int* effectiveSampleCnt, SamplePattern*) {
162928f45b949acc746849100fbe112ee5280f0594c9cdalton    // TODO: stub.
163028f45b949acc746849100fbe112ee5280f0594c9cdalton    SkASSERT(!this->caps()->sampleLocationsSupport());
163128f45b949acc746849100fbe112ee5280f0594c9cdalton    *effectiveSampleCnt = rt->desc().fSampleCnt;
163228f45b949acc746849100fbe112ee5280f0594c9cdalton}
163328f45b949acc746849100fbe112ee5280f0594c9cdalton
1634164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::onGetReadPixelsInfo(GrSurface* srcSurface, int width, int height, size_t rowBytes,
1635164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                  GrPixelConfig readConfig, DrawPreference* drawPreference,
1636164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                  ReadPixelTempDrawInfo* tempDrawInfo) {
163788e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    // These settings we will always want if a temp draw is performed.
163888e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    tempDrawInfo->fTempSurfaceDesc.fFlags = kRenderTarget_GrSurfaceFlag;
163988e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    tempDrawInfo->fTempSurfaceDesc.fWidth = width;
164088e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    tempDrawInfo->fTempSurfaceDesc.fHeight = height;
164188e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    tempDrawInfo->fTempSurfaceDesc.fSampleCnt = 0;
164288e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    tempDrawInfo->fTempSurfaceDesc.fOrigin = kTopLeft_GrSurfaceOrigin; // no CPU y-flip for TL.
1643b117ff194ff888ef9107a4797aad053b0d76be30bsalomon    tempDrawInfo->fTempSurfaceFit = SkBackingFit::kApprox;
164488e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel
164588e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    // For now assume no swizzling, we may change that below.
164688e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    tempDrawInfo->fSwizzle = GrSwizzle::RGBA();
164788e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel
164888e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    // Depends on why we need/want a temp draw. Start off assuming no change, the surface we read
164988e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    // from will be srcConfig and we will read readConfig pixels from it.
165088e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    // Not that if we require a draw and return a non-renderable format for the temp surface the
165188e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    // base class will fail for us.
165288e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    tempDrawInfo->fTempSurfaceDesc.fConfig = srcSurface->config();
165388e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    tempDrawInfo->fReadConfig = readConfig;
165488e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel
16554583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    if (srcSurface->config() == readConfig) {
16564583ec51d9ddc830eeb854db068235be96ce59c4egdaniel        return true;
1657164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1658164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
165966933552f1723c4a2b248711ab3d43921401e8e6egdaniel    if (this->vkCaps().isConfigRenderable(readConfig, srcSurface->desc().fSampleCnt > 1)) {
16604583ec51d9ddc830eeb854db068235be96ce59c4egdaniel        ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
16614583ec51d9ddc830eeb854db068235be96ce59c4egdaniel        tempDrawInfo->fTempSurfaceDesc.fConfig = readConfig;
16624583ec51d9ddc830eeb854db068235be96ce59c4egdaniel        tempDrawInfo->fReadConfig = readConfig;
16634583ec51d9ddc830eeb854db068235be96ce59c4egdaniel        return true;
1664164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1665164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
16664583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    return false;
1667164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1668164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1669164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::onReadPixels(GrSurface* surface,
1670164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           int left, int top, int width, int height,
1671164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           GrPixelConfig config,
1672164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           void* buffer,
1673164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           size_t rowBytes) {
1674164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkFormat pixelFormat;
1675164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!GrPixelConfigToVkFormat(config, &pixelFormat)) {
1676164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
1677164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1678164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
167966933552f1723c4a2b248711ab3d43921401e8e6egdaniel    GrVkImage* image = nullptr;
168066933552f1723c4a2b248711ab3d43921401e8e6egdaniel    GrVkRenderTarget* rt = static_cast<GrVkRenderTarget*>(surface->asRenderTarget());
168166933552f1723c4a2b248711ab3d43921401e8e6egdaniel    if (rt) {
168266933552f1723c4a2b248711ab3d43921401e8e6egdaniel        // resolve the render target if necessary
168366933552f1723c4a2b248711ab3d43921401e8e6egdaniel        switch (rt->getResolveType()) {
168466933552f1723c4a2b248711ab3d43921401e8e6egdaniel            case GrVkRenderTarget::kCantResolve_ResolveType:
168566933552f1723c4a2b248711ab3d43921401e8e6egdaniel                return false;
168666933552f1723c4a2b248711ab3d43921401e8e6egdaniel            case GrVkRenderTarget::kAutoResolves_ResolveType:
168766933552f1723c4a2b248711ab3d43921401e8e6egdaniel                break;
168866933552f1723c4a2b248711ab3d43921401e8e6egdaniel            case GrVkRenderTarget::kCanResolve_ResolveType:
168966933552f1723c4a2b248711ab3d43921401e8e6egdaniel                this->onResolveRenderTarget(rt);
169066933552f1723c4a2b248711ab3d43921401e8e6egdaniel                break;
169166933552f1723c4a2b248711ab3d43921401e8e6egdaniel            default:
169266933552f1723c4a2b248711ab3d43921401e8e6egdaniel                SkFAIL("Unknown resolve type");
169366933552f1723c4a2b248711ab3d43921401e8e6egdaniel        }
169466933552f1723c4a2b248711ab3d43921401e8e6egdaniel        image = rt;
169566933552f1723c4a2b248711ab3d43921401e8e6egdaniel    } else {
169666933552f1723c4a2b248711ab3d43921401e8e6egdaniel        image = static_cast<GrVkTexture*>(surface->asTexture());
169766933552f1723c4a2b248711ab3d43921401e8e6egdaniel    }
169866933552f1723c4a2b248711ab3d43921401e8e6egdaniel
169966933552f1723c4a2b248711ab3d43921401e8e6egdaniel    if (!image) {
1700164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
1701164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1702164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1703164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Change layout of our target so it can be used as copy
170466933552f1723c4a2b248711ab3d43921401e8e6egdaniel    image->setImageLayout(this,
170566933552f1723c4a2b248711ab3d43921401e8e6egdaniel                          VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
170666933552f1723c4a2b248711ab3d43921401e8e6egdaniel                          VK_ACCESS_TRANSFER_READ_BIT,
170766933552f1723c4a2b248711ab3d43921401e8e6egdaniel                          VK_PIPELINE_STAGE_TRANSFER_BIT,
170866933552f1723c4a2b248711ab3d43921401e8e6egdaniel                          false);
1709164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
17106fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel    size_t bpp = GrBytesPerPixel(config);
17116fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel    size_t tightRowBytes = bpp * width;
1712164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    bool flipY = kBottomLeft_GrSurfaceOrigin == surface->origin();
1713164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1714164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkBufferImageCopy region;
1715164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    memset(&region, 0, sizeof(VkBufferImageCopy));
17166fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel
17176fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel    bool copyFromOrigin = this->vkCaps().mustDoCopiesFromOrigin();
17186fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel    if (copyFromOrigin) {
17196fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel        region.imageOffset = { 0, 0, 0 };
17206fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel        region.imageExtent = { (uint32_t)(left + width),
17216fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel                               (uint32_t)(flipY ? surface->height() - top : top + height),
17226fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel                               1
17236fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel                             };
17246fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel    } else {
17256fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel        VkOffset3D offset = {
17266fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel            left,
17276fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel            flipY ? surface->height() - top - height : top,
17286fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel            0
17296fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel        };
17306fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel        region.imageOffset = offset;
17316fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel        region.imageExtent = { (uint32_t)width, (uint32_t)height, 1 };
17326fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel    }
17336fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel
17346fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel    size_t transBufferRowBytes = bpp * region.imageExtent.width;
17356fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel    GrVkTransferBuffer* transferBuffer =
17366fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel            static_cast<GrVkTransferBuffer*>(this->createBuffer(transBufferRowBytes * height,
17376fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel                                                                kXferGpuToCpu_GrBufferType,
17386fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel                                                                kStream_GrAccessPattern));
17396fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel
17406fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel    // Copy the image to a buffer so we can map it to cpu memory
1741db37909347d034943bd6b0922710a94c6c6ea572jvanverth    region.bufferOffset = transferBuffer->offset();
174288e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    region.bufferRowLength = 0; // Forces RowLength to be width. We handle the rowBytes below.
1743164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    region.bufferImageHeight = 0; // Forces height to be tightly packed. Only useful for 3d images.
1744164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
1745164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1746164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->copyImageToBuffer(this,
174766933552f1723c4a2b248711ab3d43921401e8e6egdaniel                                         image,
1748164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1749164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                         transferBuffer,
1750164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                         1,
1751164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                         &region);
1752164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1753164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // make sure the copy to buffer has finished
1754164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    transferBuffer->addMemoryBarrier(this,
1755164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     VK_ACCESS_TRANSFER_WRITE_BIT,
1756164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     VK_ACCESS_HOST_READ_BIT,
1757164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     VK_PIPELINE_STAGE_TRANSFER_BIT,
1758164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     VK_PIPELINE_STAGE_HOST_BIT,
1759164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     false);
1760164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1761164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // We need to submit the current command buffer to the Queue and make sure it finishes before
1762164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // we can copy the data out of the buffer.
1763164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    this->submitCommandBuffer(kForce_SyncQueue);
17649d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth    GrVkMemory::InvalidateMappedAlloc(this, transferBuffer->alloc());
1765164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    void* mappedMemory = transferBuffer->map();
1766164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
17676fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel    if (copyFromOrigin) {
17686fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel        uint32_t skipRows = region.imageExtent.height - height;
17696fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel        mappedMemory = (char*)mappedMemory + transBufferRowBytes * skipRows + bpp * left;
17706fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel    }
17716fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel
1772164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (flipY) {
177388e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel        const char* srcRow = reinterpret_cast<const char*>(mappedMemory);
177488e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel        char* dstRow = reinterpret_cast<char*>(buffer)+(height - 1) * rowBytes;
177588e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel        for (int y = 0; y < height; y++) {
177688e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel            memcpy(dstRow, srcRow, tightRowBytes);
17776fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel            srcRow += transBufferRowBytes;
177888e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel            dstRow -= rowBytes;
177988e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel        }
178088e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    } else {
17816fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel        if (transBufferRowBytes == rowBytes) {
178288e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel            memcpy(buffer, mappedMemory, rowBytes*height);
178388e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel        } else {
17846fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel            SkRectMemcpy(buffer, rowBytes, mappedMemory, transBufferRowBytes, tightRowBytes,
17856fa0a91e607343a244a8789669d3fd15a98f80f7egdaniel                         height);
1786164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
1787164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1788164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
178988e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    transferBuffer->unmap();
179088e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    transferBuffer->unref();
1791164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return true;
1792164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1793066df7ca911b65d416783f3bec6f4f1662948ad5egdaniel
179427bb28473912181cf9a838e9282e86cb62e2d44begdaniel// The RenderArea bounds we pass into BeginRenderPass must have a start x value that is a multiple
179527bb28473912181cf9a838e9282e86cb62e2d44begdaniel// of the granularity. The width must also be a multiple of the granularity or eaqual to the width
179627bb28473912181cf9a838e9282e86cb62e2d44begdaniel// the the entire attachment. Similar requirements for the y and height components.
179727bb28473912181cf9a838e9282e86cb62e2d44begdanielvoid adjust_bounds_to_granularity(SkIRect* dstBounds, const SkIRect& srcBounds,
179827bb28473912181cf9a838e9282e86cb62e2d44begdaniel                                  const VkExtent2D& granularity, int maxWidth, int maxHeight) {
179927bb28473912181cf9a838e9282e86cb62e2d44begdaniel    // Adjust Width
1800d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel    if ((0 != granularity.width && 1 != granularity.width)) {
1801d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel        // Start with the right side of rect so we know if we end up going pass the maxWidth.
1802d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel        int rightAdj = srcBounds.fRight % granularity.width;
1803d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel        if (rightAdj != 0) {
1804d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel            rightAdj = granularity.width - rightAdj;
1805d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel        }
1806d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel        dstBounds->fRight = srcBounds.fRight + rightAdj;
1807d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel        if (dstBounds->fRight > maxWidth) {
1808d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel            dstBounds->fRight = maxWidth;
1809d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel            dstBounds->fLeft = 0;
1810d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel        } else {
1811d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel            dstBounds->fLeft = srcBounds.fLeft - srcBounds.fLeft % granularity.width;
1812d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel        }
181327bb28473912181cf9a838e9282e86cb62e2d44begdaniel    } else {
1814d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel        dstBounds->fLeft = srcBounds.fLeft;
1815d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel        dstBounds->fRight = srcBounds.fRight;
181627bb28473912181cf9a838e9282e86cb62e2d44begdaniel    }
181727bb28473912181cf9a838e9282e86cb62e2d44begdaniel
181827bb28473912181cf9a838e9282e86cb62e2d44begdaniel    // Adjust height
1819d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel    if ((0 != granularity.height && 1 != granularity.height)) {
1820d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel        // Start with the bottom side of rect so we know if we end up going pass the maxHeight.
1821d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel        int bottomAdj = srcBounds.fBottom % granularity.height;
1822d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel        if (bottomAdj != 0) {
1823d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel            bottomAdj = granularity.height - bottomAdj;
1824d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel        }
1825d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel        dstBounds->fBottom = srcBounds.fBottom + bottomAdj;
1826d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel        if (dstBounds->fBottom > maxHeight) {
1827d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel            dstBounds->fBottom = maxHeight;
1828d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel            dstBounds->fTop = 0;
1829d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel        } else {
1830d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel            dstBounds->fTop = srcBounds.fTop - srcBounds.fTop % granularity.height;
1831d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel        }
183227bb28473912181cf9a838e9282e86cb62e2d44begdaniel    } else {
1833d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel        dstBounds->fTop = srcBounds.fTop;
1834d5797b3059a4037a6dce4c0a66693ba471b1588eegdaniel        dstBounds->fBottom = srcBounds.fBottom;
183527bb28473912181cf9a838e9282e86cb62e2d44begdaniel    }
183627bb28473912181cf9a838e9282e86cb62e2d44begdaniel}
183727bb28473912181cf9a838e9282e86cb62e2d44begdaniel
18387ec92413307c9da43c013d1e4e15716a44059810jvanverthvoid GrVkGpu::submitSecondaryCommandBuffer(GrVkSecondaryCommandBuffer* buffer,
18399cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel                                           const GrVkRenderPass* renderPass,
18409cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel                                           const VkClearValue* colorClear,
18419cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel                                           GrVkRenderTarget* target,
18429cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel                                           const SkIRect& bounds) {
1843e7d1b24ff0a04686aef54fcb9feaca7a03e19891egdaniel    const SkIRect* pBounds = &bounds;
1844e7d1b24ff0a04686aef54fcb9feaca7a03e19891egdaniel    SkIRect flippedBounds;
1845e7d1b24ff0a04686aef54fcb9feaca7a03e19891egdaniel    if (kBottomLeft_GrSurfaceOrigin == target->origin()) {
1846e7d1b24ff0a04686aef54fcb9feaca7a03e19891egdaniel        flippedBounds = bounds;
1847e7d1b24ff0a04686aef54fcb9feaca7a03e19891egdaniel        flippedBounds.fTop = target->height() - bounds.fBottom;
1848e7d1b24ff0a04686aef54fcb9feaca7a03e19891egdaniel        flippedBounds.fBottom = target->height() - bounds.fTop;
1849e7d1b24ff0a04686aef54fcb9feaca7a03e19891egdaniel        pBounds = &flippedBounds;
1850e7d1b24ff0a04686aef54fcb9feaca7a03e19891egdaniel    }
1851e7d1b24ff0a04686aef54fcb9feaca7a03e19891egdaniel
185227bb28473912181cf9a838e9282e86cb62e2d44begdaniel    // The bounds we use for the render pass should be of the granularity supported
185327bb28473912181cf9a838e9282e86cb62e2d44begdaniel    // by the device.
185427bb28473912181cf9a838e9282e86cb62e2d44begdaniel    const VkExtent2D& granularity = renderPass->granularity();
185527bb28473912181cf9a838e9282e86cb62e2d44begdaniel    SkIRect adjustedBounds;
185627bb28473912181cf9a838e9282e86cb62e2d44begdaniel    if ((0 != granularity.width && 1 != granularity.width) ||
185727bb28473912181cf9a838e9282e86cb62e2d44begdaniel        (0 != granularity.height && 1 != granularity.height)) {
185827bb28473912181cf9a838e9282e86cb62e2d44begdaniel        adjust_bounds_to_granularity(&adjustedBounds, *pBounds, granularity,
185927bb28473912181cf9a838e9282e86cb62e2d44begdaniel                                     target->width(), target->height());
186027bb28473912181cf9a838e9282e86cb62e2d44begdaniel        pBounds = &adjustedBounds;
186127bb28473912181cf9a838e9282e86cb62e2d44begdaniel    }
186227bb28473912181cf9a838e9282e86cb62e2d44begdaniel
18639cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel    // Currently it is fine for us to always pass in 1 for the clear count even if no attachment
18649cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel    // uses it. In the current state, we also only use the LOAD_OP_CLEAR for the color attachment
18659cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel    // which is always at the first attachment.
1866e7d1b24ff0a04686aef54fcb9feaca7a03e19891egdaniel    fCurrentCmdBuffer->beginRenderPass(this, renderPass, 1, colorClear, *target, *pBounds, true);
1867066df7ca911b65d416783f3bec6f4f1662948ad5egdaniel    fCurrentCmdBuffer->executeCommands(this, buffer);
1868164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->endRenderPass(this);
186966933552f1723c4a2b248711ab3d43921401e8e6egdaniel
1870ce3bfb1ed155880585b2d0bb0a8d3e43306e23f2egdaniel    this->didWriteToSurface(target, &bounds);
1871164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
18729cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel
187384741b308496409f4ff662658167221fc6801bbejvanverthGrFence SK_WARN_UNUSED_RESULT GrVkGpu::insertFence() const {
187484741b308496409f4ff662658167221fc6801bbejvanverth    VkFenceCreateInfo createInfo;
187584741b308496409f4ff662658167221fc6801bbejvanverth    memset(&createInfo, 0, sizeof(VkFenceCreateInfo));
187684741b308496409f4ff662658167221fc6801bbejvanverth    createInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
187784741b308496409f4ff662658167221fc6801bbejvanverth    createInfo.pNext = nullptr;
187884741b308496409f4ff662658167221fc6801bbejvanverth    createInfo.flags = 0;
187984741b308496409f4ff662658167221fc6801bbejvanverth    VkFence fence = VK_NULL_HANDLE;
188084741b308496409f4ff662658167221fc6801bbejvanverth    VkResult result = GR_VK_CALL(this->vkInterface(), CreateFence(this->device(), &createInfo,
188184741b308496409f4ff662658167221fc6801bbejvanverth                                                                  nullptr, &fence));
188284741b308496409f4ff662658167221fc6801bbejvanverth    // TODO: verify that all QueueSubmits before this will finish before this fence signals
188384741b308496409f4ff662658167221fc6801bbejvanverth    if (VK_SUCCESS == result) {
188484741b308496409f4ff662658167221fc6801bbejvanverth        GR_VK_CALL(this->vkInterface(), QueueSubmit(this->queue(), 0, nullptr, fence));
188584741b308496409f4ff662658167221fc6801bbejvanverth    }
188684741b308496409f4ff662658167221fc6801bbejvanverth    return (GrFence)fence;
188784741b308496409f4ff662658167221fc6801bbejvanverth}
188884741b308496409f4ff662658167221fc6801bbejvanverth
188984741b308496409f4ff662658167221fc6801bbejvanverthbool GrVkGpu::waitFence(GrFence fence, uint64_t timeout) const {
189084741b308496409f4ff662658167221fc6801bbejvanverth    VkResult result = GR_VK_CALL(this->vkInterface(), WaitForFences(this->device(), 1,
189184741b308496409f4ff662658167221fc6801bbejvanverth                                                                    (VkFence*)&fence,
189284741b308496409f4ff662658167221fc6801bbejvanverth                                                                    VK_TRUE,
189384741b308496409f4ff662658167221fc6801bbejvanverth                                                                    timeout));
189484741b308496409f4ff662658167221fc6801bbejvanverth    return (VK_SUCCESS == result);
189584741b308496409f4ff662658167221fc6801bbejvanverth}
189684741b308496409f4ff662658167221fc6801bbejvanverth
189784741b308496409f4ff662658167221fc6801bbejvanverthvoid GrVkGpu::deleteFence(GrFence fence) const {
189884741b308496409f4ff662658167221fc6801bbejvanverth    GR_VK_CALL(this->vkInterface(), DestroyFence(this->device(), (VkFence)fence, nullptr));
189984741b308496409f4ff662658167221fc6801bbejvanverth}
190084741b308496409f4ff662658167221fc6801bbejvanverth
1901