GrVkGpu.cpp revision a584de966a4f7ab71f3f07077cf1e226def9d730
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
39164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#define VK_CALL(X) GR_VK_CALL(this->vkInterface(), X)
40164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#define VK_CALL_RET(RET, X) GR_VK_CALL_RET(this->vkInterface(), RET, X)
41164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#define VK_CALL_ERRCHECK(X) GR_VK_CALL_ERRCHECK(this->vkInterface(), X)
42164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
43d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth#ifdef ENABLE_VK_LAYERS
44d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverthVKAPI_ATTR VkBool32 VKAPI_CALL DebugReportCallback(
45d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    VkDebugReportFlagsEXT       flags,
46d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    VkDebugReportObjectTypeEXT  objectType,
47d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    uint64_t                    object,
48d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    size_t                      location,
49d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    int32_t                     messageCode,
50d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    const char*                 pLayerPrefix,
51d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    const char*                 pMessage,
52d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    void*                       pUserData) {
53d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    if (flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
54d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        SkDebugf("Vulkan error [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
55d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    } else if (flags & VK_DEBUG_REPORT_WARNING_BIT_EXT) {
56d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        SkDebugf("Vulkan warning [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
57d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    } else if (flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) {
58d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        SkDebugf("Vulkan perf warning [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
59d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    } else {
60d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        SkDebugf("Vulkan info/debug [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
61d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    }
62d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    return VK_FALSE;
63d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth}
64d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth#endif
65d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth
66633b35657c964c32e7010b14bb2d396b4a764c52jvanverthGrGpu* GrVkGpu::Create(GrBackendContext backendContext, const GrContextOptions& options,
67633b35657c964c32e7010b14bb2d396b4a764c52jvanverth                       GrContext* context) {
68dc0fcd41e75682a8bfd5e285d684461475226330bsalomon    const GrVkBackendContext* vkBackendContext =
69dc0fcd41e75682a8bfd5e285d684461475226330bsalomon        reinterpret_cast<const GrVkBackendContext*>(backendContext);
70633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    if (!vkBackendContext) {
71dc0fcd41e75682a8bfd5e285d684461475226330bsalomon        vkBackendContext = GrVkBackendContext::Create();
72633b35657c964c32e7010b14bb2d396b4a764c52jvanverth        if (!vkBackendContext) {
73633b35657c964c32e7010b14bb2d396b4a764c52jvanverth            return nullptr;
74164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
75633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    } else {
76633b35657c964c32e7010b14bb2d396b4a764c52jvanverth        vkBackendContext->ref();
77164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
78164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
79633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    return new GrVkGpu(context, options, vkBackendContext);
80164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
81164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
82164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
83164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
849d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanaryGrVkGpu::GrVkGpu(GrContext* context, const GrContextOptions& options,
85633b35657c964c32e7010b14bb2d396b4a764c52jvanverth                 const GrVkBackendContext* backendCtx)
86164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    : INHERITED(context)
87633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    , fDevice(backendCtx->fDevice)
88633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    , fQueue(backendCtx->fQueue)
89633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    , fResourceProvider(this) {
90633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    fBackendContext.reset(backendCtx);
91164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
92d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth#ifdef ENABLE_VK_LAYERS
93419ca64f0f800dc098369b5aa5a604acd017b240brianosman    fCallback = VK_NULL_HANDLE;
94fd7bd45ac2178ce6b4a390f517f605750aaef6c8jvanverth    if (backendCtx->fExtensions & kEXT_debug_report_GrVkExtensionFlag) {
95fd7bd45ac2178ce6b4a390f517f605750aaef6c8jvanverth        // Setup callback creation information
96d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        VkDebugReportCallbackCreateInfoEXT callbackCreateInfo;
97d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        callbackCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
98d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        callbackCreateInfo.pNext = nullptr;
99d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        callbackCreateInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT |
100ef0c10cffefef90646ff2e238d7c2d82247a0370egdaniel                                   VK_DEBUG_REPORT_WARNING_BIT_EXT |
101d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth                                   //VK_DEBUG_REPORT_INFORMATION_BIT_EXT |
102d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth                                   //VK_DEBUG_REPORT_DEBUG_BIT_EXT |
103b4aa36211ca66ef127ac2954108742af1ead5082egdaniel                                   VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
104d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        callbackCreateInfo.pfnCallback = &DebugReportCallback;
105d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        callbackCreateInfo.pUserData = nullptr;
106d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth
107fd7bd45ac2178ce6b4a390f517f605750aaef6c8jvanverth        // Register the callback
108a00980e58037fa36d066be80d7fcc0f73b2dfd40jvanverth        GR_VK_CALL_ERRCHECK(this->vkInterface(), CreateDebugReportCallbackEXT(
109a00980e58037fa36d066be80d7fcc0f73b2dfd40jvanverth                            backendCtx->fInstance, &callbackCreateInfo, nullptr, &fCallback));
110d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    }
111d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth#endif
112633b35657c964c32e7010b14bb2d396b4a764c52jvanverth
113633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    fCompiler = shaderc_compiler_initialize();
114633b35657c964c32e7010b14bb2d396b4a764c52jvanverth
115fd7bd45ac2178ce6b4a390f517f605750aaef6c8jvanverth    fVkCaps.reset(new GrVkCaps(options, this->vkInterface(), backendCtx->fPhysicalDevice,
116c5ec1408298510410270ea67e895570ccfa76e54egdaniel                               backendCtx->fFeatures, backendCtx->fExtensions));
117633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    fCaps.reset(SkRef(fVkCaps.get()));
118633b35657c964c32e7010b14bb2d396b4a764c52jvanverth
119633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    VK_CALL(GetPhysicalDeviceMemoryProperties(backendCtx->fPhysicalDevice, &fPhysDevMemProps));
120633b35657c964c32e7010b14bb2d396b4a764c52jvanverth
121633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    const VkCommandPoolCreateInfo cmdPoolInfo = {
122633b35657c964c32e7010b14bb2d396b4a764c52jvanverth        VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // sType
123633b35657c964c32e7010b14bb2d396b4a764c52jvanverth        nullptr,                                    // pNext
124633b35657c964c32e7010b14bb2d396b4a764c52jvanverth        VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,       // CmdPoolCreateFlags
125b0d4352ca610654f98c3c4ebc67ed9ad9c8c8493jvanverth        backendCtx->fGraphicsQueueIndex,            // queueFamilyIndex
126633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    };
1279d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary    GR_VK_CALL_ERRCHECK(this->vkInterface(), CreateCommandPool(fDevice, &cmdPoolInfo, nullptr,
128633b35657c964c32e7010b14bb2d396b4a764c52jvanverth                                                               &fCmdPool));
129633b35657c964c32e7010b14bb2d396b4a764c52jvanverth
130633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    // must call this after creating the CommandPool
131633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    fResourceProvider.init();
1329a6cf800bc392fb4ba5065efb64f5b0320098d1aegdaniel    fCurrentCmdBuffer = fResourceProvider.createPrimaryCommandBuffer();
133633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    SkASSERT(fCurrentCmdBuffer);
134633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    fCurrentCmdBuffer->begin(this);
1356b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth
1366b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    // set up our heaps
1376b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    fHeaps[kLinearImage_Heap].reset(new GrVkHeap(this, GrVkHeap::kSubAlloc_Strategy, 16*1024*1024));
13805dceabf3422b785b52439378aa5527c42c6ca18egdaniel    // We want the OptimalImage_Heap to use a SubAlloc_strategy but it occasionally causes the
13905dceabf3422b785b52439378aa5527c42c6ca18egdaniel    // device to run out of memory. Most likely this is caused by fragmentation in the device heap
14005dceabf3422b785b52439378aa5527c42c6ca18egdaniel    // and we can't allocate more. Until we get a fix moving this to SingleAlloc.
14105dceabf3422b785b52439378aa5527c42c6ca18egdaniel    fHeaps[kOptimalImage_Heap].reset(new GrVkHeap(this, GrVkHeap::kSingleAlloc_Strategy, 64*1024*1024));
1426b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    fHeaps[kSmallOptimalImage_Heap].reset(new GrVkHeap(this, GrVkHeap::kSubAlloc_Strategy, 2*1024*1024));
1436b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    fHeaps[kVertexBuffer_Heap].reset(new GrVkHeap(this, GrVkHeap::kSingleAlloc_Strategy, 0));
1446b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    fHeaps[kIndexBuffer_Heap].reset(new GrVkHeap(this, GrVkHeap::kSingleAlloc_Strategy, 0));
1456b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    fHeaps[kUniformBuffer_Heap].reset(new GrVkHeap(this, GrVkHeap::kSubAlloc_Strategy, 64*1024));
1466b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    fHeaps[kCopyReadBuffer_Heap].reset(new GrVkHeap(this, GrVkHeap::kSingleAlloc_Strategy, 0));
1476b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    fHeaps[kCopyWriteBuffer_Heap].reset(new GrVkHeap(this, GrVkHeap::kSubAlloc_Strategy, 16*1024*1024));
148164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
149164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
150164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielGrVkGpu::~GrVkGpu() {
151164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->end(this);
152164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->unref(this);
153164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
154164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // wait for all commands to finish
155ddf9835e9cdf512b1d5172d014f00ceb6dacd039jvanverth    fResourceProvider.checkCommandBuffers();
156a00980e58037fa36d066be80d7fcc0f73b2dfd40jvanverth    SkDEBUGCODE(VkResult res = ) VK_CALL(QueueWaitIdle(fQueue));
157f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel
158f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel    // On windows, sometimes calls to QueueWaitIdle return before actually signalling the fences
159f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel    // on the command buffers even though they have completed. This causes an assert to fire when
160f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel    // destroying the command buffers. Currently this ony seems to happen on windows, so we add a
161f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel    // sleep to make sure the fence singals.
162f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel#ifdef SK_DEBUG
163f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel#if defined(SK_BUILD_FOR_WIN)
164f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel    Sleep(10); // In milliseconds
165f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel#else
166f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel    // Uncomment if above bug happens on non windows build.
167f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel    // sleep(1);        // In seconds
168f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel#endif
169f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel#endif
170f8c2be3fbccc4be0ccfce25327200e07fc99fd1fegdaniel
171ddf9835e9cdf512b1d5172d014f00ceb6dacd039jvanverth    // VK_ERROR_DEVICE_LOST is acceptable when tearing down (see 4.2.4 in spec)
172ddf9835e9cdf512b1d5172d014f00ceb6dacd039jvanverth    SkASSERT(VK_SUCCESS == res || VK_ERROR_DEVICE_LOST == res);
1739d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
174164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // must call this just before we destroy the VkDevice
175164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fResourceProvider.destroyResources();
176164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
177633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    VK_CALL(DestroyCommandPool(fDevice, fCmdPool, nullptr));
178633b35657c964c32e7010b14bb2d396b4a764c52jvanverth
179633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    shaderc_compiler_release(fCompiler);
180633b35657c964c32e7010b14bb2d396b4a764c52jvanverth
181633b35657c964c32e7010b14bb2d396b4a764c52jvanverth#ifdef ENABLE_VK_LAYERS
182a00980e58037fa36d066be80d7fcc0f73b2dfd40jvanverth    if (fCallback) {
183a00980e58037fa36d066be80d7fcc0f73b2dfd40jvanverth        VK_CALL(DestroyDebugReportCallbackEXT(fBackendContext->fInstance, fCallback, nullptr));
184419ca64f0f800dc098369b5aa5a604acd017b240brianosman        fCallback = VK_NULL_HANDLE;
185a00980e58037fa36d066be80d7fcc0f73b2dfd40jvanverth    }
186d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth#endif
187164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
188164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
189164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel///////////////////////////////////////////////////////////////////////////////
190164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1919cb6340a62a5d748e4189d50e51fa527c8c80c03egdanielGrGpuCommandBuffer* GrVkGpu::createCommandBuffer(
1929cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel            GrRenderTarget* target,
1939cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel            const GrGpuCommandBuffer::LoadAndStoreInfo& colorInfo,
1949cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel            const GrGpuCommandBuffer::LoadAndStoreInfo& stencilInfo) {
1959cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel    GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(target);
1969cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel    return new GrVkGpuCommandBuffer(this, vkRT, colorInfo, stencilInfo);
197066df7ca911b65d416783f3bec6f4f1662948ad5egdaniel}
198066df7ca911b65d416783f3bec6f4f1662948ad5egdaniel
199164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::submitCommandBuffer(SyncQueue sync) {
200164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(fCurrentCmdBuffer);
201164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->end(this);
202164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
203164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->submitToQueue(this, fQueue, sync);
204164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fResourceProvider.checkCommandBuffers();
205164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
206164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Release old command buffer and create a new one
207164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->unref(this);
2089a6cf800bc392fb4ba5065efb64f5b0320098d1aegdaniel    fCurrentCmdBuffer = fResourceProvider.createPrimaryCommandBuffer();
209164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(fCurrentCmdBuffer);
210164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
211164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->begin(this);
212164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
213164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
214164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel///////////////////////////////////////////////////////////////////////////////
2151bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdaltonGrBuffer* GrVkGpu::onCreateBuffer(size_t size, GrBufferType type, GrAccessPattern accessPattern,
2161bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton                                  const void* data) {
2171bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton    GrBuffer* buff;
218397536cabe12a9936659870dd220c869789424bacdalton    switch (type) {
219397536cabe12a9936659870dd220c869789424bacdalton        case kVertex_GrBufferType:
220397536cabe12a9936659870dd220c869789424bacdalton            SkASSERT(kDynamic_GrAccessPattern == accessPattern ||
221397536cabe12a9936659870dd220c869789424bacdalton                     kStatic_GrAccessPattern == accessPattern);
2221bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton            buff = GrVkVertexBuffer::Create(this, size, kDynamic_GrAccessPattern == accessPattern);
223e05bbbba79c569c1d32fa6475feecd1477fd3beeegdaniel            break;
224397536cabe12a9936659870dd220c869789424bacdalton        case kIndex_GrBufferType:
225397536cabe12a9936659870dd220c869789424bacdalton            SkASSERT(kDynamic_GrAccessPattern == accessPattern ||
226397536cabe12a9936659870dd220c869789424bacdalton                     kStatic_GrAccessPattern == accessPattern);
2271bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton            buff = GrVkIndexBuffer::Create(this, size, kDynamic_GrAccessPattern == accessPattern);
228e05bbbba79c569c1d32fa6475feecd1477fd3beeegdaniel            break;
229397536cabe12a9936659870dd220c869789424bacdalton        case kXferCpuToGpu_GrBufferType:
230c3d706f7ce87cdd94158d2266ab2fe2f18f5020ajvanverth            SkASSERT(kStream_GrAccessPattern == accessPattern);
2311bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton            buff = GrVkTransferBuffer::Create(this, size, GrVkBuffer::kCopyRead_Type);
232e05bbbba79c569c1d32fa6475feecd1477fd3beeegdaniel            break;
233397536cabe12a9936659870dd220c869789424bacdalton        case kXferGpuToCpu_GrBufferType:
234c3d706f7ce87cdd94158d2266ab2fe2f18f5020ajvanverth            SkASSERT(kStream_GrAccessPattern == accessPattern);
2351bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton            buff = GrVkTransferBuffer::Create(this, size, GrVkBuffer::kCopyWrite_Type);
236e05bbbba79c569c1d32fa6475feecd1477fd3beeegdaniel            break;
237397536cabe12a9936659870dd220c869789424bacdalton        default:
238397536cabe12a9936659870dd220c869789424bacdalton            SkFAIL("Unknown buffer type.");
239397536cabe12a9936659870dd220c869789424bacdalton            return nullptr;
240397536cabe12a9936659870dd220c869789424bacdalton    }
2411bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton    if (data && buff) {
2421bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton        buff->updateData(data, size);
2431bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton    }
2441bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton    return buff;
245164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
246164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
247164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
248164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::onGetWritePixelsInfo(GrSurface* dstSurface, int width, int height,
249164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                   GrPixelConfig srcConfig, DrawPreference* drawPreference,
250164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                   WritePixelTempDrawInfo* tempDrawInfo) {
251164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (kIndex_8_GrPixelConfig == srcConfig || GrPixelConfigIsCompressed(dstSurface->config())) {
252164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
253164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
254164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
2554583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    GrRenderTarget* renderTarget = dstSurface->asRenderTarget();
2564583ec51d9ddc830eeb854db068235be96ce59c4egdaniel
2574583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    // Start off assuming no swizzling
2584583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    tempDrawInfo->fSwizzle = GrSwizzle::RGBA();
2594583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    tempDrawInfo->fWriteConfig = srcConfig;
2604583ec51d9ddc830eeb854db068235be96ce59c4egdaniel
2614583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    // These settings we will always want if a temp draw is performed. Initially set the config
2624583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    // to srcConfig, though that may be modified if we decide to do a R/B swap
2634583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    tempDrawInfo->fTempSurfaceDesc.fFlags = kNone_GrSurfaceFlags;
2644583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    tempDrawInfo->fTempSurfaceDesc.fConfig = srcConfig;
2654583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    tempDrawInfo->fTempSurfaceDesc.fWidth = width;
2664583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    tempDrawInfo->fTempSurfaceDesc.fHeight = height;
2674583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    tempDrawInfo->fTempSurfaceDesc.fSampleCnt = 0;
2684583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    tempDrawInfo->fTempSurfaceDesc.fOrigin = kTopLeft_GrSurfaceOrigin;
2694583ec51d9ddc830eeb854db068235be96ce59c4egdaniel
270d66110f5972169dbcda8932c3a9a001adff23df4egdaniel    if (dstSurface->config() == srcConfig) {
271d66110f5972169dbcda8932c3a9a001adff23df4egdaniel        return true;
272d66110f5972169dbcda8932c3a9a001adff23df4egdaniel    }
273d66110f5972169dbcda8932c3a9a001adff23df4egdaniel
2744583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    if (renderTarget && this->vkCaps().isConfigRenderable(renderTarget->config(), false)) {
2754583ec51d9ddc830eeb854db068235be96ce59c4egdaniel        ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
2764583ec51d9ddc830eeb854db068235be96ce59c4egdaniel
2774583ec51d9ddc830eeb854db068235be96ce59c4egdaniel        bool configsAreRBSwaps = GrPixelConfigSwapRAndB(srcConfig) == dstSurface->config();
2784583ec51d9ddc830eeb854db068235be96ce59c4egdaniel
2794583ec51d9ddc830eeb854db068235be96ce59c4egdaniel        if (!this->vkCaps().isConfigTexturable(srcConfig) && configsAreRBSwaps) {
2804583ec51d9ddc830eeb854db068235be96ce59c4egdaniel            if (!this->vkCaps().isConfigTexturable(dstSurface->config())) {
2814583ec51d9ddc830eeb854db068235be96ce59c4egdaniel                return false;
2824583ec51d9ddc830eeb854db068235be96ce59c4egdaniel            }
2834583ec51d9ddc830eeb854db068235be96ce59c4egdaniel            tempDrawInfo->fTempSurfaceDesc.fConfig = dstSurface->config();
2844583ec51d9ddc830eeb854db068235be96ce59c4egdaniel            tempDrawInfo->fSwizzle = GrSwizzle::BGRA();
2854583ec51d9ddc830eeb854db068235be96ce59c4egdaniel            tempDrawInfo->fWriteConfig = dstSurface->config();
2864583ec51d9ddc830eeb854db068235be96ce59c4egdaniel        }
2874583ec51d9ddc830eeb854db068235be96ce59c4egdaniel        return true;
288164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
289164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
2904583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    return false;
291164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
292164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
293164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::onWritePixels(GrSurface* surface,
294164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                            int left, int top, int width, int height,
295a1e6b3be8124cef85f2e39e3cb85000ad9526d48bsalomon                            GrPixelConfig config,
296a1e6b3be8124cef85f2e39e3cb85000ad9526d48bsalomon                            const SkTArray<GrMipLevel>& texels) {
297164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkTexture* vkTex = static_cast<GrVkTexture*>(surface->asTexture());
298164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!vkTex) {
299164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
300164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
301164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
302900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // Make sure we have at least the base level
30303509eafa3e25819ff69f4d4f339d46264820c38jvanverth    if (texels.empty() || !texels.begin()->fPixels) {
30403509eafa3e25819ff69f4d4f339d46264820c38jvanverth        return false;
30503509eafa3e25819ff69f4d4f339d46264820c38jvanverth    }
306a1e6b3be8124cef85f2e39e3cb85000ad9526d48bsalomon
307164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // We assume Vulkan doesn't do sRGB <-> linear conversions when reading and writing pixels.
308164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (GrPixelConfigIsSRGB(surface->config()) != GrPixelConfigIsSRGB(config)) {
309164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
310164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
311164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
312164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    bool success = false;
313164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (GrPixelConfigIsCompressed(vkTex->desc().fConfig)) {
314164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // We check that config == desc.fConfig in GrGpu::getWritePixelsInfo()
315164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        SkASSERT(config == vkTex->desc().fConfig);
316164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // TODO: add compressed texture support
317164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // delete the following two lines and uncomment the two after that when ready
318164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        vkTex->unref();
319164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
320164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        //success = this->uploadCompressedTexData(vkTex->desc(), buffer, false, left, top, width,
321164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        //                                       height);
322164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    } else {
323164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        bool linearTiling = vkTex->isLinearTiled();
324900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        if (linearTiling) {
325900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            if (texels.count() > 1) {
326900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                SkDebugf("Can't upload mipmap data to linear tiled texture");
327900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                return false;
328900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            }
329900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            if (VK_IMAGE_LAYOUT_PREINITIALIZED != vkTex->currentLayout()) {
330900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                // Need to change the layout to general in order to perform a host write
331900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                vkTex->setImageLayout(this,
332900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                      VK_IMAGE_LAYOUT_GENERAL,
33350c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                                      VK_ACCESS_HOST_WRITE_BIT,
33450c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                                      VK_PIPELINE_STAGE_HOST_BIT,
335900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                      false);
336bdf8811b3126ab08ccff08b5e647b80cae5bd087egdaniel                this->submitCommandBuffer(kForce_SyncQueue);
337900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            }
338900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            success = this->uploadTexDataLinear(vkTex, left, top, width, height, config,
339900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                                texels.begin()->fPixels, texels.begin()->fRowBytes);
340900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        } else {
341c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth            int newMipLevels = texels.count();
34282c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth            int currentMipLevels = vkTex->texturePriv().maxMipMapLevel() + 1;
34382c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth            if (newMipLevels != currentMipLevels) {
344c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth                if (!vkTex->reallocForMipmap(this, newMipLevels)) {
345900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                    return false;
346900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                }
347900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            }
348900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            success = this->uploadTexDataOptimal(vkTex, left, top, width, height, config, texels);
349164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
350164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
3514583ec51d9ddc830eeb854db068235be96ce59c4egdaniel
352900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    return success;
353164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
354164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
355900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverthbool GrVkGpu::uploadTexDataLinear(GrVkTexture* tex,
356900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                  int left, int top, int width, int height,
357900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                  GrPixelConfig dataConfig,
358900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                  const void* data,
359900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                  size_t rowBytes) {
360164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(data);
361900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    SkASSERT(tex->isLinearTiled());
362164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
363164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // If we're uploading compressed data then we should be using uploadCompressedTexData
364164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(!GrPixelConfigIsCompressed(dataConfig));
365164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
366164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    size_t bpp = GrBytesPerPixel(dataConfig);
367164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
368164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    const GrSurfaceDesc& desc = tex->desc();
369164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
370164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!GrSurfacePriv::AdjustWritePixelParams(desc.fWidth, desc.fHeight, bpp, &left, &top,
371164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                               &width, &height, &data, &rowBytes)) {
372164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
373164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
374164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    size_t trimRowBytes = width * bpp;
375164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
376900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    SkASSERT(VK_IMAGE_LAYOUT_PREINITIALIZED == tex->currentLayout() ||
377900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth             VK_IMAGE_LAYOUT_GENERAL == tex->currentLayout());
378900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    const VkImageSubresource subres = {
379900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        VK_IMAGE_ASPECT_COLOR_BIT,
380900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        0,  // mipLevel
381900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        0,  // arraySlice
382900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    };
383900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    VkSubresourceLayout layout;
384900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    VkResult err;
385900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
386900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    const GrVkInterface* interface = this->vkInterface();
387900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
388900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    GR_VK_CALL(interface, GetImageSubresourceLayout(fDevice,
389b2df0c2702329be6380a943d548e7377a51d8565egdaniel                                                    tex->image(),
390900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                                    &subres,
391900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                                    &layout));
392900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
393900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    int texTop = kBottomLeft_GrSurfaceOrigin == desc.fOrigin ? tex->height() - top - height : top;
3941e305ba0d6a4237020d36234e9e286d3b0489401jvanverth    const GrVkAlloc& alloc = tex->alloc();
3951e305ba0d6a4237020d36234e9e286d3b0489401jvanverth    VkDeviceSize offset = alloc.fOffset + texTop*layout.rowPitch + left*bpp;
396900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    VkDeviceSize size = height*layout.rowPitch;
397900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    void* mapPtr;
3981e305ba0d6a4237020d36234e9e286d3b0489401jvanverth    err = GR_VK_CALL(interface, MapMemory(fDevice, alloc.fMemory, offset, size, 0, &mapPtr));
399900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    if (err) {
400900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        return false;
401900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    }
402164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
403900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    if (kBottomLeft_GrSurfaceOrigin == desc.fOrigin) {
404900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        // copy into buffer by rows
405900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        const char* srcRow = reinterpret_cast<const char*>(data);
406900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        char* dstRow = reinterpret_cast<char*>(mapPtr)+(height - 1)*layout.rowPitch;
407900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        for (int y = 0; y < height; y++) {
408900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            memcpy(dstRow, srcRow, trimRowBytes);
409900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            srcRow += rowBytes;
410900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            dstRow -= layout.rowPitch;
411900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        }
412900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    } else {
413900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        // If there is no padding on the src (rowBytes) or dst (layout.rowPitch) we can memcpy
414900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        if (trimRowBytes == rowBytes && trimRowBytes == layout.rowPitch) {
415900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            memcpy(mapPtr, data, trimRowBytes * height);
416164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        } else {
41788e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel            SkRectMemcpy(mapPtr, static_cast<size_t>(layout.rowPitch), data, rowBytes, trimRowBytes,
41888e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel                         height);
419164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
420900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    }
421164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
4221e305ba0d6a4237020d36234e9e286d3b0489401jvanverth    GR_VK_CALL(interface, UnmapMemory(fDevice, alloc.fMemory));
423900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
424900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    return true;
425900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth}
426900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
427900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverthbool GrVkGpu::uploadTexDataOptimal(GrVkTexture* tex,
428a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth                                   int left, int top, int width, int height,
429a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth                                   GrPixelConfig dataConfig,
430a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth                                   const SkTArray<GrMipLevel>& texels) {
431900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    SkASSERT(!tex->isLinearTiled());
432900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // The assumption is either that we have no mipmaps, or that our rect is the entire texture
433900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    SkASSERT(1 == texels.count() ||
434900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth             (0 == left && 0 == top && width == tex->width() && height == tex->height()));
435900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
436900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // If we're uploading compressed data then we should be using uploadCompressedTexData
437900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    SkASSERT(!GrPixelConfigIsCompressed(dataConfig));
438900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
439900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    if (width == 0 || height == 0) {
440900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        return false;
441900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    }
442900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
443900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    const GrSurfaceDesc& desc = tex->desc();
444900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    SkASSERT(this->caps()->isConfigTexturable(desc.fConfig));
445900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    size_t bpp = GrBytesPerPixel(dataConfig);
446900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
447900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // texels is const.
448c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    // But we may need to adjust the fPixels ptr based on the copyRect, or fRowBytes.
449c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    // Because of this we need to make a non-const shallow copy of texels.
450c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    SkTArray<GrMipLevel> texelsShallowCopy(texels);
451900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
452c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    for (int currentMipLevel = texelsShallowCopy.count() - 1; currentMipLevel >= 0;
453c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth         currentMipLevel--) {
454c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        SkASSERT(texelsShallowCopy[currentMipLevel].fPixels);
455900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    }
456900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
457900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // Determine whether we need to flip when we copy into the buffer
458c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    bool flipY = (kBottomLeft_GrSurfaceOrigin == desc.fOrigin && !texelsShallowCopy.empty());
459900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
460c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    // adjust any params (left, top, currentWidth, currentHeight
461900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // find the combined size of all the mip levels and the relative offset of
462900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // each into the collective buffer
463c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    // Do the first level separately because we may need to adjust width and height
464c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    // (for the non-mipped case).
465c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    if (!GrSurfacePriv::AdjustWritePixelParams(desc.fWidth, desc.fHeight, bpp, &left, &top,
466c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth                                               &width,
467c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth                                               &height,
468c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth                                               &texelsShallowCopy[0].fPixels,
469c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth                                               &texelsShallowCopy[0].fRowBytes)) {
470c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        return false;
471c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    }
472c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    SkTArray<size_t> individualMipOffsets(texelsShallowCopy.count());
473c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    individualMipOffsets.push_back(0);
474c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    size_t combinedBufferSize = width * bpp * height;
475c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    int currentWidth = width;
476c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    int currentHeight = height;
477c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    for (int currentMipLevel = 1; currentMipLevel < texelsShallowCopy.count(); currentMipLevel++) {
478c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        currentWidth = SkTMax(1, currentWidth/2);
479c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        currentHeight = SkTMax(1, currentHeight/2);
480c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        if (!GrSurfacePriv::AdjustWritePixelParams(desc.fWidth, desc.fHeight, bpp, &left, &top,
481c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth                                                   &currentWidth,
482c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth                                                   &currentHeight,
483c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth                                                   &texelsShallowCopy[currentMipLevel].fPixels,
484c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth                                                   &texelsShallowCopy[currentMipLevel].fRowBytes)) {
485c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth            return false;
486c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        }
487900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        const size_t trimmedSize = currentWidth * bpp * currentHeight;
488900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        individualMipOffsets.push_back(combinedBufferSize);
489900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        combinedBufferSize += trimmedSize;
490900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    }
491900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
492900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // allocate buffer to hold our mip data
493900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    GrVkTransferBuffer* transferBuffer =
494900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                   GrVkTransferBuffer::Create(this, combinedBufferSize, GrVkBuffer::kCopyRead_Type);
495900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
496900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    char* buffer = (char*) transferBuffer->map();
497c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    SkTArray<VkBufferImageCopy> regions(texelsShallowCopy.count());
498900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
499c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    currentWidth = width;
500c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    currentHeight = height;
501c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    for (int currentMipLevel = 0; currentMipLevel < texelsShallowCopy.count(); currentMipLevel++) {
502900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        const size_t trimRowBytes = currentWidth * bpp;
503c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        const size_t rowBytes = texelsShallowCopy[currentMipLevel].fRowBytes;
504900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
505900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        // copy data into the buffer, skipping the trailing bytes
506900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        char* dst = buffer + individualMipOffsets[currentMipLevel];
507c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        const char* src = (const char*)texelsShallowCopy[currentMipLevel].fPixels;
508900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        if (flipY) {
509900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            src += (currentHeight - 1) * rowBytes;
510900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            for (int y = 0; y < currentHeight; y++) {
511900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                memcpy(dst, src, trimRowBytes);
512900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                src -= rowBytes;
513900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                dst += trimRowBytes;
514164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            }
515900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        } else if (trimRowBytes == rowBytes) {
516900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            memcpy(dst, src, trimRowBytes * currentHeight);
517164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        } else {
518900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            SkRectMemcpy(dst, trimRowBytes, src, rowBytes, trimRowBytes, currentHeight);
519164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
520164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
521900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        VkBufferImageCopy& region = regions.push_back();
522164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        memset(&region, 0, sizeof(VkBufferImageCopy));
523900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        region.bufferOffset = individualMipOffsets[currentMipLevel];
524900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        region.bufferRowLength = currentWidth;
525900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        region.bufferImageHeight = currentHeight;
526cf942c4ef750712b624867cbb2217c14857db3c6bsalomon        region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, SkToU32(currentMipLevel), 0, 1 };
527c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        region.imageOffset = { left, flipY ? tex->height() - top - currentHeight : top, 0 };
528900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        region.imageExtent = { (uint32_t)currentWidth, (uint32_t)currentHeight, 1 };
5294583ec51d9ddc830eeb854db068235be96ce59c4egdaniel
530c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        currentWidth = SkTMax(1, currentWidth/2);
531c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        currentHeight = SkTMax(1, currentHeight/2);
532900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    }
533164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
534900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    transferBuffer->unmap();
535164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
536900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // make sure the unmap has finished
537900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    transferBuffer->addMemoryBarrier(this,
538900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                     VK_ACCESS_HOST_WRITE_BIT,
539900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                     VK_ACCESS_TRANSFER_READ_BIT,
540900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                     VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
541900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                     VK_PIPELINE_STAGE_TRANSFER_BIT,
542900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                     false);
543164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
544900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // Change layout of our target so it can be copied to
545900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    tex->setImageLayout(this,
546900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                        VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
54750c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                        VK_ACCESS_TRANSFER_WRITE_BIT,
54850c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                        VK_PIPELINE_STAGE_TRANSFER_BIT,
549900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                        false);
550900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
551900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // Copy the buffer to the image
552900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    fCurrentCmdBuffer->copyBufferToImage(this,
553900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                         transferBuffer,
554900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                         tex,
555900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
556900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                         regions.count(),
557900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                         regions.begin());
558900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    transferBuffer->unref();
559164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
560164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return true;
561164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
562164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
563164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
5642e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunenGrTexture* GrVkGpu::onCreateTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted,
565a1e6b3be8124cef85f2e39e3cb85000ad9526d48bsalomon                                    const SkTArray<GrMipLevel>& texels) {
566164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag);
567164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
568164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkFormat pixelFormat;
569164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!GrPixelConfigToVkFormat(desc.fConfig, &pixelFormat)) {
570164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return nullptr;
571164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
572164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
573164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!fVkCaps->isConfigTexturable(desc.fConfig)) {
574164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return nullptr;
575164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
576164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
5770a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel    if (renderTarget && !fVkCaps->isConfigRenderable(desc.fConfig, false)) {
5780a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel        return nullptr;
5790a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel    }
5800a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel
581164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    bool linearTiling = false;
582164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (SkToBool(desc.fFlags & kZeroCopy_GrSurfaceFlag)) {
583900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        // we can't have a linear texture with a mipmap
584900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        if (texels.count() > 1) {
585900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            SkDebugf("Trying to create linear tiled texture with mipmap");
586900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            return nullptr;
587900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        }
588164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        if (fVkCaps->isConfigTexurableLinearly(desc.fConfig) &&
589164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            (!renderTarget || fVkCaps->isConfigRenderableLinearly(desc.fConfig, false))) {
590164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            linearTiling = true;
591164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        } else {
592164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            return nullptr;
593164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
594164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
595164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
596164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT;
597164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (renderTarget) {
598164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        usageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
599164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
600164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
601164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // For now we will set the VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT and
602164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // VK_IMAGE_USAGE_TRANSFER_SOURCE_BIT on every texture since we do not know whether or not we
603164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // will be using this texture in some copy or not. Also this assumes, as is the current case,
60462340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    // that all render targets in vulkan are also textures. If we change this practice of setting
605164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // both bits, we must make sure to set the destination bit if we are uploading srcData to the
606164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // texture.
607164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    usageFlags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
608164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
609a1e6b3be8124cef85f2e39e3cb85000ad9526d48bsalomon    VkFlags memProps = (!texels.empty() && linearTiling) ? VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT :
610a1e6b3be8124cef85f2e39e3cb85000ad9526d48bsalomon                                                           VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
611164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
612164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // This ImageDesc refers to the texture that will be read by the client. Thus even if msaa is
61362340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    // requested, this ImageDesc describes the resolved texture. Therefore we always have samples set
614164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // to 1.
615c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    int mipLevels = texels.empty() ? 1 : texels.count();
616164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkImage::ImageDesc imageDesc;
617164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fImageType = VK_IMAGE_TYPE_2D;
618164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fFormat = pixelFormat;
619164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fWidth = desc.fWidth;
620164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fHeight = desc.fHeight;
621c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    imageDesc.fLevels = linearTiling ? 1 : mipLevels;
622164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fSamples = 1;
623164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fImageTiling = linearTiling ? VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL;
624164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fUsageFlags = usageFlags;
625164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fMemProps = memProps;
626164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
627164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkTexture* tex;
628164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (renderTarget) {
6292e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        tex = GrVkTextureRenderTarget::CreateNewTextureRenderTarget(this, budgeted, desc,
630164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                    imageDesc);
631164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    } else {
6322e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        tex = GrVkTexture::CreateNewTexture(this, budgeted, desc, imageDesc);
633164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
634164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
635164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!tex) {
636164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return nullptr;
637164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
638164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
639e699d0cd25fd059e3f0c4949e613e50c83a52179bsalomon    if (!texels.empty()) {
640e699d0cd25fd059e3f0c4949e613e50c83a52179bsalomon        SkASSERT(texels.begin()->fPixels);
641900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        bool success;
642900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        if (linearTiling) {
643900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            success = this->uploadTexDataLinear(tex, 0, 0, desc.fWidth, desc.fHeight, desc.fConfig,
644900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                                texels.begin()->fPixels, texels.begin()->fRowBytes);
645900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        } else {
646900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            success = this->uploadTexDataOptimal(tex, 0, 0, desc.fWidth, desc.fHeight, desc.fConfig,
647900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                                 texels);
648900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        }
649900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        if (!success) {
650164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            tex->unref();
651164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            return nullptr;
652164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
653164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
654164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
655164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return tex;
656164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
657164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
658164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
659164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
660a584de966a4f7ab71f3f07077cf1e226def9d730jvanverthbool GrVkGpu::updateBuffer(GrVkBuffer* buffer, const void* src, size_t srcSizeInBytes) {
661a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth
662a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth    // Update the buffer
663a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth    fCurrentCmdBuffer->updateBuffer(this, buffer, 0, srcSizeInBytes, src);
664a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth
665a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth    return true;
666a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth}
667a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth
668a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth////////////////////////////////////////////////////////////////////////////////
669a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth
670164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielstatic GrSurfaceOrigin resolve_origin(GrSurfaceOrigin origin) {
671164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // By default, all textures in Vk use TopLeft
672164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (kDefault_GrSurfaceOrigin == origin) {
673164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return kTopLeft_GrSurfaceOrigin;
674164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    } else {
675164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return origin;
676164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
677164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
678164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
679164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielGrTexture* GrVkGpu::onWrapBackendTexture(const GrBackendTextureDesc& desc,
680164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                         GrWrapOwnership ownership) {
681164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (0 == desc.fTextureHandle) {
682164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return nullptr;
683164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
684164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
685164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    int maxSize = this->caps()->maxTextureSize();
686164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (desc.fWidth > maxSize || desc.fHeight > maxSize) {
687164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return nullptr;
688164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
689164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
690b2df0c2702329be6380a943d548e7377a51d8565egdaniel    const GrVkImageInfo* info = reinterpret_cast<const GrVkImageInfo*>(desc.fTextureHandle);
6911e305ba0d6a4237020d36234e9e286d3b0489401jvanverth    if (VK_NULL_HANDLE == info->fImage || VK_NULL_HANDLE == info->fAlloc.fMemory) {
692fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        return nullptr;
693fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    }
694b2df0c2702329be6380a943d548e7377a51d8565egdaniel#ifdef SK_DEBUG
695b2df0c2702329be6380a943d548e7377a51d8565egdaniel    VkFormat format;
696b2df0c2702329be6380a943d548e7377a51d8565egdaniel    if (!GrPixelConfigToVkFormat(desc.fConfig, &format)) {
697b2df0c2702329be6380a943d548e7377a51d8565egdaniel        return nullptr;
698b2df0c2702329be6380a943d548e7377a51d8565egdaniel    }
699b2df0c2702329be6380a943d548e7377a51d8565egdaniel    SkASSERT(format == info->fFormat);
700b2df0c2702329be6380a943d548e7377a51d8565egdaniel#endif
701164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
702164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrSurfaceDesc surfDesc;
703164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // next line relies on GrBackendTextureDesc's flags matching GrTexture's
704164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    surfDesc.fFlags = (GrSurfaceFlags)desc.fFlags;
705164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    surfDesc.fWidth = desc.fWidth;
706164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    surfDesc.fHeight = desc.fHeight;
707164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    surfDesc.fConfig = desc.fConfig;
708164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    surfDesc.fSampleCnt = SkTMin(desc.fSampleCnt, this->caps()->maxSampleCount());
709164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrBackendTextureFlag);
710164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // In GL, Chrome assumes all textures are BottomLeft
711164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // In VK, we don't have this restriction
712164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    surfDesc.fOrigin = resolve_origin(desc.fOrigin);
713164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
714164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkTexture* texture = nullptr;
715164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (renderTarget) {
7169d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary        texture = GrVkTextureRenderTarget::CreateWrappedTextureRenderTarget(this, surfDesc,
717b2df0c2702329be6380a943d548e7377a51d8565egdaniel                                                                            ownership, info);
718164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    } else {
719b2df0c2702329be6380a943d548e7377a51d8565egdaniel        texture = GrVkTexture::CreateWrappedTexture(this, surfDesc, ownership, info);
720164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
721164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!texture) {
722164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return nullptr;
723164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
724164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
725164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return texture;
726164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
727164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
728164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielGrRenderTarget* GrVkGpu::onWrapBackendRenderTarget(const GrBackendRenderTargetDesc& wrapDesc,
729164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                   GrWrapOwnership ownership) {
7309d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
731b2df0c2702329be6380a943d548e7377a51d8565egdaniel    const GrVkImageInfo* info =
732b2df0c2702329be6380a943d548e7377a51d8565egdaniel        reinterpret_cast<const GrVkImageInfo*>(wrapDesc.fRenderTargetHandle);
733fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    if (VK_NULL_HANDLE == info->fImage ||
7341e305ba0d6a4237020d36234e9e286d3b0489401jvanverth        (VK_NULL_HANDLE == info->fAlloc.fMemory && kAdopt_GrWrapOwnership == ownership)) {
735fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        return nullptr;
736fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    }
737164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
738164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrSurfaceDesc desc;
739164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    desc.fConfig = wrapDesc.fConfig;
740164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    desc.fFlags = kCheckAllocation_GrSurfaceFlag;
741164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    desc.fWidth = wrapDesc.fWidth;
742164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    desc.fHeight = wrapDesc.fHeight;
743164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    desc.fSampleCnt = SkTMin(wrapDesc.fSampleCnt, this->caps()->maxSampleCount());
744164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
745164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    desc.fOrigin = resolve_origin(wrapDesc.fOrigin);
746164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
747164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkRenderTarget* tgt = GrVkRenderTarget::CreateWrappedRenderTarget(this, desc,
7482e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen                                                                        ownership,
749fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth                                                                        info);
750164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (tgt && wrapDesc.fStencilBits) {
751164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        if (!createStencilAttachmentForRenderTarget(tgt, desc.fWidth, desc.fHeight)) {
752164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            tgt->unref();
753164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            return nullptr;
754164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
755164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
756164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return tgt;
757164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
758164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
75962340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverthvoid GrVkGpu::generateMipmap(GrVkTexture* tex) const {
760900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // don't do anything for linearly tiled textures (can't have mipmaps)
76162340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    if (tex->isLinearTiled()) {
762900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        SkDebugf("Trying to create mipmap for linear tiled texture");
76362340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth        return;
76462340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    }
76562340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth
76662340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    // We cannot generate mipmaps for images that are multisampled.
76762340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    // TODO: does it even make sense for rendertargets in general?
76862340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    if (tex->asRenderTarget() && tex->asRenderTarget()->numColorSamples() > 1) {
76962340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth        return;
77062340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    }
77162340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth
77262340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    // determine if we can blit to and from this format
77362340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    const GrVkCaps& caps = this->vkCaps();
77462340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    if (!caps.configCanBeDstofBlit(tex->config(), false) ||
77562340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth        !caps.configCanBeSrcofBlit(tex->config(), false)) {
77662340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth        return;
77762340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    }
77862340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth
77962340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    // change the original image's layout
78062340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    tex->setImageLayout(this, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
78150c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                        VK_ACCESS_TRANSFER_READ_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, false);
78262340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth
78362340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    // grab handle to the original image resource
784b2df0c2702329be6380a943d548e7377a51d8565egdaniel    const GrVkResource* oldResource = tex->resource();
78562340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    oldResource->ref();
786b2df0c2702329be6380a943d548e7377a51d8565egdaniel    VkImage oldImage = tex->image();
78762340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth
78882c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth    // SkMipMap doesn't include the base level in the level count so we have to add 1
78982c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth    uint32_t levelCount = SkMipMap::ComputeLevelCount(tex->width(), tex->height()) + 1;
79082c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth    if (!tex->reallocForMipmap(this, levelCount)) {
79162340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth        oldResource->unref(this);
79262340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth        return;
79362340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    }
79462340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth
79562340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    // change the new image's layout
79650c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth    tex->setImageLayout(this, VK_IMAGE_LAYOUT_GENERAL,
79750c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                        VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, false);
79862340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth
79962340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    // Blit original image
80062340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    int width = tex->width();
80162340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    int height = tex->height();
80262340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth
80362340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    VkImageBlit blitRegion;
80462340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    memset(&blitRegion, 0, sizeof(VkImageBlit));
80562340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    blitRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
80662340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    blitRegion.srcOffsets[0] = { 0, 0, 0 };
807e9906e71fbc29968ea10680f0fcd53a4153c7568brianosman    blitRegion.srcOffsets[1] = { width, height, 1 };
80882c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth    blitRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
80962340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    blitRegion.dstOffsets[0] = { 0, 0, 0 };
810e9906e71fbc29968ea10680f0fcd53a4153c7568brianosman    blitRegion.dstOffsets[1] = { width, height, 1 };
81162340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth
81262340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    fCurrentCmdBuffer->blitImage(this,
81362340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth                                 oldResource,
814b2df0c2702329be6380a943d548e7377a51d8565egdaniel                                 oldImage,
81562340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth                                 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
81662340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth                                 tex->resource(),
817b2df0c2702329be6380a943d548e7377a51d8565egdaniel                                 tex->image(),
81850c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                                 VK_IMAGE_LAYOUT_GENERAL,
81962340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth                                 1,
82062340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth                                 &blitRegion,
82162340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth                                 VK_FILTER_LINEAR);
82250c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth
82350c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth    // setup memory barrier
824b2df0c2702329be6380a943d548e7377a51d8565egdaniel    SkASSERT(GrVkFormatToPixelConfig(tex->imageFormat(), nullptr));
82550c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth    VkImageAspectFlags aspectFlags = VK_IMAGE_ASPECT_COLOR_BIT;
82650c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth    VkImageMemoryBarrier imageMemoryBarrier = {
82750c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth        VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,          // sType
82850c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth        NULL,                                            // pNext
82950c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth        VK_ACCESS_TRANSFER_WRITE_BIT,                    // outputMask
83050c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth        VK_ACCESS_TRANSFER_READ_BIT,                     // inputMask
83150c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth        VK_IMAGE_LAYOUT_GENERAL,                         // oldLayout
83250c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth        VK_IMAGE_LAYOUT_GENERAL,                         // newLayout
83350c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth        VK_QUEUE_FAMILY_IGNORED,                         // srcQueueFamilyIndex
83450c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth        VK_QUEUE_FAMILY_IGNORED,                         // dstQueueFamilyIndex
835b2df0c2702329be6380a943d548e7377a51d8565egdaniel        tex->image(),                                    // image
83650c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth        { aspectFlags, 0, 1, 0, 1 }                      // subresourceRange
83750c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth    };
83850c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth
83962340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    // Blit the miplevels
84082c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth    uint32_t mipLevel = 1;
84182c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth    while (mipLevel < levelCount) {
84282c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth        int prevWidth = width;
84382c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth        int prevHeight = height;
84482c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth        width = SkTMax(1, width / 2);
84582c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth        height = SkTMax(1, height / 2);
84682c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth
84750c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth        imageMemoryBarrier.subresourceRange.baseMipLevel = mipLevel - 1;
84850c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth        this->addImageMemoryBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
84950c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                                    false, &imageMemoryBarrier);
85050c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth
85150c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth        blitRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, mipLevel - 1, 0, 1 };
85262340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth        blitRegion.srcOffsets[0] = { 0, 0, 0 };
853e9906e71fbc29968ea10680f0fcd53a4153c7568brianosman        blitRegion.srcOffsets[1] = { prevWidth, prevHeight, 1 };
85482c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth        blitRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, mipLevel, 0, 1 };
85562340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth        blitRegion.dstOffsets[0] = { 0, 0, 0 };
856e9906e71fbc29968ea10680f0fcd53a4153c7568brianosman        blitRegion.dstOffsets[1] = { width, height, 1 };
85762340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth        fCurrentCmdBuffer->blitImage(this,
858b2df0c2702329be6380a943d548e7377a51d8565egdaniel                                     *tex,
859b2df0c2702329be6380a943d548e7377a51d8565egdaniel                                     *tex,
86062340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth                                     1,
86162340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth                                     &blitRegion,
86262340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth                                     VK_FILTER_LINEAR);
86382c0558d93b15e13f5ad431eeef44055af25bbcbjvanverth        ++mipLevel;
86462340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    }
86562340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth
86662340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    oldResource->unref(this);
86762340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth}
86862340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth
869164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
870164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
871164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielGrStencilAttachment* GrVkGpu::createStencilAttachmentForRenderTarget(const GrRenderTarget* rt,
872164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                     int width,
873164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                     int height) {
874164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(width >= rt->width());
875164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(height >= rt->height());
876164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
877164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    int samples = rt->numStencilSamples();
878164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
8798f1dcaa6f3cc098bd5efd2595ca20e0bc1847d10egdaniel    const GrVkCaps::StencilFormat& sFmt = this->vkCaps().preferedStencilFormat();
880164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
881164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkStencilAttachment* stencil(GrVkStencilAttachment::Create(this,
882164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                 width,
883164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                 height,
884164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                 samples,
885164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                 sFmt));
886164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fStats.incStencilAttachmentCreates();
887164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return stencil;
888164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
889164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
890164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
891164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
892164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielGrBackendObject GrVkGpu::createTestingOnlyBackendTexture(void* srcData, int w, int h,
8930a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel                                                         GrPixelConfig config,
8940a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel                                                         bool isRenderTarget) {
895164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
896164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkFormat pixelFormat;
897164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!GrPixelConfigToVkFormat(config, &pixelFormat)) {
898164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return 0;
899164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
900164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
901164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    bool linearTiling = false;
902164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!fVkCaps->isConfigTexturable(config)) {
903164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return 0;
904164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
905164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
9060a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel    if (isRenderTarget && !fVkCaps->isConfigRenderable(config, false)) {
9070a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel        return 0;
9080a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel    }
9090a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel
9100a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel    if (fVkCaps->isConfigTexurableLinearly(config) &&
9110a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel        (!isRenderTarget || fVkCaps->isConfigRenderableLinearly(config, false))) {
912164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        linearTiling = true;
913164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
914164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
915164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Currently this is not supported since it requires a copy which has not yet been implemented.
916164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (srcData && !linearTiling) {
917164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return 0;
918164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
919164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
920164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT;
921164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    usageFlags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
922164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    usageFlags |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
9230a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel    if (isRenderTarget) {
9240a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel        usageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
9250a3a7f7303273151f1585b3cf5f6968e3932bfedegdaniel    }
926164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
927fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    VkImage image = VK_NULL_HANDLE;
9286b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    GrVkAlloc alloc = { VK_NULL_HANDLE, 0, 0 };
929164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
930fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    VkImageTiling imageTiling = linearTiling ? VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL;
931fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    VkImageLayout initialLayout = (VK_IMAGE_TILING_LINEAR == imageTiling)
932fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth                                ? VK_IMAGE_LAYOUT_PREINITIALIZED
933fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth                                : VK_IMAGE_LAYOUT_UNDEFINED;
934fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth
935fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    // Create Image
936fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    VkSampleCountFlagBits vkSamples;
937fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    if (!GrSampleCountToVkSampleCount(1, &vkSamples)) {
938fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        return 0;
939fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    }
940fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth
941fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    const VkImageCreateInfo imageCreateInfo = {
942fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,         // sType
943fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        NULL,                                        // pNext
944fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        0,                                           // VkImageCreateFlags
945fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        VK_IMAGE_TYPE_2D,                            // VkImageType
946fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        pixelFormat,                                 // VkFormat
947384b5e9cd36e443437de8df3b0f78ef4150efbacethannicholas        { (uint32_t) w, (uint32_t) h, 1 },           // VkExtent3D
948fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        1,                                           // mipLevels
949fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        1,                                           // arrayLayers
950fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        vkSamples,                                   // samples
951fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        imageTiling,                                 // VkImageTiling
952fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        usageFlags,                                  // VkImageUsageFlags
953fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        VK_SHARING_MODE_EXCLUSIVE,                   // VkSharingMode
954fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        0,                                           // queueFamilyCount
955fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        0,                                           // pQueueFamilyIndices
956fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        initialLayout                                // initialLayout
957fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    };
958fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth
959fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    GR_VK_CALL_ERRCHECK(this->vkInterface(), CreateImage(this->device(), &imageCreateInfo, nullptr, &image));
960fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth
9616b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    if (!GrVkMemory::AllocAndBindImageMemory(this, image, linearTiling, &alloc)) {
962fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        VK_CALL(DestroyImage(this->device(), image, nullptr));
963164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return 0;
964164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
965164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
966164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (srcData) {
967164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        if (linearTiling) {
968164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            const VkImageSubresource subres = {
969164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                VK_IMAGE_ASPECT_COLOR_BIT,
970164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                0,  // mipLevel
971164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                0,  // arraySlice
972164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            };
973164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            VkSubresourceLayout layout;
974164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            VkResult err;
975164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
976fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth            VK_CALL(GetImageSubresourceLayout(fDevice, image, &subres, &layout));
977164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
978164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            void* mapPtr;
9791e305ba0d6a4237020d36234e9e286d3b0489401jvanverth            err = VK_CALL(MapMemory(fDevice, alloc.fMemory, alloc.fOffset, layout.rowPitch * h,
9801e305ba0d6a4237020d36234e9e286d3b0489401jvanverth                                    0, &mapPtr));
981164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            if (err) {
9826b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth                GrVkMemory::FreeImageMemory(this, linearTiling, alloc);
983fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth                VK_CALL(DestroyImage(this->device(), image, nullptr));
984164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                return 0;
985164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            }
986164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
987164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            size_t bpp = GrBytesPerPixel(config);
988164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            size_t rowCopyBytes = bpp * w;
989164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            // If there is no padding on dst (layout.rowPitch) we can do a single memcopy.
990164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            // This assumes the srcData comes in with no padding.
991164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            if (rowCopyBytes == layout.rowPitch) {
992164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                memcpy(mapPtr, srcData, rowCopyBytes * h);
993164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            } else {
994fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth                SkRectMemcpy(mapPtr, static_cast<size_t>(layout.rowPitch), srcData, rowCopyBytes,
995fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth                             rowCopyBytes, h);
996164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            }
9971e305ba0d6a4237020d36234e9e286d3b0489401jvanverth            VK_CALL(UnmapMemory(fDevice, alloc.fMemory));
998164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        } else {
999164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            // TODO: Add support for copying to optimal tiling
1000164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            SkASSERT(false);
1001164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
1002164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1003164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1004b2df0c2702329be6380a943d548e7377a51d8565egdaniel    GrVkImageInfo* info = new GrVkImageInfo;
1005fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    info->fImage = image;
1006fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    info->fAlloc = alloc;
1007fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    info->fImageTiling = imageTiling;
1008fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    info->fImageLayout = initialLayout;
100958a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel    info->fFormat = pixelFormat;
10102af0f1b014b9aabb6119bf66fac20e4cd3a8279bjvanverth    info->fLevelCount = 1;
1011fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth
1012fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    return (GrBackendObject)info;
1013164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1014164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1015164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::isTestingOnlyBackendTexture(GrBackendObject id) const {
1016b2df0c2702329be6380a943d548e7377a51d8565egdaniel    const GrVkImageInfo* backend = reinterpret_cast<const GrVkImageInfo*>(id);
1017164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
10181e305ba0d6a4237020d36234e9e286d3b0489401jvanverth    if (backend && backend->fImage && backend->fAlloc.fMemory) {
1019164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkMemoryRequirements req;
1020164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        memset(&req, 0, sizeof(req));
1021164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        GR_VK_CALL(this->vkInterface(), GetImageMemoryRequirements(fDevice,
1022164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                   backend->fImage,
1023164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                   &req));
1024164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // TODO: find a better check
1025164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // This will probably fail with a different driver
1026164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return (req.size > 0) && (req.size <= 8192 * 8192);
1027164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1028164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1029164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return false;
1030164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1031164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1032164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::deleteTestingOnlyBackendTexture(GrBackendObject id, bool abandon) {
10336b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    GrVkImageInfo* backend = reinterpret_cast<GrVkImageInfo*>(id);
1034164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (backend) {
1035164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        if (!abandon) {
1036fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth            // something in the command buffer may still be using this, so force submit
1037fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth            this->submitCommandBuffer(kForce_SyncQueue);
10386b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth            GrVkImage::DestroyImageInfo(this, backend);
1039164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
1040fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        delete backend;
1041164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1042164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1043164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1044164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
1045164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1046164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::addMemoryBarrier(VkPipelineStageFlags srcStageMask,
1047164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                               VkPipelineStageFlags dstStageMask,
1048164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                               bool byRegion,
1049164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                               VkMemoryBarrier* barrier) const {
1050164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(fCurrentCmdBuffer);
1051164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->pipelineBarrier(this,
1052164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       srcStageMask,
1053164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       dstStageMask,
1054164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       byRegion,
1055164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       GrVkCommandBuffer::kMemory_BarrierType,
1056164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       barrier);
1057164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1058164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1059164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::addBufferMemoryBarrier(VkPipelineStageFlags srcStageMask,
1060164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     VkPipelineStageFlags dstStageMask,
1061164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     bool byRegion,
1062164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     VkBufferMemoryBarrier* barrier) const {
1063164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(fCurrentCmdBuffer);
1064164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->pipelineBarrier(this,
1065164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       srcStageMask,
1066164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       dstStageMask,
1067164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       byRegion,
1068164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       GrVkCommandBuffer::kBufferMemory_BarrierType,
1069164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       barrier);
1070164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1071164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1072164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::addImageMemoryBarrier(VkPipelineStageFlags srcStageMask,
1073164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                    VkPipelineStageFlags dstStageMask,
1074164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                    bool byRegion,
1075164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                    VkImageMemoryBarrier* barrier) const {
1076164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(fCurrentCmdBuffer);
1077164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->pipelineBarrier(this,
1078164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       srcStageMask,
1079164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       dstStageMask,
1080164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       byRegion,
1081164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       GrVkCommandBuffer::kImageMemory_BarrierType,
1082164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       barrier);
1083164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1084164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1085164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::finishDrawTarget() {
1086164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Submit the current command buffer to the Queue
1087164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    this->submitCommandBuffer(kSkip_SyncQueue);
1088164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1089164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
10903d5d9ac426ea926f37eaa47e13acf7492068667begdanielvoid GrVkGpu::clearStencil(GrRenderTarget* target) {
10913d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    if (nullptr == target) {
10923d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        return;
10933d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    }
10943d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    GrStencilAttachment* stencil = target->renderTargetPriv().getStencilAttachment();
10953d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    GrVkStencilAttachment* vkStencil = (GrVkStencilAttachment*)stencil;
10963d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
10973d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
10983d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    VkClearDepthStencilValue vkStencilColor;
10993d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    memset(&vkStencilColor, 0, sizeof(VkClearDepthStencilValue));
11003d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
11013d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    vkStencil->setImageLayout(this,
11023d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                              VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
110350c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                              VK_ACCESS_TRANSFER_WRITE_BIT,
110450c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                              VK_PIPELINE_STAGE_TRANSFER_BIT,
11053d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                              false);
11063d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
11073d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    VkImageSubresourceRange subRange;
11083d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    memset(&subRange, 0, sizeof(VkImageSubresourceRange));
11093d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    subRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
11103d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    subRange.baseMipLevel = 0;
11113d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    subRange.levelCount = 1;
11123d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    subRange.baseArrayLayer = 0;
11133d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    subRange.layerCount = 1;
11143d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
11153d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    // TODO: I imagine that most times we want to clear a stencil it will be at the beginning of a
11163d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    // draw. Thus we should look into using the load op functions on the render pass to clear out
11173d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    // the stencil there.
11183d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    fCurrentCmdBuffer->clearDepthStencilImage(this, vkStencil, &vkStencilColor, 1, &subRange);
11193d5d9ac426ea926f37eaa47e13acf7492068667begdaniel}
11203d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
1121164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielinline bool can_copy_image(const GrSurface* dst,
1122164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           const GrSurface* src,
1123164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           const GrVkGpu* gpu) {
112417b892551465e5a44560a06e4b34dc3592b49622egdaniel    // Currently we don't support msaa
112517b892551465e5a44560a06e4b34dc3592b49622egdaniel    if ((dst->asRenderTarget() && dst->asRenderTarget()->numColorSamples() > 1) ||
112617b892551465e5a44560a06e4b34dc3592b49622egdaniel        (src->asRenderTarget() && src->asRenderTarget()->numColorSamples() > 1)) {
112717b892551465e5a44560a06e4b34dc3592b49622egdaniel        return false;
112817b892551465e5a44560a06e4b34dc3592b49622egdaniel    }
112917b892551465e5a44560a06e4b34dc3592b49622egdaniel
113017b892551465e5a44560a06e4b34dc3592b49622egdaniel    // We require that all vulkan GrSurfaces have been created with transfer_dst and transfer_src
113117b892551465e5a44560a06e4b34dc3592b49622egdaniel    // as image usage flags.
113217b892551465e5a44560a06e4b34dc3592b49622egdaniel    if (src->origin() == dst->origin() &&
113317b892551465e5a44560a06e4b34dc3592b49622egdaniel        GrBytesPerPixel(src->config()) == GrBytesPerPixel(dst->config())) {
1134164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return true;
1135164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1136164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1137164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // How does msaa play into this? If a VkTexture is multisampled, are we copying the multisampled
113817b892551465e5a44560a06e4b34dc3592b49622egdaniel    // or the resolved image here? Im multisampled, Vulkan requires sample counts to be the same.
1139164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1140164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return false;
1141164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1142164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1143164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::copySurfaceAsCopyImage(GrSurface* dst,
1144164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     GrSurface* src,
114517b892551465e5a44560a06e4b34dc3592b49622egdaniel                                     GrVkImage* dstImage,
114617b892551465e5a44560a06e4b34dc3592b49622egdaniel                                     GrVkImage* srcImage,
1147164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     const SkIRect& srcRect,
1148164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     const SkIPoint& dstPoint) {
1149164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(can_copy_image(dst, src, this));
1150164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1151164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // These flags are for flushing/invalidating caches and for the dst image it doesn't matter if
1152164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // the cache is flushed since it is only being written to.
115317b892551465e5a44560a06e4b34dc3592b49622egdaniel    dstImage->setImageLayout(this,
115450c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                             VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
115550c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                             VK_ACCESS_TRANSFER_WRITE_BIT,
115650c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                             VK_PIPELINE_STAGE_TRANSFER_BIT,
115750c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                             false);
1158164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
115917b892551465e5a44560a06e4b34dc3592b49622egdaniel    srcImage->setImageLayout(this,
116017b892551465e5a44560a06e4b34dc3592b49622egdaniel                             VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
116150c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                             VK_ACCESS_TRANSFER_READ_BIT,
116250c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                             VK_PIPELINE_STAGE_TRANSFER_BIT,
116317b892551465e5a44560a06e4b34dc3592b49622egdaniel                             false);
1164164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1165164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Flip rect if necessary
1166164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkIRect srcVkRect = srcRect;
1167164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    int32_t dstY = dstPoint.fY;
1168164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1169164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (kBottomLeft_GrSurfaceOrigin == src->origin()) {
1170164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        SkASSERT(kBottomLeft_GrSurfaceOrigin == dst->origin());
1171164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        srcVkRect.fTop = src->height() - srcRect.fBottom;
1172164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        srcVkRect.fBottom =  src->height() - srcRect.fTop;
1173164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        dstY = dst->height() - dstPoint.fY - srcVkRect.height();
1174164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1175164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1176164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkImageCopy copyRegion;
1177164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    memset(&copyRegion, 0, sizeof(VkImageCopy));
1178164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    copyRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
1179164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    copyRegion.srcOffset = { srcVkRect.fLeft, srcVkRect.fTop, 0 };
1180164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    copyRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
1181164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    copyRegion.dstOffset = { dstPoint.fX, dstY, 0 };
1182c355bc8dd117291b63ee7b7b39ec37a0e768eec5egdaniel    // The depth value of the extent is ignored according the vulkan spec for 2D images. However, on
1183c355bc8dd117291b63ee7b7b39ec37a0e768eec5egdaniel    // at least the nexus 5X it seems to be checking it. Thus as a working around we must have the
1184c355bc8dd117291b63ee7b7b39ec37a0e768eec5egdaniel    // depth value be 1.
1185c355bc8dd117291b63ee7b7b39ec37a0e768eec5egdaniel    copyRegion.extent = { (uint32_t)srcVkRect.width(), (uint32_t)srcVkRect.height(), 1 };
1186164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1187164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->copyImage(this,
118817b892551465e5a44560a06e4b34dc3592b49622egdaniel                                 srcImage,
1189164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
119017b892551465e5a44560a06e4b34dc3592b49622egdaniel                                 dstImage,
1191164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1192164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                 1,
1193164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                 &copyRegion);
1194900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
1195900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY,
1196900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                        srcRect.width(), srcRect.height());
1197900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    this->didWriteToSurface(dst, &dstRect);
1198164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1199164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
120017b892551465e5a44560a06e4b34dc3592b49622egdanielinline bool can_copy_as_blit(const GrSurface* dst,
120117b892551465e5a44560a06e4b34dc3592b49622egdaniel                             const GrSurface* src,
120217b892551465e5a44560a06e4b34dc3592b49622egdaniel                             const GrVkImage* dstImage,
120317b892551465e5a44560a06e4b34dc3592b49622egdaniel                             const GrVkImage* srcImage,
120417b892551465e5a44560a06e4b34dc3592b49622egdaniel                             const GrVkGpu* gpu) {
120517b892551465e5a44560a06e4b34dc3592b49622egdaniel    // We require that all vulkan GrSurfaces have been created with transfer_dst and transfer_src
120617b892551465e5a44560a06e4b34dc3592b49622egdaniel    // as image usage flags.
120717b892551465e5a44560a06e4b34dc3592b49622egdaniel    const GrVkCaps& caps = gpu->vkCaps();
120817b892551465e5a44560a06e4b34dc3592b49622egdaniel    if (!caps.configCanBeDstofBlit(dst->config(), dstImage->isLinearTiled()) ||
120917b892551465e5a44560a06e4b34dc3592b49622egdaniel        !caps.configCanBeSrcofBlit(src->config(), srcImage->isLinearTiled())) {
121017b892551465e5a44560a06e4b34dc3592b49622egdaniel        return false;
121117b892551465e5a44560a06e4b34dc3592b49622egdaniel    }
121217b892551465e5a44560a06e4b34dc3592b49622egdaniel
121317b892551465e5a44560a06e4b34dc3592b49622egdaniel    // We cannot blit images that are multisampled. Will need to figure out if we can blit the
121417b892551465e5a44560a06e4b34dc3592b49622egdaniel    // resolved msaa though.
121517b892551465e5a44560a06e4b34dc3592b49622egdaniel    if ((dst->asRenderTarget() && dst->asRenderTarget()->numColorSamples() > 1) ||
121617b892551465e5a44560a06e4b34dc3592b49622egdaniel        (src->asRenderTarget() && src->asRenderTarget()->numColorSamples() > 1)) {
121717b892551465e5a44560a06e4b34dc3592b49622egdaniel        return false;
121817b892551465e5a44560a06e4b34dc3592b49622egdaniel    }
121917b892551465e5a44560a06e4b34dc3592b49622egdaniel
122017b892551465e5a44560a06e4b34dc3592b49622egdaniel    return true;
122117b892551465e5a44560a06e4b34dc3592b49622egdaniel}
122217b892551465e5a44560a06e4b34dc3592b49622egdaniel
122317b892551465e5a44560a06e4b34dc3592b49622egdanielvoid GrVkGpu::copySurfaceAsBlit(GrSurface* dst,
122417b892551465e5a44560a06e4b34dc3592b49622egdaniel                                GrSurface* src,
122517b892551465e5a44560a06e4b34dc3592b49622egdaniel                                GrVkImage* dstImage,
122617b892551465e5a44560a06e4b34dc3592b49622egdaniel                                GrVkImage* srcImage,
122717b892551465e5a44560a06e4b34dc3592b49622egdaniel                                const SkIRect& srcRect,
122817b892551465e5a44560a06e4b34dc3592b49622egdaniel                                const SkIPoint& dstPoint) {
122917b892551465e5a44560a06e4b34dc3592b49622egdaniel    SkASSERT(can_copy_as_blit(dst, src, dstImage, srcImage, this));
123017b892551465e5a44560a06e4b34dc3592b49622egdaniel
123117b892551465e5a44560a06e4b34dc3592b49622egdaniel    dstImage->setImageLayout(this,
123217b892551465e5a44560a06e4b34dc3592b49622egdaniel                             VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
123350c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                             VK_ACCESS_TRANSFER_WRITE_BIT,
123450c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                             VK_PIPELINE_STAGE_TRANSFER_BIT,
123517b892551465e5a44560a06e4b34dc3592b49622egdaniel                             false);
123617b892551465e5a44560a06e4b34dc3592b49622egdaniel
123717b892551465e5a44560a06e4b34dc3592b49622egdaniel    srcImage->setImageLayout(this,
123817b892551465e5a44560a06e4b34dc3592b49622egdaniel                             VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
123950c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                             VK_ACCESS_TRANSFER_READ_BIT,
124050c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                             VK_PIPELINE_STAGE_TRANSFER_BIT,
124117b892551465e5a44560a06e4b34dc3592b49622egdaniel                             false);
124217b892551465e5a44560a06e4b34dc3592b49622egdaniel
124317b892551465e5a44560a06e4b34dc3592b49622egdaniel    // Flip rect if necessary
124417b892551465e5a44560a06e4b34dc3592b49622egdaniel    SkIRect srcVkRect;
12458af936d3047208def585b7bc824f013b994f6312egdaniel    srcVkRect.fLeft = srcRect.fLeft;
12468af936d3047208def585b7bc824f013b994f6312egdaniel    srcVkRect.fRight = srcRect.fRight;
124717b892551465e5a44560a06e4b34dc3592b49622egdaniel    SkIRect dstRect;
124817b892551465e5a44560a06e4b34dc3592b49622egdaniel    dstRect.fLeft = dstPoint.fX;
12498af936d3047208def585b7bc824f013b994f6312egdaniel    dstRect.fRight = dstPoint.fX + srcRect.width();
125017b892551465e5a44560a06e4b34dc3592b49622egdaniel
125117b892551465e5a44560a06e4b34dc3592b49622egdaniel    if (kBottomLeft_GrSurfaceOrigin == src->origin()) {
125217b892551465e5a44560a06e4b34dc3592b49622egdaniel        srcVkRect.fTop = src->height() - srcRect.fBottom;
125317b892551465e5a44560a06e4b34dc3592b49622egdaniel        srcVkRect.fBottom = src->height() - srcRect.fTop;
125417b892551465e5a44560a06e4b34dc3592b49622egdaniel    } else {
12558af936d3047208def585b7bc824f013b994f6312egdaniel        srcVkRect.fTop = srcRect.fTop;
12568af936d3047208def585b7bc824f013b994f6312egdaniel        srcVkRect.fBottom = srcRect.fBottom;
125717b892551465e5a44560a06e4b34dc3592b49622egdaniel    }
125817b892551465e5a44560a06e4b34dc3592b49622egdaniel
125917b892551465e5a44560a06e4b34dc3592b49622egdaniel    if (kBottomLeft_GrSurfaceOrigin == dst->origin()) {
126017b892551465e5a44560a06e4b34dc3592b49622egdaniel        dstRect.fTop = dst->height() - dstPoint.fY - srcVkRect.height();
126117b892551465e5a44560a06e4b34dc3592b49622egdaniel    } else {
126217b892551465e5a44560a06e4b34dc3592b49622egdaniel        dstRect.fTop = dstPoint.fY;
126317b892551465e5a44560a06e4b34dc3592b49622egdaniel    }
126417b892551465e5a44560a06e4b34dc3592b49622egdaniel    dstRect.fBottom = dstRect.fTop + srcVkRect.height();
126517b892551465e5a44560a06e4b34dc3592b49622egdaniel
126617b892551465e5a44560a06e4b34dc3592b49622egdaniel    // If we have different origins, we need to flip the top and bottom of the dst rect so that we
126717b892551465e5a44560a06e4b34dc3592b49622egdaniel    // get the correct origintation of the copied data.
126817b892551465e5a44560a06e4b34dc3592b49622egdaniel    if (src->origin() != dst->origin()) {
126917b892551465e5a44560a06e4b34dc3592b49622egdaniel        SkTSwap(dstRect.fTop, dstRect.fBottom);
127017b892551465e5a44560a06e4b34dc3592b49622egdaniel    }
127117b892551465e5a44560a06e4b34dc3592b49622egdaniel
127217b892551465e5a44560a06e4b34dc3592b49622egdaniel    VkImageBlit blitRegion;
127317b892551465e5a44560a06e4b34dc3592b49622egdaniel    memset(&blitRegion, 0, sizeof(VkImageBlit));
127417b892551465e5a44560a06e4b34dc3592b49622egdaniel    blitRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
127517b892551465e5a44560a06e4b34dc3592b49622egdaniel    blitRegion.srcOffsets[0] = { srcVkRect.fLeft, srcVkRect.fTop, 0 };
127617b892551465e5a44560a06e4b34dc3592b49622egdaniel    blitRegion.srcOffsets[1] = { srcVkRect.fRight, srcVkRect.fBottom, 0 };
127717b892551465e5a44560a06e4b34dc3592b49622egdaniel    blitRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
127817b892551465e5a44560a06e4b34dc3592b49622egdaniel    blitRegion.dstOffsets[0] = { dstRect.fLeft, dstRect.fTop, 0 };
127917b892551465e5a44560a06e4b34dc3592b49622egdaniel    blitRegion.dstOffsets[1] = { dstRect.fRight, dstRect.fBottom, 0 };
128017b892551465e5a44560a06e4b34dc3592b49622egdaniel
128117b892551465e5a44560a06e4b34dc3592b49622egdaniel    fCurrentCmdBuffer->blitImage(this,
1282b2df0c2702329be6380a943d548e7377a51d8565egdaniel                                 *srcImage,
1283b2df0c2702329be6380a943d548e7377a51d8565egdaniel                                 *dstImage,
128417b892551465e5a44560a06e4b34dc3592b49622egdaniel                                 1,
128517b892551465e5a44560a06e4b34dc3592b49622egdaniel                                 &blitRegion,
128617b892551465e5a44560a06e4b34dc3592b49622egdaniel                                 VK_FILTER_NEAREST); // We never scale so any filter works here
1287900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
1288900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    this->didWriteToSurface(dst, &dstRect);
128917b892551465e5a44560a06e4b34dc3592b49622egdaniel}
129017b892551465e5a44560a06e4b34dc3592b49622egdaniel
1291164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielinline bool can_copy_as_draw(const GrSurface* dst,
1292164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                             const GrSurface* src,
1293164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                             const GrVkGpu* gpu) {
1294164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return false;
1295164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1296164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1297164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::copySurfaceAsDraw(GrSurface* dst,
1298164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                GrSurface* src,
1299164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                const SkIRect& srcRect,
1300164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                const SkIPoint& dstPoint) {
1301164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(false);
1302164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1303164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1304164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::onCopySurface(GrSurface* dst,
1305164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                            GrSurface* src,
1306164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                            const SkIRect& srcRect,
1307164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                            const SkIPoint& dstPoint) {
130817b892551465e5a44560a06e4b34dc3592b49622egdaniel    GrVkImage* dstImage;
130917b892551465e5a44560a06e4b34dc3592b49622egdaniel    GrVkImage* srcImage;
131017b892551465e5a44560a06e4b34dc3592b49622egdaniel    if (dst->asTexture()) {
131117b892551465e5a44560a06e4b34dc3592b49622egdaniel        dstImage = static_cast<GrVkTexture*>(dst->asTexture());
131217b892551465e5a44560a06e4b34dc3592b49622egdaniel    } else {
131317b892551465e5a44560a06e4b34dc3592b49622egdaniel        SkASSERT(dst->asRenderTarget());
131417b892551465e5a44560a06e4b34dc3592b49622egdaniel        dstImage = static_cast<GrVkRenderTarget*>(dst->asRenderTarget());
131517b892551465e5a44560a06e4b34dc3592b49622egdaniel    }
131617b892551465e5a44560a06e4b34dc3592b49622egdaniel    if (src->asTexture()) {
131717b892551465e5a44560a06e4b34dc3592b49622egdaniel        srcImage = static_cast<GrVkTexture*>(src->asTexture());
131817b892551465e5a44560a06e4b34dc3592b49622egdaniel    } else {
131917b892551465e5a44560a06e4b34dc3592b49622egdaniel        SkASSERT(src->asRenderTarget());
132017b892551465e5a44560a06e4b34dc3592b49622egdaniel        srcImage = static_cast<GrVkRenderTarget*>(src->asRenderTarget());
132117b892551465e5a44560a06e4b34dc3592b49622egdaniel    }
132217b892551465e5a44560a06e4b34dc3592b49622egdaniel
1323164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (can_copy_image(dst, src, this)) {
132417b892551465e5a44560a06e4b34dc3592b49622egdaniel        this->copySurfaceAsCopyImage(dst, src, dstImage, srcImage, srcRect, dstPoint);
132517b892551465e5a44560a06e4b34dc3592b49622egdaniel        return true;
132617b892551465e5a44560a06e4b34dc3592b49622egdaniel    }
132717b892551465e5a44560a06e4b34dc3592b49622egdaniel
132817b892551465e5a44560a06e4b34dc3592b49622egdaniel    if (can_copy_as_blit(dst, src, dstImage, srcImage, this)) {
132917b892551465e5a44560a06e4b34dc3592b49622egdaniel        this->copySurfaceAsBlit(dst, src, dstImage, srcImage, srcRect, dstPoint);
1330164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return true;
1331164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1332164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1333164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (can_copy_as_draw(dst, src, this)) {
1334164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        this->copySurfaceAsDraw(dst, src, srcRect, dstPoint);
1335164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return true;
1336164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1337164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1338164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return false;
1339164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1340164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
134137798fbd82a7d064c5cc1516f120546a3408044begdanielbool GrVkGpu::initCopySurfaceDstDesc(const GrSurface* src, GrSurfaceDesc* desc) const {
134237798fbd82a7d064c5cc1516f120546a3408044begdaniel    // Currently we don't support msaa
134337798fbd82a7d064c5cc1516f120546a3408044begdaniel    if (src->asRenderTarget() && src->asRenderTarget()->numColorSamples() > 1) {
134437798fbd82a7d064c5cc1516f120546a3408044begdaniel        return false;
134537798fbd82a7d064c5cc1516f120546a3408044begdaniel    }
134637798fbd82a7d064c5cc1516f120546a3408044begdaniel
134737798fbd82a7d064c5cc1516f120546a3408044begdaniel    // This will support copying the dst as CopyImage since all of our surfaces require transferSrc
134837798fbd82a7d064c5cc1516f120546a3408044begdaniel    // and transferDst usage flags in Vulkan.
134937798fbd82a7d064c5cc1516f120546a3408044begdaniel    desc->fOrigin = src->origin();
135037798fbd82a7d064c5cc1516f120546a3408044begdaniel    desc->fConfig = src->config();
135137798fbd82a7d064c5cc1516f120546a3408044begdaniel    desc->fFlags = kNone_GrSurfaceFlags;
135237798fbd82a7d064c5cc1516f120546a3408044begdaniel    return true;
135337798fbd82a7d064c5cc1516f120546a3408044begdaniel}
135437798fbd82a7d064c5cc1516f120546a3408044begdaniel
135528f45b949acc746849100fbe112ee5280f0594c9cdaltonvoid GrVkGpu::onGetMultisampleSpecs(GrRenderTarget* rt, const GrStencilSettings&,
135628f45b949acc746849100fbe112ee5280f0594c9cdalton                                    int* effectiveSampleCnt, SkAutoTDeleteArray<SkPoint>*) {
135728f45b949acc746849100fbe112ee5280f0594c9cdalton    // TODO: stub.
135828f45b949acc746849100fbe112ee5280f0594c9cdalton    SkASSERT(!this->caps()->sampleLocationsSupport());
135928f45b949acc746849100fbe112ee5280f0594c9cdalton    *effectiveSampleCnt = rt->desc().fSampleCnt;
136028f45b949acc746849100fbe112ee5280f0594c9cdalton}
136128f45b949acc746849100fbe112ee5280f0594c9cdalton
1362164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::onGetReadPixelsInfo(GrSurface* srcSurface, int width, int height, size_t rowBytes,
1363164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                  GrPixelConfig readConfig, DrawPreference* drawPreference,
1364164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                  ReadPixelTempDrawInfo* tempDrawInfo) {
136588e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    // These settings we will always want if a temp draw is performed.
136688e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    tempDrawInfo->fTempSurfaceDesc.fFlags = kRenderTarget_GrSurfaceFlag;
136788e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    tempDrawInfo->fTempSurfaceDesc.fWidth = width;
136888e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    tempDrawInfo->fTempSurfaceDesc.fHeight = height;
136988e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    tempDrawInfo->fTempSurfaceDesc.fSampleCnt = 0;
137088e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    tempDrawInfo->fTempSurfaceDesc.fOrigin = kTopLeft_GrSurfaceOrigin; // no CPU y-flip for TL.
137188e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    tempDrawInfo->fUseExactScratch = false;
137288e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel
137388e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    // For now assume no swizzling, we may change that below.
137488e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    tempDrawInfo->fSwizzle = GrSwizzle::RGBA();
137588e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel
137688e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    // Depends on why we need/want a temp draw. Start off assuming no change, the surface we read
137788e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    // from will be srcConfig and we will read readConfig pixels from it.
137888e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    // Not that if we require a draw and return a non-renderable format for the temp surface the
137988e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    // base class will fail for us.
138088e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    tempDrawInfo->fTempSurfaceDesc.fConfig = srcSurface->config();
138188e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    tempDrawInfo->fReadConfig = readConfig;
138288e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel
13834583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    if (srcSurface->config() == readConfig) {
13844583ec51d9ddc830eeb854db068235be96ce59c4egdaniel        return true;
1385164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1386164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
13874583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    if (this->vkCaps().isConfigRenderable(readConfig, false)) {
13884583ec51d9ddc830eeb854db068235be96ce59c4egdaniel        ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
13894583ec51d9ddc830eeb854db068235be96ce59c4egdaniel        tempDrawInfo->fTempSurfaceDesc.fConfig = readConfig;
13904583ec51d9ddc830eeb854db068235be96ce59c4egdaniel        tempDrawInfo->fReadConfig = readConfig;
13914583ec51d9ddc830eeb854db068235be96ce59c4egdaniel        return true;
1392164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1393164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
13944583ec51d9ddc830eeb854db068235be96ce59c4egdaniel    return false;
1395164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1396164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1397164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::onReadPixels(GrSurface* surface,
1398164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           int left, int top, int width, int height,
1399164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           GrPixelConfig config,
1400164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           void* buffer,
1401164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           size_t rowBytes) {
1402164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkFormat pixelFormat;
1403164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!GrPixelConfigToVkFormat(config, &pixelFormat)) {
1404164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
1405164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1406164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1407164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkTexture* tgt = static_cast<GrVkTexture*>(surface->asTexture());
1408164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!tgt) {
1409164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
1410164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1411164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1412164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Change layout of our target so it can be used as copy
1413164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    tgt->setImageLayout(this,
1414164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                        VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
141550c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                        VK_ACCESS_TRANSFER_READ_BIT,
141650c46c7b189caf94abb79cdc125245a6c0de0b4ejvanverth                        VK_PIPELINE_STAGE_TRANSFER_BIT,
1417164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                        false);
1418164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
14199d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary    GrVkTransferBuffer* transferBuffer =
1420e2e71c2df4e72e897bbe745752be0444aee5c29fcdalton        static_cast<GrVkTransferBuffer*>(this->createBuffer(rowBytes * height,
1421e2e71c2df4e72e897bbe745752be0444aee5c29fcdalton                                                            kXferGpuToCpu_GrBufferType,
1422397536cabe12a9936659870dd220c869789424bacdalton                                                            kStream_GrAccessPattern));
1423164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1424164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    bool flipY = kBottomLeft_GrSurfaceOrigin == surface->origin();
1425164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkOffset3D offset = {
1426164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        left,
1427164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        flipY ? surface->height() - top - height : top,
1428164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        0
1429164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    };
1430164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1431164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Copy the image to a buffer so we can map it to cpu memory
1432164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkBufferImageCopy region;
1433164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    memset(&region, 0, sizeof(VkBufferImageCopy));
1434164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    region.bufferOffset = 0;
143588e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    region.bufferRowLength = 0; // Forces RowLength to be width. We handle the rowBytes below.
1436164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    region.bufferImageHeight = 0; // Forces height to be tightly packed. Only useful for 3d images.
1437164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
1438164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    region.imageOffset = offset;
1439164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    region.imageExtent = { (uint32_t)width, (uint32_t)height, 1 };
1440164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1441164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->copyImageToBuffer(this,
1442164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                         tgt,
1443164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1444164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                         transferBuffer,
1445164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                         1,
1446164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                         &region);
1447164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1448164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // make sure the copy to buffer has finished
1449164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    transferBuffer->addMemoryBarrier(this,
1450164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     VK_ACCESS_TRANSFER_WRITE_BIT,
1451164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     VK_ACCESS_HOST_READ_BIT,
1452164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     VK_PIPELINE_STAGE_TRANSFER_BIT,
1453164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     VK_PIPELINE_STAGE_HOST_BIT,
1454164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     false);
1455164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1456164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // We need to submit the current command buffer to the Queue and make sure it finishes before
1457164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // we can copy the data out of the buffer.
1458164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    this->submitCommandBuffer(kForce_SyncQueue);
1459164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1460164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    void* mappedMemory = transferBuffer->map();
1461164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
146288e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    size_t tightRowBytes = GrBytesPerPixel(config) * width;
1463164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (flipY) {
146488e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel        const char* srcRow = reinterpret_cast<const char*>(mappedMemory);
146588e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel        char* dstRow = reinterpret_cast<char*>(buffer)+(height - 1) * rowBytes;
146688e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel        for (int y = 0; y < height; y++) {
146788e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel            memcpy(dstRow, srcRow, tightRowBytes);
146888e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel            srcRow += tightRowBytes;
146988e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel            dstRow -= rowBytes;
147088e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel        }
147188e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    } else {
147288e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel        if (tightRowBytes == rowBytes) {
147388e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel            memcpy(buffer, mappedMemory, rowBytes*height);
147488e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel        } else {
147588e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel            SkRectMemcpy(buffer, rowBytes, mappedMemory, tightRowBytes, tightRowBytes, height);
1476164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
1477164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1478164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
147988e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    transferBuffer->unmap();
148088e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel    transferBuffer->unref();
148188e8aef3916454e5f6916cc8b3420345b1cf0584egdaniel
1482164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return true;
1483164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1484066df7ca911b65d416783f3bec6f4f1662948ad5egdaniel
14859cb6340a62a5d748e4189d50e51fa527c8c80c03egdanielvoid GrVkGpu::submitSecondaryCommandBuffer(const GrVkSecondaryCommandBuffer* buffer,
14869cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel                                           const GrVkRenderPass* renderPass,
14879cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel                                           const VkClearValue* colorClear,
14889cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel                                           GrVkRenderTarget* target,
14899cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel                                           const SkIRect& bounds) {
14909cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel    // Currently it is fine for us to always pass in 1 for the clear count even if no attachment
14919cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel    // uses it. In the current state, we also only use the LOAD_OP_CLEAR for the color attachment
14929cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel    // which is always at the first attachment.
14939cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel    fCurrentCmdBuffer->beginRenderPass(this, renderPass, 1, colorClear, *target, bounds, true);
1494066df7ca911b65d416783f3bec6f4f1662948ad5egdaniel    fCurrentCmdBuffer->executeCommands(this, buffer);
1495164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->endRenderPass(this);
1496164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
14979cb6340a62a5d748e4189d50e51fa527c8c80c03egdaniel
1498