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"
13164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrPipeline.h"
14164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrRenderTargetPriv.h"
15164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrSurfacePriv.h"
16164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrTexturePriv.h"
17164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVertices.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"
24164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkProgram.h"
25164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkProgramBuilder.h"
26164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkProgramDesc.h"
27164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkRenderPass.h"
28164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkResourceProvider.h"
29164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkTexture.h"
30164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkTextureRenderTarget.h"
31164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkTransferBuffer.h"
32164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkVertexBuffer.h"
33164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
34164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "SkConfig8888.h"
35164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
36164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "vk/GrVkInterface.h"
37164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
38164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#define VK_CALL(X) GR_VK_CALL(this->vkInterface(), X)
39164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#define VK_CALL_RET(RET, X) GR_VK_CALL_RET(this->vkInterface(), RET, X)
40164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#define VK_CALL_ERRCHECK(X) GR_VK_CALL_ERRCHECK(this->vkInterface(), X)
41164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
42164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
43164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel// Stuff used to set up a GrVkGpu secrectly for now.
44164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
45164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel// For now the VkGpuCreate is using the same signature as GL. This is mostly for ease of
46164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel// hiding this code from offical skia. In the end the VkGpuCreate will not take a GrBackendContext
47164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel// and mostly likely would take an optional device and queues to use.
48164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielGrGpu* vk_gpu_create(GrBackendContext backendContext, const GrContextOptions& options,
49164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                     GrContext* context) {
50164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Below is Vulkan setup code that normal would be done by a client, but will do here for now
51164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // for testing purposes.
52164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkPhysicalDevice physDev;
53164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkDevice device;
54164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkInstance inst;
55164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkResult err;
56164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
57164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    const VkApplicationInfo app_info = {
58164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VK_STRUCTURE_TYPE_APPLICATION_INFO, // sType
59164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        nullptr,                            // pNext
60164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        "vktest",                           // pApplicationName
61164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        0,                                  // applicationVersion
62164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        "vktest",                           // pEngineName
63164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        0,                                  // engineVerison
64164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VK_API_VERSION,                     // apiVersion
65164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    };
66164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    const VkInstanceCreateInfo instance_create = {
67164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, // sType
68164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        nullptr,                                // pNext
69164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        0,                                      // flags
70164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        &app_info,                              // pApplicationInfo
71164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        0,                                      // enabledLayerNameCount
72164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        nullptr,                                // ppEnabledLayerNames
73164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        0,                                      // enabledExtensionNameCount
74164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        nullptr,                                // ppEnabledExtensionNames
75164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    };
76164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    err = vkCreateInstance(&instance_create, nullptr, &inst);
77164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (err < 0) {
78164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        SkDebugf("vkCreateInstanced failed: %d\n", err);
79164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        SkFAIL("failing");
80164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
81164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
82164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    uint32_t gpuCount;
83164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    err = vkEnumeratePhysicalDevices(inst, &gpuCount, nullptr);
84164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (err) {
85164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        SkDebugf("vkEnumeratePhysicalDevices failed: %d\n", err);
86164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        SkFAIL("failing");
87164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
88164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(gpuCount > 0);
89164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Just returning the first physical device instead of getting the whole array.
90164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    gpuCount = 1;
91164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    err = vkEnumeratePhysicalDevices(inst, &gpuCount, &physDev);
92164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (err) {
93164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        SkDebugf("vkEnumeratePhysicalDevices failed: %d\n", err);
94164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        SkFAIL("failing");
95164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
96164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
97164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // query to get the initial queue props size
98164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    uint32_t queueCount;
99164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    vkGetPhysicalDeviceQueueFamilyProperties(physDev, &queueCount, nullptr);
100164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(queueCount >= 1);
101164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
102164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkAutoMalloc queuePropsAlloc(queueCount * sizeof(VkQueueFamilyProperties));
103164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // now get the actual queue props
104164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkQueueFamilyProperties* queueProps = (VkQueueFamilyProperties*)queuePropsAlloc.get();
105164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
106164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    vkGetPhysicalDeviceQueueFamilyProperties(physDev, &queueCount, queueProps);
107164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
108164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // iterate to find the graphics queue
109164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    uint32_t graphicsQueueIndex = -1;
110164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    for (uint32_t i = 0; i < queueCount; i++) {
111164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        if (queueProps[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
112164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            graphicsQueueIndex = i;
113164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            break;
114164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
115164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
116164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(graphicsQueueIndex < queueCount);
117164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
118164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    float queuePriorities[1] = { 0.0 };
119164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    const VkDeviceQueueCreateInfo queueInfo = {
120164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType
121164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        nullptr,                                    // pNext
122164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        0,                                          // VkDeviceQueueCreateFlags
123164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        0,                                          // queueFamilyIndex
124164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        1,                                          // queueCount
125164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        queuePriorities,                            // pQueuePriorities
126164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    };
127164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    const VkDeviceCreateInfo deviceInfo = {
128164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,  // sType
129164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        nullptr,                               // pNext
130164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        0,                                     // VkDeviceCreateFlags
131164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        1,                                     // queueCreateInfoCount
132164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        &queueInfo,                            // pQueueCreateInfos
133164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        0,                                     // layerCount
134164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        nullptr,                               // ppEnabledLayerNames
135164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        0,                                     // extensionCount
136164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        nullptr,                               // ppEnabledExtensionNames
137164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        nullptr                                // ppEnabledFeatures
138164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    };
139164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
140164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    err = vkCreateDevice(physDev, &deviceInfo, nullptr, &device);
141164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (err) {
142164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        SkDebugf("CreateDevice failed: %d\n", err);
143164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        SkFAIL("failing");
144164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
145164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
146164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkQueue queue;
147164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    vkGetDeviceQueue(device, graphicsQueueIndex, 0, &queue);
148164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
149164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    const VkCommandPoolCreateInfo cmdPoolInfo = {
150164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // sType
151164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        nullptr,                                    // pNext
152164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        0,                                          // CmdPoolCreateFlags
153164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        graphicsQueueIndex,                         // queueFamilyIndex
154164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    };
155164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
156164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkCommandPool cmdPool;
157164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    err = vkCreateCommandPool(device, &cmdPoolInfo, nullptr, &cmdPool);
158164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (err) {
159164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        SkDebugf("CreateCommandPool failed: %d\n", err);
160164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        SkFAIL("failing");
161164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
162164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
163164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return new GrVkGpu(context, options, physDev, device, queue, cmdPool, inst);
164164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
165164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
166164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
167164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
168164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielGrVkGpu::GrVkGpu(GrContext* context, const GrContextOptions& options,
169164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                 VkPhysicalDevice physDev, VkDevice device, VkQueue queue, VkCommandPool cmdPool,
170164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                 VkInstance inst)
171164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    : INHERITED(context)
172164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    , fDevice(device)
173164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    , fQueue(queue)
174164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    , fCmdPool(cmdPool)
175164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    , fResourceProvider(this)
176164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    , fVkInstance(inst) {
177164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fInterface.reset(GrVkCreateInterface(fVkInstance));
178164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCompiler = shaderc_compiler_initialize();
179164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
180164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fVkCaps.reset(new GrVkCaps(options, fInterface, physDev));
181164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCaps.reset(SkRef(fVkCaps.get()));
182164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
183164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer = fResourceProvider.createCommandBuffer();
184164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(fCurrentCmdBuffer);
185164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->begin(this);
186164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VK_CALL(GetPhysicalDeviceMemoryProperties(physDev, &fPhysDevMemProps));
187164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
188164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
189164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
190164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielGrVkGpu::~GrVkGpu() {
191164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    shaderc_compiler_release(fCompiler);
192164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->end(this);
193164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->unref(this);
194164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
195164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // wait for all commands to finish
196164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VK_CALL(QueueWaitIdle(fQueue));
197164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
198164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // must call this just before we destroy the VkDevice
199164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fResourceProvider.destroyResources();
200164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
201164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VK_CALL(DestroyCommandPool(fDevice, fCmdPool, nullptr));
202164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VK_CALL(DestroyDevice(fDevice, nullptr));
203164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VK_CALL(DestroyInstance(fVkInstance, nullptr));
204164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
205164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
206164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel///////////////////////////////////////////////////////////////////////////////
207164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
208164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::submitCommandBuffer(SyncQueue sync) {
209164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(fCurrentCmdBuffer);
210164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->end(this);
211164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
212164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->submitToQueue(this, fQueue, sync);
213164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fResourceProvider.checkCommandBuffers();
214164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
215164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Release old command buffer and create a new one
216164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->unref(this);
217164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer = fResourceProvider.createCommandBuffer();
218164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(fCurrentCmdBuffer);
219164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
220164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->begin(this);
221164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
222164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
223164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel///////////////////////////////////////////////////////////////////////////////
224164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielGrVertexBuffer* GrVkGpu::onCreateVertexBuffer(size_t size, bool dynamic) {
225164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return GrVkVertexBuffer::Create(this, size, dynamic);
226164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
227164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
228164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielGrIndexBuffer* GrVkGpu::onCreateIndexBuffer(size_t size, bool dynamic) {
229164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return GrVkIndexBuffer::Create(this, size, dynamic);
230164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
231164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
232164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielGrTransferBuffer* GrVkGpu::onCreateTransferBuffer(size_t size, TransferType type) {
233164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkBuffer::Type bufferType = kCpuToGpu_TransferType ? GrVkBuffer::kCopyRead_Type
234164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                         : GrVkBuffer::kCopyWrite_Type;
235164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return GrVkTransferBuffer::Create(this, size, bufferType);
236164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
237164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
238164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
239164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::onGetWritePixelsInfo(GrSurface* dstSurface, int width, int height,
240164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                   GrPixelConfig srcConfig, DrawPreference* drawPreference,
241164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                   WritePixelTempDrawInfo* tempDrawInfo) {
242164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (kIndex_8_GrPixelConfig == srcConfig || GrPixelConfigIsCompressed(dstSurface->config())) {
243164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
244164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
245164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
246164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Currently we don't handle draws, so if the caller wants/needs to do a draw we need to fail
247164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (kNoDraw_DrawPreference != *drawPreference) {
248164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
249164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
250164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
251164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (dstSurface->config() != srcConfig) {
252164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // TODO: This should fall back to drawing or copying to change config of dstSurface to
253164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // match that of srcConfig.
254164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
255164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
256164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
257164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return true;
258164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
259164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
260164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::onWritePixels(GrSurface* surface,
261164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                            int left, int top, int width, int height,
262164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                            GrPixelConfig config, const void* buffer,
263164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                            size_t rowBytes) {
264164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkTexture* vkTex = static_cast<GrVkTexture*>(surface->asTexture());
265164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!vkTex) {
266164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
267164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
268164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
269164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // We assume Vulkan doesn't do sRGB <-> linear conversions when reading and writing pixels.
270164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (GrPixelConfigIsSRGB(surface->config()) != GrPixelConfigIsSRGB(config)) {
271164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
272164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
273164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
274164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    bool success = false;
275164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (GrPixelConfigIsCompressed(vkTex->desc().fConfig)) {
276164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // We check that config == desc.fConfig in GrGpu::getWritePixelsInfo()
277164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        SkASSERT(config == vkTex->desc().fConfig);
278164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // TODO: add compressed texture support
279164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // delete the following two lines and uncomment the two after that when ready
280164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        vkTex->unref();
281164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
282164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        //success = this->uploadCompressedTexData(vkTex->desc(), buffer, false, left, top, width,
283164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        //                                       height);
284164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    } else {
285164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        bool linearTiling = vkTex->isLinearTiled();
286164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        if (linearTiling && VK_IMAGE_LAYOUT_PREINITIALIZED != vkTex->currentLayout()) {
287164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            // Need to change the layout to general in order to perform a host write
288164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            VkImageLayout layout = vkTex->currentLayout();
289164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            VkPipelineStageFlags srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(layout);
290164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_HOST_BIT;
291164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(layout);
292164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            VkAccessFlags dstAccessMask = VK_ACCESS_HOST_WRITE_BIT;
293164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            vkTex->setImageLayout(this,
294164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                  VK_IMAGE_LAYOUT_GENERAL,
295164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                  srcAccessMask,
296164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                  dstAccessMask,
297164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                  srcStageMask,
298164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                  dstStageMask,
299164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                  false);
300164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
301164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        success = this->uploadTexData(vkTex, left, top, width, height, config,
302164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                      buffer, rowBytes);
303164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
304164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
305164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (success) {
306164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        vkTex->texturePriv().dirtyMipMaps(true);
307164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return true;
308164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
309164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
310164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return false;
311164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
312164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
313164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::uploadTexData(GrVkTexture* tex,
314164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                            int left, int top, int width, int height,
315164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                            GrPixelConfig dataConfig,
316164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                            const void* data,
317164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                            size_t rowBytes) {
318164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(data);
319164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
320164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // If we're uploading compressed data then we should be using uploadCompressedTexData
321164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(!GrPixelConfigIsCompressed(dataConfig));
322164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
323164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    bool linearTiling = tex->isLinearTiled();
324164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
325164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    size_t bpp = GrBytesPerPixel(dataConfig);
326164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
327164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    const GrSurfaceDesc& desc = tex->desc();
328164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
329164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!GrSurfacePriv::AdjustWritePixelParams(desc.fWidth, desc.fHeight, bpp, &left, &top,
330164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                               &width, &height, &data, &rowBytes)) {
331164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
332164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
333164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    size_t trimRowBytes = width * bpp;
334164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
335164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (linearTiling) {
336164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        SkASSERT(VK_IMAGE_LAYOUT_PREINITIALIZED == tex->currentLayout() ||
337164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                 VK_IMAGE_LAYOUT_GENERAL == tex->currentLayout());
338164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        const VkImageSubresource subres = {
339164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            VK_IMAGE_ASPECT_COLOR_BIT,
340164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            0,  // mipLevel
341164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            0,  // arraySlice
342164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        };
343164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkSubresourceLayout layout;
344164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkResult err;
345164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
346164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        const GrVkInterface* interface = this->vkInterface();
347164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
348164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        GR_VK_CALL(interface, GetImageSubresourceLayout(fDevice,
349164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                        tex->textureImage(),
350164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                        &subres,
351164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                        &layout));
352164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
353164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        int texTop = kBottomLeft_GrSurfaceOrigin == desc.fOrigin ? tex->height() - top - height
354164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                    : top;
355164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkDeviceSize offset = texTop*layout.rowPitch + left*bpp;
356164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkDeviceSize size = height*layout.rowPitch;
357164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        void* mapPtr;
358164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        err = GR_VK_CALL(interface, MapMemory(fDevice, tex->textureMemory(), offset, size, 0,
359164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                &mapPtr));
360164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        if (err) {
361164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            return false;
362164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
363164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
364164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        if (kBottomLeft_GrSurfaceOrigin == desc.fOrigin) {
365164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            // copy into buffer by rows
366164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            const char* srcRow = reinterpret_cast<const char*>(data);
367164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            char* dstRow = reinterpret_cast<char*>(mapPtr)+(height - 1)*layout.rowPitch;
368164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            for (int y = 0; y < height; y++) {
369164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                memcpy(dstRow, srcRow, trimRowBytes);
370164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                srcRow += rowBytes;
371164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                dstRow -= layout.rowPitch;
372164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            }
373164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        } else {
374164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            // If there is no padding on the src (rowBytes) or dst (layout.rowPitch) we can memcpy
375164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            if (trimRowBytes == rowBytes && trimRowBytes == layout.rowPitch) {
376164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                memcpy(mapPtr, data, trimRowBytes * height);
377164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            } else {
378164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                SkRectMemcpy(mapPtr, layout.rowPitch, data, rowBytes, trimRowBytes, height);
379164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            }
380164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
381164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
382164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        GR_VK_CALL(interface, UnmapMemory(fDevice, tex->textureMemory()));
383164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    } else {
384164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        GrVkTransferBuffer* transferBuffer =
385164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            GrVkTransferBuffer::Create(this, trimRowBytes * height, GrVkBuffer::kCopyRead_Type);
386164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
387164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        void* mapPtr = transferBuffer->map();
388164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
389164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        if (kBottomLeft_GrSurfaceOrigin == desc.fOrigin) {
390164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            // copy into buffer by rows
391164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            const char* srcRow = reinterpret_cast<const char*>(data);
392164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            char* dstRow = reinterpret_cast<char*>(mapPtr)+(height - 1)*trimRowBytes;
393164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            for (int y = 0; y < height; y++) {
394164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                memcpy(dstRow, srcRow, trimRowBytes);
395164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                srcRow += rowBytes;
396164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                dstRow -= trimRowBytes;
397164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            }
398164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        } else {
399164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            // If there is no padding on the src data rows, we can do a single memcpy
400164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            if (trimRowBytes == rowBytes) {
401164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                memcpy(mapPtr, data, trimRowBytes * height);
402164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            } else {
403164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                SkRectMemcpy(mapPtr, trimRowBytes, data, rowBytes, trimRowBytes, height);
404164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            }
405164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
406164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
407164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        transferBuffer->unmap();
408164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
409164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // make sure the unmap has finished
410164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        transferBuffer->addMemoryBarrier(this,
411164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                         VK_ACCESS_HOST_WRITE_BIT,
412164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                         VK_ACCESS_TRANSFER_READ_BIT,
413164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                         VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
414164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                         VK_PIPELINE_STAGE_TRANSFER_BIT,
415164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                         false);
416164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
417164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // Set up copy region
418164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        bool flipY = kBottomLeft_GrSurfaceOrigin == tex->origin();
419164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkOffset3D offset = {
420164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            left,
421164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            flipY ? tex->height() - top - height : top,
422164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            0
423164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        };
424164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
425164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkBufferImageCopy region;
426164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        memset(&region, 0, sizeof(VkBufferImageCopy));
427164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        region.bufferOffset = 0;
428164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        region.bufferRowLength = width;
429164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        region.bufferImageHeight = height;
430164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
431164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        region.imageOffset = offset;
432164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        region.imageExtent = { (uint32_t)width, (uint32_t)height, 1 };
433164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
434164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // Change layout of our target so it can be copied to
435164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkImageLayout layout = tex->currentLayout();
436164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkPipelineStageFlags srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(layout);
437164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
438164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(layout);
439164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkAccessFlags dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
440164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        tex->setImageLayout(this,
441164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                            VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
442164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                            srcAccessMask,
443164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                            dstAccessMask,
444164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                            srcStageMask,
445164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                            dstStageMask,
446164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                            false);
447164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
448164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // Copy the buffer to the image
449164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        fCurrentCmdBuffer->copyBufferToImage(this,
450164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                             transferBuffer,
451164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                             tex,
452164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                             VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
453164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                             1,
454164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                             &region);
455164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
456164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // Submit the current command buffer to the Queue
457164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        this->submitCommandBuffer(kSkip_SyncQueue);
458164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
459164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        transferBuffer->unref();
460164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
461164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
462164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return true;
463164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
464164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
465164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
466164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielGrTexture* GrVkGpu::onCreateTexture(const GrSurfaceDesc& desc, GrGpuResource::LifeCycle lifeCycle,
467164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                    const void* srcData, size_t rowBytes) {
468164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag);
469164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
470164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkFormat pixelFormat;
471164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!GrPixelConfigToVkFormat(desc.fConfig, &pixelFormat)) {
472164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return nullptr;
473164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
474164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
475164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!fVkCaps->isConfigTexturable(desc.fConfig)) {
476164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return nullptr;
477164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
478164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
479164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    bool linearTiling = false;
480164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (SkToBool(desc.fFlags & kZeroCopy_GrSurfaceFlag)) {
481164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        if (fVkCaps->isConfigTexurableLinearly(desc.fConfig) &&
482164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            (!renderTarget || fVkCaps->isConfigRenderableLinearly(desc.fConfig, false))) {
483164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            linearTiling = true;
484164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        } else {
485164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            return nullptr;
486164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
487164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
488164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
489164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT;
490164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (renderTarget) {
491164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        usageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
492164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
493164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
494164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // For now we will set the VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT and
495164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // VK_IMAGE_USAGE_TRANSFER_SOURCE_BIT on every texture since we do not know whether or not we
496164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // will be using this texture in some copy or not. Also this assumes, as is the current case,
497164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // that all render targets in vulkan are also texutres. If we change this practice of setting
498164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // both bits, we must make sure to set the destination bit if we are uploading srcData to the
499164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // texture.
500164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    usageFlags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
501164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
502164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkFlags memProps = (srcData && linearTiling) ? VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT :
503164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                   VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
504164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
505164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // This ImageDesc refers to the texture that will be read by the client. Thus even if msaa is
506164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // requested, this ImageDesc describes the resolved texutre. Therefore we always have samples set
507164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // to 1.
508164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkImage::ImageDesc imageDesc;
509164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fImageType = VK_IMAGE_TYPE_2D;
510164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fFormat = pixelFormat;
511164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fWidth = desc.fWidth;
512164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fHeight = desc.fHeight;
513164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fLevels = 1;
514164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fSamples = 1;
515164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fImageTiling = linearTiling ? VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL;
516164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fUsageFlags = usageFlags;
517164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fMemProps = memProps;
518164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
519164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkTexture* tex;
520164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (renderTarget) {
521164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        tex = GrVkTextureRenderTarget::CreateNewTextureRenderTarget(this, desc, lifeCycle,
522164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                    imageDesc);
523164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    } else {
524164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        tex = GrVkTexture::CreateNewTexture(this, desc, lifeCycle, imageDesc);
525164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
526164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
527164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!tex) {
528164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return nullptr;
529164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
530164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
531164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (srcData) {
532164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        if (!this->uploadTexData(tex, 0, 0, desc.fWidth, desc.fHeight, desc.fConfig, srcData,
533164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                 rowBytes)) {
534164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            tex->unref();
535164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            return nullptr;
536164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
537164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
538164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
539164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return tex;
540164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
541164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
542164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
543164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
544164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielstatic GrSurfaceOrigin resolve_origin(GrSurfaceOrigin origin) {
545164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // By default, all textures in Vk use TopLeft
546164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (kDefault_GrSurfaceOrigin == origin) {
547164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return kTopLeft_GrSurfaceOrigin;
548164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    } else {
549164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return origin;
550164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
551164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
552164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
553164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielGrTexture* GrVkGpu::onWrapBackendTexture(const GrBackendTextureDesc& desc,
554164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                         GrWrapOwnership ownership) {
555164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkFormat format;
556164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!GrPixelConfigToVkFormat(desc.fConfig, &format)) {
557164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return nullptr;
558164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
559164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
560164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (0 == desc.fTextureHandle) {
561164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return nullptr;
562164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
563164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
564164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    int maxSize = this->caps()->maxTextureSize();
565164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (desc.fWidth > maxSize || desc.fHeight > maxSize) {
566164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return nullptr;
567164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
568164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
569164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // TODO: determine what format Chrome will actually send us and turn it into a Resource
570164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkImage::Resource* imageRsrc = reinterpret_cast<GrVkImage::Resource*>(desc.fTextureHandle);
571164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
572164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrGpuResource::LifeCycle lifeCycle;
573164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    switch (ownership) {
574164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        case kAdopt_GrWrapOwnership:
575164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            lifeCycle = GrGpuResource::kAdopted_LifeCycle;
576164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            break;
577164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        case kBorrow_GrWrapOwnership:
578164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            lifeCycle = GrGpuResource::kBorrowed_LifeCycle;
579164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            break;
580164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
581164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
582164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrSurfaceDesc surfDesc;
583164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // next line relies on GrBackendTextureDesc's flags matching GrTexture's
584164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    surfDesc.fFlags = (GrSurfaceFlags)desc.fFlags;
585164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    surfDesc.fWidth = desc.fWidth;
586164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    surfDesc.fHeight = desc.fHeight;
587164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    surfDesc.fConfig = desc.fConfig;
588164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    surfDesc.fSampleCnt = SkTMin(desc.fSampleCnt, this->caps()->maxSampleCount());
589164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrBackendTextureFlag);
590164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // In GL, Chrome assumes all textures are BottomLeft
591164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // In VK, we don't have this restriction
592164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    surfDesc.fOrigin = resolve_origin(desc.fOrigin);
593164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
594164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkTexture* texture = nullptr;
595164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (renderTarget) {
596164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        texture = GrVkTextureRenderTarget::CreateWrappedTextureRenderTarget(this, surfDesc,
597164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                            lifeCycle, format,
598164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                            imageRsrc);
599164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    } else {
600164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        texture = GrVkTexture::CreateWrappedTexture(this, surfDesc, lifeCycle, format, imageRsrc);
601164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
602164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!texture) {
603164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return nullptr;
604164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
605164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
606164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return texture;
607164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
608164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
609164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielGrRenderTarget* GrVkGpu::onWrapBackendRenderTarget(const GrBackendRenderTargetDesc& wrapDesc,
610164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                   GrWrapOwnership ownership) {
611164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
612164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // TODO: determine what format Chrome will actually send us and turn it into a Resource
613164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkImage::Resource* imageRsrc =
614164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        reinterpret_cast<GrVkImage::Resource*>(wrapDesc.fRenderTargetHandle);
615164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
616164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrGpuResource::LifeCycle lifeCycle;
617164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    switch (ownership) {
618164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        case kAdopt_GrWrapOwnership:
619164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            lifeCycle = GrGpuResource::kAdopted_LifeCycle;
620164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            break;
621164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        case kBorrow_GrWrapOwnership:
622164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            lifeCycle = GrGpuResource::kBorrowed_LifeCycle;
623164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            break;
624164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
625164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
626164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrSurfaceDesc desc;
627164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    desc.fConfig = wrapDesc.fConfig;
628164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    desc.fFlags = kCheckAllocation_GrSurfaceFlag;
629164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    desc.fWidth = wrapDesc.fWidth;
630164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    desc.fHeight = wrapDesc.fHeight;
631164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    desc.fSampleCnt = SkTMin(wrapDesc.fSampleCnt, this->caps()->maxSampleCount());
632164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
633164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    desc.fOrigin = resolve_origin(wrapDesc.fOrigin);
634164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
635164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkRenderTarget* tgt = GrVkRenderTarget::CreateWrappedRenderTarget(this, desc,
636164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                        lifeCycle, imageRsrc);
637164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (tgt && wrapDesc.fStencilBits) {
638164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        if (!createStencilAttachmentForRenderTarget(tgt, desc.fWidth, desc.fHeight)) {
639164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            tgt->unref();
640164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            return nullptr;
641164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
642164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
643164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return tgt;
644164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
645164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
646164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
647164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
648164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::bindGeometry(const GrPrimitiveProcessor& primProc,
649164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           const GrNonInstancedVertices& vertices) {
650164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkVertexBuffer* vbuf;
651164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    vbuf = (GrVkVertexBuffer*)vertices.vertexBuffer();
652164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(vbuf);
653164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(!vbuf->isMapped());
654164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
655164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    vbuf->addMemoryBarrier(this,
656164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           VK_ACCESS_HOST_WRITE_BIT,
657164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT,
658164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           VK_PIPELINE_STAGE_HOST_BIT,
659164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           VK_PIPELINE_STAGE_VERTEX_INPUT_BIT,
660164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           false);
661164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
662164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->bindVertexBuffer(this, vbuf);
663164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
664164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (vertices.isIndexed()) {
665164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        GrVkIndexBuffer* ibuf = (GrVkIndexBuffer*)vertices.indexBuffer();
666164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        SkASSERT(ibuf);
667164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        SkASSERT(!ibuf->isMapped());
668164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
669164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        ibuf->addMemoryBarrier(this,
670164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                               VK_ACCESS_HOST_WRITE_BIT,
671164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                               VK_ACCESS_INDEX_READ_BIT,
672164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                               VK_PIPELINE_STAGE_HOST_BIT,
673164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                               VK_PIPELINE_STAGE_VERTEX_INPUT_BIT,
674164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                               false);
675164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
676164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        fCurrentCmdBuffer->bindIndexBuffer(this, ibuf);
677164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
678164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
679164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
680164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::buildProgramDesc(GrProgramDesc* desc,
681164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                               const GrPrimitiveProcessor& primProc,
682164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                               const GrPipeline& pipeline) const {
683164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!GrVkProgramDescBuilder::Build(desc, primProc, pipeline, *this->vkCaps().glslCaps())) {
684164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        SkDEBUGFAIL("Failed to generate GL program descriptor");
685164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
686164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
687164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
688164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
689164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
690164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielGrStencilAttachment* GrVkGpu::createStencilAttachmentForRenderTarget(const GrRenderTarget* rt,
691164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                     int width,
692164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                     int height) {
693164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(rt->asTexture());
694164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(width >= rt->width());
695164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(height >= rt->height());
696164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
697164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    int samples = rt->numStencilSamples();
698164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
699164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(this->vkCaps().stencilFormats().count());
700164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    const GrVkCaps::StencilFormat& sFmt = this->vkCaps().stencilFormats()[0];
701164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
702164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkStencilAttachment* stencil(GrVkStencilAttachment::Create(this,
703164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                 GrGpuResource::kCached_LifeCycle,
704164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                 width,
705164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                 height,
706164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                 samples,
707164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                 sFmt));
708164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fStats.incStencilAttachmentCreates();
709164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return stencil;
710164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
711164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
712164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
713164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
714164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielGrBackendObject GrVkGpu::createTestingOnlyBackendTexture(void* srcData, int w, int h,
715164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                         GrPixelConfig config) {
716164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
717164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkFormat pixelFormat;
718164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!GrPixelConfigToVkFormat(config, &pixelFormat)) {
719164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return 0;
720164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
721164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
722164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    bool linearTiling = false;
723164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!fVkCaps->isConfigTexturable(config)) {
724164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return 0;
725164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
726164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
727164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (fVkCaps->isConfigTexurableLinearly(config)) {
728164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        linearTiling = true;
729164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
730164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
731164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Currently this is not supported since it requires a copy which has not yet been implemented.
732164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (srcData && !linearTiling) {
733164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return 0;
734164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
735164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
736164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT;
737164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    usageFlags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
738164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    usageFlags |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
739164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
740164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkFlags memProps = (srcData && linearTiling) ? VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT :
741164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                   VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
742164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
743164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // This ImageDesc refers to the texture that will be read by the client. Thus even if msaa is
744164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // requested, this ImageDesc describes the resolved texutre. Therefore we always have samples set
745164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // to 1.
746164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkImage::ImageDesc imageDesc;
747164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fImageType = VK_IMAGE_TYPE_2D;
748164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fFormat = pixelFormat;
749164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fWidth = w;
750164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fHeight = h;
751164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fLevels = 1;
752164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fSamples = 1;
753164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fImageTiling = linearTiling ? VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL;
754164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fUsageFlags = usageFlags;
755164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    imageDesc.fMemProps = memProps;
756164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
757164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    const GrVkImage::Resource* imageRsrc = GrVkImage::CreateResource(this, imageDesc);
758164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!imageRsrc) {
759164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return 0;
760164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
761164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
762164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (srcData) {
763164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        if (linearTiling) {
764164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            const VkImageSubresource subres = {
765164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                VK_IMAGE_ASPECT_COLOR_BIT,
766164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                0,  // mipLevel
767164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                0,  // arraySlice
768164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            };
769164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            VkSubresourceLayout layout;
770164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            VkResult err;
771164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
772164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            const GrVkInterface* interface = this->vkInterface();
773164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
774164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            GR_VK_CALL(interface, GetImageSubresourceLayout(fDevice,
775164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                            imageRsrc->fImage,
776164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                            &subres,
777164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                            &layout));
778164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
779164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            void* mapPtr;
780164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            err = GR_VK_CALL(interface, MapMemory(fDevice,
781164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                  imageRsrc->fAlloc,
782164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                  0,
783164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                  layout.rowPitch * h,
784164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                  0,
785164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                  &mapPtr));
786164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            if (err) {
787164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                imageRsrc->unref(this);
788164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                return 0;
789164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            }
790164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
791164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            size_t bpp = GrBytesPerPixel(config);
792164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            size_t rowCopyBytes = bpp * w;
793164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            // If there is no padding on dst (layout.rowPitch) we can do a single memcopy.
794164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            // This assumes the srcData comes in with no padding.
795164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            if (rowCopyBytes == layout.rowPitch) {
796164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                memcpy(mapPtr, srcData, rowCopyBytes * h);
797164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            } else {
798164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                SkRectMemcpy(mapPtr, layout.rowPitch, srcData, w, rowCopyBytes, h);
799164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            }
800164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            GR_VK_CALL(interface, UnmapMemory(fDevice, imageRsrc->fAlloc));
801164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        } else {
802164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            // TODO: Add support for copying to optimal tiling
803164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            SkASSERT(false);
804164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
805164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
806164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
807164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return (GrBackendObject)imageRsrc;
808164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
809164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
810164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::isTestingOnlyBackendTexture(GrBackendObject id) const {
811164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkImage::Resource* backend = reinterpret_cast<GrVkImage::Resource*>(id);
812164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
813164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (backend && backend->fImage && backend->fAlloc) {
814164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkMemoryRequirements req;
815164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        memset(&req, 0, sizeof(req));
816164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        GR_VK_CALL(this->vkInterface(), GetImageMemoryRequirements(fDevice,
817164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                   backend->fImage,
818164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                   &req));
819164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // TODO: find a better check
820164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // This will probably fail with a different driver
821164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return (req.size > 0) && (req.size <= 8192 * 8192);
822164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
823164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
824164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return false;
825164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
826164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
827164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::deleteTestingOnlyBackendTexture(GrBackendObject id, bool abandon) {
828164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkImage::Resource* backend = reinterpret_cast<GrVkImage::Resource*>(id);
829164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
830164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (backend) {
831164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        if (!abandon) {
832164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            backend->unref(this);
833164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        } else {
834164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            backend->unrefAndAbandon();
835164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
836164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
837164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
838164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
839164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel////////////////////////////////////////////////////////////////////////////////
840164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
841164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::addMemoryBarrier(VkPipelineStageFlags srcStageMask,
842164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                               VkPipelineStageFlags dstStageMask,
843164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                               bool byRegion,
844164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                               VkMemoryBarrier* barrier) const {
845164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(fCurrentCmdBuffer);
846164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->pipelineBarrier(this,
847164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       srcStageMask,
848164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       dstStageMask,
849164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       byRegion,
850164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       GrVkCommandBuffer::kMemory_BarrierType,
851164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       barrier);
852164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
853164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
854164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::addBufferMemoryBarrier(VkPipelineStageFlags srcStageMask,
855164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     VkPipelineStageFlags dstStageMask,
856164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     bool byRegion,
857164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     VkBufferMemoryBarrier* barrier) const {
858164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(fCurrentCmdBuffer);
859164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->pipelineBarrier(this,
860164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       srcStageMask,
861164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       dstStageMask,
862164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       byRegion,
863164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       GrVkCommandBuffer::kBufferMemory_BarrierType,
864164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       barrier);
865164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
866164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
867164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::addImageMemoryBarrier(VkPipelineStageFlags srcStageMask,
868164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                    VkPipelineStageFlags dstStageMask,
869164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                    bool byRegion,
870164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                    VkImageMemoryBarrier* barrier) const {
871164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(fCurrentCmdBuffer);
872164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->pipelineBarrier(this,
873164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       srcStageMask,
874164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       dstStageMask,
875164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       byRegion,
876164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       GrVkCommandBuffer::kImageMemory_BarrierType,
877164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       barrier);
878164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
879164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
880164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::finishDrawTarget() {
881164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Submit the current command buffer to the Queue
882164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    this->submitCommandBuffer(kSkip_SyncQueue);
883164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
884164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
885164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::onClear(GrRenderTarget* target, const SkIRect& rect, GrColor color) {
886164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // parent class should never let us get here with no RT
887164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(target);
888164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
889164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkClearColorValue vkColor;
890164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrColorToRGBAFloat(color, vkColor.float32);
891164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
892164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(target);
893164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkImageLayout origDstLayout = vkRT->currentLayout();
894164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
895164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (rect.width() != target->width() || rect.height() != target->height()) {
896164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origDstLayout);
897164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkAccessFlags dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
898164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkPipelineStageFlags srcStageMask =
899164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            GrVkMemory::LayoutToPipelineStageFlags(vkRT->currentLayout());
900164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
901164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        vkRT->setImageLayout(this,
902164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                             VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
903164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                             srcAccessMask,
904164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                             dstAccessMask,
905164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                             srcStageMask,
906164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                             dstStageMask,
907164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                             false);
908164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
909164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkClearRect clearRect;
910164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        clearRect.rect.offset = { rect.fLeft, rect.fTop };
911164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        clearRect.rect.extent = { (uint32_t)rect.width(), (uint32_t)rect.height() };
912164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        clearRect.baseArrayLayer = 0;
913164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        clearRect.layerCount = 1;
914164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
915164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
916164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
917164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        const GrVkRenderPass* renderPass = vkRT->simpleRenderPass();
918164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        SkASSERT(renderPass);
919164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        fCurrentCmdBuffer->beginRenderPass(this, renderPass, *vkRT);
920164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
921164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        uint32_t colorIndex;
922164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        SkAssertResult(renderPass->colorAttachmentIndex(&colorIndex));
923164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
924164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        VkClearAttachment attachment;
925164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
926164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        attachment.colorAttachment = colorIndex;
927164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        attachment.clearValue.color = vkColor;
928164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
929164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        fCurrentCmdBuffer->clearAttachments(this, 1, &attachment, 1, &clearRect);
930164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        fCurrentCmdBuffer->endRenderPass(this);
931164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return;
932164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
933164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
934164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkPipelineStageFlags srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(origDstLayout);
935164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
936164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
937164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origDstLayout);;
938164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkAccessFlags dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
939164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
940164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    vkRT->setImageLayout(this,
941164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
942164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         srcAccessMask,
943164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         dstAccessMask,
944164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         srcStageMask,
945164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         dstStageMask,
946164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         false);
947164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
948164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
949164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkImageSubresourceRange subRange;
950164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    memset(&subRange, 0, sizeof(VkImageSubresourceRange));
951164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    subRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
952164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    subRange.baseMipLevel = 0;
953164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    subRange.levelCount = 1;
954164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    subRange.baseArrayLayer = 0;
955164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    subRange.layerCount = 1;
956164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
957164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // In the future we may not actually be doing this type of clear at all. If we are inside a
958164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // render pass or doing a non full clear then we will use CmdClearColorAttachment. The more
959164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // common use case will be clearing an attachment at the start of a render pass, in which case
960164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // we will use the clear load ops.
961164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->clearColorImage(this,
962164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       vkRT,
963164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       &vkColor,
964164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       1, &subRange);
965164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
966164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
967164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielinline bool can_copy_image(const GrSurface* dst,
968164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           const GrSurface* src,
969164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           const GrVkGpu* gpu) {
970164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (src->asTexture() &&
971164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        dst->asTexture() &&
972164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        src->origin() == dst->origin() &&
973164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        src->config() == dst->config()) {
974164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return true;
975164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
976164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
977164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // How does msaa play into this? If a VkTexture is multisampled, are we copying the multisampled
978164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // or the resolved image here?
979164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
980164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return false;
981164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
982164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
983164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::copySurfaceAsCopyImage(GrSurface* dst,
984164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     GrSurface* src,
985164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     const SkIRect& srcRect,
986164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     const SkIPoint& dstPoint) {
987164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(can_copy_image(dst, src, this));
988164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
989164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Insert memory barriers to switch src and dst to transfer_source and transfer_dst layouts
990164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkTexture* dstTex = static_cast<GrVkTexture*>(dst->asTexture());
991164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkTexture* srcTex = static_cast<GrVkTexture*>(src->asTexture());
992164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
993164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkImageLayout origDstLayout = dstTex->currentLayout();
994164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkImageLayout origSrcLayout = srcTex->currentLayout();
995164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
996164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkPipelineStageFlags srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(origDstLayout);
997164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
998164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
999164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // These flags are for flushing/invalidating caches and for the dst image it doesn't matter if
1000164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // the cache is flushed since it is only being written to.
1001164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origDstLayout);;
1002164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkAccessFlags dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
1003164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1004164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    dstTex->setImageLayout(this,
1005164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1006164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           srcAccessMask,
1007164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           dstAccessMask,
1008164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           srcStageMask,
1009164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           dstStageMask,
1010164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           false);
1011164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1012164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(origSrcLayout);
1013164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
1014164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1015164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(origSrcLayout);
1016164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
1017164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1018164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    srcTex->setImageLayout(this,
1019164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1020164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           srcAccessMask,
1021164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           dstAccessMask,
1022164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           srcStageMask,
1023164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           dstStageMask,
1024164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           false);
1025164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1026164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Flip rect if necessary
1027164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkIRect srcVkRect = srcRect;
1028164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    int32_t dstY = dstPoint.fY;
1029164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1030164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (kBottomLeft_GrSurfaceOrigin == src->origin()) {
1031164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        SkASSERT(kBottomLeft_GrSurfaceOrigin == dst->origin());
1032164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        srcVkRect.fTop = src->height() - srcRect.fBottom;
1033164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        srcVkRect.fBottom =  src->height() - srcRect.fTop;
1034164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        dstY = dst->height() - dstPoint.fY - srcVkRect.height();
1035164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1036164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1037164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkImageCopy copyRegion;
1038164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    memset(&copyRegion, 0, sizeof(VkImageCopy));
1039164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    copyRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
1040164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    copyRegion.srcOffset = { srcVkRect.fLeft, srcVkRect.fTop, 0 };
1041164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    copyRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
1042164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    copyRegion.dstOffset = { dstPoint.fX, dstY, 0 };
1043164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    copyRegion.extent = { (uint32_t)srcVkRect.width(), (uint32_t)srcVkRect.height(), 0 };
1044164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1045164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->copyImage(this,
1046164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                 srcTex,
1047164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1048164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                 dstTex,
1049164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1050164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                 1,
1051164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                 &copyRegion);
1052164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1053164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1054164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielinline bool can_copy_as_draw(const GrSurface* dst,
1055164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                             const GrSurface* src,
1056164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                             const GrVkGpu* gpu) {
1057164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return false;
1058164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1059164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1060164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::copySurfaceAsDraw(GrSurface* dst,
1061164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                GrSurface* src,
1062164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                const SkIRect& srcRect,
1063164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                const SkIPoint& dstPoint) {
1064164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(false);
1065164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1066164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1067164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::onCopySurface(GrSurface* dst,
1068164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                            GrSurface* src,
1069164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                            const SkIRect& srcRect,
1070164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                            const SkIPoint& dstPoint) {
1071164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (can_copy_image(dst, src, this)) {
1072164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        this->copySurfaceAsCopyImage(dst, src, srcRect, dstPoint);
1073164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return true;
1074164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1075164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1076164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (can_copy_as_draw(dst, src, this)) {
1077164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        this->copySurfaceAsDraw(dst, src, srcRect, dstPoint);
1078164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return true;
1079164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1080164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1081164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return false;
1082164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1083164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1084164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::onGetReadPixelsInfo(GrSurface* srcSurface, int width, int height, size_t rowBytes,
1085164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                  GrPixelConfig readConfig, DrawPreference* drawPreference,
1086164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                  ReadPixelTempDrawInfo* tempDrawInfo) {
1087164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Currently we don't handle draws, so if the caller wants/needs to do a draw we need to fail
1088164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (kNoDraw_DrawPreference != *drawPreference) {
1089164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
1090164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1091164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1092164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (srcSurface->config() != readConfig) {
1093164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // TODO: This should fall back to drawing or copying to change config of srcSurface to match
1094164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // that of readConfig.
1095164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
1096164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1097164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1098164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return true;
1099164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1100164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1101164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkGpu::onReadPixels(GrSurface* surface,
1102164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           int left, int top, int width, int height,
1103164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           GrPixelConfig config,
1104164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           void* buffer,
1105164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                           size_t rowBytes) {
1106164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkFormat pixelFormat;
1107164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!GrPixelConfigToVkFormat(config, &pixelFormat)) {
1108164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
1109164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1110164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1111164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkTexture* tgt = static_cast<GrVkTexture*>(surface->asTexture());
1112164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!tgt) {
1113164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
1114164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1115164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1116164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Change layout of our target so it can be used as copy
1117164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkImageLayout layout = tgt->currentLayout();
1118164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkPipelineStageFlags srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(layout);
1119164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
1120164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(layout);
1121164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkAccessFlags dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
1122164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    tgt->setImageLayout(this,
1123164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                        VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1124164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                        srcAccessMask,
1125164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                        dstAccessMask,
1126164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                        srcStageMask,
1127164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                        dstStageMask,
1128164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                        false);
1129164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1130164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkTransferBuffer* transferBuffer =
1131164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        reinterpret_cast<GrVkTransferBuffer*>(this->createTransferBuffer(rowBytes * height,
1132164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                                         kGpuToCpu_TransferType));
1133164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1134164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    bool flipY = kBottomLeft_GrSurfaceOrigin == surface->origin();
1135164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkOffset3D offset = {
1136164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        left,
1137164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        flipY ? surface->height() - top - height : top,
1138164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        0
1139164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    };
1140164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1141164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Copy the image to a buffer so we can map it to cpu memory
1142164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkBufferImageCopy region;
1143164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    memset(&region, 0, sizeof(VkBufferImageCopy));
1144164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    region.bufferOffset = 0;
1145164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    region.bufferRowLength = 0; // Forces RowLength to be imageExtent.width
1146164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    region.bufferImageHeight = 0; // Forces height to be tightly packed. Only useful for 3d images.
1147164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
1148164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    region.imageOffset = offset;
1149164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    region.imageExtent = { (uint32_t)width, (uint32_t)height, 1 };
1150164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1151164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->copyImageToBuffer(this,
1152164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                         tgt,
1153164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1154164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                         transferBuffer,
1155164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                         1,
1156164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                         &region);
1157164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1158164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // make sure the copy to buffer has finished
1159164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    transferBuffer->addMemoryBarrier(this,
1160164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     VK_ACCESS_TRANSFER_WRITE_BIT,
1161164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     VK_ACCESS_HOST_READ_BIT,
1162164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     VK_PIPELINE_STAGE_TRANSFER_BIT,
1163164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     VK_PIPELINE_STAGE_HOST_BIT,
1164164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                     false);
1165164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1166164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // We need to submit the current command buffer to the Queue and make sure it finishes before
1167164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // we can copy the data out of the buffer.
1168164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    this->submitCommandBuffer(kForce_SyncQueue);
1169164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1170164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    void* mappedMemory = transferBuffer->map();
1171164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1172164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    memcpy(buffer, mappedMemory, rowBytes*height);
1173164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1174164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    transferBuffer->unmap();
1175164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    transferBuffer->unref();
1176164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1177164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (flipY) {
1178164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        SkAutoSMalloc<32 * sizeof(GrColor)> scratch;
1179164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        size_t tightRowBytes = GrBytesPerPixel(config) * width;
1180164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        scratch.reset(tightRowBytes);
1181164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        void* tmpRow = scratch.get();
1182164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        // flip y in-place by rows
1183164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        const int halfY = height >> 1;
1184164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        char* top = reinterpret_cast<char*>(buffer);
1185164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        char* bottom = top + (height - 1) * rowBytes;
1186164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        for (int y = 0; y < halfY; y++) {
1187164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            memcpy(tmpRow, top, tightRowBytes);
1188164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            memcpy(top, bottom, tightRowBytes);
1189164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            memcpy(bottom, tmpRow, tightRowBytes);
1190164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            top += rowBytes;
1191164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            bottom -= rowBytes;
1192164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
1193164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1194164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1195164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return true;
1196164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1197164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1198164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielvoid GrVkGpu::onDraw(const DrawArgs& args, const GrNonInstancedVertices& vertices) {
1199164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrRenderTarget* rt = args.fPipeline->getRenderTarget();
1200164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(rt);
1201164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    const GrVkRenderPass* renderPass = vkRT->simpleRenderPass();
1202164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(renderPass);
1203164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1204164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1205164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    GrVkProgram* program = GrVkProgramBuilder::CreateProgram(this, args,
1206164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                             vertices.primitiveType(),
1207164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                                             *renderPass);
1208164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1209164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (!program) {
1210164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return;
1211164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1212164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1213164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    program->setData(this, *args.fPrimitiveProcessor, *args.fPipeline);
1214164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1215164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->beginRenderPass(this, renderPass, *vkRT);
1216164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1217164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    program->bind(this, fCurrentCmdBuffer);
1218164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1219164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    this->bindGeometry(*args.fPrimitiveProcessor, vertices);
1220164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1221164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Change layout of our render target so it can be used as the color attachment
1222164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkImageLayout layout = vkRT->currentLayout();
1223164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Our color attachment is purely a destination and won't be read so don't need to flush or
1224164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // invalidate any caches
1225164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkPipelineStageFlags srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(layout);
1226164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1227164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(layout);
1228164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkAccessFlags dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
1229164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    vkRT->setImageLayout(this,
1230164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1231164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         srcAccessMask,
1232164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         dstAccessMask,
1233164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         srcStageMask,
1234164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         dstStageMask,
1235164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                         false);
1236164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1237164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (vertices.isIndexed()) {
1238164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        fCurrentCmdBuffer->drawIndexed(this,
1239164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       vertices.indexCount(),
1240164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       1,
1241164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       vertices.startIndex(),
1242164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       vertices.startVertex(),
1243164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                       0);
1244164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    } else {
1245164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        fCurrentCmdBuffer->draw(this, vertices.vertexCount(), 1, vertices.startVertex(),  0);
1246164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1247164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1248164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    fCurrentCmdBuffer->endRenderPass(this);
1249164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1250164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Technically we don't have to call this here (since there is a safety check in program:setData
1251164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // but this will allow for quicker freeing of resources if the program sits in a cache for a
1252164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // while.
1253164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    program->freeTempResources(this);
1254164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // This free will go away once we setup a program cache, and then the cache will be responsible
1255164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // for call freeGpuResources.
1256164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    program->freeGPUResources(this);
1257164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    program->unref();
1258164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1259164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#if SWAP_PER_DRAW
1260164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    glFlush();
1261164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#if defined(SK_BUILD_FOR_MAC)
1262164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    aglSwapBuffers(aglGetCurrentContext());
1263164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    int set_a_break_pt_here = 9;
1264164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    aglSwapBuffers(aglGetCurrentContext());
1265164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#elif defined(SK_BUILD_FOR_WIN32)
1266164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SwapBuf();
1267164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    int set_a_break_pt_here = 9;
1268164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SwapBuf();
1269164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#endif
1270164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#endif
1271164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
1272164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1273