GrVkGpu.cpp revision 2af0f1b014b9aabb6119bf66fac20e4cd3a8279b
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"
20164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkImage.h"
21164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkIndexBuffer.h"
22164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkMemory.h"
23164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkPipeline.h"
2422281c13a13c4b4e275516e9fe02185a53a7e5aaegdaniel#include "GrVkPipelineState.h"
25164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkRenderPass.h"
26164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkResourceProvider.h"
27164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkTexture.h"
28164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkTextureRenderTarget.h"
29164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkTransferBuffer.h"
30164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkVertexBuffer.h"
31164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
32164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "SkConfig8888.h"
33900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth#include "SkMipMap.h"
34164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
35164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "vk/GrVkInterface.h"
36fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth#include "vk/GrVkTypes.h"
37164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
38164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#define VK_CALL(X) GR_VK_CALL(this->vkInterface(), X)
39164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#define VK_CALL_RET(RET, X) GR_VK_CALL_RET(this->vkInterface(), RET, X)
40164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#define VK_CALL_ERRCHECK(X) GR_VK_CALL_ERRCHECK(this->vkInterface(), X)
41164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
42d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth#ifdef ENABLE_VK_LAYERS
43d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverthVKAPI_ATTR VkBool32 VKAPI_CALL DebugReportCallback(
44d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    VkDebugReportFlagsEXT       flags,
45d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    VkDebugReportObjectTypeEXT  objectType,
46d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    uint64_t                    object,
47d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    size_t                      location,
48d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    int32_t                     messageCode,
49d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    const char*                 pLayerPrefix,
50d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    const char*                 pMessage,
51d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    void*                       pUserData) {
52d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    if (flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
53d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        SkDebugf("Vulkan error [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
54d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    } else if (flags & VK_DEBUG_REPORT_WARNING_BIT_EXT) {
55d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        SkDebugf("Vulkan warning [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
56d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    } else if (flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) {
57d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        SkDebugf("Vulkan perf warning [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
58d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    } else {
59d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        SkDebugf("Vulkan info/debug [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
60d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    }
61d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    return VK_FALSE;
62d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth}
63d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth#endif
64d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth
65633b35657c964c32e7010b14bb2d396b4a764c52jvanverthGrGpu* GrVkGpu::Create(GrBackendContext backendContext, const GrContextOptions& options,
66633b35657c964c32e7010b14bb2d396b4a764c52jvanverth                       GrContext* context) {
67dc0fcd41e75682a8bfd5e285d684461475226330bsalomon    const GrVkBackendContext* vkBackendContext =
68dc0fcd41e75682a8bfd5e285d684461475226330bsalomon        reinterpret_cast<const GrVkBackendContext*>(backendContext);
69633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    if (!vkBackendContext) {
70dc0fcd41e75682a8bfd5e285d684461475226330bsalomon        vkBackendContext = GrVkBackendContext::Create();
71633b35657c964c32e7010b14bb2d396b4a764c52jvanverth        if (!vkBackendContext) {
72633b35657c964c32e7010b14bb2d396b4a764c52jvanverth            return nullptr;
73164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
74633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    } else {
75633b35657c964c32e7010b14bb2d396b4a764c52jvanverth        vkBackendContext->ref();
76164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
77164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
78633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    return new GrVkGpu(context, options, vkBackendContext);
79164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
80164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
81164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
82164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
839d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanaryGrVkGpu::GrVkGpu(GrContext* context, const GrContextOptions& options,
84633b35657c964c32e7010b14bb2d396b4a764c52jvanverth                 const GrVkBackendContext* backendCtx)
85164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    : INHERITED(context)
86633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    , fDevice(backendCtx->fDevice)
87633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    , fQueue(backendCtx->fQueue)
88633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    , fResourceProvider(this) {
89633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    fBackendContext.reset(backendCtx);
90164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
91d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth#ifdef ENABLE_VK_LAYERS
92a00980e58037fa36d066be80d7fcc0f73b2dfd40jvanverth    fCallback = nullptr;
93fd7bd45ac2178ce6b4a390f517f605750aaef6c8jvanverth    if (backendCtx->fExtensions & kEXT_debug_report_GrVkExtensionFlag) {
94fd7bd45ac2178ce6b4a390f517f605750aaef6c8jvanverth        // Setup callback creation information
95d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        VkDebugReportCallbackCreateInfoEXT callbackCreateInfo;
96d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        callbackCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
97d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        callbackCreateInfo.pNext = nullptr;
98d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        callbackCreateInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT |
99ef0c10cffefef90646ff2e238d7c2d82247a0370egdaniel                                   VK_DEBUG_REPORT_WARNING_BIT_EXT |
100d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth                                   //VK_DEBUG_REPORT_INFORMATION_BIT_EXT |
101d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth                                   //VK_DEBUG_REPORT_DEBUG_BIT_EXT |
102b4aa36211ca66ef127ac2954108742af1ead5082egdaniel                                   VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
103d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        callbackCreateInfo.pfnCallback = &DebugReportCallback;
104d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        callbackCreateInfo.pUserData = nullptr;
105d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth
106fd7bd45ac2178ce6b4a390f517f605750aaef6c8jvanverth        // Register the callback
107a00980e58037fa36d066be80d7fcc0f73b2dfd40jvanverth        GR_VK_CALL_ERRCHECK(this->vkInterface(), CreateDebugReportCallbackEXT(
108a00980e58037fa36d066be80d7fcc0f73b2dfd40jvanverth                            backendCtx->fInstance, &callbackCreateInfo, nullptr, &fCallback));
109d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    }
110d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth#endif
111633b35657c964c32e7010b14bb2d396b4a764c52jvanverth
112633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    fCompiler = shaderc_compiler_initialize();
113633b35657c964c32e7010b14bb2d396b4a764c52jvanverth
114fd7bd45ac2178ce6b4a390f517f605750aaef6c8jvanverth    fVkCaps.reset(new GrVkCaps(options, this->vkInterface(), backendCtx->fPhysicalDevice,
115c5ec1408298510410270ea67e895570ccfa76e54egdaniel                               backendCtx->fFeatures, backendCtx->fExtensions));
116633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    fCaps.reset(SkRef(fVkCaps.get()));
117633b35657c964c32e7010b14bb2d396b4a764c52jvanverth
118633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    VK_CALL(GetPhysicalDeviceMemoryProperties(backendCtx->fPhysicalDevice, &fPhysDevMemProps));
119633b35657c964c32e7010b14bb2d396b4a764c52jvanverth
120633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    const VkCommandPoolCreateInfo cmdPoolInfo = {
121633b35657c964c32e7010b14bb2d396b4a764c52jvanverth        VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // sType
122633b35657c964c32e7010b14bb2d396b4a764c52jvanverth        nullptr,                                    // pNext
123633b35657c964c32e7010b14bb2d396b4a764c52jvanverth        VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,       // CmdPoolCreateFlags
124b0d4352ca610654f98c3c4ebc67ed9ad9c8c8493jvanverth        backendCtx->fGraphicsQueueIndex,            // queueFamilyIndex
125633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    };
1269d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary    GR_VK_CALL_ERRCHECK(this->vkInterface(), CreateCommandPool(fDevice, &cmdPoolInfo, nullptr,
127633b35657c964c32e7010b14bb2d396b4a764c52jvanverth                                                               &fCmdPool));
128633b35657c964c32e7010b14bb2d396b4a764c52jvanverth
129633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    // must call this after creating the CommandPool
130633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    fResourceProvider.init();
131633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    fCurrentCmdBuffer = fResourceProvider.createCommandBuffer();
132633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    SkASSERT(fCurrentCmdBuffer);
133633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    fCurrentCmdBuffer->begin(this);
134164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
135164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
136164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielGrVkGpu::~GrVkGpu() {
137164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->end(this);
138164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->unref(this);
139164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
140164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // wait for all commands to finish
141ddf9835e9cdf512b1d5172d014f00ceb6dacd039jvanverth    fResourceProvider.checkCommandBuffers();
142a00980e58037fa36d066be80d7fcc0f73b2dfd40jvanverth    SkDEBUGCODE(VkResult res = ) VK_CALL(QueueWaitIdle(fQueue));
143ddf9835e9cdf512b1d5172d014f00ceb6dacd039jvanverth    // VK_ERROR_DEVICE_LOST is acceptable when tearing down (see 4.2.4 in spec)
144ddf9835e9cdf512b1d5172d014f00ceb6dacd039jvanverth    SkASSERT(VK_SUCCESS == res || VK_ERROR_DEVICE_LOST == res);
1459d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
146164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // must call this just before we destroy the VkDevice
147164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fResourceProvider.destroyResources();
148164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
149633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    VK_CALL(DestroyCommandPool(fDevice, fCmdPool, nullptr));
150633b35657c964c32e7010b14bb2d396b4a764c52jvanverth
151633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    shaderc_compiler_release(fCompiler);
152633b35657c964c32e7010b14bb2d396b4a764c52jvanverth
153633b35657c964c32e7010b14bb2d396b4a764c52jvanverth#ifdef ENABLE_VK_LAYERS
154a00980e58037fa36d066be80d7fcc0f73b2dfd40jvanverth    if (fCallback) {
155a00980e58037fa36d066be80d7fcc0f73b2dfd40jvanverth        VK_CALL(DestroyDebugReportCallbackEXT(fBackendContext->fInstance, fCallback, nullptr));
156a00980e58037fa36d066be80d7fcc0f73b2dfd40jvanverth        fCallback = nullptr;
157a00980e58037fa36d066be80d7fcc0f73b2dfd40jvanverth    }
158d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth#endif
159164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
160164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
161164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel///////////////////////////////////////////////////////////////////////////////
162164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
163164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::submitCommandBuffer(SyncQueue sync) {
164164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(fCurrentCmdBuffer);
165164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->end(this);
166164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
167164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->submitToQueue(this, fQueue, sync);
168164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fResourceProvider.checkCommandBuffers();
169164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
170164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Release old command buffer and create a new one
171164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->unref(this);
172164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer = fResourceProvider.createCommandBuffer();
173164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(fCurrentCmdBuffer);
174164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
175164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->begin(this);
176164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
177164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
178164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel///////////////////////////////////////////////////////////////////////////////
1791bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdaltonGrBuffer* GrVkGpu::onCreateBuffer(size_t size, GrBufferType type, GrAccessPattern accessPattern,
1801bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton                                  const void* data) {
1811bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton    GrBuffer* buff;
182397536cabe12a9936659870dd220c869789424bacdalton    switch (type) {
183397536cabe12a9936659870dd220c869789424bacdalton        case kVertex_GrBufferType:
184397536cabe12a9936659870dd220c869789424bacdalton            SkASSERT(kDynamic_GrAccessPattern == accessPattern ||
185397536cabe12a9936659870dd220c869789424bacdalton                     kStatic_GrAccessPattern == accessPattern);
1861bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton            buff = GrVkVertexBuffer::Create(this, size, kDynamic_GrAccessPattern == accessPattern);
187e05bbbba79c569c1d32fa6475feecd1477fd3beeegdaniel            break;
188397536cabe12a9936659870dd220c869789424bacdalton        case kIndex_GrBufferType:
189397536cabe12a9936659870dd220c869789424bacdalton            SkASSERT(kDynamic_GrAccessPattern == accessPattern ||
190397536cabe12a9936659870dd220c869789424bacdalton                     kStatic_GrAccessPattern == accessPattern);
1911bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton            buff = GrVkIndexBuffer::Create(this, size, kDynamic_GrAccessPattern == accessPattern);
192e05bbbba79c569c1d32fa6475feecd1477fd3beeegdaniel            break;
193397536cabe12a9936659870dd220c869789424bacdalton        case kXferCpuToGpu_GrBufferType:
194c3d706f7ce87cdd94158d2266ab2fe2f18f5020ajvanverth            SkASSERT(kStream_GrAccessPattern == accessPattern);
1951bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton            buff = GrVkTransferBuffer::Create(this, size, GrVkBuffer::kCopyRead_Type);
196e05bbbba79c569c1d32fa6475feecd1477fd3beeegdaniel            break;
197397536cabe12a9936659870dd220c869789424bacdalton        case kXferGpuToCpu_GrBufferType:
198c3d706f7ce87cdd94158d2266ab2fe2f18f5020ajvanverth            SkASSERT(kStream_GrAccessPattern == accessPattern);
1991bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton            buff = GrVkTransferBuffer::Create(this, size, GrVkBuffer::kCopyWrite_Type);
200e05bbbba79c569c1d32fa6475feecd1477fd3beeegdaniel            break;
201397536cabe12a9936659870dd220c869789424bacdalton        default:
202397536cabe12a9936659870dd220c869789424bacdalton            SkFAIL("Unknown buffer type.");
203397536cabe12a9936659870dd220c869789424bacdalton            return nullptr;
204397536cabe12a9936659870dd220c869789424bacdalton    }
2051bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton    if (data && buff) {
2061bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton        buff->updateData(data, size);
2071bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton    }
2081bf3e71ad06a318613ccc09e1cf47d3c2465b23ccdalton    return buff;
209164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
210164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
211164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
212164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::onGetWritePixelsInfo(GrSurface* dstSurface, int width, int height,
213164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                   GrPixelConfig srcConfig, DrawPreference* drawPreference,
214164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                   WritePixelTempDrawInfo* tempDrawInfo) {
215164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (kIndex_8_GrPixelConfig == srcConfig || GrPixelConfigIsCompressed(dstSurface->config())) {
216164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
217164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
218164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
219164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Currently we don't handle draws, so if the caller wants/needs to do a draw we need to fail
220164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (kNoDraw_DrawPreference != *drawPreference) {
221164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
222164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
223164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
224164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (dstSurface->config() != srcConfig) {
2259d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary        // TODO: This should fall back to drawing or copying to change config of dstSurface to
226164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // match that of srcConfig.
227164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
228164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
229164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
230164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return true;
231164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
232164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
233164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::onWritePixels(GrSurface* surface,
234164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                            int left, int top, int width, int height,
235a1e6b3be8124cef85f2e39e3cb85000ad9526d48bsalomon                            GrPixelConfig config,
236a1e6b3be8124cef85f2e39e3cb85000ad9526d48bsalomon                            const SkTArray<GrMipLevel>& texels) {
237164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkTexture* vkTex = static_cast<GrVkTexture*>(surface->asTexture());
238164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!vkTex) {
239164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
240164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
241164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
242900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // Make sure we have at least the base level
24303509eafa3e25819ff69f4d4f339d46264820c38jvanverth    if (texels.empty() || !texels.begin()->fPixels) {
24403509eafa3e25819ff69f4d4f339d46264820c38jvanverth        return false;
24503509eafa3e25819ff69f4d4f339d46264820c38jvanverth    }
246a1e6b3be8124cef85f2e39e3cb85000ad9526d48bsalomon
247164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // We assume Vulkan doesn't do sRGB <-> linear conversions when reading and writing pixels.
248164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (GrPixelConfigIsSRGB(surface->config()) != GrPixelConfigIsSRGB(config)) {
249164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
250164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
251164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
252164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    bool success = false;
253164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (GrPixelConfigIsCompressed(vkTex->desc().fConfig)) {
254164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // We check that config == desc.fConfig in GrGpu::getWritePixelsInfo()
255164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        SkASSERT(config == vkTex->desc().fConfig);
256164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // TODO: add compressed texture support
257164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // delete the following two lines and uncomment the two after that when ready
258164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        vkTex->unref();
259164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
260164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        //success = this->uploadCompressedTexData(vkTex->desc(), buffer, false, left, top, width,
261164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        //                                       height);
262164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    } else {
263164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        bool linearTiling = vkTex->isLinearTiled();
264900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        if (linearTiling) {
265900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            if (texels.count() > 1) {
266900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                SkDebugf("Can't upload mipmap data to linear tiled texture");
267900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                return false;
268900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            }
269900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            if (VK_IMAGE_LAYOUT_PREINITIALIZED != vkTex->currentLayout()) {
270900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                // Need to change the layout to general in order to perform a host write
271900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                VkImageLayout layout = vkTex->currentLayout();
272900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                VkPipelineStageFlags srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(layout);
273900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_HOST_BIT;
274900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(layout);
275900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                VkAccessFlags dstAccessMask = VK_ACCESS_HOST_WRITE_BIT;
276900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                vkTex->setImageLayout(this,
277900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                      VK_IMAGE_LAYOUT_GENERAL,
278900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                      srcAccessMask,
279900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                      dstAccessMask,
280900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                      srcStageMask,
281900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                      dstStageMask,
282900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                      false);
283bdf8811b3126ab08ccff08b5e647b80cae5bd087egdaniel                this->submitCommandBuffer(kForce_SyncQueue);
284900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            }
285900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            success = this->uploadTexDataLinear(vkTex, left, top, width, height, config,
286900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                                texels.begin()->fPixels, texels.begin()->fRowBytes);
287900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        } else {
288c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth            int newMipLevels = texels.count();
289c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth            int currentMipLevels = vkTex->texturePriv().maxMipMapLevel();
290c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth            if ((currentMipLevels || newMipLevels != 1) && newMipLevels != currentMipLevels) {
291c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth                if (!vkTex->reallocForMipmap(this, newMipLevels)) {
292900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                    return false;
293900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                }
294900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            }
295900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            success = this->uploadTexDataOptimal(vkTex, left, top, width, height, config, texels);
296164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
297164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
298900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
299900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    return success;
300164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
301164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
302900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverthbool GrVkGpu::uploadTexDataLinear(GrVkTexture* tex,
303900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                  int left, int top, int width, int height,
304900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                  GrPixelConfig dataConfig,
305900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                  const void* data,
306900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                  size_t rowBytes) {
307164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(data);
308900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    SkASSERT(tex->isLinearTiled());
309164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
310164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // If we're uploading compressed data then we should be using uploadCompressedTexData
311164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(!GrPixelConfigIsCompressed(dataConfig));
312164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
313164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    size_t bpp = GrBytesPerPixel(dataConfig);
314164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
315164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    const GrSurfaceDesc& desc = tex->desc();
316164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
317164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!GrSurfacePriv::AdjustWritePixelParams(desc.fWidth, desc.fHeight, bpp, &left, &top,
318164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                               &width, &height, &data, &rowBytes)) {
319164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
320164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
321164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    size_t trimRowBytes = width * bpp;
322164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
323900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    SkASSERT(VK_IMAGE_LAYOUT_PREINITIALIZED == tex->currentLayout() ||
324900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth             VK_IMAGE_LAYOUT_GENERAL == tex->currentLayout());
325900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    const VkImageSubresource subres = {
326900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        VK_IMAGE_ASPECT_COLOR_BIT,
327900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        0,  // mipLevel
328900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        0,  // arraySlice
329900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    };
330900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    VkSubresourceLayout layout;
331900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    VkResult err;
332900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
333900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    const GrVkInterface* interface = this->vkInterface();
334900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
335900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    GR_VK_CALL(interface, GetImageSubresourceLayout(fDevice,
336900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                                    tex->textureImage(),
337900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                                    &subres,
338900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                                    &layout));
339900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
340900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    int texTop = kBottomLeft_GrSurfaceOrigin == desc.fOrigin ? tex->height() - top - height : top;
341900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    VkDeviceSize offset = texTop*layout.rowPitch + left*bpp;
342900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    VkDeviceSize size = height*layout.rowPitch;
343900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    void* mapPtr;
344900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    err = GR_VK_CALL(interface, MapMemory(fDevice, tex->textureMemory(), offset, size, 0,
345900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                            &mapPtr));
346900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    if (err) {
347900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        return false;
348900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    }
349164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
350900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    if (kBottomLeft_GrSurfaceOrigin == desc.fOrigin) {
351900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        // copy into buffer by rows
352900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        const char* srcRow = reinterpret_cast<const char*>(data);
353900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        char* dstRow = reinterpret_cast<char*>(mapPtr)+(height - 1)*layout.rowPitch;
354900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        for (int y = 0; y < height; y++) {
355900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            memcpy(dstRow, srcRow, trimRowBytes);
356900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            srcRow += rowBytes;
357900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            dstRow -= layout.rowPitch;
358900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        }
359900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    } else {
360900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        // If there is no padding on the src (rowBytes) or dst (layout.rowPitch) we can memcpy
361900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        if (trimRowBytes == rowBytes && trimRowBytes == layout.rowPitch) {
362900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            memcpy(mapPtr, data, trimRowBytes * height);
363164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        } else {
364900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            SkRectMemcpy(mapPtr, static_cast<size_t>(layout.rowPitch), data, rowBytes,
365900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                            trimRowBytes, height);
366164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
367900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    }
368164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
369900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    GR_VK_CALL(interface, UnmapMemory(fDevice, tex->textureMemory()));
370900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
371900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    return true;
372900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth}
373900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
374900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverthbool GrVkGpu::uploadTexDataOptimal(GrVkTexture* tex,
375900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                    int left, int top, int width, int height,
376900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                    GrPixelConfig dataConfig,
377900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                    const SkTArray<GrMipLevel>& texels) {
378900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    SkASSERT(!tex->isLinearTiled());
379900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // The assumption is either that we have no mipmaps, or that our rect is the entire texture
380900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    SkASSERT(1 == texels.count() ||
381900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth             (0 == left && 0 == top && width == tex->width() && height == tex->height()));
382900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
383900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // If we're uploading compressed data then we should be using uploadCompressedTexData
384900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    SkASSERT(!GrPixelConfigIsCompressed(dataConfig));
385900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
386900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    if (width == 0 || height == 0) {
387900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        return false;
388900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    }
389900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
390900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    const GrSurfaceDesc& desc = tex->desc();
391900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    SkASSERT(this->caps()->isConfigTexturable(desc.fConfig));
392900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    size_t bpp = GrBytesPerPixel(dataConfig);
393900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
394900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // texels is const.
395c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    // But we may need to adjust the fPixels ptr based on the copyRect, or fRowBytes.
396c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    // Because of this we need to make a non-const shallow copy of texels.
397c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    SkTArray<GrMipLevel> texelsShallowCopy(texels);
398900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
399c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    for (int currentMipLevel = texelsShallowCopy.count() - 1; currentMipLevel >= 0;
400c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth         currentMipLevel--) {
401c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        SkASSERT(texelsShallowCopy[currentMipLevel].fPixels);
402900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    }
403900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
404900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // Determine whether we need to flip when we copy into the buffer
405c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    bool flipY = (kBottomLeft_GrSurfaceOrigin == desc.fOrigin && !texelsShallowCopy.empty());
406900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
407c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    // adjust any params (left, top, currentWidth, currentHeight
408900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // find the combined size of all the mip levels and the relative offset of
409900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // each into the collective buffer
410c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    // Do the first level separately because we may need to adjust width and height
411c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    // (for the non-mipped case).
412c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    if (!GrSurfacePriv::AdjustWritePixelParams(desc.fWidth, desc.fHeight, bpp, &left, &top,
413c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth                                               &width,
414c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth                                               &height,
415c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth                                               &texelsShallowCopy[0].fPixels,
416c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth                                               &texelsShallowCopy[0].fRowBytes)) {
417c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        return false;
418c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    }
419c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    SkTArray<size_t> individualMipOffsets(texelsShallowCopy.count());
420c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    individualMipOffsets.push_back(0);
421c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    size_t combinedBufferSize = width * bpp * height;
422c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    int currentWidth = width;
423c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    int currentHeight = height;
424c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    for (int currentMipLevel = 1; currentMipLevel < texelsShallowCopy.count(); currentMipLevel++) {
425c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        currentWidth = SkTMax(1, currentWidth/2);
426c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        currentHeight = SkTMax(1, currentHeight/2);
427c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        if (!GrSurfacePriv::AdjustWritePixelParams(desc.fWidth, desc.fHeight, bpp, &left, &top,
428c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth                                                   &currentWidth,
429c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth                                                   &currentHeight,
430c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth                                                   &texelsShallowCopy[currentMipLevel].fPixels,
431c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth                                                   &texelsShallowCopy[currentMipLevel].fRowBytes)) {
432c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth            return false;
433c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        }
434900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        const size_t trimmedSize = currentWidth * bpp * currentHeight;
435900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        individualMipOffsets.push_back(combinedBufferSize);
436900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        combinedBufferSize += trimmedSize;
437900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    }
438900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
439900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // allocate buffer to hold our mip data
440900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    GrVkTransferBuffer* transferBuffer =
441900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                   GrVkTransferBuffer::Create(this, combinedBufferSize, GrVkBuffer::kCopyRead_Type);
442900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
443900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    char* buffer = (char*) transferBuffer->map();
444c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    SkTArray<VkBufferImageCopy> regions(texelsShallowCopy.count());
445900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
446c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    currentWidth = width;
447c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    currentHeight = height;
448c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    for (int currentMipLevel = 0; currentMipLevel < texelsShallowCopy.count(); currentMipLevel++) {
449900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        const size_t trimRowBytes = currentWidth * bpp;
450c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        const size_t rowBytes = texelsShallowCopy[currentMipLevel].fRowBytes;
451900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
452900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        // copy data into the buffer, skipping the trailing bytes
453900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        char* dst = buffer + individualMipOffsets[currentMipLevel];
454c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        const char* src = (const char*)texelsShallowCopy[currentMipLevel].fPixels;
455900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        if (flipY) {
456900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            src += (currentHeight - 1) * rowBytes;
457900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            for (int y = 0; y < currentHeight; y++) {
458900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                memcpy(dst, src, trimRowBytes);
459900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                src -= rowBytes;
460900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                dst += trimRowBytes;
461164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            }
462900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        } else if (trimRowBytes == rowBytes) {
463900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            memcpy(dst, src, trimRowBytes * currentHeight);
464164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        } else {
465900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            SkRectMemcpy(dst, trimRowBytes, src, rowBytes, trimRowBytes, currentHeight);
466164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
467164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
468900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        VkBufferImageCopy& region = regions.push_back();
469164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        memset(&region, 0, sizeof(VkBufferImageCopy));
470900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        region.bufferOffset = individualMipOffsets[currentMipLevel];
471900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        region.bufferRowLength = currentWidth;
472900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        region.bufferImageHeight = currentHeight;
473cf942c4ef750712b624867cbb2217c14857db3c6bsalomon        region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, SkToU32(currentMipLevel), 0, 1 };
474c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        region.imageOffset = { left, flipY ? tex->height() - top - currentHeight : top, 0 };
475900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        region.imageExtent = { (uint32_t)currentWidth, (uint32_t)currentHeight, 1 };
476c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth
477c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        currentWidth = SkTMax(1, currentWidth/2);
478c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth        currentHeight = SkTMax(1, currentHeight/2);
479900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    }
480164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
481900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    transferBuffer->unmap();
482164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
483900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // make sure the unmap has finished
484900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    transferBuffer->addMemoryBarrier(this,
485900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                     VK_ACCESS_HOST_WRITE_BIT,
486900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                     VK_ACCESS_TRANSFER_READ_BIT,
487900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                     VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
488900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                     VK_PIPELINE_STAGE_TRANSFER_BIT,
489900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                     false);
490164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
491900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // Change layout of our target so it can be copied to
492900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    VkImageLayout layout = tex->currentLayout();
493900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    VkPipelineStageFlags srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(layout);
494900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
495900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(layout);
496900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    VkAccessFlags dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
497900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    tex->setImageLayout(this,
498900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                        VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
499900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                        srcAccessMask,
500900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                        dstAccessMask,
501900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                        srcStageMask,
502900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                        dstStageMask,
503900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                        false);
504900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
505900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // Copy the buffer to the image
506900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    fCurrentCmdBuffer->copyBufferToImage(this,
507900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                         transferBuffer,
508900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                         tex,
509900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
510900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                         regions.count(),
511900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                         regions.begin());
512900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
513900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // Submit the current command buffer to the Queue
514900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    this->submitCommandBuffer(kSkip_SyncQueue);
515900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
516900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    transferBuffer->unref();
517164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
518164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return true;
519164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
520164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
521164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
5222e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunenGrTexture* GrVkGpu::onCreateTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted,
523a1e6b3be8124cef85f2e39e3cb85000ad9526d48bsalomon                                    const SkTArray<GrMipLevel>& texels) {
524164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag);
525164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
526164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkFormat pixelFormat;
527164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!GrPixelConfigToVkFormat(desc.fConfig, &pixelFormat)) {
528164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return nullptr;
529164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
530164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
531164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!fVkCaps->isConfigTexturable(desc.fConfig)) {
532164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return nullptr;
533164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
534164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
535164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    bool linearTiling = false;
536164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (SkToBool(desc.fFlags & kZeroCopy_GrSurfaceFlag)) {
537900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        // we can't have a linear texture with a mipmap
538900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        if (texels.count() > 1) {
539900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            SkDebugf("Trying to create linear tiled texture with mipmap");
540900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            return nullptr;
541900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        }
542164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        if (fVkCaps->isConfigTexurableLinearly(desc.fConfig) &&
543164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            (!renderTarget || fVkCaps->isConfigRenderableLinearly(desc.fConfig, false))) {
544164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            linearTiling = true;
545164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        } else {
546164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            return nullptr;
547164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
548164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
549164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
550164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT;
551164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (renderTarget) {
552164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        usageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
553164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
554164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
555164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // For now we will set the VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT and
556164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // VK_IMAGE_USAGE_TRANSFER_SOURCE_BIT on every texture since we do not know whether or not we
557164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // will be using this texture in some copy or not. Also this assumes, as is the current case,
55862340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    // that all render targets in vulkan are also textures. If we change this practice of setting
559164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // both bits, we must make sure to set the destination bit if we are uploading srcData to the
560164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // texture.
561164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    usageFlags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
562164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
563a1e6b3be8124cef85f2e39e3cb85000ad9526d48bsalomon    VkFlags memProps = (!texels.empty() && linearTiling) ? VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT :
564a1e6b3be8124cef85f2e39e3cb85000ad9526d48bsalomon                                                           VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
565164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
566164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // This ImageDesc refers to the texture that will be read by the client. Thus even if msaa is
56762340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    // requested, this ImageDesc describes the resolved texture. Therefore we always have samples set
568164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // to 1.
569c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    int mipLevels = texels.empty() ? 1 : texels.count();
570164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkImage::ImageDesc imageDesc;
571164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fImageType = VK_IMAGE_TYPE_2D;
572164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fFormat = pixelFormat;
573164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fWidth = desc.fWidth;
574164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fHeight = desc.fHeight;
575c578b06319f271ac46ac78e3b86f74fbceed360ejvanverth    imageDesc.fLevels = linearTiling ? 1 : mipLevels;
576164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fSamples = 1;
577164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fImageTiling = linearTiling ? VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL;
578164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fUsageFlags = usageFlags;
579164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fMemProps = memProps;
580164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
581164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkTexture* tex;
582164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (renderTarget) {
5832e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        tex = GrVkTextureRenderTarget::CreateNewTextureRenderTarget(this, budgeted, desc,
584164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                    imageDesc);
585164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    } else {
5862e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        tex = GrVkTexture::CreateNewTexture(this, budgeted, desc, imageDesc);
587164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
588164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
589164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!tex) {
590164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return nullptr;
591164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
592164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
593e699d0cd25fd059e3f0c4949e613e50c83a52179bsalomon    if (!texels.empty()) {
594e699d0cd25fd059e3f0c4949e613e50c83a52179bsalomon        SkASSERT(texels.begin()->fPixels);
595900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        bool success;
596900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        if (linearTiling) {
597900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            success = this->uploadTexDataLinear(tex, 0, 0, desc.fWidth, desc.fHeight, desc.fConfig,
598900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                                texels.begin()->fPixels, texels.begin()->fRowBytes);
599900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        } else {
600900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth            success = this->uploadTexDataOptimal(tex, 0, 0, desc.fWidth, desc.fHeight, desc.fConfig,
601900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                                 texels);
602900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        }
603900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        if (!success) {
604164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            tex->unref();
605164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            return nullptr;
606164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
607164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
608164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
609164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return tex;
610164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
611164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
612164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
613164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
614164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielstatic GrSurfaceOrigin resolve_origin(GrSurfaceOrigin origin) {
615164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // By default, all textures in Vk use TopLeft
616164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (kDefault_GrSurfaceOrigin == origin) {
617164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return kTopLeft_GrSurfaceOrigin;
618164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    } else {
619164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return origin;
620164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
621164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
622164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
623164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielGrTexture* GrVkGpu::onWrapBackendTexture(const GrBackendTextureDesc& desc,
624164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                         GrWrapOwnership ownership) {
625164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkFormat format;
626164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!GrPixelConfigToVkFormat(desc.fConfig, &format)) {
627164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return nullptr;
628164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
629164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
630164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (0 == desc.fTextureHandle) {
631164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return nullptr;
632164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
633164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
634164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    int maxSize = this->caps()->maxTextureSize();
635164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (desc.fWidth > maxSize || desc.fHeight > maxSize) {
636164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return nullptr;
637164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
638164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
639fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    const GrVkTextureInfo* info = reinterpret_cast<const GrVkTextureInfo*>(desc.fTextureHandle);
640fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    if (VK_NULL_HANDLE == info->fImage || VK_NULL_HANDLE == info->fAlloc) {
641fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        return nullptr;
642fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    }
643164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
644164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrSurfaceDesc surfDesc;
645164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // next line relies on GrBackendTextureDesc's flags matching GrTexture's
646164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    surfDesc.fFlags = (GrSurfaceFlags)desc.fFlags;
647164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    surfDesc.fWidth = desc.fWidth;
648164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    surfDesc.fHeight = desc.fHeight;
649164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    surfDesc.fConfig = desc.fConfig;
650164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    surfDesc.fSampleCnt = SkTMin(desc.fSampleCnt, this->caps()->maxSampleCount());
651164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrBackendTextureFlag);
652164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // In GL, Chrome assumes all textures are BottomLeft
653164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // In VK, we don't have this restriction
654164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    surfDesc.fOrigin = resolve_origin(desc.fOrigin);
655164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
656164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkTexture* texture = nullptr;
657164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (renderTarget) {
6589d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary        texture = GrVkTextureRenderTarget::CreateWrappedTextureRenderTarget(this, surfDesc,
6592e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen                                                                            ownership, format,
660fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth                                                                            info);
661164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    } else {
6622e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        texture = GrVkTexture::CreateWrappedTexture(this, surfDesc, ownership, format, info);
663164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
664164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!texture) {
665164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return nullptr;
666164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
667164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
668164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return texture;
669164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
670164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
671164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielGrRenderTarget* GrVkGpu::onWrapBackendRenderTarget(const GrBackendRenderTargetDesc& wrapDesc,
672164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                   GrWrapOwnership ownership) {
6739d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
674fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    const GrVkTextureInfo* info =
675fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        reinterpret_cast<const GrVkTextureInfo*>(wrapDesc.fRenderTargetHandle);
676fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    if (VK_NULL_HANDLE == info->fImage ||
677fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        (VK_NULL_HANDLE == info->fAlloc && kAdopt_GrWrapOwnership == ownership)) {
678fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        return nullptr;
679fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    }
680164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
681164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrSurfaceDesc desc;
682164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    desc.fConfig = wrapDesc.fConfig;
683164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    desc.fFlags = kCheckAllocation_GrSurfaceFlag;
684164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    desc.fWidth = wrapDesc.fWidth;
685164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    desc.fHeight = wrapDesc.fHeight;
686164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    desc.fSampleCnt = SkTMin(wrapDesc.fSampleCnt, this->caps()->maxSampleCount());
687164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
688164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    desc.fOrigin = resolve_origin(wrapDesc.fOrigin);
689164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
690164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkRenderTarget* tgt = GrVkRenderTarget::CreateWrappedRenderTarget(this, desc,
6912e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen                                                                        ownership,
692fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth                                                                        info);
693164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (tgt && wrapDesc.fStencilBits) {
694164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        if (!createStencilAttachmentForRenderTarget(tgt, desc.fWidth, desc.fHeight)) {
695164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            tgt->unref();
696164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            return nullptr;
697164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
698164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
699164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return tgt;
700164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
701164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
70262340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverthvoid GrVkGpu::generateMipmap(GrVkTexture* tex) const {
703900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    // don't do anything for linearly tiled textures (can't have mipmaps)
70462340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    if (tex->isLinearTiled()) {
705900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        SkDebugf("Trying to create mipmap for linear tiled texture");
70662340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth        return;
70762340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    }
70862340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth
70962340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    // We cannot generate mipmaps for images that are multisampled.
71062340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    // TODO: does it even make sense for rendertargets in general?
71162340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    if (tex->asRenderTarget() && tex->asRenderTarget()->numColorSamples() > 1) {
71262340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth        return;
71362340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    }
71462340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth
71562340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    // determine if we can blit to and from this format
71662340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    const GrVkCaps& caps = this->vkCaps();
71762340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    if (!caps.configCanBeDstofBlit(tex->config(), false) ||
71862340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth        !caps.configCanBeSrcofBlit(tex->config(), false)) {
71962340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth        return;
72062340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    }
72162340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth
72262340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    // change the original image's layout
72362340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    VkImageLayout origSrcLayout = tex->currentLayout();
72462340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    VkPipelineStageFlags srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(origSrcLayout);
72562340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
72662340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth
72762340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origSrcLayout);
72862340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    VkAccessFlags dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
72962340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth
73062340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    tex->setImageLayout(this, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
73162340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth                        srcAccessMask, dstAccessMask, srcStageMask, dstStageMask, false);
73262340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth
73362340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    // grab handle to the original image resource
73462340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    const GrVkImage::Resource* oldResource = tex->resource();
73562340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    oldResource->ref();
73662340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth
737900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    uint32_t mipLevels = SkMipMap::ComputeLevelCount(tex->width(), tex->height());
738900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    if (!tex->reallocForMipmap(this, mipLevels)) {
73962340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth        oldResource->unref(this);
74062340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth        return;
74162340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    }
74262340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth
74362340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    // change the new image's layout
74462340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    VkImageLayout origDstLayout = tex->currentLayout();
74562340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth
74662340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(origDstLayout);
74762340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
74862340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth
74962340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origDstLayout);
75062340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
75162340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth
7522af0f1b014b9aabb6119bf66fac20e4cd3a8279bjvanverth    tex->setImageLayout(this, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
7532af0f1b014b9aabb6119bf66fac20e4cd3a8279bjvanverth                        srcAccessMask, dstAccessMask, srcStageMask, dstStageMask, false);
75462340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth
75562340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    // Blit original image
75662340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    int width = tex->width();
75762340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    int height = tex->height();
75862340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    uint32_t mipLevel = 0;
75962340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth
76062340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    VkImageBlit blitRegion;
76162340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    memset(&blitRegion, 0, sizeof(VkImageBlit));
76262340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    blitRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
76362340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    blitRegion.srcOffsets[0] = { 0, 0, 0 };
76462340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    blitRegion.srcOffsets[1] = { width, height, 0 };
76562340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    blitRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, mipLevel, 0, 1 };
76662340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    blitRegion.dstOffsets[0] = { 0, 0, 0 };
76762340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    blitRegion.dstOffsets[1] = { width, height, 0 };
76862340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth
76962340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    fCurrentCmdBuffer->blitImage(this,
77062340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth                                 oldResource,
77162340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth                                 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
77262340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth                                 tex->resource(),
77362340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth                                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
77462340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth                                 1,
77562340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth                                 &blitRegion,
77662340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth                                 VK_FILTER_LINEAR);
77762340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    // Blit the miplevels
77862340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    while (width/2 > 0 && height/2 > 0) {
77962340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth        blitRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, mipLevel, 0, 1 };
78062340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth        blitRegion.srcOffsets[0] = { 0, 0, 0 };
78162340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth        blitRegion.srcOffsets[1] = { width, height, 0 };
78262340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth        blitRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, mipLevel+1, 0, 1 };
78362340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth        blitRegion.dstOffsets[0] = { 0, 0, 0 };
78462340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth        blitRegion.dstOffsets[1] = { width/2, height/2, 0 };
78562340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth
786900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth        // TODO: insert image barrier to wait on previous blit
7872af0f1b014b9aabb6119bf66fac20e4cd3a8279bjvanverth        // TODO: change layout of src subresource to TRANSFER_SRC_OPTIMAL
788900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
78962340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth        fCurrentCmdBuffer->blitImage(this,
79062340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth                                     tex->resource(),
79162340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth                                     VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
79262340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth                                     tex->resource(),
79362340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth                                     VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
79462340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth                                     1,
79562340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth                                     &blitRegion,
79662340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth                                     VK_FILTER_LINEAR);
79762340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth
79862340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth        width /= 2;
79962340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth        height /= 2;
80062340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth        mipLevel++;
80162340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    }
80262340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth
80362340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth    oldResource->unref(this);
80462340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth}
80562340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth
80662340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth
80762340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth
808164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
809164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
810164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::bindGeometry(const GrPrimitiveProcessor& primProc,
8110e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                           const GrNonInstancedMesh& mesh) {
81258a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel    // There is no need to put any memory barriers to make sure host writes have finished here.
81358a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel    // When a command buffer is submitted to a queue, there is an implicit memory barrier that
81458a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel    // occurs for all host writes. Additionally, BufferMemoryBarriers are not allowed inside of
81558a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel    // an active RenderPass.
816164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkVertexBuffer* vbuf;
8170e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel    vbuf = (GrVkVertexBuffer*)mesh.vertexBuffer();
818164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(vbuf);
819164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(!vbuf->isMapped());
820164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
821164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->bindVertexBuffer(this, vbuf);
822164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
8230e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel    if (mesh.isIndexed()) {
8240e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel        GrVkIndexBuffer* ibuf = (GrVkIndexBuffer*)mesh.indexBuffer();
825164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        SkASSERT(ibuf);
826164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        SkASSERT(!ibuf->isMapped());
827164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
828164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        fCurrentCmdBuffer->bindIndexBuffer(this, ibuf);
829164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
830164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
831164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
832164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
833164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
834164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielGrStencilAttachment* GrVkGpu::createStencilAttachmentForRenderTarget(const GrRenderTarget* rt,
835164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                     int width,
836164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                     int height) {
837164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(width >= rt->width());
838164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(height >= rt->height());
839164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
840164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    int samples = rt->numStencilSamples();
841164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
8428f1dcaa6f3cc098bd5efd2595ca20e0bc1847d10egdaniel    const GrVkCaps::StencilFormat& sFmt = this->vkCaps().preferedStencilFormat();
843164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
844164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkStencilAttachment* stencil(GrVkStencilAttachment::Create(this,
845164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                 width,
846164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                 height,
847164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                 samples,
848164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                 sFmt));
849164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fStats.incStencilAttachmentCreates();
850164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return stencil;
851164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
852164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
853164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
854164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
855164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielGrBackendObject GrVkGpu::createTestingOnlyBackendTexture(void* srcData, int w, int h,
856164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                         GrPixelConfig config) {
857164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
858164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkFormat pixelFormat;
859164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!GrPixelConfigToVkFormat(config, &pixelFormat)) {
860164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return 0;
861164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
862164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
863164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    bool linearTiling = false;
864164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!fVkCaps->isConfigTexturable(config)) {
865164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return 0;
866164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
867164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
868164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (fVkCaps->isConfigTexurableLinearly(config)) {
869164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        linearTiling = true;
870164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
871164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
872164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Currently this is not supported since it requires a copy which has not yet been implemented.
873164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (srcData && !linearTiling) {
874164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return 0;
875164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
876164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
877164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT;
878164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    usageFlags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
879164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    usageFlags |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
880164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
881164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkFlags memProps = (srcData && linearTiling) ? VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT :
882164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                   VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
883164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
884fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    VkImage image = VK_NULL_HANDLE;
885fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    VkDeviceMemory alloc = VK_NULL_HANDLE;
886164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
887fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    VkImageTiling imageTiling = linearTiling ? VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL;
888fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    VkImageLayout initialLayout = (VK_IMAGE_TILING_LINEAR == imageTiling)
889fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth                                ? VK_IMAGE_LAYOUT_PREINITIALIZED
890fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth                                : VK_IMAGE_LAYOUT_UNDEFINED;
891fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth
892fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    // Create Image
893fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    VkSampleCountFlagBits vkSamples;
894fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    if (!GrSampleCountToVkSampleCount(1, &vkSamples)) {
895fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        return 0;
896fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    }
897fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth
898fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    const VkImageCreateInfo imageCreateInfo = {
899fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,         // sType
900fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        NULL,                                        // pNext
901fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        0,                                           // VkImageCreateFlags
902fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        VK_IMAGE_TYPE_2D,                            // VkImageType
903fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        pixelFormat,                                 // VkFormat
904384b5e9cd36e443437de8df3b0f78ef4150efbacethannicholas        { (uint32_t) w, (uint32_t) h, 1 },           // VkExtent3D
905fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        1,                                           // mipLevels
906fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        1,                                           // arrayLayers
907fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        vkSamples,                                   // samples
908fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        imageTiling,                                 // VkImageTiling
909fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        usageFlags,                                  // VkImageUsageFlags
910fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        VK_SHARING_MODE_EXCLUSIVE,                   // VkSharingMode
911fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        0,                                           // queueFamilyCount
912fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        0,                                           // pQueueFamilyIndices
913fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        initialLayout                                // initialLayout
914fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    };
915fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth
916fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    GR_VK_CALL_ERRCHECK(this->vkInterface(), CreateImage(this->device(), &imageCreateInfo, nullptr, &image));
917fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth
918fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    if (!GrVkMemory::AllocAndBindImageMemory(this, image, memProps, &alloc)) {
919fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        VK_CALL(DestroyImage(this->device(), image, nullptr));
920164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return 0;
921164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
922164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
923164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (srcData) {
924164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        if (linearTiling) {
925164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            const VkImageSubresource subres = {
926164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                VK_IMAGE_ASPECT_COLOR_BIT,
927164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                0,  // mipLevel
928164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                0,  // arraySlice
929164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            };
930164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            VkSubresourceLayout layout;
931164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            VkResult err;
932164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
933fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth            VK_CALL(GetImageSubresourceLayout(fDevice, image, &subres, &layout));
934164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
935164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            void* mapPtr;
936fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth            err = VK_CALL(MapMemory(fDevice, alloc, 0, layout.rowPitch * h, 0, &mapPtr));
937164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            if (err) {
938fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth                VK_CALL(FreeMemory(this->device(), alloc, nullptr));
939fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth                VK_CALL(DestroyImage(this->device(), image, nullptr));
940164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                return 0;
941164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            }
942164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
943164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            size_t bpp = GrBytesPerPixel(config);
944164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            size_t rowCopyBytes = bpp * w;
945164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            // If there is no padding on dst (layout.rowPitch) we can do a single memcopy.
946164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            // This assumes the srcData comes in with no padding.
947164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            if (rowCopyBytes == layout.rowPitch) {
948164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                memcpy(mapPtr, srcData, rowCopyBytes * h);
949164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            } else {
950fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth                SkRectMemcpy(mapPtr, static_cast<size_t>(layout.rowPitch), srcData, rowCopyBytes,
951fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth                             rowCopyBytes, h);
952164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            }
953fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth            VK_CALL(UnmapMemory(fDevice, alloc));
954164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        } else {
955164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            // TODO: Add support for copying to optimal tiling
956164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            SkASSERT(false);
957164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
958164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
959164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
960fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    GrVkTextureInfo* info = new GrVkTextureInfo;
961fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    info->fImage = image;
962fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    info->fAlloc = alloc;
963fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    info->fImageTiling = imageTiling;
964fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    info->fImageLayout = initialLayout;
96558a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel    info->fFormat = pixelFormat;
9662af0f1b014b9aabb6119bf66fac20e4cd3a8279bjvanverth    info->fLevelCount = 1;
967fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth
968fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    return (GrBackendObject)info;
969164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
970164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
971164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::isTestingOnlyBackendTexture(GrBackendObject id) const {
972fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    const GrVkTextureInfo* backend = reinterpret_cast<const GrVkTextureInfo*>(id);
973164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
974164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (backend && backend->fImage && backend->fAlloc) {
975164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkMemoryRequirements req;
976164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        memset(&req, 0, sizeof(req));
977164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        GR_VK_CALL(this->vkInterface(), GetImageMemoryRequirements(fDevice,
978164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                   backend->fImage,
979164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                   &req));
980164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // TODO: find a better check
981164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // This will probably fail with a different driver
982164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return (req.size > 0) && (req.size <= 8192 * 8192);
983164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
984164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
985164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return false;
986164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
987164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
988164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::deleteTestingOnlyBackendTexture(GrBackendObject id, bool abandon) {
989fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    const GrVkTextureInfo* backend = reinterpret_cast<const GrVkTextureInfo*>(id);
990164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
991164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (backend) {
992164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        if (!abandon) {
993fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth            // something in the command buffer may still be using this, so force submit
994fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth            this->submitCommandBuffer(kForce_SyncQueue);
995fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth
996fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth            VK_CALL(FreeMemory(this->device(), backend->fAlloc, nullptr));
997fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth            VK_CALL(DestroyImage(this->device(), backend->fImage, nullptr));
998164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
999fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        delete backend;
1000164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1001164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1002164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1003164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
1004164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1005164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::addMemoryBarrier(VkPipelineStageFlags srcStageMask,
1006164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                               VkPipelineStageFlags dstStageMask,
1007164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                               bool byRegion,
1008164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                               VkMemoryBarrier* barrier) const {
1009164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(fCurrentCmdBuffer);
1010164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->pipelineBarrier(this,
1011164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       srcStageMask,
1012164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       dstStageMask,
1013164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       byRegion,
1014164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       GrVkCommandBuffer::kMemory_BarrierType,
1015164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       barrier);
1016164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1017164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1018164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::addBufferMemoryBarrier(VkPipelineStageFlags srcStageMask,
1019164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     VkPipelineStageFlags dstStageMask,
1020164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     bool byRegion,
1021164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     VkBufferMemoryBarrier* barrier) const {
1022164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(fCurrentCmdBuffer);
1023164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->pipelineBarrier(this,
1024164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       srcStageMask,
1025164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       dstStageMask,
1026164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       byRegion,
1027164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       GrVkCommandBuffer::kBufferMemory_BarrierType,
1028164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       barrier);
1029164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1030164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1031164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::addImageMemoryBarrier(VkPipelineStageFlags srcStageMask,
1032164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                    VkPipelineStageFlags dstStageMask,
1033164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                    bool byRegion,
1034164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                    VkImageMemoryBarrier* barrier) const {
1035164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(fCurrentCmdBuffer);
1036164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->pipelineBarrier(this,
1037164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       srcStageMask,
1038164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       dstStageMask,
1039164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       byRegion,
1040164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       GrVkCommandBuffer::kImageMemory_BarrierType,
1041164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       barrier);
1042164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1043164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1044164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::finishDrawTarget() {
1045164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Submit the current command buffer to the Queue
1046164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    this->submitCommandBuffer(kSkip_SyncQueue);
1047164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1048164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
10493d5d9ac426ea926f37eaa47e13acf7492068667begdanielvoid GrVkGpu::clearStencil(GrRenderTarget* target) {
10503d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    if (nullptr == target) {
10513d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        return;
10523d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    }
10533d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    GrStencilAttachment* stencil = target->renderTargetPriv().getStencilAttachment();
10543d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    GrVkStencilAttachment* vkStencil = (GrVkStencilAttachment*)stencil;
10553d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
10563d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
10573d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    VkClearDepthStencilValue vkStencilColor;
10583d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    memset(&vkStencilColor, 0, sizeof(VkClearDepthStencilValue));
10593d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
10603d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    VkImageLayout origDstLayout = vkStencil->currentLayout();
10613d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
10623d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    VkPipelineStageFlags srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(origDstLayout);
10633d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
10643d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
10653d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origDstLayout);;
10663d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    VkAccessFlags dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
10673d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
10683d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    vkStencil->setImageLayout(this,
10693d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                              VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
10703d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                              srcAccessMask,
10713d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                              dstAccessMask,
10723d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                              srcStageMask,
10733d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                              dstStageMask,
10743d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                              false);
10753d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
10763d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
10773d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    VkImageSubresourceRange subRange;
10783d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    memset(&subRange, 0, sizeof(VkImageSubresourceRange));
10793d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    subRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
10803d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    subRange.baseMipLevel = 0;
10813d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    subRange.levelCount = 1;
10823d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    subRange.baseArrayLayer = 0;
10833d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    subRange.layerCount = 1;
10843d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
10853d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    // TODO: I imagine that most times we want to clear a stencil it will be at the beginning of a
10863d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    // draw. Thus we should look into using the load op functions on the render pass to clear out
10873d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    // the stencil there.
10883d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    fCurrentCmdBuffer->clearDepthStencilImage(this, vkStencil, &vkStencilColor, 1, &subRange);
10893d5d9ac426ea926f37eaa47e13acf7492068667begdaniel}
10903d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
10913d5d9ac426ea926f37eaa47e13acf7492068667begdanielvoid GrVkGpu::onClearStencilClip(GrRenderTarget* target, const SkIRect& rect, bool insideClip) {
10923d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    SkASSERT(target);
10933d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
10943d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(target);
10953d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    GrStencilAttachment* sb = target->renderTargetPriv().getStencilAttachment();
10963d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    GrVkStencilAttachment* vkStencil = (GrVkStencilAttachment*)sb;
10973d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
10983d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    // this should only be called internally when we know we have a
10993d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    // stencil buffer.
11003d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    SkASSERT(sb);
11013d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    int stencilBitCount = sb->bits();
11023d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
11033d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    // The contract with the callers does not guarantee that we preserve all bits in the stencil
11043d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    // during this clear. Thus we will clear the entire stencil to the desired value.
11053d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
11063d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    VkClearDepthStencilValue vkStencilColor;
11073d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    memset(&vkStencilColor, 0, sizeof(VkClearDepthStencilValue));
11083d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    if (insideClip) {
11093d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        vkStencilColor.stencil = (1 << (stencilBitCount - 1));
11103d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    } else {
11113d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        vkStencilColor.stencil = 0;
11123d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    }
11133d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
11143d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    VkImageLayout origDstLayout = vkStencil->currentLayout();
11153d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origDstLayout);
11163d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    VkAccessFlags dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
111758a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel    VkPipelineStageFlags srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(origDstLayout);
11183d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
11193d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    vkStencil->setImageLayout(this,
11203d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                              VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
11213d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                              srcAccessMask,
11223d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                              dstAccessMask,
11233d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                              srcStageMask,
11243d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                              dstStageMask,
11253d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                              false);
11263d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
112758a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel    // Change layout of our render target so it can be used as the color attachment. This is what
112858a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel    // the render pass expects when it begins.
112958a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel    VkImageLayout layout = vkRT->currentLayout();
113058a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel    srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(layout);
113158a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel    dstStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
113258a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel    srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(layout);
113358a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel    dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
113458a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel    vkRT->setImageLayout(this,
113558a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
113658a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel                         srcAccessMask,
113758a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel                         dstAccessMask,
113858a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel                         srcStageMask,
113958a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel                         dstStageMask,
114058a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel                         false);
114158a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel
11423d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    VkClearRect clearRect;
11433d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    // Flip rect if necessary
11443d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    SkIRect vkRect = rect;
11453d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
11463d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    if (kBottomLeft_GrSurfaceOrigin == vkRT->origin()) {
11473d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        vkRect.fTop = vkRT->height() - rect.fBottom;
11483d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        vkRect.fBottom = vkRT->height() - rect.fTop;
11493d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    }
11503d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
11513d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    clearRect.rect.offset = { vkRect.fLeft, vkRect.fTop };
11523d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    clearRect.rect.extent = { (uint32_t)vkRect.width(), (uint32_t)vkRect.height() };
11533d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
11543d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    clearRect.baseArrayLayer = 0;
11553d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    clearRect.layerCount = 1;
11563d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
11573d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    const GrVkRenderPass* renderPass = vkRT->simpleRenderPass();
11583d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    SkASSERT(renderPass);
11593d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    fCurrentCmdBuffer->beginRenderPass(this, renderPass, *vkRT);
11603d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
11613d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    uint32_t stencilIndex;
11623d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    SkAssertResult(renderPass->stencilAttachmentIndex(&stencilIndex));
11633d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
11643d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    VkClearAttachment attachment;
11653d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    attachment.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
11663d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    attachment.colorAttachment = 0; // this value shouldn't matter
11673d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    attachment.clearValue.depthStencil = vkStencilColor;
11683d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
11693d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    fCurrentCmdBuffer->clearAttachments(this, 1, &attachment, 1, &clearRect);
11703d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    fCurrentCmdBuffer->endRenderPass(this);
11713d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
11723d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    return;
11733d5d9ac426ea926f37eaa47e13acf7492068667begdaniel}
11743d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
1175164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::onClear(GrRenderTarget* target, const SkIRect& rect, GrColor color) {
1176164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // parent class should never let us get here with no RT
1177164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(target);
1178164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1179164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkClearColorValue vkColor;
1180164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrColorToRGBAFloat(color, vkColor.float32);
11819d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
1182164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(target);
1183164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkImageLayout origDstLayout = vkRT->currentLayout();
1184164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1185164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (rect.width() != target->width() || rect.height() != target->height()) {
1186164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origDstLayout);
1187164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkAccessFlags dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
118858a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel        VkPipelineStageFlags srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(origDstLayout);
1189164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1190164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        vkRT->setImageLayout(this,
1191164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                             VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1192164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                             srcAccessMask,
1193164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                             dstAccessMask,
1194164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                             srcStageMask,
1195164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                             dstStageMask,
1196164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                             false);
1197164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
119858a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel        // If we are using a stencil attachment we also need to change its layout to what the render
119958a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel        // pass is expecting.
120058a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel        if (GrStencilAttachment* stencil = vkRT->renderTargetPriv().getStencilAttachment()) {
120158a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel            GrVkStencilAttachment* vkStencil = (GrVkStencilAttachment*)stencil;
120258a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel            origDstLayout = vkStencil->currentLayout();
120358a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel            srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origDstLayout);
120458a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel            dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
120558a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel                            VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
120658a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel            srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(origDstLayout);
120758a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel            dstStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
120858a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel            vkStencil->setImageLayout(this,
120958a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel                                      VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
121058a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel                                      srcAccessMask,
121158a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel                                      dstAccessMask,
121258a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel                                      srcStageMask,
121358a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel                                      dstStageMask,
121458a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel                                      false);
121558a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel        }
121658a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel
1217164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkClearRect clearRect;
12183d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        // Flip rect if necessary
12193d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        SkIRect vkRect = rect;
12203d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        if (kBottomLeft_GrSurfaceOrigin == vkRT->origin()) {
12213d5d9ac426ea926f37eaa47e13acf7492068667begdaniel            vkRect.fTop = vkRT->height() - rect.fBottom;
12223d5d9ac426ea926f37eaa47e13acf7492068667begdaniel            vkRect.fBottom = vkRT->height() - rect.fTop;
12233d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        }
12243d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        clearRect.rect.offset = { vkRect.fLeft, vkRect.fTop };
12253d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        clearRect.rect.extent = { (uint32_t)vkRect.width(), (uint32_t)vkRect.height() };
1226e77875aa425d51cc8db3463343a6308f9d2aadccjvanverth        clearRect.baseArrayLayer = 0;
1227e77875aa425d51cc8db3463343a6308f9d2aadccjvanverth        clearRect.layerCount = 1;
1228164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1229164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        const GrVkRenderPass* renderPass = vkRT->simpleRenderPass();
1230164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        SkASSERT(renderPass);
1231164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        fCurrentCmdBuffer->beginRenderPass(this, renderPass, *vkRT);
1232164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1233164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        uint32_t colorIndex;
1234164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        SkAssertResult(renderPass->colorAttachmentIndex(&colorIndex));
1235164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1236164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkClearAttachment attachment;
1237164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
1238164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        attachment.colorAttachment = colorIndex;
1239164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        attachment.clearValue.color = vkColor;
1240164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1241164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        fCurrentCmdBuffer->clearAttachments(this, 1, &attachment, 1, &clearRect);
1242164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        fCurrentCmdBuffer->endRenderPass(this);
1243164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return;
1244164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1245164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1246164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkPipelineStageFlags srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(origDstLayout);
1247164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
1248164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1249164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origDstLayout);;
1250164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkAccessFlags dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
1251164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1252164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    vkRT->setImageLayout(this,
1253164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1254164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         srcAccessMask,
1255164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         dstAccessMask,
1256164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         srcStageMask,
1257164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         dstStageMask,
1258164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         false);
1259164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1260164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1261164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkImageSubresourceRange subRange;
1262164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    memset(&subRange, 0, sizeof(VkImageSubresourceRange));
1263164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    subRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
1264164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    subRange.baseMipLevel = 0;
1265164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    subRange.levelCount = 1;
1266164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    subRange.baseArrayLayer = 0;
1267164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    subRange.layerCount = 1;
1268164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
12699d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary    // In the future we may not actually be doing this type of clear at all. If we are inside a
1270164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // render pass or doing a non full clear then we will use CmdClearColorAttachment. The more
1271164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // common use case will be clearing an attachment at the start of a render pass, in which case
1272164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // we will use the clear load ops.
1273164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->clearColorImage(this,
1274164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       vkRT,
1275164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       &vkColor,
1276164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       1, &subRange);
1277164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1278164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1279164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielinline bool can_copy_image(const GrSurface* dst,
1280164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           const GrSurface* src,
1281164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           const GrVkGpu* gpu) {
128217b892551465e5a44560a06e4b34dc3592b49622egdaniel    // Currently we don't support msaa
128317b892551465e5a44560a06e4b34dc3592b49622egdaniel    if ((dst->asRenderTarget() && dst->asRenderTarget()->numColorSamples() > 1) ||
128417b892551465e5a44560a06e4b34dc3592b49622egdaniel        (src->asRenderTarget() && src->asRenderTarget()->numColorSamples() > 1)) {
128517b892551465e5a44560a06e4b34dc3592b49622egdaniel        return false;
128617b892551465e5a44560a06e4b34dc3592b49622egdaniel    }
128717b892551465e5a44560a06e4b34dc3592b49622egdaniel
128817b892551465e5a44560a06e4b34dc3592b49622egdaniel    // We require that all vulkan GrSurfaces have been created with transfer_dst and transfer_src
128917b892551465e5a44560a06e4b34dc3592b49622egdaniel    // as image usage flags.
129017b892551465e5a44560a06e4b34dc3592b49622egdaniel    if (src->origin() == dst->origin() &&
129117b892551465e5a44560a06e4b34dc3592b49622egdaniel        GrBytesPerPixel(src->config()) == GrBytesPerPixel(dst->config())) {
1292164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return true;
1293164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1294164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1295164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // How does msaa play into this? If a VkTexture is multisampled, are we copying the multisampled
129617b892551465e5a44560a06e4b34dc3592b49622egdaniel    // or the resolved image here? Im multisampled, Vulkan requires sample counts to be the same.
1297164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1298164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return false;
1299164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1300164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1301164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::copySurfaceAsCopyImage(GrSurface* dst,
1302164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     GrSurface* src,
130317b892551465e5a44560a06e4b34dc3592b49622egdaniel                                     GrVkImage* dstImage,
130417b892551465e5a44560a06e4b34dc3592b49622egdaniel                                     GrVkImage* srcImage,
1305164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     const SkIRect& srcRect,
1306164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     const SkIPoint& dstPoint) {
1307164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(can_copy_image(dst, src, this));
1308164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
130917b892551465e5a44560a06e4b34dc3592b49622egdaniel    VkImageLayout origDstLayout = dstImage->currentLayout();
131017b892551465e5a44560a06e4b34dc3592b49622egdaniel    VkImageLayout origSrcLayout = srcImage->currentLayout();
1311164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1312164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkPipelineStageFlags srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(origDstLayout);
1313164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
1314164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1315164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // These flags are for flushing/invalidating caches and for the dst image it doesn't matter if
1316164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // the cache is flushed since it is only being written to.
1317164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origDstLayout);;
1318164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkAccessFlags dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
13199d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
132017b892551465e5a44560a06e4b34dc3592b49622egdaniel    dstImage->setImageLayout(this,
132117b892551465e5a44560a06e4b34dc3592b49622egdaniel                            VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
132217b892551465e5a44560a06e4b34dc3592b49622egdaniel                            srcAccessMask,
132317b892551465e5a44560a06e4b34dc3592b49622egdaniel                            dstAccessMask,
132417b892551465e5a44560a06e4b34dc3592b49622egdaniel                            srcStageMask,
132517b892551465e5a44560a06e4b34dc3592b49622egdaniel                            dstStageMask,
132617b892551465e5a44560a06e4b34dc3592b49622egdaniel                            false);
13279d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
1328164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(origSrcLayout);
1329164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
1330164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1331164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origSrcLayout);
1332164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
1333164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
133417b892551465e5a44560a06e4b34dc3592b49622egdaniel    srcImage->setImageLayout(this,
133517b892551465e5a44560a06e4b34dc3592b49622egdaniel                             VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
133617b892551465e5a44560a06e4b34dc3592b49622egdaniel                             srcAccessMask,
133717b892551465e5a44560a06e4b34dc3592b49622egdaniel                             dstAccessMask,
133817b892551465e5a44560a06e4b34dc3592b49622egdaniel                             srcStageMask,
133917b892551465e5a44560a06e4b34dc3592b49622egdaniel                             dstStageMask,
134017b892551465e5a44560a06e4b34dc3592b49622egdaniel                             false);
1341164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1342164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Flip rect if necessary
1343164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkIRect srcVkRect = srcRect;
1344164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    int32_t dstY = dstPoint.fY;
1345164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1346164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (kBottomLeft_GrSurfaceOrigin == src->origin()) {
1347164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        SkASSERT(kBottomLeft_GrSurfaceOrigin == dst->origin());
1348164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        srcVkRect.fTop = src->height() - srcRect.fBottom;
1349164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        srcVkRect.fBottom =  src->height() - srcRect.fTop;
1350164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        dstY = dst->height() - dstPoint.fY - srcVkRect.height();
1351164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1352164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1353164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkImageCopy copyRegion;
1354164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    memset(&copyRegion, 0, sizeof(VkImageCopy));
1355164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    copyRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
1356164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    copyRegion.srcOffset = { srcVkRect.fLeft, srcVkRect.fTop, 0 };
1357164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    copyRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
1358164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    copyRegion.dstOffset = { dstPoint.fX, dstY, 0 };
1359c355bc8dd117291b63ee7b7b39ec37a0e768eec5egdaniel    // The depth value of the extent is ignored according the vulkan spec for 2D images. However, on
1360c355bc8dd117291b63ee7b7b39ec37a0e768eec5egdaniel    // at least the nexus 5X it seems to be checking it. Thus as a working around we must have the
1361c355bc8dd117291b63ee7b7b39ec37a0e768eec5egdaniel    // depth value be 1.
1362c355bc8dd117291b63ee7b7b39ec37a0e768eec5egdaniel    copyRegion.extent = { (uint32_t)srcVkRect.width(), (uint32_t)srcVkRect.height(), 1 };
1363164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1364164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->copyImage(this,
136517b892551465e5a44560a06e4b34dc3592b49622egdaniel                                 srcImage,
1366164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
136717b892551465e5a44560a06e4b34dc3592b49622egdaniel                                 dstImage,
1368164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1369164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                 1,
1370164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                 &copyRegion);
1371900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
1372900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY,
1373900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth                                        srcRect.width(), srcRect.height());
1374900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    this->didWriteToSurface(dst, &dstRect);
1375164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1376164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
137717b892551465e5a44560a06e4b34dc3592b49622egdanielinline bool can_copy_as_blit(const GrSurface* dst,
137817b892551465e5a44560a06e4b34dc3592b49622egdaniel                             const GrSurface* src,
137917b892551465e5a44560a06e4b34dc3592b49622egdaniel                             const GrVkImage* dstImage,
138017b892551465e5a44560a06e4b34dc3592b49622egdaniel                             const GrVkImage* srcImage,
138117b892551465e5a44560a06e4b34dc3592b49622egdaniel                             const GrVkGpu* gpu) {
138217b892551465e5a44560a06e4b34dc3592b49622egdaniel    // We require that all vulkan GrSurfaces have been created with transfer_dst and transfer_src
138317b892551465e5a44560a06e4b34dc3592b49622egdaniel    // as image usage flags.
138417b892551465e5a44560a06e4b34dc3592b49622egdaniel    const GrVkCaps& caps = gpu->vkCaps();
138517b892551465e5a44560a06e4b34dc3592b49622egdaniel    if (!caps.configCanBeDstofBlit(dst->config(), dstImage->isLinearTiled()) ||
138617b892551465e5a44560a06e4b34dc3592b49622egdaniel        !caps.configCanBeSrcofBlit(src->config(), srcImage->isLinearTiled())) {
138717b892551465e5a44560a06e4b34dc3592b49622egdaniel        return false;
138817b892551465e5a44560a06e4b34dc3592b49622egdaniel    }
138917b892551465e5a44560a06e4b34dc3592b49622egdaniel
139017b892551465e5a44560a06e4b34dc3592b49622egdaniel    // We cannot blit images that are multisampled. Will need to figure out if we can blit the
139117b892551465e5a44560a06e4b34dc3592b49622egdaniel    // resolved msaa though.
139217b892551465e5a44560a06e4b34dc3592b49622egdaniel    if ((dst->asRenderTarget() && dst->asRenderTarget()->numColorSamples() > 1) ||
139317b892551465e5a44560a06e4b34dc3592b49622egdaniel        (src->asRenderTarget() && src->asRenderTarget()->numColorSamples() > 1)) {
139417b892551465e5a44560a06e4b34dc3592b49622egdaniel        return false;
139517b892551465e5a44560a06e4b34dc3592b49622egdaniel    }
139617b892551465e5a44560a06e4b34dc3592b49622egdaniel
139717b892551465e5a44560a06e4b34dc3592b49622egdaniel    return true;
139817b892551465e5a44560a06e4b34dc3592b49622egdaniel}
139917b892551465e5a44560a06e4b34dc3592b49622egdaniel
140017b892551465e5a44560a06e4b34dc3592b49622egdanielvoid GrVkGpu::copySurfaceAsBlit(GrSurface* dst,
140117b892551465e5a44560a06e4b34dc3592b49622egdaniel                                GrSurface* src,
140217b892551465e5a44560a06e4b34dc3592b49622egdaniel                                GrVkImage* dstImage,
140317b892551465e5a44560a06e4b34dc3592b49622egdaniel                                GrVkImage* srcImage,
140417b892551465e5a44560a06e4b34dc3592b49622egdaniel                                const SkIRect& srcRect,
140517b892551465e5a44560a06e4b34dc3592b49622egdaniel                                const SkIPoint& dstPoint) {
140617b892551465e5a44560a06e4b34dc3592b49622egdaniel    SkASSERT(can_copy_as_blit(dst, src, dstImage, srcImage, this));
140717b892551465e5a44560a06e4b34dc3592b49622egdaniel
140817b892551465e5a44560a06e4b34dc3592b49622egdaniel    VkImageLayout origDstLayout = dstImage->currentLayout();
140917b892551465e5a44560a06e4b34dc3592b49622egdaniel    VkImageLayout origSrcLayout = srcImage->currentLayout();
141017b892551465e5a44560a06e4b34dc3592b49622egdaniel
141117b892551465e5a44560a06e4b34dc3592b49622egdaniel    VkPipelineStageFlags srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(origDstLayout);
141217b892551465e5a44560a06e4b34dc3592b49622egdaniel    VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
141317b892551465e5a44560a06e4b34dc3592b49622egdaniel
141417b892551465e5a44560a06e4b34dc3592b49622egdaniel    VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origDstLayout);;
141517b892551465e5a44560a06e4b34dc3592b49622egdaniel    VkAccessFlags dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
141617b892551465e5a44560a06e4b34dc3592b49622egdaniel
141717b892551465e5a44560a06e4b34dc3592b49622egdaniel    dstImage->setImageLayout(this,
141817b892551465e5a44560a06e4b34dc3592b49622egdaniel                             VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
141917b892551465e5a44560a06e4b34dc3592b49622egdaniel                             srcAccessMask,
142017b892551465e5a44560a06e4b34dc3592b49622egdaniel                             dstAccessMask,
142117b892551465e5a44560a06e4b34dc3592b49622egdaniel                             srcStageMask,
142217b892551465e5a44560a06e4b34dc3592b49622egdaniel                             dstStageMask,
142317b892551465e5a44560a06e4b34dc3592b49622egdaniel                             false);
142417b892551465e5a44560a06e4b34dc3592b49622egdaniel
142517b892551465e5a44560a06e4b34dc3592b49622egdaniel    srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(origSrcLayout);
142617b892551465e5a44560a06e4b34dc3592b49622egdaniel    dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
142717b892551465e5a44560a06e4b34dc3592b49622egdaniel
142817b892551465e5a44560a06e4b34dc3592b49622egdaniel    srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origSrcLayout);
142917b892551465e5a44560a06e4b34dc3592b49622egdaniel    dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
143017b892551465e5a44560a06e4b34dc3592b49622egdaniel
143117b892551465e5a44560a06e4b34dc3592b49622egdaniel    srcImage->setImageLayout(this,
143217b892551465e5a44560a06e4b34dc3592b49622egdaniel                             VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
143317b892551465e5a44560a06e4b34dc3592b49622egdaniel                             srcAccessMask,
143417b892551465e5a44560a06e4b34dc3592b49622egdaniel                             dstAccessMask,
143517b892551465e5a44560a06e4b34dc3592b49622egdaniel                             srcStageMask,
143617b892551465e5a44560a06e4b34dc3592b49622egdaniel                             dstStageMask,
143717b892551465e5a44560a06e4b34dc3592b49622egdaniel                             false);
143817b892551465e5a44560a06e4b34dc3592b49622egdaniel
143917b892551465e5a44560a06e4b34dc3592b49622egdaniel    // Flip rect if necessary
144017b892551465e5a44560a06e4b34dc3592b49622egdaniel    SkIRect srcVkRect;
14418af936d3047208def585b7bc824f013b994f6312egdaniel    srcVkRect.fLeft = srcRect.fLeft;
14428af936d3047208def585b7bc824f013b994f6312egdaniel    srcVkRect.fRight = srcRect.fRight;
144317b892551465e5a44560a06e4b34dc3592b49622egdaniel    SkIRect dstRect;
144417b892551465e5a44560a06e4b34dc3592b49622egdaniel    dstRect.fLeft = dstPoint.fX;
14458af936d3047208def585b7bc824f013b994f6312egdaniel    dstRect.fRight = dstPoint.fX + srcRect.width();
144617b892551465e5a44560a06e4b34dc3592b49622egdaniel
144717b892551465e5a44560a06e4b34dc3592b49622egdaniel    if (kBottomLeft_GrSurfaceOrigin == src->origin()) {
144817b892551465e5a44560a06e4b34dc3592b49622egdaniel        srcVkRect.fTop = src->height() - srcRect.fBottom;
144917b892551465e5a44560a06e4b34dc3592b49622egdaniel        srcVkRect.fBottom = src->height() - srcRect.fTop;
145017b892551465e5a44560a06e4b34dc3592b49622egdaniel    } else {
14518af936d3047208def585b7bc824f013b994f6312egdaniel        srcVkRect.fTop = srcRect.fTop;
14528af936d3047208def585b7bc824f013b994f6312egdaniel        srcVkRect.fBottom = srcRect.fBottom;
145317b892551465e5a44560a06e4b34dc3592b49622egdaniel    }
145417b892551465e5a44560a06e4b34dc3592b49622egdaniel
145517b892551465e5a44560a06e4b34dc3592b49622egdaniel    if (kBottomLeft_GrSurfaceOrigin == dst->origin()) {
145617b892551465e5a44560a06e4b34dc3592b49622egdaniel        dstRect.fTop = dst->height() - dstPoint.fY - srcVkRect.height();
145717b892551465e5a44560a06e4b34dc3592b49622egdaniel    } else {
145817b892551465e5a44560a06e4b34dc3592b49622egdaniel        dstRect.fTop = dstPoint.fY;
145917b892551465e5a44560a06e4b34dc3592b49622egdaniel    }
146017b892551465e5a44560a06e4b34dc3592b49622egdaniel    dstRect.fBottom = dstRect.fTop + srcVkRect.height();
146117b892551465e5a44560a06e4b34dc3592b49622egdaniel
146217b892551465e5a44560a06e4b34dc3592b49622egdaniel    // If we have different origins, we need to flip the top and bottom of the dst rect so that we
146317b892551465e5a44560a06e4b34dc3592b49622egdaniel    // get the correct origintation of the copied data.
146417b892551465e5a44560a06e4b34dc3592b49622egdaniel    if (src->origin() != dst->origin()) {
146517b892551465e5a44560a06e4b34dc3592b49622egdaniel        SkTSwap(dstRect.fTop, dstRect.fBottom);
146617b892551465e5a44560a06e4b34dc3592b49622egdaniel    }
146717b892551465e5a44560a06e4b34dc3592b49622egdaniel
146817b892551465e5a44560a06e4b34dc3592b49622egdaniel    VkImageBlit blitRegion;
146917b892551465e5a44560a06e4b34dc3592b49622egdaniel    memset(&blitRegion, 0, sizeof(VkImageBlit));
147017b892551465e5a44560a06e4b34dc3592b49622egdaniel    blitRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
147117b892551465e5a44560a06e4b34dc3592b49622egdaniel    blitRegion.srcOffsets[0] = { srcVkRect.fLeft, srcVkRect.fTop, 0 };
147217b892551465e5a44560a06e4b34dc3592b49622egdaniel    blitRegion.srcOffsets[1] = { srcVkRect.fRight, srcVkRect.fBottom, 0 };
147317b892551465e5a44560a06e4b34dc3592b49622egdaniel    blitRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
147417b892551465e5a44560a06e4b34dc3592b49622egdaniel    blitRegion.dstOffsets[0] = { dstRect.fLeft, dstRect.fTop, 0 };
147517b892551465e5a44560a06e4b34dc3592b49622egdaniel    blitRegion.dstOffsets[1] = { dstRect.fRight, dstRect.fBottom, 0 };
147617b892551465e5a44560a06e4b34dc3592b49622egdaniel
147717b892551465e5a44560a06e4b34dc3592b49622egdaniel    fCurrentCmdBuffer->blitImage(this,
147862340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth                                 srcImage->resource(),
147917b892551465e5a44560a06e4b34dc3592b49622egdaniel                                 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
148062340067270c5c3365afa6b40b8e995ae6a6c1ecjvanverth                                 dstImage->resource(),
148117b892551465e5a44560a06e4b34dc3592b49622egdaniel                                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
148217b892551465e5a44560a06e4b34dc3592b49622egdaniel                                 1,
148317b892551465e5a44560a06e4b34dc3592b49622egdaniel                                 &blitRegion,
148417b892551465e5a44560a06e4b34dc3592b49622egdaniel                                 VK_FILTER_NEAREST); // We never scale so any filter works here
1485900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth
1486900bd4a0463bc6471ef07a77120b413bd8f472b2jvanverth    this->didWriteToSurface(dst, &dstRect);
148717b892551465e5a44560a06e4b34dc3592b49622egdaniel}
148817b892551465e5a44560a06e4b34dc3592b49622egdaniel
1489164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielinline bool can_copy_as_draw(const GrSurface* dst,
1490164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                             const GrSurface* src,
1491164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                             const GrVkGpu* gpu) {
1492164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return false;
1493164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1494164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1495164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::copySurfaceAsDraw(GrSurface* dst,
1496164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                GrSurface* src,
1497164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                const SkIRect& srcRect,
1498164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                const SkIPoint& dstPoint) {
1499164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(false);
1500164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1501164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1502164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::onCopySurface(GrSurface* dst,
1503164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                            GrSurface* src,
1504164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                            const SkIRect& srcRect,
1505164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                            const SkIPoint& dstPoint) {
150617b892551465e5a44560a06e4b34dc3592b49622egdaniel    GrVkImage* dstImage;
150717b892551465e5a44560a06e4b34dc3592b49622egdaniel    GrVkImage* srcImage;
150817b892551465e5a44560a06e4b34dc3592b49622egdaniel    if (dst->asTexture()) {
150917b892551465e5a44560a06e4b34dc3592b49622egdaniel        dstImage = static_cast<GrVkTexture*>(dst->asTexture());
151017b892551465e5a44560a06e4b34dc3592b49622egdaniel    } else {
151117b892551465e5a44560a06e4b34dc3592b49622egdaniel        SkASSERT(dst->asRenderTarget());
151217b892551465e5a44560a06e4b34dc3592b49622egdaniel        dstImage = static_cast<GrVkRenderTarget*>(dst->asRenderTarget());
151317b892551465e5a44560a06e4b34dc3592b49622egdaniel    }
151417b892551465e5a44560a06e4b34dc3592b49622egdaniel    if (src->asTexture()) {
151517b892551465e5a44560a06e4b34dc3592b49622egdaniel        srcImage = static_cast<GrVkTexture*>(src->asTexture());
151617b892551465e5a44560a06e4b34dc3592b49622egdaniel    } else {
151717b892551465e5a44560a06e4b34dc3592b49622egdaniel        SkASSERT(src->asRenderTarget());
151817b892551465e5a44560a06e4b34dc3592b49622egdaniel        srcImage = static_cast<GrVkRenderTarget*>(src->asRenderTarget());
151917b892551465e5a44560a06e4b34dc3592b49622egdaniel    }
152017b892551465e5a44560a06e4b34dc3592b49622egdaniel
1521164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (can_copy_image(dst, src, this)) {
152217b892551465e5a44560a06e4b34dc3592b49622egdaniel        this->copySurfaceAsCopyImage(dst, src, dstImage, srcImage, srcRect, dstPoint);
152317b892551465e5a44560a06e4b34dc3592b49622egdaniel        return true;
152417b892551465e5a44560a06e4b34dc3592b49622egdaniel    }
152517b892551465e5a44560a06e4b34dc3592b49622egdaniel
152617b892551465e5a44560a06e4b34dc3592b49622egdaniel    if (can_copy_as_blit(dst, src, dstImage, srcImage, this)) {
152717b892551465e5a44560a06e4b34dc3592b49622egdaniel        this->copySurfaceAsBlit(dst, src, dstImage, srcImage, srcRect, dstPoint);
1528164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return true;
1529164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1530164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1531164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (can_copy_as_draw(dst, src, this)) {
1532164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        this->copySurfaceAsDraw(dst, src, srcRect, dstPoint);
1533164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return true;
1534164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1535164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1536164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return false;
1537164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1538164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
153937798fbd82a7d064c5cc1516f120546a3408044begdanielbool GrVkGpu::initCopySurfaceDstDesc(const GrSurface* src, GrSurfaceDesc* desc) const {
154037798fbd82a7d064c5cc1516f120546a3408044begdaniel    // Currently we don't support msaa
154137798fbd82a7d064c5cc1516f120546a3408044begdaniel    if (src->asRenderTarget() && src->asRenderTarget()->numColorSamples() > 1) {
154237798fbd82a7d064c5cc1516f120546a3408044begdaniel        return false;
154337798fbd82a7d064c5cc1516f120546a3408044begdaniel    }
154437798fbd82a7d064c5cc1516f120546a3408044begdaniel
154537798fbd82a7d064c5cc1516f120546a3408044begdaniel    // This will support copying the dst as CopyImage since all of our surfaces require transferSrc
154637798fbd82a7d064c5cc1516f120546a3408044begdaniel    // and transferDst usage flags in Vulkan.
154737798fbd82a7d064c5cc1516f120546a3408044begdaniel    desc->fOrigin = src->origin();
154837798fbd82a7d064c5cc1516f120546a3408044begdaniel    desc->fConfig = src->config();
154937798fbd82a7d064c5cc1516f120546a3408044begdaniel    desc->fFlags = kNone_GrSurfaceFlags;
155037798fbd82a7d064c5cc1516f120546a3408044begdaniel    return true;
155137798fbd82a7d064c5cc1516f120546a3408044begdaniel}
155237798fbd82a7d064c5cc1516f120546a3408044begdaniel
155328f45b949acc746849100fbe112ee5280f0594c9cdaltonvoid GrVkGpu::onGetMultisampleSpecs(GrRenderTarget* rt, const GrStencilSettings&,
155428f45b949acc746849100fbe112ee5280f0594c9cdalton                                    int* effectiveSampleCnt, SkAutoTDeleteArray<SkPoint>*) {
155528f45b949acc746849100fbe112ee5280f0594c9cdalton    // TODO: stub.
155628f45b949acc746849100fbe112ee5280f0594c9cdalton    SkASSERT(!this->caps()->sampleLocationsSupport());
155728f45b949acc746849100fbe112ee5280f0594c9cdalton    *effectiveSampleCnt = rt->desc().fSampleCnt;
155828f45b949acc746849100fbe112ee5280f0594c9cdalton}
155928f45b949acc746849100fbe112ee5280f0594c9cdalton
1560164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::onGetReadPixelsInfo(GrSurface* srcSurface, int width, int height, size_t rowBytes,
1561164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                  GrPixelConfig readConfig, DrawPreference* drawPreference,
1562164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                  ReadPixelTempDrawInfo* tempDrawInfo) {
1563164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Currently we don't handle draws, so if the caller wants/needs to do a draw we need to fail
1564164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (kNoDraw_DrawPreference != *drawPreference) {
1565164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
1566164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1567164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1568164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (srcSurface->config() != readConfig) {
1569164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // TODO: This should fall back to drawing or copying to change config of srcSurface to match
1570164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // that of readConfig.
1571164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
1572164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1573164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1574164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return true;
1575164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1576164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1577164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::onReadPixels(GrSurface* surface,
1578164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           int left, int top, int width, int height,
1579164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           GrPixelConfig config,
1580164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           void* buffer,
1581164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           size_t rowBytes) {
1582164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkFormat pixelFormat;
1583164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!GrPixelConfigToVkFormat(config, &pixelFormat)) {
1584164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
1585164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1586164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1587164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkTexture* tgt = static_cast<GrVkTexture*>(surface->asTexture());
1588164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!tgt) {
1589164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
1590164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1591164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1592164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Change layout of our target so it can be used as copy
1593164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkImageLayout layout = tgt->currentLayout();
1594164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkPipelineStageFlags srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(layout);
1595164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
1596164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(layout);
1597164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkAccessFlags dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
1598164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    tgt->setImageLayout(this,
1599164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                        VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1600164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                        srcAccessMask,
1601164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                        dstAccessMask,
1602164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                        srcStageMask,
1603164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                        dstStageMask,
1604164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                        false);
1605164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
16069d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary    GrVkTransferBuffer* transferBuffer =
1607e2e71c2df4e72e897bbe745752be0444aee5c29fcdalton        static_cast<GrVkTransferBuffer*>(this->createBuffer(rowBytes * height,
1608e2e71c2df4e72e897bbe745752be0444aee5c29fcdalton                                                            kXferGpuToCpu_GrBufferType,
1609397536cabe12a9936659870dd220c869789424bacdalton                                                            kStream_GrAccessPattern));
1610164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1611164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    bool flipY = kBottomLeft_GrSurfaceOrigin == surface->origin();
1612164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkOffset3D offset = {
1613164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        left,
1614164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        flipY ? surface->height() - top - height : top,
1615164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        0
1616164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    };
1617164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1618164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Copy the image to a buffer so we can map it to cpu memory
1619164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkBufferImageCopy region;
1620164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    memset(&region, 0, sizeof(VkBufferImageCopy));
1621164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    region.bufferOffset = 0;
1622164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    region.bufferRowLength = 0; // Forces RowLength to be imageExtent.width
1623164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    region.bufferImageHeight = 0; // Forces height to be tightly packed. Only useful for 3d images.
1624164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
1625164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    region.imageOffset = offset;
1626164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    region.imageExtent = { (uint32_t)width, (uint32_t)height, 1 };
1627164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1628164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->copyImageToBuffer(this,
1629164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                         tgt,
1630164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1631164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                         transferBuffer,
1632164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                         1,
1633164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                         &region);
1634164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1635164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // make sure the copy to buffer has finished
1636164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    transferBuffer->addMemoryBarrier(this,
1637164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     VK_ACCESS_TRANSFER_WRITE_BIT,
1638164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     VK_ACCESS_HOST_READ_BIT,
1639164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     VK_PIPELINE_STAGE_TRANSFER_BIT,
1640164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     VK_PIPELINE_STAGE_HOST_BIT,
1641164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     false);
1642164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1643164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // We need to submit the current command buffer to the Queue and make sure it finishes before
1644164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // we can copy the data out of the buffer.
1645164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    this->submitCommandBuffer(kForce_SyncQueue);
1646164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1647164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    void* mappedMemory = transferBuffer->map();
1648164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1649164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    memcpy(buffer, mappedMemory, rowBytes*height);
1650164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1651164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    transferBuffer->unmap();
1652164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    transferBuffer->unref();
1653164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1654164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (flipY) {
1655164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        SkAutoSMalloc<32 * sizeof(GrColor)> scratch;
1656164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        size_t tightRowBytes = GrBytesPerPixel(config) * width;
1657164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        scratch.reset(tightRowBytes);
1658164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        void* tmpRow = scratch.get();
1659164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // flip y in-place by rows
1660164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        const int halfY = height >> 1;
1661164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        char* top = reinterpret_cast<char*>(buffer);
1662164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        char* bottom = top + (height - 1) * rowBytes;
1663164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        for (int y = 0; y < halfY; y++) {
1664164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            memcpy(tmpRow, top, tightRowBytes);
1665164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            memcpy(top, bottom, tightRowBytes);
1666164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            memcpy(bottom, tmpRow, tightRowBytes);
1667164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            top += rowBytes;
1668164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            bottom -= rowBytes;
1669164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
1670164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1671164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1672164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return true;
1673164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1674af132770a9462f6bb9cff47254e44675d9241fe8egdanielsk_sp<GrVkPipelineState> GrVkGpu::prepareDrawState(const GrPipeline& pipeline,
1675af132770a9462f6bb9cff47254e44675d9241fe8egdaniel                                                   const GrPrimitiveProcessor& primProc,
1676af132770a9462f6bb9cff47254e44675d9241fe8egdaniel                                                   GrPrimitiveType primitiveType,
1677af132770a9462f6bb9cff47254e44675d9241fe8egdaniel                                                   const GrVkRenderPass& renderPass) {
1678af132770a9462f6bb9cff47254e44675d9241fe8egdaniel    sk_sp<GrVkPipelineState> pipelineState =
1679af132770a9462f6bb9cff47254e44675d9241fe8egdaniel        fResourceProvider.findOrCreateCompatiblePipelineState(pipeline,
1680af132770a9462f6bb9cff47254e44675d9241fe8egdaniel                                                              primProc,
1681af132770a9462f6bb9cff47254e44675d9241fe8egdaniel                                                              primitiveType,
1682af132770a9462f6bb9cff47254e44675d9241fe8egdaniel                                                              renderPass);
168322281c13a13c4b4e275516e9fe02185a53a7e5aaegdaniel    if (!pipelineState) {
1684af132770a9462f6bb9cff47254e44675d9241fe8egdaniel        return pipelineState;
1685164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1686164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1687af132770a9462f6bb9cff47254e44675d9241fe8egdaniel    pipelineState->setData(this, primProc, pipeline);
1688164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1689af132770a9462f6bb9cff47254e44675d9241fe8egdaniel    pipelineState->bind(this, fCurrentCmdBuffer);
1690470d77a1d7dc286cdad98b145dac735cd7638e56egdaniel
1691470d77a1d7dc286cdad98b145dac735cd7638e56egdaniel    GrVkPipeline::SetDynamicState(this, fCurrentCmdBuffer, pipeline);
1692470d77a1d7dc286cdad98b145dac735cd7638e56egdaniel
1693af132770a9462f6bb9cff47254e44675d9241fe8egdaniel    return pipelineState;
16940e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel}
1695164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
16960e1853c89615d14d0d03c87c7e0c604e5285cc54egdanielvoid GrVkGpu::onDraw(const GrPipeline& pipeline,
16970e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                     const GrPrimitiveProcessor& primProc,
16980e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                     const GrMesh* meshes,
16990e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                     int meshCount) {
17000e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel    if (!meshCount) {
17010e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel        return;
17020e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel    }
17030e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel    GrRenderTarget* rt = pipeline.getRenderTarget();
17040e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel    GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(rt);
17050e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel    const GrVkRenderPass* renderPass = vkRT->simpleRenderPass();
17060e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel    SkASSERT(renderPass);
1707164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
17080e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel    GrPrimitiveType primitiveType = meshes[0].primitiveType();
1709af132770a9462f6bb9cff47254e44675d9241fe8egdaniel    sk_sp<GrVkPipelineState> pipelineState = this->prepareDrawState(pipeline,
1710af132770a9462f6bb9cff47254e44675d9241fe8egdaniel                                                                    primProc,
1711af132770a9462f6bb9cff47254e44675d9241fe8egdaniel                                                                    primitiveType,
1712af132770a9462f6bb9cff47254e44675d9241fe8egdaniel                                                                    *renderPass);
1713af132770a9462f6bb9cff47254e44675d9241fe8egdaniel    if (!pipelineState) {
17140e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel        return;
17150e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel    }
1716164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1717164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Change layout of our render target so it can be used as the color attachment
1718164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkImageLayout layout = vkRT->currentLayout();
1719164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkPipelineStageFlags srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(layout);
1720164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1721164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(layout);
1722164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkAccessFlags dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
1723164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    vkRT->setImageLayout(this,
1724164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1725164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         srcAccessMask,
1726164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         dstAccessMask,
1727164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         srcStageMask,
1728164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         dstStageMask,
1729164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         false);
1730164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
17313d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    // If we are using a stencil attachment we also need to update its layout
173258a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel    if (GrStencilAttachment* stencil = vkRT->renderTargetPriv().getStencilAttachment()) {
17333d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        GrVkStencilAttachment* vkStencil = (GrVkStencilAttachment*)stencil;
17343d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        VkImageLayout origDstLayout = vkStencil->currentLayout();
17353d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origDstLayout);
17363d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        VkAccessFlags dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
17370e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel            VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
17383d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        VkPipelineStageFlags srcStageMask =
17393d5d9ac426ea926f37eaa47e13acf7492068667begdaniel            GrVkMemory::LayoutToPipelineStageFlags(origDstLayout);
17403d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
17413d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        vkStencil->setImageLayout(this,
17423d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                                  VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
17433d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                                  srcAccessMask,
17443d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                                  dstAccessMask,
17453d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                                  srcStageMask,
17463d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                                  dstStageMask,
17473d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                                  false);
17483d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    }
17493d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
175058a8d9214a70e0f6c81c88a8b0b563c06bf0f70eegdaniel    fCurrentCmdBuffer->beginRenderPass(this, renderPass, *vkRT);
17510e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel
17520e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel    for (int i = 0; i < meshCount; ++i) {
17530e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel        const GrMesh& mesh = meshes[i];
17540e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel        GrMesh::Iterator iter;
17550e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel        const GrNonInstancedMesh* nonIdxMesh = iter.init(mesh);
17560e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel        do {
17570e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel            if (nonIdxMesh->primitiveType() != primitiveType) {
17580e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                // Technically we don't have to call this here (since there is a safety check in
175922281c13a13c4b4e275516e9fe02185a53a7e5aaegdaniel                // pipelineState:setData but this will allow for quicker freeing of resources if the
176022281c13a13c4b4e275516e9fe02185a53a7e5aaegdaniel                // pipelineState sits in a cache for a while.
176122281c13a13c4b4e275516e9fe02185a53a7e5aaegdaniel                pipelineState->freeTempResources(this);
176222281c13a13c4b4e275516e9fe02185a53a7e5aaegdaniel                SkDEBUGCODE(pipelineState = nullptr);
17630e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                primitiveType = nonIdxMesh->primitiveType();
1764af132770a9462f6bb9cff47254e44675d9241fe8egdaniel                pipelineState = this->prepareDrawState(pipeline,
1765af132770a9462f6bb9cff47254e44675d9241fe8egdaniel                                                       primProc,
1766af132770a9462f6bb9cff47254e44675d9241fe8egdaniel                                                       primitiveType,
1767af132770a9462f6bb9cff47254e44675d9241fe8egdaniel                                                       *renderPass);
1768af132770a9462f6bb9cff47254e44675d9241fe8egdaniel                if (!pipelineState) {
17690e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                    return;
17700e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                }
17710e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel            }
177222281c13a13c4b4e275516e9fe02185a53a7e5aaegdaniel            SkASSERT(pipelineState);
17730e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel            this->bindGeometry(primProc, *nonIdxMesh);
17740e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel
17750e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel            if (nonIdxMesh->isIndexed()) {
17760e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                fCurrentCmdBuffer->drawIndexed(this,
17770e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                                               nonIdxMesh->indexCount(),
17780e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                                               1,
17790e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                                               nonIdxMesh->startIndex(),
17800e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                                               nonIdxMesh->startVertex(),
17810e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                                               0);
17820e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel            } else {
17830e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                fCurrentCmdBuffer->draw(this,
17840e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                                        nonIdxMesh->vertexCount(),
17850e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                                        1,
17860e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                                        nonIdxMesh->startVertex(),
17870e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                                        0);
17880e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel            }
17890e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel
17900e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel            fStats.incNumDraws();
17910e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel        } while ((nonIdxMesh = iter.next()));
1792164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1793164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1794164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->endRenderPass(this);
1795164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
179622281c13a13c4b4e275516e9fe02185a53a7e5aaegdaniel    // Technically we don't have to call this here (since there is a safety check in
179722281c13a13c4b4e275516e9fe02185a53a7e5aaegdaniel    // pipelineState:setData but this will allow for quicker freeing of resources if the
179822281c13a13c4b4e275516e9fe02185a53a7e5aaegdaniel    // pipelineState sits in a cache for a while.
179922281c13a13c4b4e275516e9fe02185a53a7e5aaegdaniel    pipelineState->freeTempResources(this);
1800164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1801164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#if SWAP_PER_DRAW
1802164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    glFlush();
1803164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#if defined(SK_BUILD_FOR_MAC)
1804164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    aglSwapBuffers(aglGetCurrentContext());
1805164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    int set_a_break_pt_here = 9;
1806164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    aglSwapBuffers(aglGetCurrentContext());
1807164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#elif defined(SK_BUILD_FOR_WIN32)
1808164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SwapBuf();
1809164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    int set_a_break_pt_here = 9;
1810164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SwapBuf();
1811164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#endif
1812164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#endif
1813164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1814