GrVkGpu.cpp revision 9d524f22bfde5dc3dc8f48e1be39bdebd3bb0304
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"
33164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
34164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "vk/GrVkInterface.h"
35fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth#include "vk/GrVkTypes.h"
36164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
37164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#define VK_CALL(X) GR_VK_CALL(this->vkInterface(), X)
38164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#define VK_CALL_RET(RET, X) GR_VK_CALL_RET(this->vkInterface(), RET, X)
39164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#define VK_CALL_ERRCHECK(X) GR_VK_CALL_ERRCHECK(this->vkInterface(), X)
40164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
41d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth#ifdef ENABLE_VK_LAYERS
42d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverthVKAPI_ATTR VkBool32 VKAPI_CALL DebugReportCallback(
43d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    VkDebugReportFlagsEXT       flags,
44d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    VkDebugReportObjectTypeEXT  objectType,
45d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    uint64_t                    object,
46d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    size_t                      location,
47d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    int32_t                     messageCode,
48d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    const char*                 pLayerPrefix,
49d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    const char*                 pMessage,
50d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    void*                       pUserData) {
51d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    if (flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
52d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        SkDebugf("Vulkan error [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
53d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    } else if (flags & VK_DEBUG_REPORT_WARNING_BIT_EXT) {
54d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        SkDebugf("Vulkan warning [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
55d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    } else if (flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) {
56d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        SkDebugf("Vulkan perf warning [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
57d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    } else {
58d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        SkDebugf("Vulkan info/debug [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
59d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    }
60d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    return VK_FALSE;
61d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth}
62d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth#endif
63d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth
64633b35657c964c32e7010b14bb2d396b4a764c52jvanverthGrGpu* GrVkGpu::Create(GrBackendContext backendContext, const GrContextOptions& options,
65633b35657c964c32e7010b14bb2d396b4a764c52jvanverth                       GrContext* context) {
66633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    SkAutoTUnref<const GrVkBackendContext> vkBackendContext(
67633b35657c964c32e7010b14bb2d396b4a764c52jvanverth                                       reinterpret_cast<const GrVkBackendContext*>(backendContext));
68633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    if (!vkBackendContext) {
69633b35657c964c32e7010b14bb2d396b4a764c52jvanverth        vkBackendContext.reset(GrVkBackendContext::Create());
70633b35657c964c32e7010b14bb2d396b4a764c52jvanverth        if (!vkBackendContext) {
71633b35657c964c32e7010b14bb2d396b4a764c52jvanverth            return nullptr;
72164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
73633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    } else {
74633b35657c964c32e7010b14bb2d396b4a764c52jvanverth        vkBackendContext->ref();
75164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
76164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
77633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    return new GrVkGpu(context, options, vkBackendContext);
78164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
79164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
80164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
81164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
829d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanaryGrVkGpu::GrVkGpu(GrContext* context, const GrContextOptions& options,
83633b35657c964c32e7010b14bb2d396b4a764c52jvanverth                 const GrVkBackendContext* backendCtx)
84164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    : INHERITED(context)
85633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    , fVkInstance(backendCtx->fInstance)
86633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    , fDevice(backendCtx->fDevice)
87633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    , fQueue(backendCtx->fQueue)
88633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    , fResourceProvider(this) {
89633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    fBackendContext.reset(backendCtx);
90164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
91d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth#ifdef ENABLE_VK_LAYERS
92fd7bd45ac2178ce6b4a390f517f605750aaef6c8jvanverth    if (backendCtx->fExtensions & kEXT_debug_report_GrVkExtensionFlag) {
93fd7bd45ac2178ce6b4a390f517f605750aaef6c8jvanverth        // Setup callback creation information
94d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        VkDebugReportCallbackCreateInfoEXT callbackCreateInfo;
95d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        callbackCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
96d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        callbackCreateInfo.pNext = nullptr;
97d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        callbackCreateInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT |
98d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth                                   VK_DEBUG_REPORT_WARNING_BIT_EXT |
99d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth                                   //VK_DEBUG_REPORT_INFORMATION_BIT_EXT |
100d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth                                   //VK_DEBUG_REPORT_DEBUG_BIT_EXT |
101d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth                                   VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
102d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        callbackCreateInfo.pfnCallback = &DebugReportCallback;
103d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth        callbackCreateInfo.pUserData = nullptr;
104d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth
105fd7bd45ac2178ce6b4a390f517f605750aaef6c8jvanverth        // Register the callback
106633b35657c964c32e7010b14bb2d396b4a764c52jvanverth        GR_VK_CALL_ERRCHECK(this->vkInterface(), CreateDebugReportCallbackEXT(fVkInstance,
107633b35657c964c32e7010b14bb2d396b4a764c52jvanverth                            &callbackCreateInfo, nullptr, &fCallback));
108d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    }
109d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth#endif
110633b35657c964c32e7010b14bb2d396b4a764c52jvanverth
111633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    fCompiler = shaderc_compiler_initialize();
112633b35657c964c32e7010b14bb2d396b4a764c52jvanverth
113fd7bd45ac2178ce6b4a390f517f605750aaef6c8jvanverth    fVkCaps.reset(new GrVkCaps(options, this->vkInterface(), backendCtx->fPhysicalDevice,
114c5ec1408298510410270ea67e895570ccfa76e54egdaniel                               backendCtx->fFeatures, backendCtx->fExtensions));
115633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    fCaps.reset(SkRef(fVkCaps.get()));
116633b35657c964c32e7010b14bb2d396b4a764c52jvanverth
117633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    VK_CALL(GetPhysicalDeviceMemoryProperties(backendCtx->fPhysicalDevice, &fPhysDevMemProps));
118633b35657c964c32e7010b14bb2d396b4a764c52jvanverth
119633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    const VkCommandPoolCreateInfo cmdPoolInfo = {
120633b35657c964c32e7010b14bb2d396b4a764c52jvanverth        VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // sType
121633b35657c964c32e7010b14bb2d396b4a764c52jvanverth        nullptr,                                    // pNext
122633b35657c964c32e7010b14bb2d396b4a764c52jvanverth        VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,       // CmdPoolCreateFlags
123633b35657c964c32e7010b14bb2d396b4a764c52jvanverth        backendCtx->fQueueFamilyIndex,              // queueFamilyIndex
124633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    };
1259d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary    GR_VK_CALL_ERRCHECK(this->vkInterface(), CreateCommandPool(fDevice, &cmdPoolInfo, nullptr,
126633b35657c964c32e7010b14bb2d396b4a764c52jvanverth                                                               &fCmdPool));
127633b35657c964c32e7010b14bb2d396b4a764c52jvanverth
128633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    // must call this after creating the CommandPool
129633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    fResourceProvider.init();
130633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    fCurrentCmdBuffer = fResourceProvider.createCommandBuffer();
131633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    SkASSERT(fCurrentCmdBuffer);
132633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    fCurrentCmdBuffer->begin(this);
133164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
134164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
135164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielGrVkGpu::~GrVkGpu() {
136164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->end(this);
137164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->unref(this);
138164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
139164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // wait for all commands to finish
140ddf9835e9cdf512b1d5172d014f00ceb6dacd039jvanverth    fResourceProvider.checkCommandBuffers();
1412cab66be9c47660da6a2cc94b469c14d5bed958eegdaniel    SkDEBUGCODE(VkResult res =) VK_CALL(QueueWaitIdle(fQueue));
142ddf9835e9cdf512b1d5172d014f00ceb6dacd039jvanverth    // VK_ERROR_DEVICE_LOST is acceptable when tearing down (see 4.2.4 in spec)
143ddf9835e9cdf512b1d5172d014f00ceb6dacd039jvanverth    SkASSERT(VK_SUCCESS == res || VK_ERROR_DEVICE_LOST == res);
1449d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
145164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // must call this just before we destroy the VkDevice
146164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fResourceProvider.destroyResources();
147164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
148633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    VK_CALL(DestroyCommandPool(fDevice, fCmdPool, nullptr));
149633b35657c964c32e7010b14bb2d396b4a764c52jvanverth
150633b35657c964c32e7010b14bb2d396b4a764c52jvanverth    shaderc_compiler_release(fCompiler);
151633b35657c964c32e7010b14bb2d396b4a764c52jvanverth
152633b35657c964c32e7010b14bb2d396b4a764c52jvanverth#ifdef ENABLE_VK_LAYERS
153d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth    VK_CALL(DestroyDebugReportCallbackEXT(fVkInstance, fCallback, nullptr));
154d2497f35ce9e9e70ab6c7acd82b212c80cb86d3ajvanverth#endif
155164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
156164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
157164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel///////////////////////////////////////////////////////////////////////////////
158164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
159164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::submitCommandBuffer(SyncQueue sync) {
160164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(fCurrentCmdBuffer);
161164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->end(this);
162164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
163164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->submitToQueue(this, fQueue, sync);
164164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fResourceProvider.checkCommandBuffers();
165164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
166164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Release old command buffer and create a new one
167164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->unref(this);
168164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer = fResourceProvider.createCommandBuffer();
169164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(fCurrentCmdBuffer);
170164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
171164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->begin(this);
172164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
173164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
174164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel///////////////////////////////////////////////////////////////////////////////
175397536cabe12a9936659870dd220c869789424bacdaltonGrBuffer* GrVkGpu::onCreateBuffer(GrBufferType type, size_t size, GrAccessPattern accessPattern) {
176397536cabe12a9936659870dd220c869789424bacdalton    switch (type) {
177397536cabe12a9936659870dd220c869789424bacdalton        case kVertex_GrBufferType:
178397536cabe12a9936659870dd220c869789424bacdalton            SkASSERT(kDynamic_GrAccessPattern == accessPattern ||
179397536cabe12a9936659870dd220c869789424bacdalton                     kStatic_GrAccessPattern == accessPattern);
180397536cabe12a9936659870dd220c869789424bacdalton            return GrVkVertexBuffer::Create(this, size, kDynamic_GrAccessPattern == accessPattern);
181397536cabe12a9936659870dd220c869789424bacdalton        case kIndex_GrBufferType:
182397536cabe12a9936659870dd220c869789424bacdalton            SkASSERT(kDynamic_GrAccessPattern == accessPattern ||
183397536cabe12a9936659870dd220c869789424bacdalton                     kStatic_GrAccessPattern == accessPattern);
184397536cabe12a9936659870dd220c869789424bacdalton            return GrVkIndexBuffer::Create(this, size, kDynamic_GrAccessPattern == accessPattern);
185397536cabe12a9936659870dd220c869789424bacdalton        case kXferCpuToGpu_GrBufferType:
186397536cabe12a9936659870dd220c869789424bacdalton            SkASSERT(kStream_GrAccessPattern == accessPattern);
187397536cabe12a9936659870dd220c869789424bacdalton            return GrVkTransferBuffer::Create(this, size, GrVkBuffer::kCopyRead_Type);
188397536cabe12a9936659870dd220c869789424bacdalton        case kXferGpuToCpu_GrBufferType:
189397536cabe12a9936659870dd220c869789424bacdalton            SkASSERT(kStream_GrAccessPattern == accessPattern);
190397536cabe12a9936659870dd220c869789424bacdalton            return GrVkTransferBuffer::Create(this, size, GrVkBuffer::kCopyWrite_Type);
191397536cabe12a9936659870dd220c869789424bacdalton        default:
192397536cabe12a9936659870dd220c869789424bacdalton            SkFAIL("Unknown buffer type.");
193397536cabe12a9936659870dd220c869789424bacdalton            return nullptr;
194397536cabe12a9936659870dd220c869789424bacdalton    }
195164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
196164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
197164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
198164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::onGetWritePixelsInfo(GrSurface* dstSurface, int width, int height,
199164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                   GrPixelConfig srcConfig, DrawPreference* drawPreference,
200164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                   WritePixelTempDrawInfo* tempDrawInfo) {
201164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (kIndex_8_GrPixelConfig == srcConfig || GrPixelConfigIsCompressed(dstSurface->config())) {
202164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
203164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
204164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
205164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Currently we don't handle draws, so if the caller wants/needs to do a draw we need to fail
206164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (kNoDraw_DrawPreference != *drawPreference) {
207164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
208164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
209164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
210164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (dstSurface->config() != srcConfig) {
2119d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary        // TODO: This should fall back to drawing or copying to change config of dstSurface to
212164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // match that of srcConfig.
213164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
214164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
215164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
216164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return true;
217164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
218164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
219164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::onWritePixels(GrSurface* surface,
220164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                            int left, int top, int width, int height,
221a1e6b3be8124cef85f2e39e3cb85000ad9526d48bsalomon                            GrPixelConfig config,
222a1e6b3be8124cef85f2e39e3cb85000ad9526d48bsalomon                            const SkTArray<GrMipLevel>& texels) {
223164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkTexture* vkTex = static_cast<GrVkTexture*>(surface->asTexture());
224164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!vkTex) {
225164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
226164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
227164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
228a1e6b3be8124cef85f2e39e3cb85000ad9526d48bsalomon    // TODO: We're ignoring MIP levels here.
22903509eafa3e25819ff69f4d4f339d46264820c38jvanverth    if (texels.empty() || !texels.begin()->fPixels) {
23003509eafa3e25819ff69f4d4f339d46264820c38jvanverth        return false;
23103509eafa3e25819ff69f4d4f339d46264820c38jvanverth    }
232a1e6b3be8124cef85f2e39e3cb85000ad9526d48bsalomon
233164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // We assume Vulkan doesn't do sRGB <-> linear conversions when reading and writing pixels.
234164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (GrPixelConfigIsSRGB(surface->config()) != GrPixelConfigIsSRGB(config)) {
235164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
236164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
237164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
238164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    bool success = false;
239164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (GrPixelConfigIsCompressed(vkTex->desc().fConfig)) {
240164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // We check that config == desc.fConfig in GrGpu::getWritePixelsInfo()
241164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        SkASSERT(config == vkTex->desc().fConfig);
242164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // TODO: add compressed texture support
243164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // delete the following two lines and uncomment the two after that when ready
244164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        vkTex->unref();
245164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
246164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        //success = this->uploadCompressedTexData(vkTex->desc(), buffer, false, left, top, width,
247164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        //                                       height);
248164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    } else {
249164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        bool linearTiling = vkTex->isLinearTiled();
250164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        if (linearTiling && VK_IMAGE_LAYOUT_PREINITIALIZED != vkTex->currentLayout()) {
251164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            // Need to change the layout to general in order to perform a host write
252164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            VkImageLayout layout = vkTex->currentLayout();
253164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            VkPipelineStageFlags srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(layout);
254164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_HOST_BIT;
255164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(layout);
256164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            VkAccessFlags dstAccessMask = VK_ACCESS_HOST_WRITE_BIT;
257164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            vkTex->setImageLayout(this,
258164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                  VK_IMAGE_LAYOUT_GENERAL,
259164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                  srcAccessMask,
260164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                  dstAccessMask,
261164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                  srcStageMask,
262164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                  dstStageMask,
263164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                  false);
264164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
265164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        success = this->uploadTexData(vkTex, left, top, width, height, config,
266a1e6b3be8124cef85f2e39e3cb85000ad9526d48bsalomon                                      texels.begin()->fPixels, texels.begin()->fRowBytes);
267164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
268164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
269164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (success) {
270164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        vkTex->texturePriv().dirtyMipMaps(true);
271164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return true;
272164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
273164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
274164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return false;
275164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
276164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
277164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::uploadTexData(GrVkTexture* tex,
278164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                            int left, int top, int width, int height,
279164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                            GrPixelConfig dataConfig,
280164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                            const void* data,
281164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                            size_t rowBytes) {
282164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(data);
283164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
284164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // If we're uploading compressed data then we should be using uploadCompressedTexData
285164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(!GrPixelConfigIsCompressed(dataConfig));
286164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
287164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    bool linearTiling = tex->isLinearTiled();
288164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
289164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    size_t bpp = GrBytesPerPixel(dataConfig);
290164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
291164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    const GrSurfaceDesc& desc = tex->desc();
292164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
293164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!GrSurfacePriv::AdjustWritePixelParams(desc.fWidth, desc.fHeight, bpp, &left, &top,
294164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                               &width, &height, &data, &rowBytes)) {
295164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
296164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
297164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    size_t trimRowBytes = width * bpp;
298164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
299164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (linearTiling) {
300164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        SkASSERT(VK_IMAGE_LAYOUT_PREINITIALIZED == tex->currentLayout() ||
301164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                 VK_IMAGE_LAYOUT_GENERAL == tex->currentLayout());
302164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        const VkImageSubresource subres = {
303164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            VK_IMAGE_ASPECT_COLOR_BIT,
304164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            0,  // mipLevel
305164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            0,  // arraySlice
306164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        };
307164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkSubresourceLayout layout;
308164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkResult err;
309164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
310164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        const GrVkInterface* interface = this->vkInterface();
311164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
312164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        GR_VK_CALL(interface, GetImageSubresourceLayout(fDevice,
313164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                        tex->textureImage(),
314164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                        &subres,
315164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                        &layout));
316164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
317164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        int texTop = kBottomLeft_GrSurfaceOrigin == desc.fOrigin ? tex->height() - top - height
318164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                    : top;
319164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkDeviceSize offset = texTop*layout.rowPitch + left*bpp;
320164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkDeviceSize size = height*layout.rowPitch;
321164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        void* mapPtr;
3229d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary        err = GR_VK_CALL(interface, MapMemory(fDevice, tex->textureMemory(), offset, size, 0,
323164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                &mapPtr));
324164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        if (err) {
325164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            return false;
326164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
327164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
328164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        if (kBottomLeft_GrSurfaceOrigin == desc.fOrigin) {
329164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            // copy into buffer by rows
330164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            const char* srcRow = reinterpret_cast<const char*>(data);
331164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            char* dstRow = reinterpret_cast<char*>(mapPtr)+(height - 1)*layout.rowPitch;
332164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            for (int y = 0; y < height; y++) {
333164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                memcpy(dstRow, srcRow, trimRowBytes);
334164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                srcRow += rowBytes;
335164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                dstRow -= layout.rowPitch;
336164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            }
337164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        } else {
338164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            // If there is no padding on the src (rowBytes) or dst (layout.rowPitch) we can memcpy
339164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            if (trimRowBytes == rowBytes && trimRowBytes == layout.rowPitch) {
340164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                memcpy(mapPtr, data, trimRowBytes * height);
341164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            } else {
342a6b439a0af614e2e79b35ad41df7b72736d5d1b9bsalomon                SkRectMemcpy(mapPtr, static_cast<size_t>(layout.rowPitch), data, rowBytes,
343a6b439a0af614e2e79b35ad41df7b72736d5d1b9bsalomon                             trimRowBytes, height);
344164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            }
345164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
346164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
347164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        GR_VK_CALL(interface, UnmapMemory(fDevice, tex->textureMemory()));
348164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    } else {
349164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        GrVkTransferBuffer* transferBuffer =
350164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            GrVkTransferBuffer::Create(this, trimRowBytes * height, GrVkBuffer::kCopyRead_Type);
351164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
352164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        void* mapPtr = transferBuffer->map();
353164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
354164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        if (kBottomLeft_GrSurfaceOrigin == desc.fOrigin) {
355164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            // copy into buffer by rows
356164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            const char* srcRow = reinterpret_cast<const char*>(data);
357164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            char* dstRow = reinterpret_cast<char*>(mapPtr)+(height - 1)*trimRowBytes;
358164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            for (int y = 0; y < height; y++) {
359164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                memcpy(dstRow, srcRow, trimRowBytes);
360164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                srcRow += rowBytes;
361164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                dstRow -= trimRowBytes;
362164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            }
363164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        } else {
364164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            // If there is no padding on the src data rows, we can do a single memcpy
365164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            if (trimRowBytes == rowBytes) {
366164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                memcpy(mapPtr, data, trimRowBytes * height);
367164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            } else {
368164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                SkRectMemcpy(mapPtr, trimRowBytes, data, rowBytes, trimRowBytes, height);
369164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            }
370164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
371164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
372164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        transferBuffer->unmap();
373164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
374164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // make sure the unmap has finished
375164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        transferBuffer->addMemoryBarrier(this,
376164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                         VK_ACCESS_HOST_WRITE_BIT,
377164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                         VK_ACCESS_TRANSFER_READ_BIT,
378164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                         VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
379164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                         VK_PIPELINE_STAGE_TRANSFER_BIT,
380164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                         false);
381164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
382164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // Set up copy region
383164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        bool flipY = kBottomLeft_GrSurfaceOrigin == tex->origin();
384164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkOffset3D offset = {
385164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            left,
386164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            flipY ? tex->height() - top - height : top,
387164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            0
388164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        };
389164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
390164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkBufferImageCopy region;
391164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        memset(&region, 0, sizeof(VkBufferImageCopy));
392164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        region.bufferOffset = 0;
393164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        region.bufferRowLength = width;
394164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        region.bufferImageHeight = height;
395164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
396164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        region.imageOffset = offset;
397164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        region.imageExtent = { (uint32_t)width, (uint32_t)height, 1 };
398164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
399164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // Change layout of our target so it can be copied to
400164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkImageLayout layout = tex->currentLayout();
401164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkPipelineStageFlags srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(layout);
402164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
403164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(layout);
404164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkAccessFlags dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
405164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        tex->setImageLayout(this,
406164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                            VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
407164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                            srcAccessMask,
408164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                            dstAccessMask,
409164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                            srcStageMask,
410164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                            dstStageMask,
411164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                            false);
412164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
413164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // Copy the buffer to the image
414164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        fCurrentCmdBuffer->copyBufferToImage(this,
415164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                             transferBuffer,
416164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                             tex,
417164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                             VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
418164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                             1,
419164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                             &region);
420164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
421164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // Submit the current command buffer to the Queue
422164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        this->submitCommandBuffer(kSkip_SyncQueue);
423164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
424164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        transferBuffer->unref();
425164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
426164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
427164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return true;
428164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
429164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
430164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
431164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielGrTexture* GrVkGpu::onCreateTexture(const GrSurfaceDesc& desc, GrGpuResource::LifeCycle lifeCycle,
432a1e6b3be8124cef85f2e39e3cb85000ad9526d48bsalomon                                    const SkTArray<GrMipLevel>& texels) {
433164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag);
434164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
435164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkFormat pixelFormat;
436164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!GrPixelConfigToVkFormat(desc.fConfig, &pixelFormat)) {
437164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return nullptr;
438164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
439164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
440164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!fVkCaps->isConfigTexturable(desc.fConfig)) {
441164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return nullptr;
442164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
443164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
444164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    bool linearTiling = false;
445164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (SkToBool(desc.fFlags & kZeroCopy_GrSurfaceFlag)) {
446164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        if (fVkCaps->isConfigTexurableLinearly(desc.fConfig) &&
447164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            (!renderTarget || fVkCaps->isConfigRenderableLinearly(desc.fConfig, false))) {
448164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            linearTiling = true;
449164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        } else {
450164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            return nullptr;
451164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
452164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
453164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
454164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT;
455164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (renderTarget) {
456164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        usageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
457164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
458164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
459164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // For now we will set the VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT and
460164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // VK_IMAGE_USAGE_TRANSFER_SOURCE_BIT on every texture since we do not know whether or not we
461164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // will be using this texture in some copy or not. Also this assumes, as is the current case,
462164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // that all render targets in vulkan are also texutres. If we change this practice of setting
463164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // both bits, we must make sure to set the destination bit if we are uploading srcData to the
464164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // texture.
465164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    usageFlags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
466164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
467a1e6b3be8124cef85f2e39e3cb85000ad9526d48bsalomon    VkFlags memProps = (!texels.empty() && linearTiling) ? VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT :
468a1e6b3be8124cef85f2e39e3cb85000ad9526d48bsalomon                                                           VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
469164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
470164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // This ImageDesc refers to the texture that will be read by the client. Thus even if msaa is
471164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // requested, this ImageDesc describes the resolved texutre. Therefore we always have samples set
472164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // to 1.
473164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkImage::ImageDesc imageDesc;
474164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fImageType = VK_IMAGE_TYPE_2D;
475164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fFormat = pixelFormat;
476164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fWidth = desc.fWidth;
477164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fHeight = desc.fHeight;
478164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fLevels = 1;
479164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fSamples = 1;
480164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fImageTiling = linearTiling ? VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL;
481164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fUsageFlags = usageFlags;
482164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fMemProps = memProps;
483164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
484164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkTexture* tex;
485164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (renderTarget) {
486164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        tex = GrVkTextureRenderTarget::CreateNewTextureRenderTarget(this, desc, lifeCycle,
487164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                    imageDesc);
488164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    } else {
489164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        tex = GrVkTexture::CreateNewTexture(this, desc, lifeCycle, imageDesc);
490164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
491164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
492164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!tex) {
493164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return nullptr;
494164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
495164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
496a1e6b3be8124cef85f2e39e3cb85000ad9526d48bsalomon    // TODO: We're ignoring MIP levels here.
497e699d0cd25fd059e3f0c4949e613e50c83a52179bsalomon    if (!texels.empty()) {
498e699d0cd25fd059e3f0c4949e613e50c83a52179bsalomon        SkASSERT(texels.begin()->fPixels);
499a1e6b3be8124cef85f2e39e3cb85000ad9526d48bsalomon        if (!this->uploadTexData(tex, 0, 0, desc.fWidth, desc.fHeight, desc.fConfig,
500a1e6b3be8124cef85f2e39e3cb85000ad9526d48bsalomon                                 texels.begin()->fPixels, texels.begin()->fRowBytes)) {
501164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            tex->unref();
502164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            return nullptr;
503164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
504164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
505164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
506164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return tex;
507164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
508164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
509164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
510164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
511164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielstatic GrSurfaceOrigin resolve_origin(GrSurfaceOrigin origin) {
512164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // By default, all textures in Vk use TopLeft
513164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (kDefault_GrSurfaceOrigin == origin) {
514164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return kTopLeft_GrSurfaceOrigin;
515164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    } else {
516164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return origin;
517164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
518164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
519164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
520164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielGrTexture* GrVkGpu::onWrapBackendTexture(const GrBackendTextureDesc& desc,
521164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                         GrWrapOwnership ownership) {
522164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkFormat format;
523164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!GrPixelConfigToVkFormat(desc.fConfig, &format)) {
524164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return nullptr;
525164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
526164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
527164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (0 == desc.fTextureHandle) {
528164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return nullptr;
529164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
530164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
531164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    int maxSize = this->caps()->maxTextureSize();
532164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (desc.fWidth > maxSize || desc.fHeight > maxSize) {
533164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return nullptr;
534164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
535164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
536fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    const GrVkTextureInfo* info = reinterpret_cast<const GrVkTextureInfo*>(desc.fTextureHandle);
537fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    if (VK_NULL_HANDLE == info->fImage || VK_NULL_HANDLE == info->fAlloc) {
538fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        return nullptr;
539fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    }
540164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
5410fcfb7525f60eabfdaf9761c75c7d4fd1b46d0c5jvanverth    GrGpuResource::LifeCycle lifeCycle = (kAdopt_GrWrapOwnership == ownership)
5420fcfb7525f60eabfdaf9761c75c7d4fd1b46d0c5jvanverth                                         ? GrGpuResource::kAdopted_LifeCycle
5430fcfb7525f60eabfdaf9761c75c7d4fd1b46d0c5jvanverth                                         : GrGpuResource::kBorrowed_LifeCycle;
544164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
545164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrSurfaceDesc surfDesc;
546164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // next line relies on GrBackendTextureDesc's flags matching GrTexture's
547164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    surfDesc.fFlags = (GrSurfaceFlags)desc.fFlags;
548164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    surfDesc.fWidth = desc.fWidth;
549164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    surfDesc.fHeight = desc.fHeight;
550164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    surfDesc.fConfig = desc.fConfig;
551164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    surfDesc.fSampleCnt = SkTMin(desc.fSampleCnt, this->caps()->maxSampleCount());
552164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrBackendTextureFlag);
553164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // In GL, Chrome assumes all textures are BottomLeft
554164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // In VK, we don't have this restriction
555164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    surfDesc.fOrigin = resolve_origin(desc.fOrigin);
556164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
557164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkTexture* texture = nullptr;
558164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (renderTarget) {
5599d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary        texture = GrVkTextureRenderTarget::CreateWrappedTextureRenderTarget(this, surfDesc,
560164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                            lifeCycle, format,
561fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth                                                                            info);
562164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    } else {
5639d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary        texture = GrVkTexture::CreateWrappedTexture(this, surfDesc, lifeCycle, format,
564fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth                                                    info);
565164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
566164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!texture) {
567164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return nullptr;
568164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
569164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
570164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return texture;
571164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
572164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
573164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielGrRenderTarget* GrVkGpu::onWrapBackendRenderTarget(const GrBackendRenderTargetDesc& wrapDesc,
574164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                   GrWrapOwnership ownership) {
5759d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
576fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    const GrVkTextureInfo* info =
577fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        reinterpret_cast<const GrVkTextureInfo*>(wrapDesc.fRenderTargetHandle);
578fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    if (VK_NULL_HANDLE == info->fImage ||
579fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        (VK_NULL_HANDLE == info->fAlloc && kAdopt_GrWrapOwnership == ownership)) {
580fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        return nullptr;
581fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    }
582164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
5830fcfb7525f60eabfdaf9761c75c7d4fd1b46d0c5jvanverth    GrGpuResource::LifeCycle lifeCycle = (kAdopt_GrWrapOwnership == ownership)
5840fcfb7525f60eabfdaf9761c75c7d4fd1b46d0c5jvanverth                                         ? GrGpuResource::kAdopted_LifeCycle
5850fcfb7525f60eabfdaf9761c75c7d4fd1b46d0c5jvanverth                                         : GrGpuResource::kBorrowed_LifeCycle;
586164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
587164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrSurfaceDesc desc;
588164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    desc.fConfig = wrapDesc.fConfig;
589164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    desc.fFlags = kCheckAllocation_GrSurfaceFlag;
590164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    desc.fWidth = wrapDesc.fWidth;
591164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    desc.fHeight = wrapDesc.fHeight;
592164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    desc.fSampleCnt = SkTMin(wrapDesc.fSampleCnt, this->caps()->maxSampleCount());
593164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
594164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    desc.fOrigin = resolve_origin(wrapDesc.fOrigin);
595164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
596164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkRenderTarget* tgt = GrVkRenderTarget::CreateWrappedRenderTarget(this, desc,
5979d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary                                                                        lifeCycle,
598fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth                                                                        info);
599164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (tgt && wrapDesc.fStencilBits) {
600164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        if (!createStencilAttachmentForRenderTarget(tgt, desc.fWidth, desc.fHeight)) {
601164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            tgt->unref();
602164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            return nullptr;
603164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
604164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
605164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return tgt;
606164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
607164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
608164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
609164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
610164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::bindGeometry(const GrPrimitiveProcessor& primProc,
6110e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                           const GrNonInstancedMesh& mesh) {
612164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkVertexBuffer* vbuf;
6130e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel    vbuf = (GrVkVertexBuffer*)mesh.vertexBuffer();
614164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(vbuf);
615164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(!vbuf->isMapped());
616164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
617164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    vbuf->addMemoryBarrier(this,
618164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           VK_ACCESS_HOST_WRITE_BIT,
619164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT,
620164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           VK_PIPELINE_STAGE_HOST_BIT,
621164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           VK_PIPELINE_STAGE_VERTEX_INPUT_BIT,
622164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           false);
623164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
624164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->bindVertexBuffer(this, vbuf);
625164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
6260e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel    if (mesh.isIndexed()) {
6270e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel        GrVkIndexBuffer* ibuf = (GrVkIndexBuffer*)mesh.indexBuffer();
628164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        SkASSERT(ibuf);
629164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        SkASSERT(!ibuf->isMapped());
630164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
631164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        ibuf->addMemoryBarrier(this,
632164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                               VK_ACCESS_HOST_WRITE_BIT,
633164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                               VK_ACCESS_INDEX_READ_BIT,
634164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                               VK_PIPELINE_STAGE_HOST_BIT,
635164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                               VK_PIPELINE_STAGE_VERTEX_INPUT_BIT,
636164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                               false);
637164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
638164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        fCurrentCmdBuffer->bindIndexBuffer(this, ibuf);
639164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
640164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
641164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
642164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
643164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
644164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielGrStencilAttachment* GrVkGpu::createStencilAttachmentForRenderTarget(const GrRenderTarget* rt,
645164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                     int width,
646164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                     int height) {
647164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(rt->asTexture());
648164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(width >= rt->width());
649164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(height >= rt->height());
650164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
651164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    int samples = rt->numStencilSamples();
652164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
653164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(this->vkCaps().stencilFormats().count());
654164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    const GrVkCaps::StencilFormat& sFmt = this->vkCaps().stencilFormats()[0];
655164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
656164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkStencilAttachment* stencil(GrVkStencilAttachment::Create(this,
657164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                 GrGpuResource::kCached_LifeCycle,
658164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                 width,
659164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                 height,
660164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                 samples,
661164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                 sFmt));
662164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fStats.incStencilAttachmentCreates();
663164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return stencil;
664164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
665164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
666164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
667164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
668164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielGrBackendObject GrVkGpu::createTestingOnlyBackendTexture(void* srcData, int w, int h,
669164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                         GrPixelConfig config) {
670164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
671164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkFormat pixelFormat;
672164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!GrPixelConfigToVkFormat(config, &pixelFormat)) {
673164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return 0;
674164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
675164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
676164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    bool linearTiling = false;
677164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!fVkCaps->isConfigTexturable(config)) {
678164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return 0;
679164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
680164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
681164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (fVkCaps->isConfigTexurableLinearly(config)) {
682164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        linearTiling = true;
683164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
684164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
685164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Currently this is not supported since it requires a copy which has not yet been implemented.
686164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (srcData && !linearTiling) {
687164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return 0;
688164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
689164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
690164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT;
691164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    usageFlags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
692164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    usageFlags |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
693164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
694164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkFlags memProps = (srcData && linearTiling) ? VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT :
695164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                   VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
696164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
697fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    VkImage image = VK_NULL_HANDLE;
698fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    VkDeviceMemory alloc = VK_NULL_HANDLE;
699164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
700fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    VkImageTiling imageTiling = linearTiling ? VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL;
701fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    VkImageLayout initialLayout = (VK_IMAGE_TILING_LINEAR == imageTiling)
702fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth                                ? VK_IMAGE_LAYOUT_PREINITIALIZED
703fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth                                : VK_IMAGE_LAYOUT_UNDEFINED;
704fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth
705fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    // Create Image
706fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    VkSampleCountFlagBits vkSamples;
707fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    if (!GrSampleCountToVkSampleCount(1, &vkSamples)) {
708fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        return 0;
709fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    }
710fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth
711fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    const VkImageCreateInfo imageCreateInfo = {
712fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,         // sType
713fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        NULL,                                        // pNext
714fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        0,                                           // VkImageCreateFlags
715fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        VK_IMAGE_TYPE_2D,                            // VkImageType
716fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        pixelFormat,                                 // VkFormat
717384b5e9cd36e443437de8df3b0f78ef4150efbacethannicholas        { (uint32_t) w, (uint32_t) h, 1 },           // VkExtent3D
718fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        1,                                           // mipLevels
719fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        1,                                           // arrayLayers
720fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        vkSamples,                                   // samples
721fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        imageTiling,                                 // VkImageTiling
722fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        usageFlags,                                  // VkImageUsageFlags
723fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        VK_SHARING_MODE_EXCLUSIVE,                   // VkSharingMode
724fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        0,                                           // queueFamilyCount
725fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        0,                                           // pQueueFamilyIndices
726fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        initialLayout                                // initialLayout
727fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    };
728fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth
729fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    GR_VK_CALL_ERRCHECK(this->vkInterface(), CreateImage(this->device(), &imageCreateInfo, nullptr, &image));
730fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth
731fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    if (!GrVkMemory::AllocAndBindImageMemory(this, image, memProps, &alloc)) {
732fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        VK_CALL(DestroyImage(this->device(), image, nullptr));
733164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return 0;
734164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
735164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
736164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (srcData) {
737164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        if (linearTiling) {
738164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            const VkImageSubresource subres = {
739164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                VK_IMAGE_ASPECT_COLOR_BIT,
740164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                0,  // mipLevel
741164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                0,  // arraySlice
742164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            };
743164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            VkSubresourceLayout layout;
744164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            VkResult err;
745164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
746fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth            VK_CALL(GetImageSubresourceLayout(fDevice, image, &subres, &layout));
747164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
748164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            void* mapPtr;
749fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth            err = VK_CALL(MapMemory(fDevice, alloc, 0, layout.rowPitch * h, 0, &mapPtr));
750164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            if (err) {
751fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth                VK_CALL(FreeMemory(this->device(), alloc, nullptr));
752fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth                VK_CALL(DestroyImage(this->device(), image, nullptr));
753164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                return 0;
754164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            }
755164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
756164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            size_t bpp = GrBytesPerPixel(config);
757164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            size_t rowCopyBytes = bpp * w;
758164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            // If there is no padding on dst (layout.rowPitch) we can do a single memcopy.
759164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            // This assumes the srcData comes in with no padding.
760164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            if (rowCopyBytes == layout.rowPitch) {
761164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                memcpy(mapPtr, srcData, rowCopyBytes * h);
762164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            } else {
763fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth                SkRectMemcpy(mapPtr, static_cast<size_t>(layout.rowPitch), srcData, rowCopyBytes,
764fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth                             rowCopyBytes, h);
765164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            }
766fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth            VK_CALL(UnmapMemory(fDevice, alloc));
767164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        } else {
768164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            // TODO: Add support for copying to optimal tiling
769164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            SkASSERT(false);
770164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
771164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
772164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
773fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    GrVkTextureInfo* info = new GrVkTextureInfo;
774fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    info->fImage = image;
775fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    info->fAlloc = alloc;
776fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    info->fImageTiling = imageTiling;
777fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    info->fImageLayout = initialLayout;
778fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth
779fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    return (GrBackendObject)info;
780164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
781164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
782164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::isTestingOnlyBackendTexture(GrBackendObject id) const {
783fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    const GrVkTextureInfo* backend = reinterpret_cast<const GrVkTextureInfo*>(id);
784164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
785164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (backend && backend->fImage && backend->fAlloc) {
786164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkMemoryRequirements req;
787164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        memset(&req, 0, sizeof(req));
788164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        GR_VK_CALL(this->vkInterface(), GetImageMemoryRequirements(fDevice,
789164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                   backend->fImage,
790164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                   &req));
791164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // TODO: find a better check
792164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // This will probably fail with a different driver
793164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return (req.size > 0) && (req.size <= 8192 * 8192);
794164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
795164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
796164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return false;
797164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
798164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
799164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::deleteTestingOnlyBackendTexture(GrBackendObject id, bool abandon) {
800fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    const GrVkTextureInfo* backend = reinterpret_cast<const GrVkTextureInfo*>(id);
801164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
802164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (backend) {
803164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        if (!abandon) {
804fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth            // something in the command buffer may still be using this, so force submit
805fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth            this->submitCommandBuffer(kForce_SyncQueue);
806fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth
807fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth            VK_CALL(FreeMemory(this->device(), backend->fAlloc, nullptr));
808fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth            VK_CALL(DestroyImage(this->device(), backend->fImage, nullptr));
809164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
810fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        delete backend;
811164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
812164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
813164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
814164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
815164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
816164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::addMemoryBarrier(VkPipelineStageFlags srcStageMask,
817164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                               VkPipelineStageFlags dstStageMask,
818164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                               bool byRegion,
819164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                               VkMemoryBarrier* barrier) const {
820164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(fCurrentCmdBuffer);
821164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->pipelineBarrier(this,
822164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       srcStageMask,
823164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       dstStageMask,
824164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       byRegion,
825164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       GrVkCommandBuffer::kMemory_BarrierType,
826164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       barrier);
827164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
828164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
829164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::addBufferMemoryBarrier(VkPipelineStageFlags srcStageMask,
830164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     VkPipelineStageFlags dstStageMask,
831164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     bool byRegion,
832164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     VkBufferMemoryBarrier* barrier) const {
833164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(fCurrentCmdBuffer);
834164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->pipelineBarrier(this,
835164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       srcStageMask,
836164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       dstStageMask,
837164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       byRegion,
838164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       GrVkCommandBuffer::kBufferMemory_BarrierType,
839164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       barrier);
840164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
841164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
842164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::addImageMemoryBarrier(VkPipelineStageFlags srcStageMask,
843164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                    VkPipelineStageFlags dstStageMask,
844164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                    bool byRegion,
845164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                    VkImageMemoryBarrier* barrier) const {
846164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(fCurrentCmdBuffer);
847164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->pipelineBarrier(this,
848164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       srcStageMask,
849164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       dstStageMask,
850164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       byRegion,
851164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       GrVkCommandBuffer::kImageMemory_BarrierType,
852164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       barrier);
853164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
854164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
855164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::finishDrawTarget() {
856164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Submit the current command buffer to the Queue
857164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    this->submitCommandBuffer(kSkip_SyncQueue);
858164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
859164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
8603d5d9ac426ea926f37eaa47e13acf7492068667begdanielvoid GrVkGpu::clearStencil(GrRenderTarget* target) {
8613d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    if (nullptr == target) {
8623d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        return;
8633d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    }
8643d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    GrStencilAttachment* stencil = target->renderTargetPriv().getStencilAttachment();
8653d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    GrVkStencilAttachment* vkStencil = (GrVkStencilAttachment*)stencil;
8663d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
8673d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
8683d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    VkClearDepthStencilValue vkStencilColor;
8693d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    memset(&vkStencilColor, 0, sizeof(VkClearDepthStencilValue));
8703d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
8713d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    VkImageLayout origDstLayout = vkStencil->currentLayout();
8723d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
8733d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    VkPipelineStageFlags srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(origDstLayout);
8743d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
8753d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
8763d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origDstLayout);;
8773d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    VkAccessFlags dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
8783d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
8793d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    vkStencil->setImageLayout(this,
8803d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                              VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
8813d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                              srcAccessMask,
8823d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                              dstAccessMask,
8833d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                              srcStageMask,
8843d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                              dstStageMask,
8853d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                              false);
8863d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
8873d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
8883d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    VkImageSubresourceRange subRange;
8893d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    memset(&subRange, 0, sizeof(VkImageSubresourceRange));
8903d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    subRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
8913d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    subRange.baseMipLevel = 0;
8923d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    subRange.levelCount = 1;
8933d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    subRange.baseArrayLayer = 0;
8943d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    subRange.layerCount = 1;
8953d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
8963d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    // TODO: I imagine that most times we want to clear a stencil it will be at the beginning of a
8973d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    // draw. Thus we should look into using the load op functions on the render pass to clear out
8983d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    // the stencil there.
8993d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    fCurrentCmdBuffer->clearDepthStencilImage(this, vkStencil, &vkStencilColor, 1, &subRange);
9003d5d9ac426ea926f37eaa47e13acf7492068667begdaniel}
9013d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
9023d5d9ac426ea926f37eaa47e13acf7492068667begdanielvoid GrVkGpu::onClearStencilClip(GrRenderTarget* target, const SkIRect& rect, bool insideClip) {
9033d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    SkASSERT(target);
9043d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
9053d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(target);
9063d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    GrStencilAttachment* sb = target->renderTargetPriv().getStencilAttachment();
9073d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    GrVkStencilAttachment* vkStencil = (GrVkStencilAttachment*)sb;
9083d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
9093d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    // this should only be called internally when we know we have a
9103d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    // stencil buffer.
9113d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    SkASSERT(sb);
9123d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    int stencilBitCount = sb->bits();
9133d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
9143d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    // The contract with the callers does not guarantee that we preserve all bits in the stencil
9153d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    // during this clear. Thus we will clear the entire stencil to the desired value.
9163d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
9173d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    VkClearDepthStencilValue vkStencilColor;
9183d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    memset(&vkStencilColor, 0, sizeof(VkClearDepthStencilValue));
9193d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    if (insideClip) {
9203d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        vkStencilColor.stencil = (1 << (stencilBitCount - 1));
9213d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    } else {
9223d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        vkStencilColor.stencil = 0;
9233d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    }
9243d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
9253d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    VkImageLayout origDstLayout = vkStencil->currentLayout();
9263d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origDstLayout);
9273d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    VkAccessFlags dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
9283d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    VkPipelineStageFlags srcStageMask =
9293d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        GrVkMemory::LayoutToPipelineStageFlags(origDstLayout);
9303d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
9313d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    vkStencil->setImageLayout(this,
9323d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                              VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
9333d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                              srcAccessMask,
9343d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                              dstAccessMask,
9353d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                              srcStageMask,
9363d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                              dstStageMask,
9373d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                              false);
9383d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
9393d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    VkClearRect clearRect;
9403d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    // Flip rect if necessary
9413d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    SkIRect vkRect = rect;
9423d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
9433d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    if (kBottomLeft_GrSurfaceOrigin == vkRT->origin()) {
9443d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        vkRect.fTop = vkRT->height() - rect.fBottom;
9453d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        vkRect.fBottom = vkRT->height() - rect.fTop;
9463d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    }
9473d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
9483d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    clearRect.rect.offset = { vkRect.fLeft, vkRect.fTop };
9493d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    clearRect.rect.extent = { (uint32_t)vkRect.width(), (uint32_t)vkRect.height() };
9503d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
9513d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    clearRect.baseArrayLayer = 0;
9523d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    clearRect.layerCount = 1;
9533d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
9543d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    const GrVkRenderPass* renderPass = vkRT->simpleRenderPass();
9553d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    SkASSERT(renderPass);
9563d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    fCurrentCmdBuffer->beginRenderPass(this, renderPass, *vkRT);
9573d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
9583d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    uint32_t stencilIndex;
9593d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    SkAssertResult(renderPass->stencilAttachmentIndex(&stencilIndex));
9603d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
9613d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    VkClearAttachment attachment;
9623d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    attachment.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
9633d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    attachment.colorAttachment = 0; // this value shouldn't matter
9643d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    attachment.clearValue.depthStencil = vkStencilColor;
9653d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
9663d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    fCurrentCmdBuffer->clearAttachments(this, 1, &attachment, 1, &clearRect);
9673d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    fCurrentCmdBuffer->endRenderPass(this);
9683d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
9693d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    return;
9703d5d9ac426ea926f37eaa47e13acf7492068667begdaniel}
9713d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
972164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::onClear(GrRenderTarget* target, const SkIRect& rect, GrColor color) {
973164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // parent class should never let us get here with no RT
974164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(target);
975164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
976164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkClearColorValue vkColor;
977164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrColorToRGBAFloat(color, vkColor.float32);
9789d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
979164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(target);
980164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkImageLayout origDstLayout = vkRT->currentLayout();
981164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
982164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (rect.width() != target->width() || rect.height() != target->height()) {
983164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origDstLayout);
984164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkAccessFlags dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
985164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkPipelineStageFlags srcStageMask =
9863d5d9ac426ea926f37eaa47e13acf7492068667begdaniel            GrVkMemory::LayoutToPipelineStageFlags(origDstLayout);
987164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
988164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        vkRT->setImageLayout(this,
989164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                             VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
990164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                             srcAccessMask,
991164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                             dstAccessMask,
992164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                             srcStageMask,
993164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                             dstStageMask,
994164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                             false);
995164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
996164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkClearRect clearRect;
9973d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        // Flip rect if necessary
9983d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        SkIRect vkRect = rect;
9993d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        if (kBottomLeft_GrSurfaceOrigin == vkRT->origin()) {
10003d5d9ac426ea926f37eaa47e13acf7492068667begdaniel            vkRect.fTop = vkRT->height() - rect.fBottom;
10013d5d9ac426ea926f37eaa47e13acf7492068667begdaniel            vkRect.fBottom = vkRT->height() - rect.fTop;
10023d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        }
10033d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        clearRect.rect.offset = { vkRect.fLeft, vkRect.fTop };
10043d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        clearRect.rect.extent = { (uint32_t)vkRect.width(), (uint32_t)vkRect.height() };
1005e77875aa425d51cc8db3463343a6308f9d2aadccjvanverth        clearRect.baseArrayLayer = 0;
1006e77875aa425d51cc8db3463343a6308f9d2aadccjvanverth        clearRect.layerCount = 1;
1007164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1008164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        const GrVkRenderPass* renderPass = vkRT->simpleRenderPass();
1009164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        SkASSERT(renderPass);
1010164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        fCurrentCmdBuffer->beginRenderPass(this, renderPass, *vkRT);
1011164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1012164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        uint32_t colorIndex;
1013164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        SkAssertResult(renderPass->colorAttachmentIndex(&colorIndex));
1014164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1015164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkClearAttachment attachment;
1016164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
1017164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        attachment.colorAttachment = colorIndex;
1018164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        attachment.clearValue.color = vkColor;
1019164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1020164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        fCurrentCmdBuffer->clearAttachments(this, 1, &attachment, 1, &clearRect);
1021164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        fCurrentCmdBuffer->endRenderPass(this);
1022164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return;
1023164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1024164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1025164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkPipelineStageFlags srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(origDstLayout);
1026164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
1027164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1028164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origDstLayout);;
1029164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkAccessFlags dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
1030164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1031164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    vkRT->setImageLayout(this,
1032164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1033164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         srcAccessMask,
1034164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         dstAccessMask,
1035164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         srcStageMask,
1036164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         dstStageMask,
1037164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         false);
1038164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1039164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1040164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkImageSubresourceRange subRange;
1041164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    memset(&subRange, 0, sizeof(VkImageSubresourceRange));
1042164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    subRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
1043164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    subRange.baseMipLevel = 0;
1044164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    subRange.levelCount = 1;
1045164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    subRange.baseArrayLayer = 0;
1046164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    subRange.layerCount = 1;
1047164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
10489d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary    // In the future we may not actually be doing this type of clear at all. If we are inside a
1049164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // render pass or doing a non full clear then we will use CmdClearColorAttachment. The more
1050164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // common use case will be clearing an attachment at the start of a render pass, in which case
1051164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // we will use the clear load ops.
1052164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->clearColorImage(this,
1053164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       vkRT,
1054164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       &vkColor,
1055164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       1, &subRange);
1056164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1057164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1058164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielinline bool can_copy_image(const GrSurface* dst,
1059164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           const GrSurface* src,
1060164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           const GrVkGpu* gpu) {
1061164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (src->asTexture() &&
1062164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        dst->asTexture() &&
1063164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        src->origin() == dst->origin() &&
1064164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        src->config() == dst->config()) {
1065164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return true;
1066164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1067164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1068164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // How does msaa play into this? If a VkTexture is multisampled, are we copying the multisampled
1069164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // or the resolved image here?
1070164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1071164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return false;
1072164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1073164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1074164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::copySurfaceAsCopyImage(GrSurface* dst,
1075164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     GrSurface* src,
1076164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     const SkIRect& srcRect,
1077164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     const SkIPoint& dstPoint) {
1078164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(can_copy_image(dst, src, this));
1079164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1080164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Insert memory barriers to switch src and dst to transfer_source and transfer_dst layouts
1081164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkTexture* dstTex = static_cast<GrVkTexture*>(dst->asTexture());
1082164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkTexture* srcTex = static_cast<GrVkTexture*>(src->asTexture());
1083164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1084164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkImageLayout origDstLayout = dstTex->currentLayout();
1085164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkImageLayout origSrcLayout = srcTex->currentLayout();
1086164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1087164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkPipelineStageFlags srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(origDstLayout);
1088164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
1089164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1090164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // These flags are for flushing/invalidating caches and for the dst image it doesn't matter if
1091164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // the cache is flushed since it is only being written to.
1092164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origDstLayout);;
1093164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkAccessFlags dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
10949d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
1095164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    dstTex->setImageLayout(this,
1096164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1097164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           srcAccessMask,
1098164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           dstAccessMask,
1099164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           srcStageMask,
1100164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           dstStageMask,
1101164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           false);
11029d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
1103164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(origSrcLayout);
1104164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
1105164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1106164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origSrcLayout);
1107164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
1108164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1109164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    srcTex->setImageLayout(this,
1110164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1111164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           srcAccessMask,
1112164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           dstAccessMask,
1113164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           srcStageMask,
1114164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           dstStageMask,
1115164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           false);
1116164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1117164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Flip rect if necessary
1118164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkIRect srcVkRect = srcRect;
1119164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    int32_t dstY = dstPoint.fY;
1120164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1121164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (kBottomLeft_GrSurfaceOrigin == src->origin()) {
1122164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        SkASSERT(kBottomLeft_GrSurfaceOrigin == dst->origin());
1123164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        srcVkRect.fTop = src->height() - srcRect.fBottom;
1124164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        srcVkRect.fBottom =  src->height() - srcRect.fTop;
1125164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        dstY = dst->height() - dstPoint.fY - srcVkRect.height();
1126164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1127164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1128164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkImageCopy copyRegion;
1129164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    memset(&copyRegion, 0, sizeof(VkImageCopy));
1130164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    copyRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
1131164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    copyRegion.srcOffset = { srcVkRect.fLeft, srcVkRect.fTop, 0 };
1132164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    copyRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
1133164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    copyRegion.dstOffset = { dstPoint.fX, dstY, 0 };
1134164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    copyRegion.extent = { (uint32_t)srcVkRect.width(), (uint32_t)srcVkRect.height(), 0 };
1135164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1136164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->copyImage(this,
1137164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                 srcTex,
1138164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1139164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                 dstTex,
1140164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1141164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                 1,
1142164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                 &copyRegion);
1143164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1144164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1145164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielinline bool can_copy_as_draw(const GrSurface* dst,
1146164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                             const GrSurface* src,
1147164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                             const GrVkGpu* gpu) {
1148164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return false;
1149164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1150164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1151164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::copySurfaceAsDraw(GrSurface* dst,
1152164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                GrSurface* src,
1153164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                const SkIRect& srcRect,
1154164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                const SkIPoint& dstPoint) {
1155164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(false);
1156164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1157164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1158164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::onCopySurface(GrSurface* dst,
1159164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                            GrSurface* src,
1160164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                            const SkIRect& srcRect,
1161164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                            const SkIPoint& dstPoint) {
1162164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (can_copy_image(dst, src, this)) {
1163164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        this->copySurfaceAsCopyImage(dst, src, srcRect, dstPoint);
1164164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return true;
1165164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1166164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1167164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (can_copy_as_draw(dst, src, this)) {
1168164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        this->copySurfaceAsDraw(dst, src, srcRect, dstPoint);
1169164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return true;
1170164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1171164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1172164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return false;
1173164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1174164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
117528f45b949acc746849100fbe112ee5280f0594c9cdaltonvoid GrVkGpu::onGetMultisampleSpecs(GrRenderTarget* rt, const GrStencilSettings&,
117628f45b949acc746849100fbe112ee5280f0594c9cdalton                                    int* effectiveSampleCnt, SkAutoTDeleteArray<SkPoint>*) {
117728f45b949acc746849100fbe112ee5280f0594c9cdalton    // TODO: stub.
117828f45b949acc746849100fbe112ee5280f0594c9cdalton    SkASSERT(!this->caps()->sampleLocationsSupport());
117928f45b949acc746849100fbe112ee5280f0594c9cdalton    *effectiveSampleCnt = rt->desc().fSampleCnt;
118028f45b949acc746849100fbe112ee5280f0594c9cdalton}
118128f45b949acc746849100fbe112ee5280f0594c9cdalton
1182164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::onGetReadPixelsInfo(GrSurface* srcSurface, int width, int height, size_t rowBytes,
1183164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                  GrPixelConfig readConfig, DrawPreference* drawPreference,
1184164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                  ReadPixelTempDrawInfo* tempDrawInfo) {
1185164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Currently we don't handle draws, so if the caller wants/needs to do a draw we need to fail
1186164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (kNoDraw_DrawPreference != *drawPreference) {
1187164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
1188164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1189164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1190164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (srcSurface->config() != readConfig) {
1191164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // TODO: This should fall back to drawing or copying to change config of srcSurface to match
1192164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // that of readConfig.
1193164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
1194164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1195164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1196164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return true;
1197164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1198164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1199164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::onReadPixels(GrSurface* surface,
1200164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           int left, int top, int width, int height,
1201164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           GrPixelConfig config,
1202164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           void* buffer,
1203164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           size_t rowBytes) {
1204164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkFormat pixelFormat;
1205164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!GrPixelConfigToVkFormat(config, &pixelFormat)) {
1206164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
1207164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1208164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1209164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkTexture* tgt = static_cast<GrVkTexture*>(surface->asTexture());
1210164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!tgt) {
1211164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
1212164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1213164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1214164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Change layout of our target so it can be used as copy
1215164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkImageLayout layout = tgt->currentLayout();
1216164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkPipelineStageFlags srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(layout);
1217164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
1218164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(layout);
1219164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkAccessFlags dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
1220164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    tgt->setImageLayout(this,
1221164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                        VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1222164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                        srcAccessMask,
1223164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                        dstAccessMask,
1224164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                        srcStageMask,
1225164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                        dstStageMask,
1226164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                        false);
1227164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
12289d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary    GrVkTransferBuffer* transferBuffer =
1229397536cabe12a9936659870dd220c869789424bacdalton        static_cast<GrVkTransferBuffer*>(this->createBuffer(kXferGpuToCpu_GrBufferType,
1230397536cabe12a9936659870dd220c869789424bacdalton                                                            rowBytes * height,
1231397536cabe12a9936659870dd220c869789424bacdalton                                                            kStream_GrAccessPattern));
1232164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1233164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    bool flipY = kBottomLeft_GrSurfaceOrigin == surface->origin();
1234164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkOffset3D offset = {
1235164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        left,
1236164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        flipY ? surface->height() - top - height : top,
1237164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        0
1238164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    };
1239164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1240164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Copy the image to a buffer so we can map it to cpu memory
1241164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkBufferImageCopy region;
1242164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    memset(&region, 0, sizeof(VkBufferImageCopy));
1243164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    region.bufferOffset = 0;
1244164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    region.bufferRowLength = 0; // Forces RowLength to be imageExtent.width
1245164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    region.bufferImageHeight = 0; // Forces height to be tightly packed. Only useful for 3d images.
1246164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
1247164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    region.imageOffset = offset;
1248164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    region.imageExtent = { (uint32_t)width, (uint32_t)height, 1 };
1249164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1250164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->copyImageToBuffer(this,
1251164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                         tgt,
1252164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1253164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                         transferBuffer,
1254164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                         1,
1255164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                         &region);
1256164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1257164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // make sure the copy to buffer has finished
1258164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    transferBuffer->addMemoryBarrier(this,
1259164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     VK_ACCESS_TRANSFER_WRITE_BIT,
1260164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     VK_ACCESS_HOST_READ_BIT,
1261164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     VK_PIPELINE_STAGE_TRANSFER_BIT,
1262164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     VK_PIPELINE_STAGE_HOST_BIT,
1263164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     false);
1264164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1265164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // We need to submit the current command buffer to the Queue and make sure it finishes before
1266164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // we can copy the data out of the buffer.
1267164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    this->submitCommandBuffer(kForce_SyncQueue);
1268164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1269164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    void* mappedMemory = transferBuffer->map();
1270164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1271164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    memcpy(buffer, mappedMemory, rowBytes*height);
1272164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1273164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    transferBuffer->unmap();
1274164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    transferBuffer->unref();
1275164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1276164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (flipY) {
1277164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        SkAutoSMalloc<32 * sizeof(GrColor)> scratch;
1278164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        size_t tightRowBytes = GrBytesPerPixel(config) * width;
1279164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        scratch.reset(tightRowBytes);
1280164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        void* tmpRow = scratch.get();
1281164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // flip y in-place by rows
1282164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        const int halfY = height >> 1;
1283164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        char* top = reinterpret_cast<char*>(buffer);
1284164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        char* bottom = top + (height - 1) * rowBytes;
1285164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        for (int y = 0; y < halfY; y++) {
1286164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            memcpy(tmpRow, top, tightRowBytes);
1287164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            memcpy(top, bottom, tightRowBytes);
1288164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            memcpy(bottom, tmpRow, tightRowBytes);
1289164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            top += rowBytes;
1290164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            bottom -= rowBytes;
1291164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
1292164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1293164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1294164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return true;
1295164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1296af132770a9462f6bb9cff47254e44675d9241fe8egdanielsk_sp<GrVkPipelineState> GrVkGpu::prepareDrawState(const GrPipeline& pipeline,
1297af132770a9462f6bb9cff47254e44675d9241fe8egdaniel                                                   const GrPrimitiveProcessor& primProc,
1298af132770a9462f6bb9cff47254e44675d9241fe8egdaniel                                                   GrPrimitiveType primitiveType,
1299af132770a9462f6bb9cff47254e44675d9241fe8egdaniel                                                   const GrVkRenderPass& renderPass) {
1300af132770a9462f6bb9cff47254e44675d9241fe8egdaniel    sk_sp<GrVkPipelineState> pipelineState =
1301af132770a9462f6bb9cff47254e44675d9241fe8egdaniel        fResourceProvider.findOrCreateCompatiblePipelineState(pipeline,
1302af132770a9462f6bb9cff47254e44675d9241fe8egdaniel                                                              primProc,
1303af132770a9462f6bb9cff47254e44675d9241fe8egdaniel                                                              primitiveType,
1304af132770a9462f6bb9cff47254e44675d9241fe8egdaniel                                                              renderPass);
130522281c13a13c4b4e275516e9fe02185a53a7e5aaegdaniel    if (!pipelineState) {
1306af132770a9462f6bb9cff47254e44675d9241fe8egdaniel        return pipelineState;
1307164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1308164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1309af132770a9462f6bb9cff47254e44675d9241fe8egdaniel    pipelineState->setData(this, primProc, pipeline);
1310164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1311af132770a9462f6bb9cff47254e44675d9241fe8egdaniel    pipelineState->bind(this, fCurrentCmdBuffer);
1312470d77a1d7dc286cdad98b145dac735cd7638e56egdaniel
1313470d77a1d7dc286cdad98b145dac735cd7638e56egdaniel    GrVkPipeline::SetDynamicState(this, fCurrentCmdBuffer, pipeline);
1314470d77a1d7dc286cdad98b145dac735cd7638e56egdaniel
1315af132770a9462f6bb9cff47254e44675d9241fe8egdaniel    return pipelineState;
13160e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel}
1317164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
13180e1853c89615d14d0d03c87c7e0c604e5285cc54egdanielvoid GrVkGpu::onDraw(const GrPipeline& pipeline,
13190e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                     const GrPrimitiveProcessor& primProc,
13200e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                     const GrMesh* meshes,
13210e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                     int meshCount) {
13220e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel    if (!meshCount) {
13230e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel        return;
13240e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel    }
13250e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel    GrRenderTarget* rt = pipeline.getRenderTarget();
13260e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel    GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(rt);
13270e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel    const GrVkRenderPass* renderPass = vkRT->simpleRenderPass();
13280e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel    SkASSERT(renderPass);
1329164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1330470d77a1d7dc286cdad98b145dac735cd7638e56egdaniel    fCurrentCmdBuffer->beginRenderPass(this, renderPass, *vkRT);
1331470d77a1d7dc286cdad98b145dac735cd7638e56egdaniel
13320e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel    GrPrimitiveType primitiveType = meshes[0].primitiveType();
1333af132770a9462f6bb9cff47254e44675d9241fe8egdaniel    sk_sp<GrVkPipelineState> pipelineState = this->prepareDrawState(pipeline,
1334af132770a9462f6bb9cff47254e44675d9241fe8egdaniel                                                                    primProc,
1335af132770a9462f6bb9cff47254e44675d9241fe8egdaniel                                                                    primitiveType,
1336af132770a9462f6bb9cff47254e44675d9241fe8egdaniel                                                                    *renderPass);
1337af132770a9462f6bb9cff47254e44675d9241fe8egdaniel    if (!pipelineState) {
13380e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel        return;
13390e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel    }
1340164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1341164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Change layout of our render target so it can be used as the color attachment
1342164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkImageLayout layout = vkRT->currentLayout();
1343164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Our color attachment is purely a destination and won't be read so don't need to flush or
1344164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // invalidate any caches
1345164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkPipelineStageFlags srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(layout);
1346164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1347164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(layout);
1348164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkAccessFlags dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
1349164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    vkRT->setImageLayout(this,
1350164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1351164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         srcAccessMask,
1352164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         dstAccessMask,
1353164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         srcStageMask,
1354164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         dstStageMask,
1355164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         false);
1356164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
13573d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    // If we are using a stencil attachment we also need to update its layout
13580e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel    if (!pipeline.getStencil().isDisabled()) {
13593d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        GrStencilAttachment* stencil = vkRT->renderTargetPriv().getStencilAttachment();
13603d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        GrVkStencilAttachment* vkStencil = (GrVkStencilAttachment*)stencil;
13613d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        VkImageLayout origDstLayout = vkStencil->currentLayout();
13623d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origDstLayout);
13633d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        VkAccessFlags dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
13640e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel            VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
13653d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        VkPipelineStageFlags srcStageMask =
13663d5d9ac426ea926f37eaa47e13acf7492068667begdaniel            GrVkMemory::LayoutToPipelineStageFlags(origDstLayout);
13673d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
13683d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        vkStencil->setImageLayout(this,
13693d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                                  VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
13703d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                                  srcAccessMask,
13713d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                                  dstAccessMask,
13723d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                                  srcStageMask,
13733d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                                  dstStageMask,
13743d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                                  false);
13753d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    }
13763d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
13770e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel
13780e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel    for (int i = 0; i < meshCount; ++i) {
13790e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel        if (GrXferBarrierType barrierType = pipeline.xferBarrierType(*this->caps())) {
13800e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel            this->xferBarrier(pipeline.getRenderTarget(), barrierType);
13810e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel        }
13820e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel
13830e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel        const GrMesh& mesh = meshes[i];
13840e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel        GrMesh::Iterator iter;
13850e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel        const GrNonInstancedMesh* nonIdxMesh = iter.init(mesh);
13860e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel        do {
13870e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel            if (nonIdxMesh->primitiveType() != primitiveType) {
13880e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                // Technically we don't have to call this here (since there is a safety check in
138922281c13a13c4b4e275516e9fe02185a53a7e5aaegdaniel                // pipelineState:setData but this will allow for quicker freeing of resources if the
139022281c13a13c4b4e275516e9fe02185a53a7e5aaegdaniel                // pipelineState sits in a cache for a while.
139122281c13a13c4b4e275516e9fe02185a53a7e5aaegdaniel                pipelineState->freeTempResources(this);
139222281c13a13c4b4e275516e9fe02185a53a7e5aaegdaniel                SkDEBUGCODE(pipelineState = nullptr);
13930e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                primitiveType = nonIdxMesh->primitiveType();
1394af132770a9462f6bb9cff47254e44675d9241fe8egdaniel                pipelineState = this->prepareDrawState(pipeline,
1395af132770a9462f6bb9cff47254e44675d9241fe8egdaniel                                                       primProc,
1396af132770a9462f6bb9cff47254e44675d9241fe8egdaniel                                                       primitiveType,
1397af132770a9462f6bb9cff47254e44675d9241fe8egdaniel                                                       *renderPass);
1398af132770a9462f6bb9cff47254e44675d9241fe8egdaniel                if (!pipelineState) {
13990e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                    return;
14000e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                }
14010e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel            }
140222281c13a13c4b4e275516e9fe02185a53a7e5aaegdaniel            SkASSERT(pipelineState);
14030e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel            this->bindGeometry(primProc, *nonIdxMesh);
14040e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel
14050e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel            if (nonIdxMesh->isIndexed()) {
14060e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                fCurrentCmdBuffer->drawIndexed(this,
14070e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                                               nonIdxMesh->indexCount(),
14080e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                                               1,
14090e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                                               nonIdxMesh->startIndex(),
14100e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                                               nonIdxMesh->startVertex(),
14110e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                                               0);
14120e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel            } else {
14130e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                fCurrentCmdBuffer->draw(this,
14140e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                                        nonIdxMesh->vertexCount(),
14150e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                                        1,
14160e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                                        nonIdxMesh->startVertex(),
14170e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                                        0);
14180e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel            }
14190e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel
14200e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel            fStats.incNumDraws();
14210e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel        } while ((nonIdxMesh = iter.next()));
1422164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1423164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1424164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->endRenderPass(this);
1425164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
142622281c13a13c4b4e275516e9fe02185a53a7e5aaegdaniel    // Technically we don't have to call this here (since there is a safety check in
142722281c13a13c4b4e275516e9fe02185a53a7e5aaegdaniel    // pipelineState:setData but this will allow for quicker freeing of resources if the
142822281c13a13c4b4e275516e9fe02185a53a7e5aaegdaniel    // pipelineState sits in a cache for a while.
142922281c13a13c4b4e275516e9fe02185a53a7e5aaegdaniel    pipelineState->freeTempResources(this);
1430164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1431164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#if SWAP_PER_DRAW
1432164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    glFlush();
1433164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#if defined(SK_BUILD_FOR_MAC)
1434164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    aglSwapBuffers(aglGetCurrentContext());
1435164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    int set_a_break_pt_here = 9;
1436164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    aglSwapBuffers(aglGetCurrentContext());
1437164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#elif defined(SK_BUILD_FOR_WIN32)
1438164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SwapBuf();
1439164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    int set_a_break_pt_here = 9;
1440164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SwapBuf();
1441164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#endif
1442164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#endif
1443164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1444