GrVkGpu.cpp revision 8f1dcaa6f3cc098bd5efd2595ca20e0bc1847d10
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
6538f1dcaa6f3cc098bd5efd2595ca20e0bc1847d10egdaniel    const GrVkCaps::StencilFormat& sFmt = this->vkCaps().preferedStencilFormat();
654164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
655164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkStencilAttachment* stencil(GrVkStencilAttachment::Create(this,
656164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                 GrGpuResource::kCached_LifeCycle,
657164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                 width,
658164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                 height,
659164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                 samples,
660164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                 sFmt));
661164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fStats.incStencilAttachmentCreates();
662164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return stencil;
663164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
664164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
665164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
666164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
667164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielGrBackendObject GrVkGpu::createTestingOnlyBackendTexture(void* srcData, int w, int h,
668164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                         GrPixelConfig config) {
669164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
670164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkFormat pixelFormat;
671164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!GrPixelConfigToVkFormat(config, &pixelFormat)) {
672164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return 0;
673164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
674164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
675164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    bool linearTiling = false;
676164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!fVkCaps->isConfigTexturable(config)) {
677164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return 0;
678164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
679164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
680164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (fVkCaps->isConfigTexurableLinearly(config)) {
681164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        linearTiling = true;
682164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
683164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
684164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Currently this is not supported since it requires a copy which has not yet been implemented.
685164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (srcData && !linearTiling) {
686164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return 0;
687164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
688164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
689164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT;
690164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    usageFlags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
691164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    usageFlags |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
692164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
693164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkFlags memProps = (srcData && linearTiling) ? VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT :
694164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                   VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
695164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
696fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    VkImage image = VK_NULL_HANDLE;
697fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    VkDeviceMemory alloc = VK_NULL_HANDLE;
698164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
699fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    VkImageTiling imageTiling = linearTiling ? VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL;
700fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    VkImageLayout initialLayout = (VK_IMAGE_TILING_LINEAR == imageTiling)
701fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth                                ? VK_IMAGE_LAYOUT_PREINITIALIZED
702fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth                                : VK_IMAGE_LAYOUT_UNDEFINED;
703fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth
704fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    // Create Image
705fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    VkSampleCountFlagBits vkSamples;
706fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    if (!GrSampleCountToVkSampleCount(1, &vkSamples)) {
707fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        return 0;
708fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    }
709fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth
710fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    const VkImageCreateInfo imageCreateInfo = {
711fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,         // sType
712fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        NULL,                                        // pNext
713fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        0,                                           // VkImageCreateFlags
714fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        VK_IMAGE_TYPE_2D,                            // VkImageType
715fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        pixelFormat,                                 // VkFormat
716384b5e9cd36e443437de8df3b0f78ef4150efbacethannicholas        { (uint32_t) w, (uint32_t) h, 1 },           // VkExtent3D
717fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        1,                                           // mipLevels
718fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        1,                                           // arrayLayers
719fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        vkSamples,                                   // samples
720fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        imageTiling,                                 // VkImageTiling
721fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        usageFlags,                                  // VkImageUsageFlags
722fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        VK_SHARING_MODE_EXCLUSIVE,                   // VkSharingMode
723fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        0,                                           // queueFamilyCount
724fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        0,                                           // pQueueFamilyIndices
725fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        initialLayout                                // initialLayout
726fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    };
727fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth
728fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    GR_VK_CALL_ERRCHECK(this->vkInterface(), CreateImage(this->device(), &imageCreateInfo, nullptr, &image));
729fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth
730fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    if (!GrVkMemory::AllocAndBindImageMemory(this, image, memProps, &alloc)) {
731fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        VK_CALL(DestroyImage(this->device(), image, nullptr));
732164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return 0;
733164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
734164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
735164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (srcData) {
736164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        if (linearTiling) {
737164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            const VkImageSubresource subres = {
738164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                VK_IMAGE_ASPECT_COLOR_BIT,
739164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                0,  // mipLevel
740164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                0,  // arraySlice
741164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            };
742164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            VkSubresourceLayout layout;
743164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            VkResult err;
744164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
745fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth            VK_CALL(GetImageSubresourceLayout(fDevice, image, &subres, &layout));
746164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
747164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            void* mapPtr;
748fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth            err = VK_CALL(MapMemory(fDevice, alloc, 0, layout.rowPitch * h, 0, &mapPtr));
749164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            if (err) {
750fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth                VK_CALL(FreeMemory(this->device(), alloc, nullptr));
751fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth                VK_CALL(DestroyImage(this->device(), image, nullptr));
752164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                return 0;
753164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            }
754164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
755164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            size_t bpp = GrBytesPerPixel(config);
756164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            size_t rowCopyBytes = bpp * w;
757164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            // If there is no padding on dst (layout.rowPitch) we can do a single memcopy.
758164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            // This assumes the srcData comes in with no padding.
759164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            if (rowCopyBytes == layout.rowPitch) {
760164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                memcpy(mapPtr, srcData, rowCopyBytes * h);
761164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            } else {
762fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth                SkRectMemcpy(mapPtr, static_cast<size_t>(layout.rowPitch), srcData, rowCopyBytes,
763fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth                             rowCopyBytes, h);
764164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            }
765fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth            VK_CALL(UnmapMemory(fDevice, alloc));
766164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        } else {
767164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            // TODO: Add support for copying to optimal tiling
768164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            SkASSERT(false);
769164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
770164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
771164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
772fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    GrVkTextureInfo* info = new GrVkTextureInfo;
773fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    info->fImage = image;
774fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    info->fAlloc = alloc;
775fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    info->fImageTiling = imageTiling;
776fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    info->fImageLayout = initialLayout;
777fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth
778fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    return (GrBackendObject)info;
779164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
780164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
781164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::isTestingOnlyBackendTexture(GrBackendObject id) const {
782fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    const GrVkTextureInfo* backend = reinterpret_cast<const GrVkTextureInfo*>(id);
783164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
784164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (backend && backend->fImage && backend->fAlloc) {
785164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkMemoryRequirements req;
786164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        memset(&req, 0, sizeof(req));
787164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        GR_VK_CALL(this->vkInterface(), GetImageMemoryRequirements(fDevice,
788164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                   backend->fImage,
789164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                   &req));
790164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // TODO: find a better check
791164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // This will probably fail with a different driver
792164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return (req.size > 0) && (req.size <= 8192 * 8192);
793164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
794164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
795164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return false;
796164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
797164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
798164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::deleteTestingOnlyBackendTexture(GrBackendObject id, bool abandon) {
799fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth    const GrVkTextureInfo* backend = reinterpret_cast<const GrVkTextureInfo*>(id);
800164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
801164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (backend) {
802164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        if (!abandon) {
803fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth            // something in the command buffer may still be using this, so force submit
804fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth            this->submitCommandBuffer(kForce_SyncQueue);
805fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth
806fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth            VK_CALL(FreeMemory(this->device(), backend->fAlloc, nullptr));
807fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth            VK_CALL(DestroyImage(this->device(), backend->fImage, nullptr));
808164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
809fd359caf0cbdefd759d1c788d72faba3f65a6386jvanverth        delete backend;
810164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
811164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
812164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
813164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
814164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
815164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::addMemoryBarrier(VkPipelineStageFlags srcStageMask,
816164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                               VkPipelineStageFlags dstStageMask,
817164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                               bool byRegion,
818164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                               VkMemoryBarrier* barrier) const {
819164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(fCurrentCmdBuffer);
820164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->pipelineBarrier(this,
821164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       srcStageMask,
822164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       dstStageMask,
823164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       byRegion,
824164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       GrVkCommandBuffer::kMemory_BarrierType,
825164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       barrier);
826164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
827164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
828164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::addBufferMemoryBarrier(VkPipelineStageFlags srcStageMask,
829164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     VkPipelineStageFlags dstStageMask,
830164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     bool byRegion,
831164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     VkBufferMemoryBarrier* barrier) const {
832164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(fCurrentCmdBuffer);
833164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->pipelineBarrier(this,
834164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       srcStageMask,
835164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       dstStageMask,
836164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       byRegion,
837164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       GrVkCommandBuffer::kBufferMemory_BarrierType,
838164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       barrier);
839164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
840164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
841164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::addImageMemoryBarrier(VkPipelineStageFlags srcStageMask,
842164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                    VkPipelineStageFlags dstStageMask,
843164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                    bool byRegion,
844164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                    VkImageMemoryBarrier* barrier) const {
845164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(fCurrentCmdBuffer);
846164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->pipelineBarrier(this,
847164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       srcStageMask,
848164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       dstStageMask,
849164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       byRegion,
850164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       GrVkCommandBuffer::kImageMemory_BarrierType,
851164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       barrier);
852164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
853164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
854164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::finishDrawTarget() {
855164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Submit the current command buffer to the Queue
856164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    this->submitCommandBuffer(kSkip_SyncQueue);
857164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
858164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
8593d5d9ac426ea926f37eaa47e13acf7492068667begdanielvoid GrVkGpu::clearStencil(GrRenderTarget* target) {
8603d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    if (nullptr == target) {
8613d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        return;
8623d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    }
8633d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    GrStencilAttachment* stencil = target->renderTargetPriv().getStencilAttachment();
8643d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    GrVkStencilAttachment* vkStencil = (GrVkStencilAttachment*)stencil;
8653d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
8663d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
8673d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    VkClearDepthStencilValue vkStencilColor;
8683d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    memset(&vkStencilColor, 0, sizeof(VkClearDepthStencilValue));
8693d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
8703d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    VkImageLayout origDstLayout = vkStencil->currentLayout();
8713d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
8723d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    VkPipelineStageFlags srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(origDstLayout);
8733d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
8743d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
8753d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origDstLayout);;
8763d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    VkAccessFlags dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
8773d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
8783d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    vkStencil->setImageLayout(this,
8793d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                              VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
8803d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                              srcAccessMask,
8813d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                              dstAccessMask,
8823d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                              srcStageMask,
8833d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                              dstStageMask,
8843d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                              false);
8853d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
8863d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
8873d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    VkImageSubresourceRange subRange;
8883d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    memset(&subRange, 0, sizeof(VkImageSubresourceRange));
8893d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    subRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
8903d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    subRange.baseMipLevel = 0;
8913d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    subRange.levelCount = 1;
8923d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    subRange.baseArrayLayer = 0;
8933d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    subRange.layerCount = 1;
8943d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
8953d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    // TODO: I imagine that most times we want to clear a stencil it will be at the beginning of a
8963d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    // draw. Thus we should look into using the load op functions on the render pass to clear out
8973d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    // the stencil there.
8983d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    fCurrentCmdBuffer->clearDepthStencilImage(this, vkStencil, &vkStencilColor, 1, &subRange);
8993d5d9ac426ea926f37eaa47e13acf7492068667begdaniel}
9003d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
9013d5d9ac426ea926f37eaa47e13acf7492068667begdanielvoid GrVkGpu::onClearStencilClip(GrRenderTarget* target, const SkIRect& rect, bool insideClip) {
9023d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    SkASSERT(target);
9033d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
9043d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(target);
9053d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    GrStencilAttachment* sb = target->renderTargetPriv().getStencilAttachment();
9063d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    GrVkStencilAttachment* vkStencil = (GrVkStencilAttachment*)sb;
9073d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
9083d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    // this should only be called internally when we know we have a
9093d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    // stencil buffer.
9103d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    SkASSERT(sb);
9113d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    int stencilBitCount = sb->bits();
9123d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
9133d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    // The contract with the callers does not guarantee that we preserve all bits in the stencil
9143d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    // during this clear. Thus we will clear the entire stencil to the desired value.
9153d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
9163d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    VkClearDepthStencilValue vkStencilColor;
9173d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    memset(&vkStencilColor, 0, sizeof(VkClearDepthStencilValue));
9183d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    if (insideClip) {
9193d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        vkStencilColor.stencil = (1 << (stencilBitCount - 1));
9203d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    } else {
9213d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        vkStencilColor.stencil = 0;
9223d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    }
9233d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
9243d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    VkImageLayout origDstLayout = vkStencil->currentLayout();
9253d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origDstLayout);
9263d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    VkAccessFlags dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
9273d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    VkPipelineStageFlags srcStageMask =
9283d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        GrVkMemory::LayoutToPipelineStageFlags(origDstLayout);
9293d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
9303d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    vkStencil->setImageLayout(this,
9313d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                              VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
9323d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                              srcAccessMask,
9333d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                              dstAccessMask,
9343d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                              srcStageMask,
9353d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                              dstStageMask,
9363d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                              false);
9373d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
9383d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    VkClearRect clearRect;
9393d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    // Flip rect if necessary
9403d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    SkIRect vkRect = rect;
9413d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
9423d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    if (kBottomLeft_GrSurfaceOrigin == vkRT->origin()) {
9433d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        vkRect.fTop = vkRT->height() - rect.fBottom;
9443d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        vkRect.fBottom = vkRT->height() - rect.fTop;
9453d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    }
9463d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
9473d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    clearRect.rect.offset = { vkRect.fLeft, vkRect.fTop };
9483d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    clearRect.rect.extent = { (uint32_t)vkRect.width(), (uint32_t)vkRect.height() };
9493d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
9503d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    clearRect.baseArrayLayer = 0;
9513d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    clearRect.layerCount = 1;
9523d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
9533d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    const GrVkRenderPass* renderPass = vkRT->simpleRenderPass();
9543d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    SkASSERT(renderPass);
9553d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    fCurrentCmdBuffer->beginRenderPass(this, renderPass, *vkRT);
9563d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
9573d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    uint32_t stencilIndex;
9583d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    SkAssertResult(renderPass->stencilAttachmentIndex(&stencilIndex));
9593d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
9603d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    VkClearAttachment attachment;
9613d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    attachment.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
9623d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    attachment.colorAttachment = 0; // this value shouldn't matter
9633d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    attachment.clearValue.depthStencil = vkStencilColor;
9643d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
9653d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    fCurrentCmdBuffer->clearAttachments(this, 1, &attachment, 1, &clearRect);
9663d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    fCurrentCmdBuffer->endRenderPass(this);
9673d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
9683d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    return;
9693d5d9ac426ea926f37eaa47e13acf7492068667begdaniel}
9703d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
971164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::onClear(GrRenderTarget* target, const SkIRect& rect, GrColor color) {
972164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // parent class should never let us get here with no RT
973164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(target);
974164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
975164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkClearColorValue vkColor;
976164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrColorToRGBAFloat(color, vkColor.float32);
9779d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
978164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(target);
979164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkImageLayout origDstLayout = vkRT->currentLayout();
980164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
981164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (rect.width() != target->width() || rect.height() != target->height()) {
982164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origDstLayout);
983164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkAccessFlags dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
984164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkPipelineStageFlags srcStageMask =
9853d5d9ac426ea926f37eaa47e13acf7492068667begdaniel            GrVkMemory::LayoutToPipelineStageFlags(origDstLayout);
986164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
987164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        vkRT->setImageLayout(this,
988164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                             VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
989164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                             srcAccessMask,
990164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                             dstAccessMask,
991164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                             srcStageMask,
992164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                             dstStageMask,
993164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                             false);
994164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
995164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkClearRect clearRect;
9963d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        // Flip rect if necessary
9973d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        SkIRect vkRect = rect;
9983d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        if (kBottomLeft_GrSurfaceOrigin == vkRT->origin()) {
9993d5d9ac426ea926f37eaa47e13acf7492068667begdaniel            vkRect.fTop = vkRT->height() - rect.fBottom;
10003d5d9ac426ea926f37eaa47e13acf7492068667begdaniel            vkRect.fBottom = vkRT->height() - rect.fTop;
10013d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        }
10023d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        clearRect.rect.offset = { vkRect.fLeft, vkRect.fTop };
10033d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        clearRect.rect.extent = { (uint32_t)vkRect.width(), (uint32_t)vkRect.height() };
1004e77875aa425d51cc8db3463343a6308f9d2aadccjvanverth        clearRect.baseArrayLayer = 0;
1005e77875aa425d51cc8db3463343a6308f9d2aadccjvanverth        clearRect.layerCount = 1;
1006164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1007164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        const GrVkRenderPass* renderPass = vkRT->simpleRenderPass();
1008164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        SkASSERT(renderPass);
1009164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        fCurrentCmdBuffer->beginRenderPass(this, renderPass, *vkRT);
1010164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1011164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        uint32_t colorIndex;
1012164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        SkAssertResult(renderPass->colorAttachmentIndex(&colorIndex));
1013164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1014164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkClearAttachment attachment;
1015164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
1016164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        attachment.colorAttachment = colorIndex;
1017164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        attachment.clearValue.color = vkColor;
1018164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1019164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        fCurrentCmdBuffer->clearAttachments(this, 1, &attachment, 1, &clearRect);
1020164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        fCurrentCmdBuffer->endRenderPass(this);
1021164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return;
1022164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1023164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1024164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkPipelineStageFlags srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(origDstLayout);
1025164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
1026164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1027164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origDstLayout);;
1028164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkAccessFlags dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
1029164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1030164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    vkRT->setImageLayout(this,
1031164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1032164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         srcAccessMask,
1033164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         dstAccessMask,
1034164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         srcStageMask,
1035164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         dstStageMask,
1036164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         false);
1037164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1038164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1039164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkImageSubresourceRange subRange;
1040164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    memset(&subRange, 0, sizeof(VkImageSubresourceRange));
1041164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    subRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
1042164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    subRange.baseMipLevel = 0;
1043164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    subRange.levelCount = 1;
1044164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    subRange.baseArrayLayer = 0;
1045164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    subRange.layerCount = 1;
1046164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
10479d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary    // In the future we may not actually be doing this type of clear at all. If we are inside a
1048164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // render pass or doing a non full clear then we will use CmdClearColorAttachment. The more
1049164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // common use case will be clearing an attachment at the start of a render pass, in which case
1050164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // we will use the clear load ops.
1051164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->clearColorImage(this,
1052164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       vkRT,
1053164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       &vkColor,
1054164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       1, &subRange);
1055164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1056164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1057164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielinline bool can_copy_image(const GrSurface* dst,
1058164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           const GrSurface* src,
1059164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           const GrVkGpu* gpu) {
1060164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (src->asTexture() &&
1061164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        dst->asTexture() &&
1062164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        src->origin() == dst->origin() &&
1063164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        src->config() == dst->config()) {
1064164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return true;
1065164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1066164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1067164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // How does msaa play into this? If a VkTexture is multisampled, are we copying the multisampled
1068164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // or the resolved image here?
1069164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1070164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return false;
1071164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1072164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1073164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::copySurfaceAsCopyImage(GrSurface* dst,
1074164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     GrSurface* src,
1075164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     const SkIRect& srcRect,
1076164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     const SkIPoint& dstPoint) {
1077164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(can_copy_image(dst, src, this));
1078164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1079164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Insert memory barriers to switch src and dst to transfer_source and transfer_dst layouts
1080164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkTexture* dstTex = static_cast<GrVkTexture*>(dst->asTexture());
1081164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkTexture* srcTex = static_cast<GrVkTexture*>(src->asTexture());
1082164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1083164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkImageLayout origDstLayout = dstTex->currentLayout();
1084164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkImageLayout origSrcLayout = srcTex->currentLayout();
1085164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1086164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkPipelineStageFlags srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(origDstLayout);
1087164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
1088164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1089164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // These flags are for flushing/invalidating caches and for the dst image it doesn't matter if
1090164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // the cache is flushed since it is only being written to.
1091164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origDstLayout);;
1092164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkAccessFlags dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
10939d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
1094164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    dstTex->setImageLayout(this,
1095164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1096164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           srcAccessMask,
1097164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           dstAccessMask,
1098164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           srcStageMask,
1099164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           dstStageMask,
1100164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           false);
11019d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
1102164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(origSrcLayout);
1103164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
1104164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1105164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origSrcLayout);
1106164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
1107164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1108164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    srcTex->setImageLayout(this,
1109164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1110164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           srcAccessMask,
1111164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           dstAccessMask,
1112164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           srcStageMask,
1113164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           dstStageMask,
1114164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           false);
1115164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1116164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Flip rect if necessary
1117164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkIRect srcVkRect = srcRect;
1118164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    int32_t dstY = dstPoint.fY;
1119164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1120164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (kBottomLeft_GrSurfaceOrigin == src->origin()) {
1121164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        SkASSERT(kBottomLeft_GrSurfaceOrigin == dst->origin());
1122164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        srcVkRect.fTop = src->height() - srcRect.fBottom;
1123164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        srcVkRect.fBottom =  src->height() - srcRect.fTop;
1124164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        dstY = dst->height() - dstPoint.fY - srcVkRect.height();
1125164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1126164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1127164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkImageCopy copyRegion;
1128164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    memset(&copyRegion, 0, sizeof(VkImageCopy));
1129164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    copyRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
1130164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    copyRegion.srcOffset = { srcVkRect.fLeft, srcVkRect.fTop, 0 };
1131164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    copyRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
1132164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    copyRegion.dstOffset = { dstPoint.fX, dstY, 0 };
1133164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    copyRegion.extent = { (uint32_t)srcVkRect.width(), (uint32_t)srcVkRect.height(), 0 };
1134164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1135164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->copyImage(this,
1136164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                 srcTex,
1137164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1138164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                 dstTex,
1139164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1140164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                 1,
1141164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                 &copyRegion);
1142164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1143164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1144164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielinline bool can_copy_as_draw(const GrSurface* dst,
1145164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                             const GrSurface* src,
1146164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                             const GrVkGpu* gpu) {
1147164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return false;
1148164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1149164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1150164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::copySurfaceAsDraw(GrSurface* dst,
1151164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                GrSurface* src,
1152164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                const SkIRect& srcRect,
1153164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                const SkIPoint& dstPoint) {
1154164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(false);
1155164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1156164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1157164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::onCopySurface(GrSurface* dst,
1158164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                            GrSurface* src,
1159164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                            const SkIRect& srcRect,
1160164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                            const SkIPoint& dstPoint) {
1161164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (can_copy_image(dst, src, this)) {
1162164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        this->copySurfaceAsCopyImage(dst, src, srcRect, dstPoint);
1163164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return true;
1164164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1165164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1166164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (can_copy_as_draw(dst, src, this)) {
1167164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        this->copySurfaceAsDraw(dst, src, srcRect, dstPoint);
1168164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return true;
1169164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1170164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1171164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return false;
1172164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1173164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
117428f45b949acc746849100fbe112ee5280f0594c9cdaltonvoid GrVkGpu::onGetMultisampleSpecs(GrRenderTarget* rt, const GrStencilSettings&,
117528f45b949acc746849100fbe112ee5280f0594c9cdalton                                    int* effectiveSampleCnt, SkAutoTDeleteArray<SkPoint>*) {
117628f45b949acc746849100fbe112ee5280f0594c9cdalton    // TODO: stub.
117728f45b949acc746849100fbe112ee5280f0594c9cdalton    SkASSERT(!this->caps()->sampleLocationsSupport());
117828f45b949acc746849100fbe112ee5280f0594c9cdalton    *effectiveSampleCnt = rt->desc().fSampleCnt;
117928f45b949acc746849100fbe112ee5280f0594c9cdalton}
118028f45b949acc746849100fbe112ee5280f0594c9cdalton
1181164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::onGetReadPixelsInfo(GrSurface* srcSurface, int width, int height, size_t rowBytes,
1182164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                  GrPixelConfig readConfig, DrawPreference* drawPreference,
1183164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                  ReadPixelTempDrawInfo* tempDrawInfo) {
1184164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Currently we don't handle draws, so if the caller wants/needs to do a draw we need to fail
1185164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (kNoDraw_DrawPreference != *drawPreference) {
1186164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
1187164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1188164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1189164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (srcSurface->config() != readConfig) {
1190164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // TODO: This should fall back to drawing or copying to change config of srcSurface to match
1191164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // that of readConfig.
1192164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
1193164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1194164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1195164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return true;
1196164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1197164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1198164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::onReadPixels(GrSurface* surface,
1199164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           int left, int top, int width, int height,
1200164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           GrPixelConfig config,
1201164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           void* buffer,
1202164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           size_t rowBytes) {
1203164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkFormat pixelFormat;
1204164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!GrPixelConfigToVkFormat(config, &pixelFormat)) {
1205164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
1206164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1207164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1208164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkTexture* tgt = static_cast<GrVkTexture*>(surface->asTexture());
1209164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!tgt) {
1210164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
1211164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1212164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1213164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Change layout of our target so it can be used as copy
1214164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkImageLayout layout = tgt->currentLayout();
1215164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkPipelineStageFlags srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(layout);
1216164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
1217164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(layout);
1218164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkAccessFlags dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
1219164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    tgt->setImageLayout(this,
1220164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                        VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1221164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                        srcAccessMask,
1222164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                        dstAccessMask,
1223164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                        srcStageMask,
1224164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                        dstStageMask,
1225164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                        false);
1226164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
12279d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary    GrVkTransferBuffer* transferBuffer =
1228397536cabe12a9936659870dd220c869789424bacdalton        static_cast<GrVkTransferBuffer*>(this->createBuffer(kXferGpuToCpu_GrBufferType,
1229397536cabe12a9936659870dd220c869789424bacdalton                                                            rowBytes * height,
1230397536cabe12a9936659870dd220c869789424bacdalton                                                            kStream_GrAccessPattern));
1231164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1232164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    bool flipY = kBottomLeft_GrSurfaceOrigin == surface->origin();
1233164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkOffset3D offset = {
1234164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        left,
1235164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        flipY ? surface->height() - top - height : top,
1236164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        0
1237164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    };
1238164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1239164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Copy the image to a buffer so we can map it to cpu memory
1240164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkBufferImageCopy region;
1241164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    memset(&region, 0, sizeof(VkBufferImageCopy));
1242164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    region.bufferOffset = 0;
1243164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    region.bufferRowLength = 0; // Forces RowLength to be imageExtent.width
1244164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    region.bufferImageHeight = 0; // Forces height to be tightly packed. Only useful for 3d images.
1245164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
1246164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    region.imageOffset = offset;
1247164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    region.imageExtent = { (uint32_t)width, (uint32_t)height, 1 };
1248164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1249164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->copyImageToBuffer(this,
1250164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                         tgt,
1251164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1252164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                         transferBuffer,
1253164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                         1,
1254164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                         &region);
1255164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1256164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // make sure the copy to buffer has finished
1257164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    transferBuffer->addMemoryBarrier(this,
1258164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     VK_ACCESS_TRANSFER_WRITE_BIT,
1259164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     VK_ACCESS_HOST_READ_BIT,
1260164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     VK_PIPELINE_STAGE_TRANSFER_BIT,
1261164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     VK_PIPELINE_STAGE_HOST_BIT,
1262164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     false);
1263164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1264164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // We need to submit the current command buffer to the Queue and make sure it finishes before
1265164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // we can copy the data out of the buffer.
1266164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    this->submitCommandBuffer(kForce_SyncQueue);
1267164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1268164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    void* mappedMemory = transferBuffer->map();
1269164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1270164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    memcpy(buffer, mappedMemory, rowBytes*height);
1271164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1272164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    transferBuffer->unmap();
1273164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    transferBuffer->unref();
1274164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1275164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (flipY) {
1276164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        SkAutoSMalloc<32 * sizeof(GrColor)> scratch;
1277164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        size_t tightRowBytes = GrBytesPerPixel(config) * width;
1278164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        scratch.reset(tightRowBytes);
1279164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        void* tmpRow = scratch.get();
1280164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // flip y in-place by rows
1281164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        const int halfY = height >> 1;
1282164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        char* top = reinterpret_cast<char*>(buffer);
1283164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        char* bottom = top + (height - 1) * rowBytes;
1284164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        for (int y = 0; y < halfY; y++) {
1285164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            memcpy(tmpRow, top, tightRowBytes);
1286164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            memcpy(top, bottom, tightRowBytes);
1287164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            memcpy(bottom, tmpRow, tightRowBytes);
1288164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            top += rowBytes;
1289164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            bottom -= rowBytes;
1290164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
1291164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1292164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1293164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return true;
1294164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1295af132770a9462f6bb9cff47254e44675d9241fe8egdanielsk_sp<GrVkPipelineState> GrVkGpu::prepareDrawState(const GrPipeline& pipeline,
1296af132770a9462f6bb9cff47254e44675d9241fe8egdaniel                                                   const GrPrimitiveProcessor& primProc,
1297af132770a9462f6bb9cff47254e44675d9241fe8egdaniel                                                   GrPrimitiveType primitiveType,
1298af132770a9462f6bb9cff47254e44675d9241fe8egdaniel                                                   const GrVkRenderPass& renderPass) {
1299af132770a9462f6bb9cff47254e44675d9241fe8egdaniel    sk_sp<GrVkPipelineState> pipelineState =
1300af132770a9462f6bb9cff47254e44675d9241fe8egdaniel        fResourceProvider.findOrCreateCompatiblePipelineState(pipeline,
1301af132770a9462f6bb9cff47254e44675d9241fe8egdaniel                                                              primProc,
1302af132770a9462f6bb9cff47254e44675d9241fe8egdaniel                                                              primitiveType,
1303af132770a9462f6bb9cff47254e44675d9241fe8egdaniel                                                              renderPass);
130422281c13a13c4b4e275516e9fe02185a53a7e5aaegdaniel    if (!pipelineState) {
1305af132770a9462f6bb9cff47254e44675d9241fe8egdaniel        return pipelineState;
1306164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1307164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1308af132770a9462f6bb9cff47254e44675d9241fe8egdaniel    pipelineState->setData(this, primProc, pipeline);
1309164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1310af132770a9462f6bb9cff47254e44675d9241fe8egdaniel    pipelineState->bind(this, fCurrentCmdBuffer);
1311470d77a1d7dc286cdad98b145dac735cd7638e56egdaniel
1312470d77a1d7dc286cdad98b145dac735cd7638e56egdaniel    GrVkPipeline::SetDynamicState(this, fCurrentCmdBuffer, pipeline);
1313470d77a1d7dc286cdad98b145dac735cd7638e56egdaniel
1314af132770a9462f6bb9cff47254e44675d9241fe8egdaniel    return pipelineState;
13150e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel}
1316164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
13170e1853c89615d14d0d03c87c7e0c604e5285cc54egdanielvoid GrVkGpu::onDraw(const GrPipeline& pipeline,
13180e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                     const GrPrimitiveProcessor& primProc,
13190e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                     const GrMesh* meshes,
13200e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                     int meshCount) {
13210e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel    if (!meshCount) {
13220e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel        return;
13230e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel    }
13240e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel    GrRenderTarget* rt = pipeline.getRenderTarget();
13250e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel    GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(rt);
13260e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel    const GrVkRenderPass* renderPass = vkRT->simpleRenderPass();
13270e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel    SkASSERT(renderPass);
1328164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1329470d77a1d7dc286cdad98b145dac735cd7638e56egdaniel    fCurrentCmdBuffer->beginRenderPass(this, renderPass, *vkRT);
1330470d77a1d7dc286cdad98b145dac735cd7638e56egdaniel
13310e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel    GrPrimitiveType primitiveType = meshes[0].primitiveType();
1332af132770a9462f6bb9cff47254e44675d9241fe8egdaniel    sk_sp<GrVkPipelineState> pipelineState = this->prepareDrawState(pipeline,
1333af132770a9462f6bb9cff47254e44675d9241fe8egdaniel                                                                    primProc,
1334af132770a9462f6bb9cff47254e44675d9241fe8egdaniel                                                                    primitiveType,
1335af132770a9462f6bb9cff47254e44675d9241fe8egdaniel                                                                    *renderPass);
1336af132770a9462f6bb9cff47254e44675d9241fe8egdaniel    if (!pipelineState) {
13370e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel        return;
13380e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel    }
1339164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1340164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Change layout of our render target so it can be used as the color attachment
1341164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkImageLayout layout = vkRT->currentLayout();
1342164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Our color attachment is purely a destination and won't be read so don't need to flush or
1343164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // invalidate any caches
1344164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkPipelineStageFlags srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(layout);
1345164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1346164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(layout);
1347164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkAccessFlags dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
1348164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    vkRT->setImageLayout(this,
1349164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1350164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         srcAccessMask,
1351164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         dstAccessMask,
1352164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         srcStageMask,
1353164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         dstStageMask,
1354164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         false);
1355164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
13563d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    // If we are using a stencil attachment we also need to update its layout
13570e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel    if (!pipeline.getStencil().isDisabled()) {
13583d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        GrStencilAttachment* stencil = vkRT->renderTargetPriv().getStencilAttachment();
13593d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        GrVkStencilAttachment* vkStencil = (GrVkStencilAttachment*)stencil;
13603d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        VkImageLayout origDstLayout = vkStencil->currentLayout();
13613d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origDstLayout);
13623d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        VkAccessFlags dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
13630e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel            VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
13643d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        VkPipelineStageFlags srcStageMask =
13653d5d9ac426ea926f37eaa47e13acf7492068667begdaniel            GrVkMemory::LayoutToPipelineStageFlags(origDstLayout);
13663d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
13673d5d9ac426ea926f37eaa47e13acf7492068667begdaniel        vkStencil->setImageLayout(this,
13683d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                                  VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
13693d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                                  srcAccessMask,
13703d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                                  dstAccessMask,
13713d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                                  srcStageMask,
13723d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                                  dstStageMask,
13733d5d9ac426ea926f37eaa47e13acf7492068667begdaniel                                  false);
13743d5d9ac426ea926f37eaa47e13acf7492068667begdaniel    }
13753d5d9ac426ea926f37eaa47e13acf7492068667begdaniel
13760e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel
13770e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel    for (int i = 0; i < meshCount; ++i) {
13780e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel        if (GrXferBarrierType barrierType = pipeline.xferBarrierType(*this->caps())) {
13790e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel            this->xferBarrier(pipeline.getRenderTarget(), barrierType);
13800e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel        }
13810e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel
13820e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel        const GrMesh& mesh = meshes[i];
13830e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel        GrMesh::Iterator iter;
13840e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel        const GrNonInstancedMesh* nonIdxMesh = iter.init(mesh);
13850e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel        do {
13860e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel            if (nonIdxMesh->primitiveType() != primitiveType) {
13870e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                // Technically we don't have to call this here (since there is a safety check in
138822281c13a13c4b4e275516e9fe02185a53a7e5aaegdaniel                // pipelineState:setData but this will allow for quicker freeing of resources if the
138922281c13a13c4b4e275516e9fe02185a53a7e5aaegdaniel                // pipelineState sits in a cache for a while.
139022281c13a13c4b4e275516e9fe02185a53a7e5aaegdaniel                pipelineState->freeTempResources(this);
139122281c13a13c4b4e275516e9fe02185a53a7e5aaegdaniel                SkDEBUGCODE(pipelineState = nullptr);
13920e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                primitiveType = nonIdxMesh->primitiveType();
1393af132770a9462f6bb9cff47254e44675d9241fe8egdaniel                pipelineState = this->prepareDrawState(pipeline,
1394af132770a9462f6bb9cff47254e44675d9241fe8egdaniel                                                       primProc,
1395af132770a9462f6bb9cff47254e44675d9241fe8egdaniel                                                       primitiveType,
1396af132770a9462f6bb9cff47254e44675d9241fe8egdaniel                                                       *renderPass);
1397af132770a9462f6bb9cff47254e44675d9241fe8egdaniel                if (!pipelineState) {
13980e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                    return;
13990e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                }
14000e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel            }
140122281c13a13c4b4e275516e9fe02185a53a7e5aaegdaniel            SkASSERT(pipelineState);
14020e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel            this->bindGeometry(primProc, *nonIdxMesh);
14030e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel
14040e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel            if (nonIdxMesh->isIndexed()) {
14050e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                fCurrentCmdBuffer->drawIndexed(this,
14060e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                                               nonIdxMesh->indexCount(),
14070e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                                               1,
14080e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                                               nonIdxMesh->startIndex(),
14090e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                                               nonIdxMesh->startVertex(),
14100e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                                               0);
14110e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel            } else {
14120e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                fCurrentCmdBuffer->draw(this,
14130e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                                        nonIdxMesh->vertexCount(),
14140e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                                        1,
14150e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                                        nonIdxMesh->startVertex(),
14160e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel                                        0);
14170e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel            }
14180e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel
14190e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel            fStats.incNumDraws();
14200e1853c89615d14d0d03c87c7e0c604e5285cc54egdaniel        } while ((nonIdxMesh = iter.next()));
1421164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1422164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1423164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->endRenderPass(this);
1424164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
142522281c13a13c4b4e275516e9fe02185a53a7e5aaegdaniel    // Technically we don't have to call this here (since there is a safety check in
142622281c13a13c4b4e275516e9fe02185a53a7e5aaegdaniel    // pipelineState:setData but this will allow for quicker freeing of resources if the
142722281c13a13c4b4e275516e9fe02185a53a7e5aaegdaniel    // pipelineState sits in a cache for a while.
142822281c13a13c4b4e275516e9fe02185a53a7e5aaegdaniel    pipelineState->freeTempResources(this);
1429164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1430164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#if SWAP_PER_DRAW
1431164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    glFlush();
1432164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#if defined(SK_BUILD_FOR_MAC)
1433164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    aglSwapBuffers(aglGetCurrentContext());
1434164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    int set_a_break_pt_here = 9;
1435164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    aglSwapBuffers(aglGetCurrentContext());
1436164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#elif defined(SK_BUILD_FOR_WIN32)
1437164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SwapBuf();
1438164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    int set_a_break_pt_here = 9;
1439164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SwapBuf();
1440164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#endif
1441164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#endif
1442164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1443