xref: /aosp_15_r20/external/skia/src/gpu/ganesh/vk/GrVkGpu.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2015 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker 
8*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/vk/GrVkGpu.h"
9*c8dee2aaSAndroid Build Coastguard Worker 
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkImageInfo.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPoint.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRect.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSamplingOptions.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSize.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSurface.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTextureCompressionType.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/GpuTypes.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/MutableTextureState.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrBackendSurface.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrDirectContext.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/vk/GrVkBackendSemaphore.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/vk/GrVkBackendSurface.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/vk/GrVkTypes.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/vk/VulkanBackendContext.h"
26*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/vk/VulkanExtensions.h"
27*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/vk/VulkanMemoryAllocator.h"
28*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/vk/VulkanMutableTextureState.h"
29*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/vk/VulkanTypes.h"
30*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkDebug.h"
31*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTemplates.h"
32*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTo.h"
33*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/gpu/vk/SkiaVulkan.h"
34*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkRectMemcpy.h"
35*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkCompressedDataUtils.h"
36*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkMipmap.h"
37*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkTraceEvent.h"
38*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/DataUtils.h"
39*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/RefCntedCallback.h"
40*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrBackendUtils.h"
41*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrBuffer.h"
42*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrCaps.h"
43*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrDataUtils.h"
44*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrDirectContextPriv.h"
45*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrGpuBuffer.h"
46*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrImageInfo.h"
47*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrPixmap.h"
48*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrProgramInfo.h"
49*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrRenderTarget.h"
50*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrResourceProvider.h"
51*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrSurface.h"
52*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrSurfaceProxy.h"
53*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrTexture.h"
54*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrThreadSafePipelineBuilder.h"
55*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/vk/GrVkBuffer.h"
56*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/vk/GrVkCommandBuffer.h"
57*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/vk/GrVkCommandPool.h"
58*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/vk/GrVkFramebuffer.h"
59*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/vk/GrVkImage.h"
60*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/vk/GrVkOpsRenderPass.h"
61*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/vk/GrVkRenderPass.h"
62*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/vk/GrVkRenderTarget.h"
63*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/vk/GrVkResourceProvider.h"
64*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/vk/GrVkSemaphore.h"
65*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/vk/GrVkTexture.h"
66*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/vk/GrVkTextureRenderTarget.h"
67*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/vk/GrVkUtil.h"
68*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/vk/VulkanInterface.h"
69*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/vk/VulkanMemory.h"
70*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/vk/VulkanUtilsPriv.h"
71*c8dee2aaSAndroid Build Coastguard Worker 
72*c8dee2aaSAndroid Build Coastguard Worker #include <algorithm>
73*c8dee2aaSAndroid Build Coastguard Worker #include <cstring>
74*c8dee2aaSAndroid Build Coastguard Worker #include <functional>
75*c8dee2aaSAndroid Build Coastguard Worker #include <utility>
76*c8dee2aaSAndroid Build Coastguard Worker 
77*c8dee2aaSAndroid Build Coastguard Worker class GrAttachment;
78*c8dee2aaSAndroid Build Coastguard Worker class GrBackendSemaphore;
79*c8dee2aaSAndroid Build Coastguard Worker class GrManagedResource;
80*c8dee2aaSAndroid Build Coastguard Worker class GrProgramDesc;
81*c8dee2aaSAndroid Build Coastguard Worker class GrSemaphore;
82*c8dee2aaSAndroid Build Coastguard Worker struct GrContextOptions;
83*c8dee2aaSAndroid Build Coastguard Worker 
84*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_USE_VMA)
85*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/vk/vulkanmemoryallocator/VulkanMemoryAllocatorPriv.h"
86*c8dee2aaSAndroid Build Coastguard Worker #endif
87*c8dee2aaSAndroid Build Coastguard Worker 
88*c8dee2aaSAndroid Build Coastguard Worker using namespace skia_private;
89*c8dee2aaSAndroid Build Coastguard Worker 
90*c8dee2aaSAndroid Build Coastguard Worker #define VK_CALL(X) GR_VK_CALL(this->vkInterface(), X)
91*c8dee2aaSAndroid Build Coastguard Worker #define VK_CALL_RET(RET, X) GR_VK_CALL_RESULT(this, RET, X)
92*c8dee2aaSAndroid Build Coastguard Worker 
Make(const skgpu::VulkanBackendContext & backendContext,const GrContextOptions & options,GrDirectContext * direct)93*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<GrGpu> GrVkGpu::Make(const skgpu::VulkanBackendContext& backendContext,
94*c8dee2aaSAndroid Build Coastguard Worker                                      const GrContextOptions& options,
95*c8dee2aaSAndroid Build Coastguard Worker                                      GrDirectContext* direct) {
96*c8dee2aaSAndroid Build Coastguard Worker     if (backendContext.fInstance == VK_NULL_HANDLE ||
97*c8dee2aaSAndroid Build Coastguard Worker         backendContext.fPhysicalDevice == VK_NULL_HANDLE ||
98*c8dee2aaSAndroid Build Coastguard Worker         backendContext.fDevice == VK_NULL_HANDLE ||
99*c8dee2aaSAndroid Build Coastguard Worker         backendContext.fQueue == VK_NULL_HANDLE) {
100*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
101*c8dee2aaSAndroid Build Coastguard Worker     }
102*c8dee2aaSAndroid Build Coastguard Worker     if (!backendContext.fGetProc) {
103*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
104*c8dee2aaSAndroid Build Coastguard Worker     }
105*c8dee2aaSAndroid Build Coastguard Worker 
106*c8dee2aaSAndroid Build Coastguard Worker     skgpu::VulkanExtensions ext;
107*c8dee2aaSAndroid Build Coastguard Worker     const skgpu::VulkanExtensions* extensions = &ext;
108*c8dee2aaSAndroid Build Coastguard Worker     if (backendContext.fVkExtensions) {
109*c8dee2aaSAndroid Build Coastguard Worker         extensions = backendContext.fVkExtensions;
110*c8dee2aaSAndroid Build Coastguard Worker     }
111*c8dee2aaSAndroid Build Coastguard Worker 
112*c8dee2aaSAndroid Build Coastguard Worker     uint32_t instanceVersion = 0;
113*c8dee2aaSAndroid Build Coastguard Worker     uint32_t physDevVersion = 0;
114*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<const skgpu::VulkanInterface> interface =
115*c8dee2aaSAndroid Build Coastguard Worker             skgpu::MakeInterface(backendContext, extensions, &instanceVersion, &physDevVersion);
116*c8dee2aaSAndroid Build Coastguard Worker     if (!interface) {
117*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
118*c8dee2aaSAndroid Build Coastguard Worker     }
119*c8dee2aaSAndroid Build Coastguard Worker 
120*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<GrVkCaps> caps;
121*c8dee2aaSAndroid Build Coastguard Worker     if (backendContext.fDeviceFeatures2) {
122*c8dee2aaSAndroid Build Coastguard Worker         caps.reset(new GrVkCaps(options,
123*c8dee2aaSAndroid Build Coastguard Worker                                 interface.get(),
124*c8dee2aaSAndroid Build Coastguard Worker                                 backendContext.fPhysicalDevice,
125*c8dee2aaSAndroid Build Coastguard Worker                                 *backendContext.fDeviceFeatures2,
126*c8dee2aaSAndroid Build Coastguard Worker                                 instanceVersion,
127*c8dee2aaSAndroid Build Coastguard Worker                                 physDevVersion,
128*c8dee2aaSAndroid Build Coastguard Worker                                 *extensions,
129*c8dee2aaSAndroid Build Coastguard Worker                                 backendContext.fProtectedContext));
130*c8dee2aaSAndroid Build Coastguard Worker     } else if (backendContext.fDeviceFeatures) {
131*c8dee2aaSAndroid Build Coastguard Worker         VkPhysicalDeviceFeatures2 features2;
132*c8dee2aaSAndroid Build Coastguard Worker         features2.pNext = nullptr;
133*c8dee2aaSAndroid Build Coastguard Worker         features2.features = *backendContext.fDeviceFeatures;
134*c8dee2aaSAndroid Build Coastguard Worker         caps.reset(new GrVkCaps(options,
135*c8dee2aaSAndroid Build Coastguard Worker                                 interface.get(),
136*c8dee2aaSAndroid Build Coastguard Worker                                 backendContext.fPhysicalDevice,
137*c8dee2aaSAndroid Build Coastguard Worker                                 features2,
138*c8dee2aaSAndroid Build Coastguard Worker                                 instanceVersion,
139*c8dee2aaSAndroid Build Coastguard Worker                                 physDevVersion,
140*c8dee2aaSAndroid Build Coastguard Worker                                 *extensions,
141*c8dee2aaSAndroid Build Coastguard Worker                                 backendContext.fProtectedContext));
142*c8dee2aaSAndroid Build Coastguard Worker     } else {
143*c8dee2aaSAndroid Build Coastguard Worker         VkPhysicalDeviceFeatures2 features;
144*c8dee2aaSAndroid Build Coastguard Worker         memset(&features, 0, sizeof(VkPhysicalDeviceFeatures2));
145*c8dee2aaSAndroid Build Coastguard Worker         caps.reset(new GrVkCaps(options,
146*c8dee2aaSAndroid Build Coastguard Worker                                 interface.get(),
147*c8dee2aaSAndroid Build Coastguard Worker                                 backendContext.fPhysicalDevice,
148*c8dee2aaSAndroid Build Coastguard Worker                                 features,
149*c8dee2aaSAndroid Build Coastguard Worker                                 instanceVersion,
150*c8dee2aaSAndroid Build Coastguard Worker                                 physDevVersion,
151*c8dee2aaSAndroid Build Coastguard Worker                                 *extensions,
152*c8dee2aaSAndroid Build Coastguard Worker                                 backendContext.fProtectedContext));
153*c8dee2aaSAndroid Build Coastguard Worker     }
154*c8dee2aaSAndroid Build Coastguard Worker 
155*c8dee2aaSAndroid Build Coastguard Worker     if (!caps) {
156*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
157*c8dee2aaSAndroid Build Coastguard Worker     }
158*c8dee2aaSAndroid Build Coastguard Worker 
159*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<skgpu::VulkanMemoryAllocator> memoryAllocator = backendContext.fMemoryAllocator;
160*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_USE_VMA)
161*c8dee2aaSAndroid Build Coastguard Worker     if (!memoryAllocator) {
162*c8dee2aaSAndroid Build Coastguard Worker         // We were not given a memory allocator at creation
163*c8dee2aaSAndroid Build Coastguard Worker         memoryAllocator =
164*c8dee2aaSAndroid Build Coastguard Worker                 skgpu::VulkanMemoryAllocators::Make(backendContext,
165*c8dee2aaSAndroid Build Coastguard Worker                                                     skgpu::ThreadSafe::kNo,
166*c8dee2aaSAndroid Build Coastguard Worker                                                     options.fVulkanVMALargeHeapBlockSize);
167*c8dee2aaSAndroid Build Coastguard Worker     }
168*c8dee2aaSAndroid Build Coastguard Worker #endif
169*c8dee2aaSAndroid Build Coastguard Worker     if (!memoryAllocator) {
170*c8dee2aaSAndroid Build Coastguard Worker         SkDEBUGFAIL("No supplied vulkan memory allocator and unable to create one internally.");
171*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
172*c8dee2aaSAndroid Build Coastguard Worker     }
173*c8dee2aaSAndroid Build Coastguard Worker 
174*c8dee2aaSAndroid Build Coastguard Worker     std::unique_ptr<GrVkGpu> vkGpu(new GrVkGpu(direct,
175*c8dee2aaSAndroid Build Coastguard Worker                                                backendContext,
176*c8dee2aaSAndroid Build Coastguard Worker                                                std::move(caps),
177*c8dee2aaSAndroid Build Coastguard Worker                                                interface,
178*c8dee2aaSAndroid Build Coastguard Worker                                                instanceVersion,
179*c8dee2aaSAndroid Build Coastguard Worker                                                physDevVersion,
180*c8dee2aaSAndroid Build Coastguard Worker                                                std::move(memoryAllocator)));
181*c8dee2aaSAndroid Build Coastguard Worker     if (backendContext.fProtectedContext == GrProtected::kYes &&
182*c8dee2aaSAndroid Build Coastguard Worker         !vkGpu->vkCaps().supportsProtectedContent()) {
183*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
184*c8dee2aaSAndroid Build Coastguard Worker     }
185*c8dee2aaSAndroid Build Coastguard Worker     return vkGpu;
186*c8dee2aaSAndroid Build Coastguard Worker }
187*c8dee2aaSAndroid Build Coastguard Worker 
188*c8dee2aaSAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////
189*c8dee2aaSAndroid Build Coastguard Worker 
GrVkGpu(GrDirectContext * direct,const skgpu::VulkanBackendContext & backendContext,sk_sp<GrVkCaps> caps,sk_sp<const skgpu::VulkanInterface> interface,uint32_t instanceVersion,uint32_t physicalDeviceVersion,sk_sp<skgpu::VulkanMemoryAllocator> memoryAllocator)190*c8dee2aaSAndroid Build Coastguard Worker GrVkGpu::GrVkGpu(GrDirectContext* direct,
191*c8dee2aaSAndroid Build Coastguard Worker                  const skgpu::VulkanBackendContext& backendContext,
192*c8dee2aaSAndroid Build Coastguard Worker                  sk_sp<GrVkCaps> caps,
193*c8dee2aaSAndroid Build Coastguard Worker                  sk_sp<const skgpu::VulkanInterface> interface,
194*c8dee2aaSAndroid Build Coastguard Worker                  uint32_t instanceVersion,
195*c8dee2aaSAndroid Build Coastguard Worker                  uint32_t physicalDeviceVersion,
196*c8dee2aaSAndroid Build Coastguard Worker                  sk_sp<skgpu::VulkanMemoryAllocator> memoryAllocator)
197*c8dee2aaSAndroid Build Coastguard Worker         : INHERITED(direct)
198*c8dee2aaSAndroid Build Coastguard Worker         , fInterface(std::move(interface))
199*c8dee2aaSAndroid Build Coastguard Worker         , fMemoryAllocator(std::move(memoryAllocator))
200*c8dee2aaSAndroid Build Coastguard Worker         , fVkCaps(std::move(caps))
201*c8dee2aaSAndroid Build Coastguard Worker         , fPhysicalDevice(backendContext.fPhysicalDevice)
202*c8dee2aaSAndroid Build Coastguard Worker         , fDevice(backendContext.fDevice)
203*c8dee2aaSAndroid Build Coastguard Worker         , fQueue(backendContext.fQueue)
204*c8dee2aaSAndroid Build Coastguard Worker         , fQueueIndex(backendContext.fGraphicsQueueIndex)
205*c8dee2aaSAndroid Build Coastguard Worker         , fResourceProvider(this)
206*c8dee2aaSAndroid Build Coastguard Worker         , fStagingBufferManager(this)
207*c8dee2aaSAndroid Build Coastguard Worker         , fDisconnected(false)
208*c8dee2aaSAndroid Build Coastguard Worker         , fProtectedContext(backendContext.fProtectedContext)
209*c8dee2aaSAndroid Build Coastguard Worker         , fDeviceLostContext(backendContext.fDeviceLostContext)
210*c8dee2aaSAndroid Build Coastguard Worker         , fDeviceLostProc(backendContext.fDeviceLostProc) {
211*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(fMemoryAllocator);
212*c8dee2aaSAndroid Build Coastguard Worker 
213*c8dee2aaSAndroid Build Coastguard Worker     this->initCaps(fVkCaps);
214*c8dee2aaSAndroid Build Coastguard Worker 
215*c8dee2aaSAndroid Build Coastguard Worker     VK_CALL(GetPhysicalDeviceProperties(backendContext.fPhysicalDevice, &fPhysDevProps));
216*c8dee2aaSAndroid Build Coastguard Worker     VK_CALL(GetPhysicalDeviceMemoryProperties(backendContext.fPhysicalDevice, &fPhysDevMemProps));
217*c8dee2aaSAndroid Build Coastguard Worker 
218*c8dee2aaSAndroid Build Coastguard Worker     fResourceProvider.init();
219*c8dee2aaSAndroid Build Coastguard Worker 
220*c8dee2aaSAndroid Build Coastguard Worker     fMainCmdPool = fResourceProvider.findOrCreateCommandPool();
221*c8dee2aaSAndroid Build Coastguard Worker     if (fMainCmdPool) {
222*c8dee2aaSAndroid Build Coastguard Worker         fMainCmdBuffer = fMainCmdPool->getPrimaryCommandBuffer();
223*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(this->currentCommandBuffer());
224*c8dee2aaSAndroid Build Coastguard Worker         this->currentCommandBuffer()->begin(this);
225*c8dee2aaSAndroid Build Coastguard Worker     }
226*c8dee2aaSAndroid Build Coastguard Worker }
227*c8dee2aaSAndroid Build Coastguard Worker 
destroyResources()228*c8dee2aaSAndroid Build Coastguard Worker void GrVkGpu::destroyResources() {
229*c8dee2aaSAndroid Build Coastguard Worker     if (fMainCmdPool) {
230*c8dee2aaSAndroid Build Coastguard Worker         fMainCmdPool->getPrimaryCommandBuffer()->end(this, /*abandoningBuffer=*/true);
231*c8dee2aaSAndroid Build Coastguard Worker         fMainCmdPool->close();
232*c8dee2aaSAndroid Build Coastguard Worker     }
233*c8dee2aaSAndroid Build Coastguard Worker 
234*c8dee2aaSAndroid Build Coastguard Worker     // wait for all commands to finish
235*c8dee2aaSAndroid Build Coastguard Worker     this->finishOutstandingGpuWork();
236*c8dee2aaSAndroid Build Coastguard Worker 
237*c8dee2aaSAndroid Build Coastguard Worker     if (fMainCmdPool) {
238*c8dee2aaSAndroid Build Coastguard Worker         fMainCmdPool->unref();
239*c8dee2aaSAndroid Build Coastguard Worker         fMainCmdPool = nullptr;
240*c8dee2aaSAndroid Build Coastguard Worker     }
241*c8dee2aaSAndroid Build Coastguard Worker 
242*c8dee2aaSAndroid Build Coastguard Worker     for (int i = 0; i < fSemaphoresToWaitOn.size(); ++i) {
243*c8dee2aaSAndroid Build Coastguard Worker         fSemaphoresToWaitOn[i]->unref();
244*c8dee2aaSAndroid Build Coastguard Worker     }
245*c8dee2aaSAndroid Build Coastguard Worker     fSemaphoresToWaitOn.clear();
246*c8dee2aaSAndroid Build Coastguard Worker 
247*c8dee2aaSAndroid Build Coastguard Worker     for (int i = 0; i < fSemaphoresToSignal.size(); ++i) {
248*c8dee2aaSAndroid Build Coastguard Worker         fSemaphoresToSignal[i]->unref();
249*c8dee2aaSAndroid Build Coastguard Worker     }
250*c8dee2aaSAndroid Build Coastguard Worker     fSemaphoresToSignal.clear();
251*c8dee2aaSAndroid Build Coastguard Worker 
252*c8dee2aaSAndroid Build Coastguard Worker     fStagingBufferManager.reset();
253*c8dee2aaSAndroid Build Coastguard Worker 
254*c8dee2aaSAndroid Build Coastguard Worker     fMSAALoadManager.destroyResources(this);
255*c8dee2aaSAndroid Build Coastguard Worker 
256*c8dee2aaSAndroid Build Coastguard Worker     // must call this just before we destroy the command pool and VkDevice
257*c8dee2aaSAndroid Build Coastguard Worker     fResourceProvider.destroyResources();
258*c8dee2aaSAndroid Build Coastguard Worker }
259*c8dee2aaSAndroid Build Coastguard Worker 
~GrVkGpu()260*c8dee2aaSAndroid Build Coastguard Worker GrVkGpu::~GrVkGpu() {
261*c8dee2aaSAndroid Build Coastguard Worker     if (!fDisconnected) {
262*c8dee2aaSAndroid Build Coastguard Worker         this->destroyResources();
263*c8dee2aaSAndroid Build Coastguard Worker     }
264*c8dee2aaSAndroid Build Coastguard Worker     // We don't delete the memory allocator until the very end of the GrVkGpu lifetime so that
265*c8dee2aaSAndroid Build Coastguard Worker     // clients can continue to delete backend textures even after a context has been abandoned.
266*c8dee2aaSAndroid Build Coastguard Worker     fMemoryAllocator.reset();
267*c8dee2aaSAndroid Build Coastguard Worker }
268*c8dee2aaSAndroid Build Coastguard Worker 
269*c8dee2aaSAndroid Build Coastguard Worker 
disconnect(DisconnectType type)270*c8dee2aaSAndroid Build Coastguard Worker void GrVkGpu::disconnect(DisconnectType type) {
271*c8dee2aaSAndroid Build Coastguard Worker     INHERITED::disconnect(type);
272*c8dee2aaSAndroid Build Coastguard Worker     if (!fDisconnected) {
273*c8dee2aaSAndroid Build Coastguard Worker         this->destroyResources();
274*c8dee2aaSAndroid Build Coastguard Worker 
275*c8dee2aaSAndroid Build Coastguard Worker         fSemaphoresToWaitOn.clear();
276*c8dee2aaSAndroid Build Coastguard Worker         fSemaphoresToSignal.clear();
277*c8dee2aaSAndroid Build Coastguard Worker         fMainCmdBuffer = nullptr;
278*c8dee2aaSAndroid Build Coastguard Worker         fDisconnected = true;
279*c8dee2aaSAndroid Build Coastguard Worker     }
280*c8dee2aaSAndroid Build Coastguard Worker }
281*c8dee2aaSAndroid Build Coastguard Worker 
pipelineBuilder()282*c8dee2aaSAndroid Build Coastguard Worker GrThreadSafePipelineBuilder* GrVkGpu::pipelineBuilder() {
283*c8dee2aaSAndroid Build Coastguard Worker     return fResourceProvider.pipelineStateCache();
284*c8dee2aaSAndroid Build Coastguard Worker }
285*c8dee2aaSAndroid Build Coastguard Worker 
refPipelineBuilder()286*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrThreadSafePipelineBuilder> GrVkGpu::refPipelineBuilder() {
287*c8dee2aaSAndroid Build Coastguard Worker     return fResourceProvider.refPipelineStateCache();
288*c8dee2aaSAndroid Build Coastguard Worker }
289*c8dee2aaSAndroid Build Coastguard Worker 
290*c8dee2aaSAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////
291*c8dee2aaSAndroid Build Coastguard Worker 
onGetOpsRenderPass(GrRenderTarget * rt,bool useMSAASurface,GrAttachment * stencil,GrSurfaceOrigin origin,const SkIRect & bounds,const GrOpsRenderPass::LoadAndStoreInfo & colorInfo,const GrOpsRenderPass::StencilLoadAndStoreInfo & stencilInfo,const TArray<GrSurfaceProxy *,true> & sampledProxies,GrXferBarrierFlags renderPassXferBarriers)292*c8dee2aaSAndroid Build Coastguard Worker GrOpsRenderPass* GrVkGpu::onGetOpsRenderPass(
293*c8dee2aaSAndroid Build Coastguard Worker         GrRenderTarget* rt,
294*c8dee2aaSAndroid Build Coastguard Worker         bool useMSAASurface,
295*c8dee2aaSAndroid Build Coastguard Worker         GrAttachment* stencil,
296*c8dee2aaSAndroid Build Coastguard Worker         GrSurfaceOrigin origin,
297*c8dee2aaSAndroid Build Coastguard Worker         const SkIRect& bounds,
298*c8dee2aaSAndroid Build Coastguard Worker         const GrOpsRenderPass::LoadAndStoreInfo& colorInfo,
299*c8dee2aaSAndroid Build Coastguard Worker         const GrOpsRenderPass::StencilLoadAndStoreInfo& stencilInfo,
300*c8dee2aaSAndroid Build Coastguard Worker         const TArray<GrSurfaceProxy*, true>& sampledProxies,
301*c8dee2aaSAndroid Build Coastguard Worker         GrXferBarrierFlags renderPassXferBarriers) {
302*c8dee2aaSAndroid Build Coastguard Worker     if (!fCachedOpsRenderPass) {
303*c8dee2aaSAndroid Build Coastguard Worker         fCachedOpsRenderPass = std::make_unique<GrVkOpsRenderPass>(this);
304*c8dee2aaSAndroid Build Coastguard Worker     }
305*c8dee2aaSAndroid Build Coastguard Worker 
306*c8dee2aaSAndroid Build Coastguard Worker     // For the given render target and requested render pass features we need to find a compatible
307*c8dee2aaSAndroid Build Coastguard Worker     // framebuffer to use for the render pass. Technically it is the underlying VkRenderPass that
308*c8dee2aaSAndroid Build Coastguard Worker     // is compatible, but that is part of the framebuffer that we get here.
309*c8dee2aaSAndroid Build Coastguard Worker     GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(rt);
310*c8dee2aaSAndroid Build Coastguard Worker 
311*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!useMSAASurface ||
312*c8dee2aaSAndroid Build Coastguard Worker              rt->numSamples() > 1 ||
313*c8dee2aaSAndroid Build Coastguard Worker              (this->vkCaps().supportsDiscardableMSAAForDMSAA() &&
314*c8dee2aaSAndroid Build Coastguard Worker               vkRT->resolveAttachment() &&
315*c8dee2aaSAndroid Build Coastguard Worker               vkRT->resolveAttachment()->supportsInputAttachmentUsage()));
316*c8dee2aaSAndroid Build Coastguard Worker 
317*c8dee2aaSAndroid Build Coastguard Worker     // Covert the GrXferBarrierFlags into render pass self dependency flags
318*c8dee2aaSAndroid Build Coastguard Worker     GrVkRenderPass::SelfDependencyFlags selfDepFlags = GrVkRenderPass::SelfDependencyFlags::kNone;
319*c8dee2aaSAndroid Build Coastguard Worker     if (renderPassXferBarriers & GrXferBarrierFlags::kBlend) {
320*c8dee2aaSAndroid Build Coastguard Worker         selfDepFlags |= GrVkRenderPass::SelfDependencyFlags::kForNonCoherentAdvBlend;
321*c8dee2aaSAndroid Build Coastguard Worker     }
322*c8dee2aaSAndroid Build Coastguard Worker     if (renderPassXferBarriers & GrXferBarrierFlags::kTexture) {
323*c8dee2aaSAndroid Build Coastguard Worker         selfDepFlags |= GrVkRenderPass::SelfDependencyFlags::kForInputAttachment;
324*c8dee2aaSAndroid Build Coastguard Worker     }
325*c8dee2aaSAndroid Build Coastguard Worker 
326*c8dee2aaSAndroid Build Coastguard Worker     // Figure out if we need a resolve attachment for this render pass. A resolve attachment is
327*c8dee2aaSAndroid Build Coastguard Worker     // needed if we are using msaa to draw with a discardable msaa attachment. If we are in this
328*c8dee2aaSAndroid Build Coastguard Worker     // case we also need to update the color load/store ops since we don't want to ever load or
329*c8dee2aaSAndroid Build Coastguard Worker     // store the msaa color attachment, but may need to for the resolve attachment.
330*c8dee2aaSAndroid Build Coastguard Worker     GrOpsRenderPass::LoadAndStoreInfo localColorInfo = colorInfo;
331*c8dee2aaSAndroid Build Coastguard Worker     bool withResolve = false;
332*c8dee2aaSAndroid Build Coastguard Worker     GrVkRenderPass::LoadFromResolve loadFromResolve = GrVkRenderPass::LoadFromResolve::kNo;
333*c8dee2aaSAndroid Build Coastguard Worker     GrOpsRenderPass::LoadAndStoreInfo resolveInfo{GrLoadOp::kLoad, GrStoreOp::kStore, {}};
334*c8dee2aaSAndroid Build Coastguard Worker     if (useMSAASurface && this->vkCaps().renderTargetSupportsDiscardableMSAA(vkRT)) {
335*c8dee2aaSAndroid Build Coastguard Worker         withResolve = true;
336*c8dee2aaSAndroid Build Coastguard Worker         localColorInfo.fStoreOp = GrStoreOp::kDiscard;
337*c8dee2aaSAndroid Build Coastguard Worker         if (colorInfo.fLoadOp == GrLoadOp::kLoad) {
338*c8dee2aaSAndroid Build Coastguard Worker             loadFromResolve = GrVkRenderPass::LoadFromResolve::kLoad;
339*c8dee2aaSAndroid Build Coastguard Worker             localColorInfo.fLoadOp = GrLoadOp::kDiscard;
340*c8dee2aaSAndroid Build Coastguard Worker         } else {
341*c8dee2aaSAndroid Build Coastguard Worker             resolveInfo.fLoadOp = GrLoadOp::kDiscard;
342*c8dee2aaSAndroid Build Coastguard Worker         }
343*c8dee2aaSAndroid Build Coastguard Worker     }
344*c8dee2aaSAndroid Build Coastguard Worker 
345*c8dee2aaSAndroid Build Coastguard Worker     // Get the framebuffer to use for the render pass
346*c8dee2aaSAndroid Build Coastguard Worker    sk_sp<GrVkFramebuffer> framebuffer;
347*c8dee2aaSAndroid Build Coastguard Worker     if (vkRT->wrapsSecondaryCommandBuffer()) {
348*c8dee2aaSAndroid Build Coastguard Worker         framebuffer = vkRT->externalFramebuffer();
349*c8dee2aaSAndroid Build Coastguard Worker     } else {
350*c8dee2aaSAndroid Build Coastguard Worker         auto fb = vkRT->getFramebuffer(withResolve, SkToBool(stencil), selfDepFlags,
351*c8dee2aaSAndroid Build Coastguard Worker                                        loadFromResolve);
352*c8dee2aaSAndroid Build Coastguard Worker         framebuffer = sk_ref_sp(fb);
353*c8dee2aaSAndroid Build Coastguard Worker     }
354*c8dee2aaSAndroid Build Coastguard Worker     if (!framebuffer) {
355*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
356*c8dee2aaSAndroid Build Coastguard Worker     }
357*c8dee2aaSAndroid Build Coastguard Worker 
358*c8dee2aaSAndroid Build Coastguard Worker     if (!fCachedOpsRenderPass->set(rt, std::move(framebuffer), origin, bounds, localColorInfo,
359*c8dee2aaSAndroid Build Coastguard Worker                                    stencilInfo, resolveInfo, selfDepFlags, loadFromResolve,
360*c8dee2aaSAndroid Build Coastguard Worker                                    sampledProxies)) {
361*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
362*c8dee2aaSAndroid Build Coastguard Worker     }
363*c8dee2aaSAndroid Build Coastguard Worker     return fCachedOpsRenderPass.get();
364*c8dee2aaSAndroid Build Coastguard Worker }
365*c8dee2aaSAndroid Build Coastguard Worker 
submitCommandBuffer(const GrSubmitInfo & submitInfo)366*c8dee2aaSAndroid Build Coastguard Worker bool GrVkGpu::submitCommandBuffer(const GrSubmitInfo& submitInfo) {
367*c8dee2aaSAndroid Build Coastguard Worker     TRACE_EVENT0("skia.gpu", TRACE_FUNC);
368*c8dee2aaSAndroid Build Coastguard Worker     if (!this->currentCommandBuffer()) {
369*c8dee2aaSAndroid Build Coastguard Worker         return false;
370*c8dee2aaSAndroid Build Coastguard Worker     }
371*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!fCachedOpsRenderPass || !fCachedOpsRenderPass->isActive());
372*c8dee2aaSAndroid Build Coastguard Worker 
373*c8dee2aaSAndroid Build Coastguard Worker     if (!this->currentCommandBuffer()->hasWork() && submitInfo.fSync == GrSyncCpu::kNo &&
374*c8dee2aaSAndroid Build Coastguard Worker         fSemaphoresToSignal.empty() && fSemaphoresToWaitOn.empty()) {
375*c8dee2aaSAndroid Build Coastguard Worker         // We may have added finished procs during the flush call. Since there is no actual work
376*c8dee2aaSAndroid Build Coastguard Worker         // we are not submitting the command buffer and may never come back around to submit it.
377*c8dee2aaSAndroid Build Coastguard Worker         // Thus we call all current finished procs manually, since the work has technically
378*c8dee2aaSAndroid Build Coastguard Worker         // finished.
379*c8dee2aaSAndroid Build Coastguard Worker         this->currentCommandBuffer()->callFinishedProcs();
380*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(fDrawables.empty());
381*c8dee2aaSAndroid Build Coastguard Worker         fResourceProvider.checkCommandBuffers();
382*c8dee2aaSAndroid Build Coastguard Worker         return true;
383*c8dee2aaSAndroid Build Coastguard Worker     }
384*c8dee2aaSAndroid Build Coastguard Worker 
385*c8dee2aaSAndroid Build Coastguard Worker     fMainCmdBuffer->end(this);
386*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(fMainCmdPool);
387*c8dee2aaSAndroid Build Coastguard Worker     fMainCmdPool->close();
388*c8dee2aaSAndroid Build Coastguard Worker     bool didSubmit = fMainCmdBuffer->submitToQueue(this, fQueue, fSemaphoresToSignal,
389*c8dee2aaSAndroid Build Coastguard Worker                                                    fSemaphoresToWaitOn, submitInfo);
390*c8dee2aaSAndroid Build Coastguard Worker 
391*c8dee2aaSAndroid Build Coastguard Worker     if (didSubmit && submitInfo.fSync == GrSyncCpu::kYes) {
392*c8dee2aaSAndroid Build Coastguard Worker         fMainCmdBuffer->forceSync(this);
393*c8dee2aaSAndroid Build Coastguard Worker     }
394*c8dee2aaSAndroid Build Coastguard Worker 
395*c8dee2aaSAndroid Build Coastguard Worker     // We must delete any drawables that had to wait until submit to destroy.
396*c8dee2aaSAndroid Build Coastguard Worker     fDrawables.clear();
397*c8dee2aaSAndroid Build Coastguard Worker 
398*c8dee2aaSAndroid Build Coastguard Worker     // If we didn't submit the command buffer then we did not wait on any semaphores. We will
399*c8dee2aaSAndroid Build Coastguard Worker     // continue to hold onto these semaphores and wait on them during the next command buffer
400*c8dee2aaSAndroid Build Coastguard Worker     // submission.
401*c8dee2aaSAndroid Build Coastguard Worker     if (didSubmit) {
402*c8dee2aaSAndroid Build Coastguard Worker         for (int i = 0; i < fSemaphoresToWaitOn.size(); ++i) {
403*c8dee2aaSAndroid Build Coastguard Worker             fSemaphoresToWaitOn[i]->unref();
404*c8dee2aaSAndroid Build Coastguard Worker         }
405*c8dee2aaSAndroid Build Coastguard Worker         fSemaphoresToWaitOn.clear();
406*c8dee2aaSAndroid Build Coastguard Worker     }
407*c8dee2aaSAndroid Build Coastguard Worker 
408*c8dee2aaSAndroid Build Coastguard Worker     // Even if we did not submit the command buffer, we drop all the signal semaphores since we will
409*c8dee2aaSAndroid Build Coastguard Worker     // not try to recover the work that wasn't submitted and instead just drop it all. The client
410*c8dee2aaSAndroid Build Coastguard Worker     // will be notified that the semaphores were not submit so that they will not try to wait on
411*c8dee2aaSAndroid Build Coastguard Worker     // them.
412*c8dee2aaSAndroid Build Coastguard Worker     for (int i = 0; i < fSemaphoresToSignal.size(); ++i) {
413*c8dee2aaSAndroid Build Coastguard Worker         fSemaphoresToSignal[i]->unref();
414*c8dee2aaSAndroid Build Coastguard Worker     }
415*c8dee2aaSAndroid Build Coastguard Worker     fSemaphoresToSignal.clear();
416*c8dee2aaSAndroid Build Coastguard Worker 
417*c8dee2aaSAndroid Build Coastguard Worker     // Release old command pool and create a new one
418*c8dee2aaSAndroid Build Coastguard Worker     fMainCmdPool->unref();
419*c8dee2aaSAndroid Build Coastguard Worker     fMainCmdPool = fResourceProvider.findOrCreateCommandPool();
420*c8dee2aaSAndroid Build Coastguard Worker     if (fMainCmdPool) {
421*c8dee2aaSAndroid Build Coastguard Worker         fMainCmdBuffer = fMainCmdPool->getPrimaryCommandBuffer();
422*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(fMainCmdBuffer);
423*c8dee2aaSAndroid Build Coastguard Worker         fMainCmdBuffer->begin(this);
424*c8dee2aaSAndroid Build Coastguard Worker     } else {
425*c8dee2aaSAndroid Build Coastguard Worker         fMainCmdBuffer = nullptr;
426*c8dee2aaSAndroid Build Coastguard Worker     }
427*c8dee2aaSAndroid Build Coastguard Worker     // We must wait to call checkCommandBuffers until after we get a new command buffer. The
428*c8dee2aaSAndroid Build Coastguard Worker     // checkCommandBuffers may trigger a releaseProc which may cause us to insert a barrier for a
429*c8dee2aaSAndroid Build Coastguard Worker     // released GrVkImage. That barrier needs to be put into a new command buffer and not the old
430*c8dee2aaSAndroid Build Coastguard Worker     // one that was just submitted.
431*c8dee2aaSAndroid Build Coastguard Worker     fResourceProvider.checkCommandBuffers();
432*c8dee2aaSAndroid Build Coastguard Worker     return didSubmit;
433*c8dee2aaSAndroid Build Coastguard Worker }
434*c8dee2aaSAndroid Build Coastguard Worker 
435*c8dee2aaSAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////
onCreateBuffer(size_t size,GrGpuBufferType type,GrAccessPattern accessPattern)436*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrGpuBuffer> GrVkGpu::onCreateBuffer(size_t size,
437*c8dee2aaSAndroid Build Coastguard Worker                                            GrGpuBufferType type,
438*c8dee2aaSAndroid Build Coastguard Worker                                            GrAccessPattern accessPattern) {
439*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_DEBUG
440*c8dee2aaSAndroid Build Coastguard Worker     switch (type) {
441*c8dee2aaSAndroid Build Coastguard Worker         case GrGpuBufferType::kVertex:
442*c8dee2aaSAndroid Build Coastguard Worker         case GrGpuBufferType::kIndex:
443*c8dee2aaSAndroid Build Coastguard Worker         case GrGpuBufferType::kDrawIndirect:
444*c8dee2aaSAndroid Build Coastguard Worker             SkASSERT(accessPattern == kDynamic_GrAccessPattern ||
445*c8dee2aaSAndroid Build Coastguard Worker                      accessPattern == kStatic_GrAccessPattern);
446*c8dee2aaSAndroid Build Coastguard Worker             break;
447*c8dee2aaSAndroid Build Coastguard Worker         case GrGpuBufferType::kXferCpuToGpu:
448*c8dee2aaSAndroid Build Coastguard Worker             SkASSERT(accessPattern == kDynamic_GrAccessPattern);
449*c8dee2aaSAndroid Build Coastguard Worker             break;
450*c8dee2aaSAndroid Build Coastguard Worker         case GrGpuBufferType::kXferGpuToCpu:
451*c8dee2aaSAndroid Build Coastguard Worker             SkASSERT(accessPattern == kDynamic_GrAccessPattern ||
452*c8dee2aaSAndroid Build Coastguard Worker                      accessPattern == kStream_GrAccessPattern);
453*c8dee2aaSAndroid Build Coastguard Worker             break;
454*c8dee2aaSAndroid Build Coastguard Worker         case GrGpuBufferType::kUniform:
455*c8dee2aaSAndroid Build Coastguard Worker             SkASSERT(accessPattern == kDynamic_GrAccessPattern);
456*c8dee2aaSAndroid Build Coastguard Worker             break;
457*c8dee2aaSAndroid Build Coastguard Worker     }
458*c8dee2aaSAndroid Build Coastguard Worker #endif
459*c8dee2aaSAndroid Build Coastguard Worker     return GrVkBuffer::Make(this, size, type, accessPattern);
460*c8dee2aaSAndroid Build Coastguard Worker }
461*c8dee2aaSAndroid Build Coastguard Worker 
onWritePixels(GrSurface * surface,SkIRect rect,GrColorType surfaceColorType,GrColorType srcColorType,const GrMipLevel texels[],int mipLevelCount,bool prepForTexSampling)462*c8dee2aaSAndroid Build Coastguard Worker bool GrVkGpu::onWritePixels(GrSurface* surface,
463*c8dee2aaSAndroid Build Coastguard Worker                             SkIRect rect,
464*c8dee2aaSAndroid Build Coastguard Worker                             GrColorType surfaceColorType,
465*c8dee2aaSAndroid Build Coastguard Worker                             GrColorType srcColorType,
466*c8dee2aaSAndroid Build Coastguard Worker                             const GrMipLevel texels[],
467*c8dee2aaSAndroid Build Coastguard Worker                             int mipLevelCount,
468*c8dee2aaSAndroid Build Coastguard Worker                             bool prepForTexSampling) {
469*c8dee2aaSAndroid Build Coastguard Worker     GrVkTexture* texture = static_cast<GrVkTexture*>(surface->asTexture());
470*c8dee2aaSAndroid Build Coastguard Worker     if (!texture) {
471*c8dee2aaSAndroid Build Coastguard Worker         return false;
472*c8dee2aaSAndroid Build Coastguard Worker     }
473*c8dee2aaSAndroid Build Coastguard Worker     GrVkImage* texImage = texture->textureImage();
474*c8dee2aaSAndroid Build Coastguard Worker 
475*c8dee2aaSAndroid Build Coastguard Worker     // Make sure we have at least the base level
476*c8dee2aaSAndroid Build Coastguard Worker     if (!mipLevelCount || !texels[0].fPixels) {
477*c8dee2aaSAndroid Build Coastguard Worker         return false;
478*c8dee2aaSAndroid Build Coastguard Worker     }
479*c8dee2aaSAndroid Build Coastguard Worker 
480*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!skgpu::VkFormatIsCompressed(texImage->imageFormat()));
481*c8dee2aaSAndroid Build Coastguard Worker     bool success = false;
482*c8dee2aaSAndroid Build Coastguard Worker     bool linearTiling = texImage->isLinearTiled();
483*c8dee2aaSAndroid Build Coastguard Worker     if (linearTiling) {
484*c8dee2aaSAndroid Build Coastguard Worker         if (mipLevelCount > 1) {
485*c8dee2aaSAndroid Build Coastguard Worker             SkDebugf("Can't upload mipmap data to linear tiled texture");
486*c8dee2aaSAndroid Build Coastguard Worker             return false;
487*c8dee2aaSAndroid Build Coastguard Worker         }
488*c8dee2aaSAndroid Build Coastguard Worker         if (VK_IMAGE_LAYOUT_PREINITIALIZED != texImage->currentLayout()) {
489*c8dee2aaSAndroid Build Coastguard Worker             // Need to change the layout to general in order to perform a host write
490*c8dee2aaSAndroid Build Coastguard Worker             texImage->setImageLayout(this,
491*c8dee2aaSAndroid Build Coastguard Worker                                      VK_IMAGE_LAYOUT_GENERAL,
492*c8dee2aaSAndroid Build Coastguard Worker                                      VK_ACCESS_HOST_WRITE_BIT,
493*c8dee2aaSAndroid Build Coastguard Worker                                      VK_PIPELINE_STAGE_HOST_BIT,
494*c8dee2aaSAndroid Build Coastguard Worker                                      false);
495*c8dee2aaSAndroid Build Coastguard Worker             GrSubmitInfo submitInfo;
496*c8dee2aaSAndroid Build Coastguard Worker             submitInfo.fSync = GrSyncCpu::kYes;
497*c8dee2aaSAndroid Build Coastguard Worker             if (!this->submitCommandBuffer(submitInfo)) {
498*c8dee2aaSAndroid Build Coastguard Worker                 return false;
499*c8dee2aaSAndroid Build Coastguard Worker             }
500*c8dee2aaSAndroid Build Coastguard Worker         }
501*c8dee2aaSAndroid Build Coastguard Worker         success = this->uploadTexDataLinear(texImage,
502*c8dee2aaSAndroid Build Coastguard Worker                                             rect,
503*c8dee2aaSAndroid Build Coastguard Worker                                             srcColorType,
504*c8dee2aaSAndroid Build Coastguard Worker                                             texels[0].fPixels,
505*c8dee2aaSAndroid Build Coastguard Worker                                             texels[0].fRowBytes);
506*c8dee2aaSAndroid Build Coastguard Worker     } else {
507*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(mipLevelCount <= (int)texImage->mipLevels());
508*c8dee2aaSAndroid Build Coastguard Worker         success = this->uploadTexDataOptimal(texImage,
509*c8dee2aaSAndroid Build Coastguard Worker                                              rect,
510*c8dee2aaSAndroid Build Coastguard Worker                                              srcColorType,
511*c8dee2aaSAndroid Build Coastguard Worker                                              texels,
512*c8dee2aaSAndroid Build Coastguard Worker                                              mipLevelCount);
513*c8dee2aaSAndroid Build Coastguard Worker         if (1 == mipLevelCount) {
514*c8dee2aaSAndroid Build Coastguard Worker             texture->markMipmapsDirty();
515*c8dee2aaSAndroid Build Coastguard Worker         }
516*c8dee2aaSAndroid Build Coastguard Worker     }
517*c8dee2aaSAndroid Build Coastguard Worker 
518*c8dee2aaSAndroid Build Coastguard Worker     if (prepForTexSampling) {
519*c8dee2aaSAndroid Build Coastguard Worker         texImage->setImageLayout(this,
520*c8dee2aaSAndroid Build Coastguard Worker                                       VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
521*c8dee2aaSAndroid Build Coastguard Worker                                       VK_ACCESS_SHADER_READ_BIT,
522*c8dee2aaSAndroid Build Coastguard Worker                                       VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
523*c8dee2aaSAndroid Build Coastguard Worker                                       false);
524*c8dee2aaSAndroid Build Coastguard Worker     }
525*c8dee2aaSAndroid Build Coastguard Worker 
526*c8dee2aaSAndroid Build Coastguard Worker     return success;
527*c8dee2aaSAndroid Build Coastguard Worker }
528*c8dee2aaSAndroid Build Coastguard Worker 
529*c8dee2aaSAndroid Build Coastguard Worker // When we update vertex/index buffers via transfers we assume that they may have been used
530*c8dee2aaSAndroid Build Coastguard Worker // previously in draws and will be used again in draws afterwards. So we put a barrier before and
531*c8dee2aaSAndroid Build Coastguard Worker // after. If we had a mechanism for gathering the buffers that will be used in a GrVkOpsRenderPass
532*c8dee2aaSAndroid Build Coastguard Worker // *before* we begin a subpass we could do this lazily and non-redundantly by tracking the "last
533*c8dee2aaSAndroid Build Coastguard Worker // usage" on the GrVkBuffer. Then Pass 1 draw, xfer, xfer, xfer, Pass 2 draw  would insert just two
534*c8dee2aaSAndroid Build Coastguard Worker // barriers: one before the first xfer and one before Pass 2. Currently, we'd use six barriers.
535*c8dee2aaSAndroid Build Coastguard Worker // Pass false as "after" before the transfer and true after the transfer.
add_transfer_dst_buffer_mem_barrier(GrVkGpu * gpu,GrVkBuffer * dst,size_t offset,size_t size,bool after)536*c8dee2aaSAndroid Build Coastguard Worker static void add_transfer_dst_buffer_mem_barrier(GrVkGpu* gpu,
537*c8dee2aaSAndroid Build Coastguard Worker                                                 GrVkBuffer* dst,
538*c8dee2aaSAndroid Build Coastguard Worker                                                 size_t offset,
539*c8dee2aaSAndroid Build Coastguard Worker                                                 size_t size,
540*c8dee2aaSAndroid Build Coastguard Worker                                                 bool after) {
541*c8dee2aaSAndroid Build Coastguard Worker     if (dst->intendedType() != GrGpuBufferType::kIndex &&
542*c8dee2aaSAndroid Build Coastguard Worker         dst->intendedType() != GrGpuBufferType::kVertex) {
543*c8dee2aaSAndroid Build Coastguard Worker         return;
544*c8dee2aaSAndroid Build Coastguard Worker     }
545*c8dee2aaSAndroid Build Coastguard Worker 
546*c8dee2aaSAndroid Build Coastguard Worker     VkAccessFlags srcAccessMask = dst->intendedType() == GrGpuBufferType::kIndex
547*c8dee2aaSAndroid Build Coastguard Worker                                           ? VK_ACCESS_INDEX_READ_BIT
548*c8dee2aaSAndroid Build Coastguard Worker                                           : VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
549*c8dee2aaSAndroid Build Coastguard Worker     VkAccessFlags dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
550*c8dee2aaSAndroid Build Coastguard Worker 
551*c8dee2aaSAndroid Build Coastguard Worker     VkPipelineStageFlagBits srcPipelineStageFlags = VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
552*c8dee2aaSAndroid Build Coastguard Worker     VkPipelineStageFlagBits dstPipelineStageFlags = VK_PIPELINE_STAGE_TRANSFER_BIT;
553*c8dee2aaSAndroid Build Coastguard Worker 
554*c8dee2aaSAndroid Build Coastguard Worker     if (after) {
555*c8dee2aaSAndroid Build Coastguard Worker         using std::swap;
556*c8dee2aaSAndroid Build Coastguard Worker         swap(srcAccessMask,         dstAccessMask        );
557*c8dee2aaSAndroid Build Coastguard Worker         swap(srcPipelineStageFlags, dstPipelineStageFlags);
558*c8dee2aaSAndroid Build Coastguard Worker     }
559*c8dee2aaSAndroid Build Coastguard Worker 
560*c8dee2aaSAndroid Build Coastguard Worker     VkBufferMemoryBarrier bufferMemoryBarrier = {
561*c8dee2aaSAndroid Build Coastguard Worker             VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,  // sType
562*c8dee2aaSAndroid Build Coastguard Worker             nullptr,                                  // pNext
563*c8dee2aaSAndroid Build Coastguard Worker             srcAccessMask,                            // srcAccessMask
564*c8dee2aaSAndroid Build Coastguard Worker             dstAccessMask,                            // dstAccessMask
565*c8dee2aaSAndroid Build Coastguard Worker             VK_QUEUE_FAMILY_IGNORED,                  // srcQueueFamilyIndex
566*c8dee2aaSAndroid Build Coastguard Worker             VK_QUEUE_FAMILY_IGNORED,                  // dstQueueFamilyIndex
567*c8dee2aaSAndroid Build Coastguard Worker             dst->vkBuffer(),                          // buffer
568*c8dee2aaSAndroid Build Coastguard Worker             offset,                                   // offset
569*c8dee2aaSAndroid Build Coastguard Worker             size,                                     // size
570*c8dee2aaSAndroid Build Coastguard Worker     };
571*c8dee2aaSAndroid Build Coastguard Worker 
572*c8dee2aaSAndroid Build Coastguard Worker     gpu->addBufferMemoryBarrier(srcPipelineStageFlags,
573*c8dee2aaSAndroid Build Coastguard Worker                                 dstPipelineStageFlags,
574*c8dee2aaSAndroid Build Coastguard Worker                                 /*byRegion=*/false,
575*c8dee2aaSAndroid Build Coastguard Worker                                 &bufferMemoryBarrier);
576*c8dee2aaSAndroid Build Coastguard Worker }
577*c8dee2aaSAndroid Build Coastguard Worker 
onTransferFromBufferToBuffer(sk_sp<GrGpuBuffer> src,size_t srcOffset,sk_sp<GrGpuBuffer> dst,size_t dstOffset,size_t size)578*c8dee2aaSAndroid Build Coastguard Worker bool GrVkGpu::onTransferFromBufferToBuffer(sk_sp<GrGpuBuffer> src,
579*c8dee2aaSAndroid Build Coastguard Worker                                            size_t srcOffset,
580*c8dee2aaSAndroid Build Coastguard Worker                                            sk_sp<GrGpuBuffer> dst,
581*c8dee2aaSAndroid Build Coastguard Worker                                            size_t dstOffset,
582*c8dee2aaSAndroid Build Coastguard Worker                                            size_t size) {
583*c8dee2aaSAndroid Build Coastguard Worker     if (!this->currentCommandBuffer()) {
584*c8dee2aaSAndroid Build Coastguard Worker         return false;
585*c8dee2aaSAndroid Build Coastguard Worker     }
586*c8dee2aaSAndroid Build Coastguard Worker 
587*c8dee2aaSAndroid Build Coastguard Worker     VkBufferCopy copyRegion;
588*c8dee2aaSAndroid Build Coastguard Worker     copyRegion.srcOffset = srcOffset;
589*c8dee2aaSAndroid Build Coastguard Worker     copyRegion.dstOffset = dstOffset;
590*c8dee2aaSAndroid Build Coastguard Worker     copyRegion.size = size;
591*c8dee2aaSAndroid Build Coastguard Worker 
592*c8dee2aaSAndroid Build Coastguard Worker     add_transfer_dst_buffer_mem_barrier(this,
593*c8dee2aaSAndroid Build Coastguard Worker                                         static_cast<GrVkBuffer*>(dst.get()),
594*c8dee2aaSAndroid Build Coastguard Worker                                         dstOffset,
595*c8dee2aaSAndroid Build Coastguard Worker                                         size,
596*c8dee2aaSAndroid Build Coastguard Worker                                         /*after=*/false);
597*c8dee2aaSAndroid Build Coastguard Worker     this->currentCommandBuffer()->copyBuffer(this, std::move(src), dst, 1, &copyRegion);
598*c8dee2aaSAndroid Build Coastguard Worker     add_transfer_dst_buffer_mem_barrier(this,
599*c8dee2aaSAndroid Build Coastguard Worker                                         static_cast<GrVkBuffer*>(dst.get()),
600*c8dee2aaSAndroid Build Coastguard Worker                                         dstOffset,
601*c8dee2aaSAndroid Build Coastguard Worker                                         size,
602*c8dee2aaSAndroid Build Coastguard Worker                                         /*after=*/true);
603*c8dee2aaSAndroid Build Coastguard Worker 
604*c8dee2aaSAndroid Build Coastguard Worker     return true;
605*c8dee2aaSAndroid Build Coastguard Worker }
606*c8dee2aaSAndroid Build Coastguard Worker 
onTransferPixelsTo(GrTexture * texture,SkIRect rect,GrColorType surfaceColorType,GrColorType bufferColorType,sk_sp<GrGpuBuffer> transferBuffer,size_t bufferOffset,size_t rowBytes)607*c8dee2aaSAndroid Build Coastguard Worker bool GrVkGpu::onTransferPixelsTo(GrTexture* texture,
608*c8dee2aaSAndroid Build Coastguard Worker                                  SkIRect rect,
609*c8dee2aaSAndroid Build Coastguard Worker                                  GrColorType surfaceColorType,
610*c8dee2aaSAndroid Build Coastguard Worker                                  GrColorType bufferColorType,
611*c8dee2aaSAndroid Build Coastguard Worker                                  sk_sp<GrGpuBuffer> transferBuffer,
612*c8dee2aaSAndroid Build Coastguard Worker                                  size_t bufferOffset,
613*c8dee2aaSAndroid Build Coastguard Worker                                  size_t rowBytes) {
614*c8dee2aaSAndroid Build Coastguard Worker     if (!this->currentCommandBuffer()) {
615*c8dee2aaSAndroid Build Coastguard Worker         return false;
616*c8dee2aaSAndroid Build Coastguard Worker     }
617*c8dee2aaSAndroid Build Coastguard Worker 
618*c8dee2aaSAndroid Build Coastguard Worker     size_t bpp = GrColorTypeBytesPerPixel(bufferColorType);
619*c8dee2aaSAndroid Build Coastguard Worker     if (GrBackendFormatBytesPerPixel(texture->backendFormat()) != bpp) {
620*c8dee2aaSAndroid Build Coastguard Worker         return false;
621*c8dee2aaSAndroid Build Coastguard Worker     }
622*c8dee2aaSAndroid Build Coastguard Worker 
623*c8dee2aaSAndroid Build Coastguard Worker     // Vulkan only supports offsets that are both 4-byte aligned and aligned to a pixel.
624*c8dee2aaSAndroid Build Coastguard Worker     if ((bufferOffset & 0x3) || (bufferOffset % bpp)) {
625*c8dee2aaSAndroid Build Coastguard Worker         return false;
626*c8dee2aaSAndroid Build Coastguard Worker     }
627*c8dee2aaSAndroid Build Coastguard Worker     GrVkTexture* tex = static_cast<GrVkTexture*>(texture);
628*c8dee2aaSAndroid Build Coastguard Worker     if (!tex) {
629*c8dee2aaSAndroid Build Coastguard Worker         return false;
630*c8dee2aaSAndroid Build Coastguard Worker     }
631*c8dee2aaSAndroid Build Coastguard Worker     GrVkImage* vkImage = tex->textureImage();
632*c8dee2aaSAndroid Build Coastguard Worker     VkFormat format = vkImage->imageFormat();
633*c8dee2aaSAndroid Build Coastguard Worker 
634*c8dee2aaSAndroid Build Coastguard Worker     // Can't transfer compressed data
635*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!skgpu::VkFormatIsCompressed(format));
636*c8dee2aaSAndroid Build Coastguard Worker 
637*c8dee2aaSAndroid Build Coastguard Worker     if (!transferBuffer) {
638*c8dee2aaSAndroid Build Coastguard Worker         return false;
639*c8dee2aaSAndroid Build Coastguard Worker     }
640*c8dee2aaSAndroid Build Coastguard Worker 
641*c8dee2aaSAndroid Build Coastguard Worker     if (bufferColorType != this->vkCaps().transferColorType(format, surfaceColorType)) {
642*c8dee2aaSAndroid Build Coastguard Worker         return false;
643*c8dee2aaSAndroid Build Coastguard Worker     }
644*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(skgpu::VkFormatBytesPerBlock(format) == GrColorTypeBytesPerPixel(bufferColorType));
645*c8dee2aaSAndroid Build Coastguard Worker 
646*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(SkIRect::MakeSize(texture->dimensions()).contains(rect));
647*c8dee2aaSAndroid Build Coastguard Worker 
648*c8dee2aaSAndroid Build Coastguard Worker     // Set up copy region
649*c8dee2aaSAndroid Build Coastguard Worker     VkBufferImageCopy region;
650*c8dee2aaSAndroid Build Coastguard Worker     memset(&region, 0, sizeof(VkBufferImageCopy));
651*c8dee2aaSAndroid Build Coastguard Worker     region.bufferOffset = bufferOffset;
652*c8dee2aaSAndroid Build Coastguard Worker     region.bufferRowLength = (uint32_t)(rowBytes/bpp);
653*c8dee2aaSAndroid Build Coastguard Worker     region.bufferImageHeight = 0;
654*c8dee2aaSAndroid Build Coastguard Worker     region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
655*c8dee2aaSAndroid Build Coastguard Worker     region.imageOffset = { rect.left(), rect.top(), 0 };
656*c8dee2aaSAndroid Build Coastguard Worker     region.imageExtent = { (uint32_t)rect.width(), (uint32_t)rect.height(), 1 };
657*c8dee2aaSAndroid Build Coastguard Worker 
658*c8dee2aaSAndroid Build Coastguard Worker     // Change layout of our target so it can be copied to
659*c8dee2aaSAndroid Build Coastguard Worker     vkImage->setImageLayout(this,
660*c8dee2aaSAndroid Build Coastguard Worker                             VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
661*c8dee2aaSAndroid Build Coastguard Worker                             VK_ACCESS_TRANSFER_WRITE_BIT,
662*c8dee2aaSAndroid Build Coastguard Worker                             VK_PIPELINE_STAGE_TRANSFER_BIT,
663*c8dee2aaSAndroid Build Coastguard Worker                             false);
664*c8dee2aaSAndroid Build Coastguard Worker 
665*c8dee2aaSAndroid Build Coastguard Worker     const GrVkBuffer* vkBuffer = static_cast<GrVkBuffer*>(transferBuffer.get());
666*c8dee2aaSAndroid Build Coastguard Worker 
667*c8dee2aaSAndroid Build Coastguard Worker     // Copy the buffer to the image.
668*c8dee2aaSAndroid Build Coastguard Worker     this->currentCommandBuffer()->copyBufferToImage(this,
669*c8dee2aaSAndroid Build Coastguard Worker                                                     vkBuffer->vkBuffer(),
670*c8dee2aaSAndroid Build Coastguard Worker                                                     vkImage,
671*c8dee2aaSAndroid Build Coastguard Worker                                                     VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
672*c8dee2aaSAndroid Build Coastguard Worker                                                     1,
673*c8dee2aaSAndroid Build Coastguard Worker                                                     &region);
674*c8dee2aaSAndroid Build Coastguard Worker     this->currentCommandBuffer()->addGrBuffer(std::move(transferBuffer));
675*c8dee2aaSAndroid Build Coastguard Worker 
676*c8dee2aaSAndroid Build Coastguard Worker     tex->markMipmapsDirty();
677*c8dee2aaSAndroid Build Coastguard Worker     return true;
678*c8dee2aaSAndroid Build Coastguard Worker }
679*c8dee2aaSAndroid Build Coastguard Worker 
onTransferPixelsFrom(GrSurface * surface,SkIRect rect,GrColorType surfaceColorType,GrColorType bufferColorType,sk_sp<GrGpuBuffer> transferBuffer,size_t offset)680*c8dee2aaSAndroid Build Coastguard Worker bool GrVkGpu::onTransferPixelsFrom(GrSurface* surface,
681*c8dee2aaSAndroid Build Coastguard Worker                                    SkIRect rect,
682*c8dee2aaSAndroid Build Coastguard Worker                                    GrColorType surfaceColorType,
683*c8dee2aaSAndroid Build Coastguard Worker                                    GrColorType bufferColorType,
684*c8dee2aaSAndroid Build Coastguard Worker                                    sk_sp<GrGpuBuffer> transferBuffer,
685*c8dee2aaSAndroid Build Coastguard Worker                                    size_t offset) {
686*c8dee2aaSAndroid Build Coastguard Worker     if (!this->currentCommandBuffer()) {
687*c8dee2aaSAndroid Build Coastguard Worker         return false;
688*c8dee2aaSAndroid Build Coastguard Worker     }
689*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(surface);
690*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(transferBuffer);
691*c8dee2aaSAndroid Build Coastguard Worker     if (fProtectedContext == GrProtected::kYes) {
692*c8dee2aaSAndroid Build Coastguard Worker         return false;
693*c8dee2aaSAndroid Build Coastguard Worker     }
694*c8dee2aaSAndroid Build Coastguard Worker 
695*c8dee2aaSAndroid Build Coastguard Worker     GrVkImage* srcImage;
696*c8dee2aaSAndroid Build Coastguard Worker     if (GrVkRenderTarget* rt = static_cast<GrVkRenderTarget*>(surface->asRenderTarget())) {
697*c8dee2aaSAndroid Build Coastguard Worker         // Reading from render targets that wrap a secondary command buffer is not allowed since
698*c8dee2aaSAndroid Build Coastguard Worker         // it would require us to know the VkImage, which we don't have, as well as need us to
699*c8dee2aaSAndroid Build Coastguard Worker         // stop and start the VkRenderPass which we don't have access to.
700*c8dee2aaSAndroid Build Coastguard Worker         if (rt->wrapsSecondaryCommandBuffer()) {
701*c8dee2aaSAndroid Build Coastguard Worker             return false;
702*c8dee2aaSAndroid Build Coastguard Worker         }
703*c8dee2aaSAndroid Build Coastguard Worker         if (!rt->nonMSAAAttachment()) {
704*c8dee2aaSAndroid Build Coastguard Worker             return false;
705*c8dee2aaSAndroid Build Coastguard Worker         }
706*c8dee2aaSAndroid Build Coastguard Worker         srcImage = rt->nonMSAAAttachment();
707*c8dee2aaSAndroid Build Coastguard Worker     } else {
708*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(surface->asTexture());
709*c8dee2aaSAndroid Build Coastguard Worker         srcImage = static_cast<GrVkTexture*>(surface->asTexture())->textureImage();
710*c8dee2aaSAndroid Build Coastguard Worker     }
711*c8dee2aaSAndroid Build Coastguard Worker 
712*c8dee2aaSAndroid Build Coastguard Worker     VkFormat format = srcImage->imageFormat();
713*c8dee2aaSAndroid Build Coastguard Worker     if (bufferColorType != this->vkCaps().transferColorType(format, surfaceColorType)) {
714*c8dee2aaSAndroid Build Coastguard Worker         return false;
715*c8dee2aaSAndroid Build Coastguard Worker     }
716*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(skgpu::VkFormatBytesPerBlock(format) == GrColorTypeBytesPerPixel(bufferColorType));
717*c8dee2aaSAndroid Build Coastguard Worker 
718*c8dee2aaSAndroid Build Coastguard Worker     // Set up copy region
719*c8dee2aaSAndroid Build Coastguard Worker     VkBufferImageCopy region;
720*c8dee2aaSAndroid Build Coastguard Worker     memset(&region, 0, sizeof(VkBufferImageCopy));
721*c8dee2aaSAndroid Build Coastguard Worker     region.bufferOffset = offset;
722*c8dee2aaSAndroid Build Coastguard Worker     region.bufferRowLength = rect.width();
723*c8dee2aaSAndroid Build Coastguard Worker     region.bufferImageHeight = 0;
724*c8dee2aaSAndroid Build Coastguard Worker     region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
725*c8dee2aaSAndroid Build Coastguard Worker     region.imageOffset = {rect.left(), rect.top(), 0};
726*c8dee2aaSAndroid Build Coastguard Worker     region.imageExtent = {(uint32_t)rect.width(), (uint32_t)rect.height(), 1};
727*c8dee2aaSAndroid Build Coastguard Worker 
728*c8dee2aaSAndroid Build Coastguard Worker     srcImage->setImageLayout(this,
729*c8dee2aaSAndroid Build Coastguard Worker                              VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
730*c8dee2aaSAndroid Build Coastguard Worker                              VK_ACCESS_TRANSFER_READ_BIT,
731*c8dee2aaSAndroid Build Coastguard Worker                              VK_PIPELINE_STAGE_TRANSFER_BIT,
732*c8dee2aaSAndroid Build Coastguard Worker                              false);
733*c8dee2aaSAndroid Build Coastguard Worker 
734*c8dee2aaSAndroid Build Coastguard Worker     this->currentCommandBuffer()->copyImageToBuffer(this, srcImage,
735*c8dee2aaSAndroid Build Coastguard Worker                                                     VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
736*c8dee2aaSAndroid Build Coastguard Worker                                                     transferBuffer, 1, &region);
737*c8dee2aaSAndroid Build Coastguard Worker 
738*c8dee2aaSAndroid Build Coastguard Worker     GrVkBuffer* vkBuffer = static_cast<GrVkBuffer*>(transferBuffer.get());
739*c8dee2aaSAndroid Build Coastguard Worker     // Make sure the copy to buffer has finished.
740*c8dee2aaSAndroid Build Coastguard Worker     vkBuffer->addMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT,
741*c8dee2aaSAndroid Build Coastguard Worker                                VK_ACCESS_HOST_READ_BIT,
742*c8dee2aaSAndroid Build Coastguard Worker                                VK_PIPELINE_STAGE_TRANSFER_BIT,
743*c8dee2aaSAndroid Build Coastguard Worker                                VK_PIPELINE_STAGE_HOST_BIT,
744*c8dee2aaSAndroid Build Coastguard Worker                                false);
745*c8dee2aaSAndroid Build Coastguard Worker     return true;
746*c8dee2aaSAndroid Build Coastguard Worker }
747*c8dee2aaSAndroid Build Coastguard Worker 
resolveImage(GrSurface * dst,GrVkRenderTarget * src,const SkIRect & srcRect,const SkIPoint & dstPoint)748*c8dee2aaSAndroid Build Coastguard Worker void GrVkGpu::resolveImage(GrSurface* dst, GrVkRenderTarget* src, const SkIRect& srcRect,
749*c8dee2aaSAndroid Build Coastguard Worker                            const SkIPoint& dstPoint) {
750*c8dee2aaSAndroid Build Coastguard Worker     if (!this->currentCommandBuffer()) {
751*c8dee2aaSAndroid Build Coastguard Worker         return;
752*c8dee2aaSAndroid Build Coastguard Worker     }
753*c8dee2aaSAndroid Build Coastguard Worker 
754*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(dst);
755*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(src && src->colorAttachment() && src->colorAttachment()->numSamples() > 1);
756*c8dee2aaSAndroid Build Coastguard Worker 
757*c8dee2aaSAndroid Build Coastguard Worker     VkImageResolve resolveInfo;
758*c8dee2aaSAndroid Build Coastguard Worker     resolveInfo.srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1};
759*c8dee2aaSAndroid Build Coastguard Worker     resolveInfo.srcOffset = {srcRect.fLeft, srcRect.fTop, 0};
760*c8dee2aaSAndroid Build Coastguard Worker     resolveInfo.dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1};
761*c8dee2aaSAndroid Build Coastguard Worker     resolveInfo.dstOffset = {dstPoint.fX, dstPoint.fY, 0};
762*c8dee2aaSAndroid Build Coastguard Worker     resolveInfo.extent = {(uint32_t)srcRect.width(), (uint32_t)srcRect.height(), 1};
763*c8dee2aaSAndroid Build Coastguard Worker 
764*c8dee2aaSAndroid Build Coastguard Worker     GrVkImage* dstImage;
765*c8dee2aaSAndroid Build Coastguard Worker     GrRenderTarget* dstRT = dst->asRenderTarget();
766*c8dee2aaSAndroid Build Coastguard Worker     GrTexture* dstTex = dst->asTexture();
767*c8dee2aaSAndroid Build Coastguard Worker     if (dstTex) {
768*c8dee2aaSAndroid Build Coastguard Worker         dstImage = static_cast<GrVkTexture*>(dstTex)->textureImage();
769*c8dee2aaSAndroid Build Coastguard Worker     } else {
770*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(dst->asRenderTarget());
771*c8dee2aaSAndroid Build Coastguard Worker         dstImage = static_cast<GrVkRenderTarget*>(dstRT)->nonMSAAAttachment();
772*c8dee2aaSAndroid Build Coastguard Worker     }
773*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(dstImage);
774*c8dee2aaSAndroid Build Coastguard Worker 
775*c8dee2aaSAndroid Build Coastguard Worker     dstImage->setImageLayout(this,
776*c8dee2aaSAndroid Build Coastguard Worker                              VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
777*c8dee2aaSAndroid Build Coastguard Worker                              VK_ACCESS_TRANSFER_WRITE_BIT,
778*c8dee2aaSAndroid Build Coastguard Worker                              VK_PIPELINE_STAGE_TRANSFER_BIT,
779*c8dee2aaSAndroid Build Coastguard Worker                              false);
780*c8dee2aaSAndroid Build Coastguard Worker 
781*c8dee2aaSAndroid Build Coastguard Worker     src->colorAttachment()->setImageLayout(this,
782*c8dee2aaSAndroid Build Coastguard Worker                                            VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
783*c8dee2aaSAndroid Build Coastguard Worker                                            VK_ACCESS_TRANSFER_READ_BIT,
784*c8dee2aaSAndroid Build Coastguard Worker                                            VK_PIPELINE_STAGE_TRANSFER_BIT,
785*c8dee2aaSAndroid Build Coastguard Worker                                            false);
786*c8dee2aaSAndroid Build Coastguard Worker     this->currentCommandBuffer()->addGrSurface(sk_ref_sp<const GrSurface>(src->colorAttachment()));
787*c8dee2aaSAndroid Build Coastguard Worker     this->currentCommandBuffer()->addGrSurface(sk_ref_sp<const GrSurface>(dst));
788*c8dee2aaSAndroid Build Coastguard Worker     this->currentCommandBuffer()->resolveImage(this, *src->colorAttachment(), *dstImage, 1,
789*c8dee2aaSAndroid Build Coastguard Worker                                                &resolveInfo);
790*c8dee2aaSAndroid Build Coastguard Worker }
791*c8dee2aaSAndroid Build Coastguard Worker 
onResolveRenderTarget(GrRenderTarget * target,const SkIRect & resolveRect)792*c8dee2aaSAndroid Build Coastguard Worker void GrVkGpu::onResolveRenderTarget(GrRenderTarget* target, const SkIRect& resolveRect) {
793*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(target->numSamples() > 1);
794*c8dee2aaSAndroid Build Coastguard Worker     GrVkRenderTarget* rt = static_cast<GrVkRenderTarget*>(target);
795*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(rt->colorAttachmentView() && rt->resolveAttachmentView());
796*c8dee2aaSAndroid Build Coastguard Worker 
797*c8dee2aaSAndroid Build Coastguard Worker     if (this->vkCaps().renderTargetSupportsDiscardableMSAA(rt)) {
798*c8dee2aaSAndroid Build Coastguard Worker         // We would have resolved the RT during the render pass;
799*c8dee2aaSAndroid Build Coastguard Worker         return;
800*c8dee2aaSAndroid Build Coastguard Worker     }
801*c8dee2aaSAndroid Build Coastguard Worker 
802*c8dee2aaSAndroid Build Coastguard Worker     this->resolveImage(target, rt, resolveRect,
803*c8dee2aaSAndroid Build Coastguard Worker                        SkIPoint::Make(resolveRect.x(), resolveRect.y()));
804*c8dee2aaSAndroid Build Coastguard Worker }
805*c8dee2aaSAndroid Build Coastguard Worker 
uploadTexDataLinear(GrVkImage * texImage,SkIRect rect,GrColorType dataColorType,const void * data,size_t rowBytes)806*c8dee2aaSAndroid Build Coastguard Worker bool GrVkGpu::uploadTexDataLinear(GrVkImage* texImage,
807*c8dee2aaSAndroid Build Coastguard Worker                                   SkIRect rect,
808*c8dee2aaSAndroid Build Coastguard Worker                                   GrColorType dataColorType,
809*c8dee2aaSAndroid Build Coastguard Worker                                   const void* data,
810*c8dee2aaSAndroid Build Coastguard Worker                                   size_t rowBytes) {
811*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(data);
812*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(texImage->isLinearTiled());
813*c8dee2aaSAndroid Build Coastguard Worker 
814*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(SkIRect::MakeSize(texImage->dimensions()).contains(rect));
815*c8dee2aaSAndroid Build Coastguard Worker 
816*c8dee2aaSAndroid Build Coastguard Worker     size_t bpp = GrColorTypeBytesPerPixel(dataColorType);
817*c8dee2aaSAndroid Build Coastguard Worker     size_t trimRowBytes = rect.width() * bpp;
818*c8dee2aaSAndroid Build Coastguard Worker 
819*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(VK_IMAGE_LAYOUT_PREINITIALIZED == texImage->currentLayout() ||
820*c8dee2aaSAndroid Build Coastguard Worker              VK_IMAGE_LAYOUT_GENERAL == texImage->currentLayout());
821*c8dee2aaSAndroid Build Coastguard Worker     const VkImageSubresource subres = {
822*c8dee2aaSAndroid Build Coastguard Worker         VK_IMAGE_ASPECT_COLOR_BIT,
823*c8dee2aaSAndroid Build Coastguard Worker         0,  // mipLevel
824*c8dee2aaSAndroid Build Coastguard Worker         0,  // arraySlice
825*c8dee2aaSAndroid Build Coastguard Worker     };
826*c8dee2aaSAndroid Build Coastguard Worker     VkSubresourceLayout layout;
827*c8dee2aaSAndroid Build Coastguard Worker 
828*c8dee2aaSAndroid Build Coastguard Worker     const skgpu::VulkanInterface* interface = this->vkInterface();
829*c8dee2aaSAndroid Build Coastguard Worker 
830*c8dee2aaSAndroid Build Coastguard Worker     GR_VK_CALL(interface, GetImageSubresourceLayout(fDevice,
831*c8dee2aaSAndroid Build Coastguard Worker                                                     texImage->image(),
832*c8dee2aaSAndroid Build Coastguard Worker                                                     &subres,
833*c8dee2aaSAndroid Build Coastguard Worker                                                     &layout));
834*c8dee2aaSAndroid Build Coastguard Worker 
835*c8dee2aaSAndroid Build Coastguard Worker     const skgpu::VulkanAlloc& alloc = texImage->alloc();
836*c8dee2aaSAndroid Build Coastguard Worker     if (VK_NULL_HANDLE == alloc.fMemory) {
837*c8dee2aaSAndroid Build Coastguard Worker         return false;
838*c8dee2aaSAndroid Build Coastguard Worker     }
839*c8dee2aaSAndroid Build Coastguard Worker     VkDeviceSize offset = rect.top()*layout.rowPitch + rect.left()*bpp;
840*c8dee2aaSAndroid Build Coastguard Worker     VkDeviceSize size = rect.height()*layout.rowPitch;
841*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(size + offset <= alloc.fSize);
842*c8dee2aaSAndroid Build Coastguard Worker     auto checkResult = [this](VkResult result) {
843*c8dee2aaSAndroid Build Coastguard Worker         return this->checkVkResult(result);
844*c8dee2aaSAndroid Build Coastguard Worker     };
845*c8dee2aaSAndroid Build Coastguard Worker     auto allocator = this->memoryAllocator();
846*c8dee2aaSAndroid Build Coastguard Worker     void* mapPtr = skgpu::VulkanMemory::MapAlloc(allocator, alloc, checkResult);
847*c8dee2aaSAndroid Build Coastguard Worker     if (!mapPtr) {
848*c8dee2aaSAndroid Build Coastguard Worker         return false;
849*c8dee2aaSAndroid Build Coastguard Worker     }
850*c8dee2aaSAndroid Build Coastguard Worker     mapPtr = reinterpret_cast<char*>(mapPtr) + offset;
851*c8dee2aaSAndroid Build Coastguard Worker 
852*c8dee2aaSAndroid Build Coastguard Worker     SkRectMemcpy(mapPtr,
853*c8dee2aaSAndroid Build Coastguard Worker                  static_cast<size_t>(layout.rowPitch),
854*c8dee2aaSAndroid Build Coastguard Worker                  data,
855*c8dee2aaSAndroid Build Coastguard Worker                  rowBytes,
856*c8dee2aaSAndroid Build Coastguard Worker                  trimRowBytes,
857*c8dee2aaSAndroid Build Coastguard Worker                  rect.height());
858*c8dee2aaSAndroid Build Coastguard Worker 
859*c8dee2aaSAndroid Build Coastguard Worker     skgpu::VulkanMemory::FlushMappedAlloc(allocator, alloc, offset, size, checkResult);
860*c8dee2aaSAndroid Build Coastguard Worker     skgpu::VulkanMemory::UnmapAlloc(allocator, alloc);
861*c8dee2aaSAndroid Build Coastguard Worker 
862*c8dee2aaSAndroid Build Coastguard Worker     return true;
863*c8dee2aaSAndroid Build Coastguard Worker }
864*c8dee2aaSAndroid Build Coastguard Worker 
865*c8dee2aaSAndroid Build Coastguard Worker // This fills in the 'regions' vector in preparation for copying a buffer to an image.
866*c8dee2aaSAndroid Build Coastguard Worker // 'individualMipOffsets' is filled in as a side-effect.
fill_in_compressed_regions(GrStagingBufferManager * stagingBufferManager,TArray<VkBufferImageCopy> * regions,TArray<size_t> * individualMipOffsets,GrStagingBufferManager::Slice * slice,SkTextureCompressionType compression,VkFormat vkFormat,SkISize dimensions,skgpu::Mipmapped mipmapped)867*c8dee2aaSAndroid Build Coastguard Worker static size_t fill_in_compressed_regions(GrStagingBufferManager* stagingBufferManager,
868*c8dee2aaSAndroid Build Coastguard Worker                                          TArray<VkBufferImageCopy>* regions,
869*c8dee2aaSAndroid Build Coastguard Worker                                          TArray<size_t>* individualMipOffsets,
870*c8dee2aaSAndroid Build Coastguard Worker                                          GrStagingBufferManager::Slice* slice,
871*c8dee2aaSAndroid Build Coastguard Worker                                          SkTextureCompressionType compression,
872*c8dee2aaSAndroid Build Coastguard Worker                                          VkFormat vkFormat,
873*c8dee2aaSAndroid Build Coastguard Worker                                          SkISize dimensions,
874*c8dee2aaSAndroid Build Coastguard Worker                                          skgpu::Mipmapped mipmapped) {
875*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(compression != SkTextureCompressionType::kNone);
876*c8dee2aaSAndroid Build Coastguard Worker     int numMipLevels = 1;
877*c8dee2aaSAndroid Build Coastguard Worker     if (mipmapped == skgpu::Mipmapped::kYes) {
878*c8dee2aaSAndroid Build Coastguard Worker         numMipLevels = SkMipmap::ComputeLevelCount(dimensions.width(), dimensions.height()) + 1;
879*c8dee2aaSAndroid Build Coastguard Worker     }
880*c8dee2aaSAndroid Build Coastguard Worker 
881*c8dee2aaSAndroid Build Coastguard Worker     regions->reserve_exact(regions->size() + numMipLevels);
882*c8dee2aaSAndroid Build Coastguard Worker     individualMipOffsets->reserve_exact(individualMipOffsets->size() + numMipLevels);
883*c8dee2aaSAndroid Build Coastguard Worker 
884*c8dee2aaSAndroid Build Coastguard Worker     size_t bytesPerBlock = skgpu::VkFormatBytesPerBlock(vkFormat);
885*c8dee2aaSAndroid Build Coastguard Worker 
886*c8dee2aaSAndroid Build Coastguard Worker     size_t bufferSize = SkCompressedDataSize(
887*c8dee2aaSAndroid Build Coastguard Worker             compression, dimensions, individualMipOffsets, mipmapped == skgpu::Mipmapped::kYes);
888*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(individualMipOffsets->size() == numMipLevels);
889*c8dee2aaSAndroid Build Coastguard Worker 
890*c8dee2aaSAndroid Build Coastguard Worker     // Get a staging buffer slice to hold our mip data.
891*c8dee2aaSAndroid Build Coastguard Worker     // Vulkan requires offsets in the buffer to be aligned to multiple of the texel size and 4
892*c8dee2aaSAndroid Build Coastguard Worker     size_t alignment = bytesPerBlock;
893*c8dee2aaSAndroid Build Coastguard Worker     switch (alignment & 0b11) {
894*c8dee2aaSAndroid Build Coastguard Worker         case 0:                     break;   // alignment is already a multiple of 4.
895*c8dee2aaSAndroid Build Coastguard Worker         case 2:     alignment *= 2; break;   // alignment is a multiple of 2 but not 4.
896*c8dee2aaSAndroid Build Coastguard Worker         default:    alignment *= 4; break;   // alignment is not a multiple of 2.
897*c8dee2aaSAndroid Build Coastguard Worker     }
898*c8dee2aaSAndroid Build Coastguard Worker     *slice = stagingBufferManager->allocateStagingBufferSlice(bufferSize, alignment);
899*c8dee2aaSAndroid Build Coastguard Worker     if (!slice->fBuffer) {
900*c8dee2aaSAndroid Build Coastguard Worker         return 0;
901*c8dee2aaSAndroid Build Coastguard Worker     }
902*c8dee2aaSAndroid Build Coastguard Worker 
903*c8dee2aaSAndroid Build Coastguard Worker     for (int i = 0; i < numMipLevels; ++i) {
904*c8dee2aaSAndroid Build Coastguard Worker         VkBufferImageCopy& region = regions->push_back();
905*c8dee2aaSAndroid Build Coastguard Worker         memset(&region, 0, sizeof(VkBufferImageCopy));
906*c8dee2aaSAndroid Build Coastguard Worker         region.bufferOffset = slice->fOffset + (*individualMipOffsets)[i];
907*c8dee2aaSAndroid Build Coastguard Worker         SkISize revisedDimensions = skgpu::CompressedDimensions(compression, dimensions);
908*c8dee2aaSAndroid Build Coastguard Worker         region.bufferRowLength = revisedDimensions.width();
909*c8dee2aaSAndroid Build Coastguard Worker         region.bufferImageHeight = revisedDimensions.height();
910*c8dee2aaSAndroid Build Coastguard Worker         region.imageSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, SkToU32(i), 0, 1};
911*c8dee2aaSAndroid Build Coastguard Worker         region.imageOffset = {0, 0, 0};
912*c8dee2aaSAndroid Build Coastguard Worker         region.imageExtent = {SkToU32(dimensions.width()),
913*c8dee2aaSAndroid Build Coastguard Worker                               SkToU32(dimensions.height()), 1};
914*c8dee2aaSAndroid Build Coastguard Worker 
915*c8dee2aaSAndroid Build Coastguard Worker         dimensions = {std::max(1, dimensions.width() /2),
916*c8dee2aaSAndroid Build Coastguard Worker                       std::max(1, dimensions.height()/2)};
917*c8dee2aaSAndroid Build Coastguard Worker     }
918*c8dee2aaSAndroid Build Coastguard Worker 
919*c8dee2aaSAndroid Build Coastguard Worker     return bufferSize;
920*c8dee2aaSAndroid Build Coastguard Worker }
921*c8dee2aaSAndroid Build Coastguard Worker 
uploadTexDataOptimal(GrVkImage * texImage,SkIRect rect,GrColorType dataColorType,const GrMipLevel texels[],int mipLevelCount)922*c8dee2aaSAndroid Build Coastguard Worker bool GrVkGpu::uploadTexDataOptimal(GrVkImage* texImage,
923*c8dee2aaSAndroid Build Coastguard Worker                                    SkIRect rect,
924*c8dee2aaSAndroid Build Coastguard Worker                                    GrColorType dataColorType,
925*c8dee2aaSAndroid Build Coastguard Worker                                    const GrMipLevel texels[],
926*c8dee2aaSAndroid Build Coastguard Worker                                    int mipLevelCount) {
927*c8dee2aaSAndroid Build Coastguard Worker     if (!this->currentCommandBuffer()) {
928*c8dee2aaSAndroid Build Coastguard Worker         return false;
929*c8dee2aaSAndroid Build Coastguard Worker     }
930*c8dee2aaSAndroid Build Coastguard Worker 
931*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!texImage->isLinearTiled());
932*c8dee2aaSAndroid Build Coastguard Worker     // The assumption is either that we have no mipmaps, or that our rect is the entire texture
933*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(mipLevelCount == 1 || rect == SkIRect::MakeSize(texImage->dimensions()));
934*c8dee2aaSAndroid Build Coastguard Worker 
935*c8dee2aaSAndroid Build Coastguard Worker     // We assume that if the texture has mip levels, we either upload to all the levels or just the
936*c8dee2aaSAndroid Build Coastguard Worker     // first.
937*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(mipLevelCount == 1 || mipLevelCount == (int)texImage->mipLevels());
938*c8dee2aaSAndroid Build Coastguard Worker 
939*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!rect.isEmpty());
940*c8dee2aaSAndroid Build Coastguard Worker 
941*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(this->vkCaps().surfaceSupportsWritePixels(texImage));
942*c8dee2aaSAndroid Build Coastguard Worker 
943*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(this->vkCaps().isVkFormatTexturable(texImage->imageFormat()));
944*c8dee2aaSAndroid Build Coastguard Worker     size_t bpp = GrColorTypeBytesPerPixel(dataColorType);
945*c8dee2aaSAndroid Build Coastguard Worker 
946*c8dee2aaSAndroid Build Coastguard Worker     // texels is const.
947*c8dee2aaSAndroid Build Coastguard Worker     // But we may need to adjust the fPixels ptr based on the copyRect, or fRowBytes.
948*c8dee2aaSAndroid Build Coastguard Worker     // Because of this we need to make a non-const shallow copy of texels.
949*c8dee2aaSAndroid Build Coastguard Worker     AutoTArray<GrMipLevel> texelsShallowCopy(mipLevelCount);
950*c8dee2aaSAndroid Build Coastguard Worker     std::copy_n(texels, mipLevelCount, texelsShallowCopy.get());
951*c8dee2aaSAndroid Build Coastguard Worker 
952*c8dee2aaSAndroid Build Coastguard Worker     TArray<size_t> individualMipOffsets;
953*c8dee2aaSAndroid Build Coastguard Worker     size_t combinedBufferSize;
954*c8dee2aaSAndroid Build Coastguard Worker     if (mipLevelCount > 1) {
955*c8dee2aaSAndroid Build Coastguard Worker         combinedBufferSize = GrComputeTightCombinedBufferSize(bpp,
956*c8dee2aaSAndroid Build Coastguard Worker                                                               rect.size(),
957*c8dee2aaSAndroid Build Coastguard Worker                                                               &individualMipOffsets,
958*c8dee2aaSAndroid Build Coastguard Worker                                                               mipLevelCount);
959*c8dee2aaSAndroid Build Coastguard Worker     } else {
960*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(texelsShallowCopy[0].fPixels && texelsShallowCopy[0].fRowBytes);
961*c8dee2aaSAndroid Build Coastguard Worker         combinedBufferSize = rect.width()*rect.height()*bpp;
962*c8dee2aaSAndroid Build Coastguard Worker         individualMipOffsets.push_back(0);
963*c8dee2aaSAndroid Build Coastguard Worker     }
964*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(combinedBufferSize);
965*c8dee2aaSAndroid Build Coastguard Worker 
966*c8dee2aaSAndroid Build Coastguard Worker     // Get a staging buffer slice to hold our mip data.
967*c8dee2aaSAndroid Build Coastguard Worker     // Vulkan requires offsets in the buffer to be aligned to multiple of the texel size and 4
968*c8dee2aaSAndroid Build Coastguard Worker     size_t alignment = bpp;
969*c8dee2aaSAndroid Build Coastguard Worker     switch (alignment & 0b11) {
970*c8dee2aaSAndroid Build Coastguard Worker         case 0:                     break;   // alignment is already a multiple of 4.
971*c8dee2aaSAndroid Build Coastguard Worker         case 2:     alignment *= 2; break;   // alignment is a multiple of 2 but not 4.
972*c8dee2aaSAndroid Build Coastguard Worker         default:    alignment *= 4; break;   // alignment is not a multiple of 2.
973*c8dee2aaSAndroid Build Coastguard Worker     }
974*c8dee2aaSAndroid Build Coastguard Worker     GrStagingBufferManager::Slice slice =
975*c8dee2aaSAndroid Build Coastguard Worker             fStagingBufferManager.allocateStagingBufferSlice(combinedBufferSize, alignment);
976*c8dee2aaSAndroid Build Coastguard Worker     if (!slice.fBuffer) {
977*c8dee2aaSAndroid Build Coastguard Worker         return false;
978*c8dee2aaSAndroid Build Coastguard Worker     }
979*c8dee2aaSAndroid Build Coastguard Worker 
980*c8dee2aaSAndroid Build Coastguard Worker     int uploadLeft = rect.left();
981*c8dee2aaSAndroid Build Coastguard Worker     int uploadTop = rect.top();
982*c8dee2aaSAndroid Build Coastguard Worker 
983*c8dee2aaSAndroid Build Coastguard Worker     char* buffer = (char*) slice.fOffsetMapPtr;
984*c8dee2aaSAndroid Build Coastguard Worker     TArray<VkBufferImageCopy> regions(mipLevelCount);
985*c8dee2aaSAndroid Build Coastguard Worker 
986*c8dee2aaSAndroid Build Coastguard Worker     int currentWidth = rect.width();
987*c8dee2aaSAndroid Build Coastguard Worker     int currentHeight = rect.height();
988*c8dee2aaSAndroid Build Coastguard Worker     for (int currentMipLevel = 0; currentMipLevel < mipLevelCount; currentMipLevel++) {
989*c8dee2aaSAndroid Build Coastguard Worker         if (texelsShallowCopy[currentMipLevel].fPixels) {
990*c8dee2aaSAndroid Build Coastguard Worker             const size_t trimRowBytes = currentWidth * bpp;
991*c8dee2aaSAndroid Build Coastguard Worker             const size_t rowBytes = texelsShallowCopy[currentMipLevel].fRowBytes;
992*c8dee2aaSAndroid Build Coastguard Worker 
993*c8dee2aaSAndroid Build Coastguard Worker             // copy data into the buffer, skipping the trailing bytes
994*c8dee2aaSAndroid Build Coastguard Worker             char* dst = buffer + individualMipOffsets[currentMipLevel];
995*c8dee2aaSAndroid Build Coastguard Worker             const char* src = (const char*)texelsShallowCopy[currentMipLevel].fPixels;
996*c8dee2aaSAndroid Build Coastguard Worker             SkRectMemcpy(dst, trimRowBytes, src, rowBytes, trimRowBytes, currentHeight);
997*c8dee2aaSAndroid Build Coastguard Worker 
998*c8dee2aaSAndroid Build Coastguard Worker             VkBufferImageCopy& region = regions.push_back();
999*c8dee2aaSAndroid Build Coastguard Worker             memset(&region, 0, sizeof(VkBufferImageCopy));
1000*c8dee2aaSAndroid Build Coastguard Worker             region.bufferOffset = slice.fOffset + individualMipOffsets[currentMipLevel];
1001*c8dee2aaSAndroid Build Coastguard Worker             region.bufferRowLength = currentWidth;
1002*c8dee2aaSAndroid Build Coastguard Worker             region.bufferImageHeight = currentHeight;
1003*c8dee2aaSAndroid Build Coastguard Worker             region.imageSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, SkToU32(currentMipLevel), 0, 1};
1004*c8dee2aaSAndroid Build Coastguard Worker             region.imageOffset = {uploadLeft, uploadTop, 0};
1005*c8dee2aaSAndroid Build Coastguard Worker             region.imageExtent = {(uint32_t)currentWidth, (uint32_t)currentHeight, 1};
1006*c8dee2aaSAndroid Build Coastguard Worker         }
1007*c8dee2aaSAndroid Build Coastguard Worker 
1008*c8dee2aaSAndroid Build Coastguard Worker         currentWidth  = std::max(1,  currentWidth/2);
1009*c8dee2aaSAndroid Build Coastguard Worker         currentHeight = std::max(1, currentHeight/2);
1010*c8dee2aaSAndroid Build Coastguard Worker     }
1011*c8dee2aaSAndroid Build Coastguard Worker 
1012*c8dee2aaSAndroid Build Coastguard Worker     // Change layout of our target so it can be copied to
1013*c8dee2aaSAndroid Build Coastguard Worker     texImage->setImageLayout(this,
1014*c8dee2aaSAndroid Build Coastguard Worker                              VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1015*c8dee2aaSAndroid Build Coastguard Worker                              VK_ACCESS_TRANSFER_WRITE_BIT,
1016*c8dee2aaSAndroid Build Coastguard Worker                              VK_PIPELINE_STAGE_TRANSFER_BIT,
1017*c8dee2aaSAndroid Build Coastguard Worker                              false);
1018*c8dee2aaSAndroid Build Coastguard Worker 
1019*c8dee2aaSAndroid Build Coastguard Worker     // Copy the buffer to the image. This call takes the raw VkBuffer instead of a GrGpuBuffer
1020*c8dee2aaSAndroid Build Coastguard Worker     // because we don't need the command buffer to ref the buffer here. The reason being is that
1021*c8dee2aaSAndroid Build Coastguard Worker     // the buffer is coming from the staging manager and the staging manager will make sure the
1022*c8dee2aaSAndroid Build Coastguard Worker     // command buffer has a ref on the buffer. This avoids having to add and remove a ref for ever
1023*c8dee2aaSAndroid Build Coastguard Worker     // upload in the frame.
1024*c8dee2aaSAndroid Build Coastguard Worker     GrVkBuffer* vkBuffer = static_cast<GrVkBuffer*>(slice.fBuffer);
1025*c8dee2aaSAndroid Build Coastguard Worker     this->currentCommandBuffer()->copyBufferToImage(this,
1026*c8dee2aaSAndroid Build Coastguard Worker                                                     vkBuffer->vkBuffer(),
1027*c8dee2aaSAndroid Build Coastguard Worker                                                     texImage,
1028*c8dee2aaSAndroid Build Coastguard Worker                                                     VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1029*c8dee2aaSAndroid Build Coastguard Worker                                                     regions.size(),
1030*c8dee2aaSAndroid Build Coastguard Worker                                                     regions.begin());
1031*c8dee2aaSAndroid Build Coastguard Worker     return true;
1032*c8dee2aaSAndroid Build Coastguard Worker }
1033*c8dee2aaSAndroid Build Coastguard Worker 
1034*c8dee2aaSAndroid Build Coastguard Worker // It's probably possible to roll this into uploadTexDataOptimal,
1035*c8dee2aaSAndroid Build Coastguard Worker // but for now it's easier to maintain as a separate entity.
uploadTexDataCompressed(GrVkImage * uploadTexture,SkTextureCompressionType compression,VkFormat vkFormat,SkISize dimensions,skgpu::Mipmapped mipmapped,const void * data,size_t dataSize)1036*c8dee2aaSAndroid Build Coastguard Worker bool GrVkGpu::uploadTexDataCompressed(GrVkImage* uploadTexture,
1037*c8dee2aaSAndroid Build Coastguard Worker                                       SkTextureCompressionType compression,
1038*c8dee2aaSAndroid Build Coastguard Worker                                       VkFormat vkFormat,
1039*c8dee2aaSAndroid Build Coastguard Worker                                       SkISize dimensions,
1040*c8dee2aaSAndroid Build Coastguard Worker                                       skgpu::Mipmapped mipmapped,
1041*c8dee2aaSAndroid Build Coastguard Worker                                       const void* data,
1042*c8dee2aaSAndroid Build Coastguard Worker                                       size_t dataSize) {
1043*c8dee2aaSAndroid Build Coastguard Worker     if (!this->currentCommandBuffer()) {
1044*c8dee2aaSAndroid Build Coastguard Worker         return false;
1045*c8dee2aaSAndroid Build Coastguard Worker     }
1046*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(data);
1047*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!uploadTexture->isLinearTiled());
1048*c8dee2aaSAndroid Build Coastguard Worker     // For now the assumption is that our rect is the entire texture.
1049*c8dee2aaSAndroid Build Coastguard Worker     // Compressed textures are read-only so this should be a reasonable assumption.
1050*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(dimensions.fWidth == uploadTexture->width() &&
1051*c8dee2aaSAndroid Build Coastguard Worker              dimensions.fHeight == uploadTexture->height());
1052*c8dee2aaSAndroid Build Coastguard Worker 
1053*c8dee2aaSAndroid Build Coastguard Worker     if (dimensions.fWidth == 0 || dimensions.fHeight  == 0) {
1054*c8dee2aaSAndroid Build Coastguard Worker         return false;
1055*c8dee2aaSAndroid Build Coastguard Worker     }
1056*c8dee2aaSAndroid Build Coastguard Worker 
1057*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(uploadTexture->imageFormat() == vkFormat);
1058*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(this->vkCaps().isVkFormatTexturable(vkFormat));
1059*c8dee2aaSAndroid Build Coastguard Worker 
1060*c8dee2aaSAndroid Build Coastguard Worker 
1061*c8dee2aaSAndroid Build Coastguard Worker     GrStagingBufferManager::Slice slice;
1062*c8dee2aaSAndroid Build Coastguard Worker     TArray<VkBufferImageCopy> regions;
1063*c8dee2aaSAndroid Build Coastguard Worker     TArray<size_t> individualMipOffsets;
1064*c8dee2aaSAndroid Build Coastguard Worker     SkDEBUGCODE(size_t combinedBufferSize =) fill_in_compressed_regions(&fStagingBufferManager,
1065*c8dee2aaSAndroid Build Coastguard Worker                                                                         &regions,
1066*c8dee2aaSAndroid Build Coastguard Worker                                                                         &individualMipOffsets,
1067*c8dee2aaSAndroid Build Coastguard Worker                                                                         &slice,
1068*c8dee2aaSAndroid Build Coastguard Worker                                                                         compression,
1069*c8dee2aaSAndroid Build Coastguard Worker                                                                         vkFormat,
1070*c8dee2aaSAndroid Build Coastguard Worker                                                                         dimensions,
1071*c8dee2aaSAndroid Build Coastguard Worker                                                                         mipmapped);
1072*c8dee2aaSAndroid Build Coastguard Worker     if (!slice.fBuffer) {
1073*c8dee2aaSAndroid Build Coastguard Worker         return false;
1074*c8dee2aaSAndroid Build Coastguard Worker     }
1075*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(dataSize == combinedBufferSize);
1076*c8dee2aaSAndroid Build Coastguard Worker 
1077*c8dee2aaSAndroid Build Coastguard Worker     {
1078*c8dee2aaSAndroid Build Coastguard Worker         char* buffer = (char*)slice.fOffsetMapPtr;
1079*c8dee2aaSAndroid Build Coastguard Worker         memcpy(buffer, data, dataSize);
1080*c8dee2aaSAndroid Build Coastguard Worker     }
1081*c8dee2aaSAndroid Build Coastguard Worker 
1082*c8dee2aaSAndroid Build Coastguard Worker     // Change layout of our target so it can be copied to
1083*c8dee2aaSAndroid Build Coastguard Worker     uploadTexture->setImageLayout(this,
1084*c8dee2aaSAndroid Build Coastguard Worker                                   VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1085*c8dee2aaSAndroid Build Coastguard Worker                                   VK_ACCESS_TRANSFER_WRITE_BIT,
1086*c8dee2aaSAndroid Build Coastguard Worker                                   VK_PIPELINE_STAGE_TRANSFER_BIT,
1087*c8dee2aaSAndroid Build Coastguard Worker                                   false);
1088*c8dee2aaSAndroid Build Coastguard Worker 
1089*c8dee2aaSAndroid Build Coastguard Worker     // Copy the buffer to the image. This call takes the raw VkBuffer instead of a GrGpuBuffer
1090*c8dee2aaSAndroid Build Coastguard Worker     // because we don't need the command buffer to ref the buffer here. The reason being is that
1091*c8dee2aaSAndroid Build Coastguard Worker     // the buffer is coming from the staging manager and the staging manager will make sure the
1092*c8dee2aaSAndroid Build Coastguard Worker     // command buffer has a ref on the buffer. This avoids having to add and remove a ref for ever
1093*c8dee2aaSAndroid Build Coastguard Worker     // upload in the frame.
1094*c8dee2aaSAndroid Build Coastguard Worker     GrVkBuffer* vkBuffer = static_cast<GrVkBuffer*>(slice.fBuffer);
1095*c8dee2aaSAndroid Build Coastguard Worker     this->currentCommandBuffer()->copyBufferToImage(this,
1096*c8dee2aaSAndroid Build Coastguard Worker                                                     vkBuffer->vkBuffer(),
1097*c8dee2aaSAndroid Build Coastguard Worker                                                     uploadTexture,
1098*c8dee2aaSAndroid Build Coastguard Worker                                                     VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1099*c8dee2aaSAndroid Build Coastguard Worker                                                     regions.size(),
1100*c8dee2aaSAndroid Build Coastguard Worker                                                     regions.begin());
1101*c8dee2aaSAndroid Build Coastguard Worker 
1102*c8dee2aaSAndroid Build Coastguard Worker     return true;
1103*c8dee2aaSAndroid Build Coastguard Worker }
1104*c8dee2aaSAndroid Build Coastguard Worker 
1105*c8dee2aaSAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////
1106*c8dee2aaSAndroid Build Coastguard Worker // TODO: make this take a skgpu::Mipmapped
onCreateTexture(SkISize dimensions,const GrBackendFormat & format,GrRenderable renderable,int renderTargetSampleCnt,skgpu::Budgeted budgeted,GrProtected isProtected,int mipLevelCount,uint32_t levelClearMask,std::string_view label)1107*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrTexture> GrVkGpu::onCreateTexture(SkISize dimensions,
1108*c8dee2aaSAndroid Build Coastguard Worker                                           const GrBackendFormat& format,
1109*c8dee2aaSAndroid Build Coastguard Worker                                           GrRenderable renderable,
1110*c8dee2aaSAndroid Build Coastguard Worker                                           int renderTargetSampleCnt,
1111*c8dee2aaSAndroid Build Coastguard Worker                                           skgpu::Budgeted budgeted,
1112*c8dee2aaSAndroid Build Coastguard Worker                                           GrProtected isProtected,
1113*c8dee2aaSAndroid Build Coastguard Worker                                           int mipLevelCount,
1114*c8dee2aaSAndroid Build Coastguard Worker                                           uint32_t levelClearMask,
1115*c8dee2aaSAndroid Build Coastguard Worker                                           std::string_view label) {
1116*c8dee2aaSAndroid Build Coastguard Worker     VkFormat pixelFormat;
1117*c8dee2aaSAndroid Build Coastguard Worker     SkAssertResult(GrBackendFormats::AsVkFormat(format, &pixelFormat));
1118*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!skgpu::VkFormatIsCompressed(pixelFormat));
1119*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(mipLevelCount > 0);
1120*c8dee2aaSAndroid Build Coastguard Worker 
1121*c8dee2aaSAndroid Build Coastguard Worker     GrMipmapStatus mipmapStatus =
1122*c8dee2aaSAndroid Build Coastguard Worker             mipLevelCount > 1 ? GrMipmapStatus::kDirty : GrMipmapStatus::kNotAllocated;
1123*c8dee2aaSAndroid Build Coastguard Worker 
1124*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<GrVkTexture> tex;
1125*c8dee2aaSAndroid Build Coastguard Worker     if (renderable == GrRenderable::kYes) {
1126*c8dee2aaSAndroid Build Coastguard Worker         tex = GrVkTextureRenderTarget::MakeNewTextureRenderTarget(
1127*c8dee2aaSAndroid Build Coastguard Worker                 this, budgeted, dimensions, pixelFormat, mipLevelCount, renderTargetSampleCnt,
1128*c8dee2aaSAndroid Build Coastguard Worker                 mipmapStatus, isProtected, label);
1129*c8dee2aaSAndroid Build Coastguard Worker     } else {
1130*c8dee2aaSAndroid Build Coastguard Worker         tex = GrVkTexture::MakeNewTexture(this, budgeted, dimensions, pixelFormat,
1131*c8dee2aaSAndroid Build Coastguard Worker                                           mipLevelCount, isProtected, mipmapStatus, label);
1132*c8dee2aaSAndroid Build Coastguard Worker     }
1133*c8dee2aaSAndroid Build Coastguard Worker 
1134*c8dee2aaSAndroid Build Coastguard Worker     if (!tex) {
1135*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
1136*c8dee2aaSAndroid Build Coastguard Worker     }
1137*c8dee2aaSAndroid Build Coastguard Worker 
1138*c8dee2aaSAndroid Build Coastguard Worker     if (levelClearMask) {
1139*c8dee2aaSAndroid Build Coastguard Worker         if (!this->currentCommandBuffer()) {
1140*c8dee2aaSAndroid Build Coastguard Worker             return nullptr;
1141*c8dee2aaSAndroid Build Coastguard Worker         }
1142*c8dee2aaSAndroid Build Coastguard Worker         STArray<1, VkImageSubresourceRange> ranges;
1143*c8dee2aaSAndroid Build Coastguard Worker         bool inRange = false;
1144*c8dee2aaSAndroid Build Coastguard Worker         GrVkImage* texImage = tex->textureImage();
1145*c8dee2aaSAndroid Build Coastguard Worker         for (uint32_t i = 0; i < texImage->mipLevels(); ++i) {
1146*c8dee2aaSAndroid Build Coastguard Worker             if (levelClearMask & (1U << i)) {
1147*c8dee2aaSAndroid Build Coastguard Worker                 if (inRange) {
1148*c8dee2aaSAndroid Build Coastguard Worker                     ranges.back().levelCount++;
1149*c8dee2aaSAndroid Build Coastguard Worker                 } else {
1150*c8dee2aaSAndroid Build Coastguard Worker                     auto& range = ranges.push_back();
1151*c8dee2aaSAndroid Build Coastguard Worker                     range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
1152*c8dee2aaSAndroid Build Coastguard Worker                     range.baseArrayLayer = 0;
1153*c8dee2aaSAndroid Build Coastguard Worker                     range.baseMipLevel = i;
1154*c8dee2aaSAndroid Build Coastguard Worker                     range.layerCount = 1;
1155*c8dee2aaSAndroid Build Coastguard Worker                     range.levelCount = 1;
1156*c8dee2aaSAndroid Build Coastguard Worker                     inRange = true;
1157*c8dee2aaSAndroid Build Coastguard Worker                 }
1158*c8dee2aaSAndroid Build Coastguard Worker             } else if (inRange) {
1159*c8dee2aaSAndroid Build Coastguard Worker                 inRange = false;
1160*c8dee2aaSAndroid Build Coastguard Worker             }
1161*c8dee2aaSAndroid Build Coastguard Worker         }
1162*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(!ranges.empty());
1163*c8dee2aaSAndroid Build Coastguard Worker         static constexpr VkClearColorValue kZeroClearColor = {};
1164*c8dee2aaSAndroid Build Coastguard Worker         texImage->setImageLayout(this, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1165*c8dee2aaSAndroid Build Coastguard Worker                             VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, false);
1166*c8dee2aaSAndroid Build Coastguard Worker         this->currentCommandBuffer()->clearColorImage(this, texImage, &kZeroClearColor,
1167*c8dee2aaSAndroid Build Coastguard Worker                                                       ranges.size(), ranges.begin());
1168*c8dee2aaSAndroid Build Coastguard Worker     }
1169*c8dee2aaSAndroid Build Coastguard Worker     return tex;
1170*c8dee2aaSAndroid Build Coastguard Worker }
1171*c8dee2aaSAndroid Build Coastguard Worker 
onCreateCompressedTexture(SkISize dimensions,const GrBackendFormat & format,skgpu::Budgeted budgeted,skgpu::Mipmapped mipmapped,GrProtected isProtected,const void * data,size_t dataSize)1172*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrTexture> GrVkGpu::onCreateCompressedTexture(SkISize dimensions,
1173*c8dee2aaSAndroid Build Coastguard Worker                                                     const GrBackendFormat& format,
1174*c8dee2aaSAndroid Build Coastguard Worker                                                     skgpu::Budgeted budgeted,
1175*c8dee2aaSAndroid Build Coastguard Worker                                                     skgpu::Mipmapped mipmapped,
1176*c8dee2aaSAndroid Build Coastguard Worker                                                     GrProtected isProtected,
1177*c8dee2aaSAndroid Build Coastguard Worker                                                     const void* data,
1178*c8dee2aaSAndroid Build Coastguard Worker                                                     size_t dataSize) {
1179*c8dee2aaSAndroid Build Coastguard Worker     VkFormat pixelFormat;
1180*c8dee2aaSAndroid Build Coastguard Worker     SkAssertResult(GrBackendFormats::AsVkFormat(format, &pixelFormat));
1181*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(skgpu::VkFormatIsCompressed(pixelFormat));
1182*c8dee2aaSAndroid Build Coastguard Worker 
1183*c8dee2aaSAndroid Build Coastguard Worker     int numMipLevels = 1;
1184*c8dee2aaSAndroid Build Coastguard Worker     if (mipmapped == skgpu::Mipmapped::kYes) {
1185*c8dee2aaSAndroid Build Coastguard Worker         numMipLevels = SkMipmap::ComputeLevelCount(dimensions.width(), dimensions.height())+1;
1186*c8dee2aaSAndroid Build Coastguard Worker     }
1187*c8dee2aaSAndroid Build Coastguard Worker 
1188*c8dee2aaSAndroid Build Coastguard Worker     GrMipmapStatus mipmapStatus = (mipmapped == skgpu::Mipmapped::kYes)
1189*c8dee2aaSAndroid Build Coastguard Worker                                           ? GrMipmapStatus::kValid
1190*c8dee2aaSAndroid Build Coastguard Worker                                           : GrMipmapStatus::kNotAllocated;
1191*c8dee2aaSAndroid Build Coastguard Worker 
1192*c8dee2aaSAndroid Build Coastguard Worker     auto tex = GrVkTexture::MakeNewTexture(this,
1193*c8dee2aaSAndroid Build Coastguard Worker                                            budgeted,
1194*c8dee2aaSAndroid Build Coastguard Worker                                            dimensions,
1195*c8dee2aaSAndroid Build Coastguard Worker                                            pixelFormat,
1196*c8dee2aaSAndroid Build Coastguard Worker                                            numMipLevels,
1197*c8dee2aaSAndroid Build Coastguard Worker                                            isProtected,
1198*c8dee2aaSAndroid Build Coastguard Worker                                            mipmapStatus,
1199*c8dee2aaSAndroid Build Coastguard Worker                                            /*label=*/"VkGpu_CreateCompressedTexture");
1200*c8dee2aaSAndroid Build Coastguard Worker     if (!tex) {
1201*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
1202*c8dee2aaSAndroid Build Coastguard Worker     }
1203*c8dee2aaSAndroid Build Coastguard Worker 
1204*c8dee2aaSAndroid Build Coastguard Worker     SkTextureCompressionType compression = GrBackendFormatToCompressionType(format);
1205*c8dee2aaSAndroid Build Coastguard Worker     if (!this->uploadTexDataCompressed(tex->textureImage(), compression, pixelFormat,
1206*c8dee2aaSAndroid Build Coastguard Worker                                        dimensions, mipmapped, data, dataSize)) {
1207*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
1208*c8dee2aaSAndroid Build Coastguard Worker     }
1209*c8dee2aaSAndroid Build Coastguard Worker 
1210*c8dee2aaSAndroid Build Coastguard Worker     return tex;
1211*c8dee2aaSAndroid Build Coastguard Worker }
1212*c8dee2aaSAndroid Build Coastguard Worker 
1213*c8dee2aaSAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////
1214*c8dee2aaSAndroid Build Coastguard Worker 
updateBuffer(sk_sp<GrVkBuffer> buffer,const void * src,VkDeviceSize offset,VkDeviceSize size)1215*c8dee2aaSAndroid Build Coastguard Worker bool GrVkGpu::updateBuffer(sk_sp<GrVkBuffer> buffer, const void* src,
1216*c8dee2aaSAndroid Build Coastguard Worker                            VkDeviceSize offset, VkDeviceSize size) {
1217*c8dee2aaSAndroid Build Coastguard Worker     if (!this->currentCommandBuffer()) {
1218*c8dee2aaSAndroid Build Coastguard Worker         return false;
1219*c8dee2aaSAndroid Build Coastguard Worker     }
1220*c8dee2aaSAndroid Build Coastguard Worker     add_transfer_dst_buffer_mem_barrier(this,
1221*c8dee2aaSAndroid Build Coastguard Worker                                         static_cast<GrVkBuffer*>(buffer.get()),
1222*c8dee2aaSAndroid Build Coastguard Worker                                         offset,
1223*c8dee2aaSAndroid Build Coastguard Worker                                         size,
1224*c8dee2aaSAndroid Build Coastguard Worker                                         /*after=*/false);
1225*c8dee2aaSAndroid Build Coastguard Worker     this->currentCommandBuffer()->updateBuffer(this, buffer, offset, size, src);
1226*c8dee2aaSAndroid Build Coastguard Worker     add_transfer_dst_buffer_mem_barrier(this,
1227*c8dee2aaSAndroid Build Coastguard Worker                                         static_cast<GrVkBuffer*>(buffer.get()),
1228*c8dee2aaSAndroid Build Coastguard Worker                                         offset,
1229*c8dee2aaSAndroid Build Coastguard Worker                                         size,
1230*c8dee2aaSAndroid Build Coastguard Worker                                         /*after=*/true);
1231*c8dee2aaSAndroid Build Coastguard Worker 
1232*c8dee2aaSAndroid Build Coastguard Worker     return true;
1233*c8dee2aaSAndroid Build Coastguard Worker }
1234*c8dee2aaSAndroid Build Coastguard Worker 
zeroBuffer(sk_sp<GrGpuBuffer> buffer)1235*c8dee2aaSAndroid Build Coastguard Worker bool GrVkGpu::zeroBuffer(sk_sp<GrGpuBuffer> buffer) {
1236*c8dee2aaSAndroid Build Coastguard Worker     if (!this->currentCommandBuffer()) {
1237*c8dee2aaSAndroid Build Coastguard Worker         return false;
1238*c8dee2aaSAndroid Build Coastguard Worker     }
1239*c8dee2aaSAndroid Build Coastguard Worker 
1240*c8dee2aaSAndroid Build Coastguard Worker     add_transfer_dst_buffer_mem_barrier(this,
1241*c8dee2aaSAndroid Build Coastguard Worker                                         static_cast<GrVkBuffer*>(buffer.get()),
1242*c8dee2aaSAndroid Build Coastguard Worker                                         /*offset=*/0,
1243*c8dee2aaSAndroid Build Coastguard Worker                                         buffer->size(),
1244*c8dee2aaSAndroid Build Coastguard Worker                                         /*after=*/false);
1245*c8dee2aaSAndroid Build Coastguard Worker     this->currentCommandBuffer()->fillBuffer(this,
1246*c8dee2aaSAndroid Build Coastguard Worker                                              buffer,
1247*c8dee2aaSAndroid Build Coastguard Worker                                              /*offset=*/0,
1248*c8dee2aaSAndroid Build Coastguard Worker                                              buffer->size(),
1249*c8dee2aaSAndroid Build Coastguard Worker                                              /*data=*/0);
1250*c8dee2aaSAndroid Build Coastguard Worker     add_transfer_dst_buffer_mem_barrier(this,
1251*c8dee2aaSAndroid Build Coastguard Worker                                         static_cast<GrVkBuffer*>(buffer.get()),
1252*c8dee2aaSAndroid Build Coastguard Worker                                         /*offset=*/0,
1253*c8dee2aaSAndroid Build Coastguard Worker                                         buffer->size(),
1254*c8dee2aaSAndroid Build Coastguard Worker                                         /*after=*/true);
1255*c8dee2aaSAndroid Build Coastguard Worker 
1256*c8dee2aaSAndroid Build Coastguard Worker     return true;
1257*c8dee2aaSAndroid Build Coastguard Worker }
1258*c8dee2aaSAndroid Build Coastguard Worker 
1259*c8dee2aaSAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////
1260*c8dee2aaSAndroid Build Coastguard Worker 
check_image_info(const GrVkCaps & caps,const GrVkImageInfo & info,bool needsAllocation,uint32_t graphicsQueueIndex)1261*c8dee2aaSAndroid Build Coastguard Worker static bool check_image_info(const GrVkCaps& caps,
1262*c8dee2aaSAndroid Build Coastguard Worker                              const GrVkImageInfo& info,
1263*c8dee2aaSAndroid Build Coastguard Worker                              bool needsAllocation,
1264*c8dee2aaSAndroid Build Coastguard Worker                              uint32_t graphicsQueueIndex) {
1265*c8dee2aaSAndroid Build Coastguard Worker     if (VK_NULL_HANDLE == info.fImage) {
1266*c8dee2aaSAndroid Build Coastguard Worker         return false;
1267*c8dee2aaSAndroid Build Coastguard Worker     }
1268*c8dee2aaSAndroid Build Coastguard Worker 
1269*c8dee2aaSAndroid Build Coastguard Worker     if (VK_NULL_HANDLE == info.fAlloc.fMemory && needsAllocation) {
1270*c8dee2aaSAndroid Build Coastguard Worker         return false;
1271*c8dee2aaSAndroid Build Coastguard Worker     }
1272*c8dee2aaSAndroid Build Coastguard Worker 
1273*c8dee2aaSAndroid Build Coastguard Worker     if (info.fImageLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR && !caps.supportsSwapchain()) {
1274*c8dee2aaSAndroid Build Coastguard Worker         return false;
1275*c8dee2aaSAndroid Build Coastguard Worker     }
1276*c8dee2aaSAndroid Build Coastguard Worker 
1277*c8dee2aaSAndroid Build Coastguard Worker     if (info.fCurrentQueueFamily != VK_QUEUE_FAMILY_IGNORED &&
1278*c8dee2aaSAndroid Build Coastguard Worker         info.fCurrentQueueFamily != VK_QUEUE_FAMILY_EXTERNAL &&
1279*c8dee2aaSAndroid Build Coastguard Worker         info.fCurrentQueueFamily != VK_QUEUE_FAMILY_FOREIGN_EXT) {
1280*c8dee2aaSAndroid Build Coastguard Worker         if (info.fSharingMode == VK_SHARING_MODE_EXCLUSIVE) {
1281*c8dee2aaSAndroid Build Coastguard Worker             if (info.fCurrentQueueFamily != graphicsQueueIndex) {
1282*c8dee2aaSAndroid Build Coastguard Worker                 return false;
1283*c8dee2aaSAndroid Build Coastguard Worker             }
1284*c8dee2aaSAndroid Build Coastguard Worker         } else {
1285*c8dee2aaSAndroid Build Coastguard Worker             return false;
1286*c8dee2aaSAndroid Build Coastguard Worker         }
1287*c8dee2aaSAndroid Build Coastguard Worker     }
1288*c8dee2aaSAndroid Build Coastguard Worker 
1289*c8dee2aaSAndroid Build Coastguard Worker     if (info.fYcbcrConversionInfo.isValid()) {
1290*c8dee2aaSAndroid Build Coastguard Worker         if (!caps.supportsYcbcrConversion()) {
1291*c8dee2aaSAndroid Build Coastguard Worker             return false;
1292*c8dee2aaSAndroid Build Coastguard Worker         }
1293*c8dee2aaSAndroid Build Coastguard Worker         if (info.fYcbcrConversionInfo.fExternalFormat != 0) {
1294*c8dee2aaSAndroid Build Coastguard Worker             return true;
1295*c8dee2aaSAndroid Build Coastguard Worker         }
1296*c8dee2aaSAndroid Build Coastguard Worker     }
1297*c8dee2aaSAndroid Build Coastguard Worker 
1298*c8dee2aaSAndroid Build Coastguard Worker     // We currently require everything to be made with transfer bits set
1299*c8dee2aaSAndroid Build Coastguard Worker     if (!SkToBool(info.fImageUsageFlags & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) ||
1300*c8dee2aaSAndroid Build Coastguard Worker         !SkToBool(info.fImageUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT)) {
1301*c8dee2aaSAndroid Build Coastguard Worker         return false;
1302*c8dee2aaSAndroid Build Coastguard Worker     }
1303*c8dee2aaSAndroid Build Coastguard Worker 
1304*c8dee2aaSAndroid Build Coastguard Worker     return true;
1305*c8dee2aaSAndroid Build Coastguard Worker }
1306*c8dee2aaSAndroid Build Coastguard Worker 
check_tex_image_info(const GrVkCaps & caps,const GrVkImageInfo & info)1307*c8dee2aaSAndroid Build Coastguard Worker static bool check_tex_image_info(const GrVkCaps& caps, const GrVkImageInfo& info) {
1308*c8dee2aaSAndroid Build Coastguard Worker     // We don't support directly importing multisampled textures for sampling from shaders.
1309*c8dee2aaSAndroid Build Coastguard Worker     if (info.fSampleCount != 1) {
1310*c8dee2aaSAndroid Build Coastguard Worker         return false;
1311*c8dee2aaSAndroid Build Coastguard Worker     }
1312*c8dee2aaSAndroid Build Coastguard Worker 
1313*c8dee2aaSAndroid Build Coastguard Worker     if (info.fYcbcrConversionInfo.isValid() && info.fYcbcrConversionInfo.fExternalFormat != 0) {
1314*c8dee2aaSAndroid Build Coastguard Worker         return true;
1315*c8dee2aaSAndroid Build Coastguard Worker     }
1316*c8dee2aaSAndroid Build Coastguard Worker     if (info.fImageTiling == VK_IMAGE_TILING_OPTIMAL) {
1317*c8dee2aaSAndroid Build Coastguard Worker         if (!caps.isVkFormatTexturable(info.fFormat)) {
1318*c8dee2aaSAndroid Build Coastguard Worker             return false;
1319*c8dee2aaSAndroid Build Coastguard Worker         }
1320*c8dee2aaSAndroid Build Coastguard Worker     } else if (info.fImageTiling == VK_IMAGE_TILING_LINEAR) {
1321*c8dee2aaSAndroid Build Coastguard Worker         if (!caps.isVkFormatTexturableLinearly(info.fFormat)) {
1322*c8dee2aaSAndroid Build Coastguard Worker             return false;
1323*c8dee2aaSAndroid Build Coastguard Worker         }
1324*c8dee2aaSAndroid Build Coastguard Worker     } else if (info.fImageTiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) {
1325*c8dee2aaSAndroid Build Coastguard Worker         if (!caps.supportsDRMFormatModifiers()) {
1326*c8dee2aaSAndroid Build Coastguard Worker             return false;
1327*c8dee2aaSAndroid Build Coastguard Worker         }
1328*c8dee2aaSAndroid Build Coastguard Worker         // To be technically correct we should query the vulkan support for VkFormat and
1329*c8dee2aaSAndroid Build Coastguard Worker         // drmFormatModifier pairs to confirm the required feature support is there. However, we
1330*c8dee2aaSAndroid Build Coastguard Worker         // currently don't have our caps and format tables set up to do this effeciently. So
1331*c8dee2aaSAndroid Build Coastguard Worker         // instead we just rely on the client's passed in VkImageUsageFlags and assume they we set
1332*c8dee2aaSAndroid Build Coastguard Worker         // up using valid features (checked below). In practice this should all be safe because
1333*c8dee2aaSAndroid Build Coastguard Worker         // currently we are setting all drm format modifier textures to have a
1334*c8dee2aaSAndroid Build Coastguard Worker         // GrTextureType::kExternal so we just really need to be able to read these video VkImage in
1335*c8dee2aaSAndroid Build Coastguard Worker         // a shader. The video decoder isn't going to give us VkImages that don't support being
1336*c8dee2aaSAndroid Build Coastguard Worker         // sampled.
1337*c8dee2aaSAndroid Build Coastguard Worker     } else {
1338*c8dee2aaSAndroid Build Coastguard Worker         SkUNREACHABLE;
1339*c8dee2aaSAndroid Build Coastguard Worker     }
1340*c8dee2aaSAndroid Build Coastguard Worker 
1341*c8dee2aaSAndroid Build Coastguard Worker     // We currently require all textures to be made with sample support
1342*c8dee2aaSAndroid Build Coastguard Worker     if (!SkToBool(info.fImageUsageFlags & VK_IMAGE_USAGE_SAMPLED_BIT)) {
1343*c8dee2aaSAndroid Build Coastguard Worker         return false;
1344*c8dee2aaSAndroid Build Coastguard Worker     }
1345*c8dee2aaSAndroid Build Coastguard Worker 
1346*c8dee2aaSAndroid Build Coastguard Worker     return true;
1347*c8dee2aaSAndroid Build Coastguard Worker }
1348*c8dee2aaSAndroid Build Coastguard Worker 
check_rt_image_info(const GrVkCaps & caps,const GrVkImageInfo & info,bool resolveOnly)1349*c8dee2aaSAndroid Build Coastguard Worker static bool check_rt_image_info(const GrVkCaps& caps, const GrVkImageInfo& info, bool resolveOnly) {
1350*c8dee2aaSAndroid Build Coastguard Worker     if (!caps.isFormatRenderable(info.fFormat, info.fSampleCount)) {
1351*c8dee2aaSAndroid Build Coastguard Worker         return false;
1352*c8dee2aaSAndroid Build Coastguard Worker     }
1353*c8dee2aaSAndroid Build Coastguard Worker     if (!resolveOnly && !SkToBool(info.fImageUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)) {
1354*c8dee2aaSAndroid Build Coastguard Worker         return false;
1355*c8dee2aaSAndroid Build Coastguard Worker     }
1356*c8dee2aaSAndroid Build Coastguard Worker     return true;
1357*c8dee2aaSAndroid Build Coastguard Worker }
1358*c8dee2aaSAndroid Build Coastguard Worker 
onWrapBackendTexture(const GrBackendTexture & backendTex,GrWrapOwnership ownership,GrWrapCacheable cacheable,GrIOType ioType)1359*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrTexture> GrVkGpu::onWrapBackendTexture(const GrBackendTexture& backendTex,
1360*c8dee2aaSAndroid Build Coastguard Worker                                                GrWrapOwnership ownership,
1361*c8dee2aaSAndroid Build Coastguard Worker                                                GrWrapCacheable cacheable,
1362*c8dee2aaSAndroid Build Coastguard Worker                                                GrIOType ioType) {
1363*c8dee2aaSAndroid Build Coastguard Worker     GrVkImageInfo imageInfo;
1364*c8dee2aaSAndroid Build Coastguard Worker     if (!GrBackendTextures::GetVkImageInfo(backendTex, &imageInfo)) {
1365*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
1366*c8dee2aaSAndroid Build Coastguard Worker     }
1367*c8dee2aaSAndroid Build Coastguard Worker 
1368*c8dee2aaSAndroid Build Coastguard Worker     if (!check_image_info(this->vkCaps(), imageInfo, kAdopt_GrWrapOwnership == ownership,
1369*c8dee2aaSAndroid Build Coastguard Worker                           this->queueIndex())) {
1370*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
1371*c8dee2aaSAndroid Build Coastguard Worker     }
1372*c8dee2aaSAndroid Build Coastguard Worker 
1373*c8dee2aaSAndroid Build Coastguard Worker     if (!check_tex_image_info(this->vkCaps(), imageInfo)) {
1374*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
1375*c8dee2aaSAndroid Build Coastguard Worker     }
1376*c8dee2aaSAndroid Build Coastguard Worker 
1377*c8dee2aaSAndroid Build Coastguard Worker     if (backendTex.isProtected() && (fProtectedContext == GrProtected::kNo)) {
1378*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
1379*c8dee2aaSAndroid Build Coastguard Worker     }
1380*c8dee2aaSAndroid Build Coastguard Worker 
1381*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<skgpu::MutableTextureState> mutableState = backendTex.getMutableState();
1382*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(mutableState);
1383*c8dee2aaSAndroid Build Coastguard Worker     return GrVkTexture::MakeWrappedTexture(this, backendTex.dimensions(), ownership, cacheable,
1384*c8dee2aaSAndroid Build Coastguard Worker                                            ioType, imageInfo, std::move(mutableState));
1385*c8dee2aaSAndroid Build Coastguard Worker }
1386*c8dee2aaSAndroid Build Coastguard Worker 
onWrapCompressedBackendTexture(const GrBackendTexture & beTex,GrWrapOwnership ownership,GrWrapCacheable cacheable)1387*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrTexture> GrVkGpu::onWrapCompressedBackendTexture(const GrBackendTexture& beTex,
1388*c8dee2aaSAndroid Build Coastguard Worker                                                          GrWrapOwnership ownership,
1389*c8dee2aaSAndroid Build Coastguard Worker                                                          GrWrapCacheable cacheable) {
1390*c8dee2aaSAndroid Build Coastguard Worker     return this->onWrapBackendTexture(beTex, ownership, cacheable, kRead_GrIOType);
1391*c8dee2aaSAndroid Build Coastguard Worker }
1392*c8dee2aaSAndroid Build Coastguard Worker 
onWrapRenderableBackendTexture(const GrBackendTexture & backendTex,int sampleCnt,GrWrapOwnership ownership,GrWrapCacheable cacheable)1393*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrTexture> GrVkGpu::onWrapRenderableBackendTexture(const GrBackendTexture& backendTex,
1394*c8dee2aaSAndroid Build Coastguard Worker                                                          int sampleCnt,
1395*c8dee2aaSAndroid Build Coastguard Worker                                                          GrWrapOwnership ownership,
1396*c8dee2aaSAndroid Build Coastguard Worker                                                          GrWrapCacheable cacheable) {
1397*c8dee2aaSAndroid Build Coastguard Worker     GrVkImageInfo imageInfo;
1398*c8dee2aaSAndroid Build Coastguard Worker     if (!GrBackendTextures::GetVkImageInfo(backendTex, &imageInfo)) {
1399*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
1400*c8dee2aaSAndroid Build Coastguard Worker     }
1401*c8dee2aaSAndroid Build Coastguard Worker 
1402*c8dee2aaSAndroid Build Coastguard Worker     if (!check_image_info(this->vkCaps(), imageInfo, kAdopt_GrWrapOwnership == ownership,
1403*c8dee2aaSAndroid Build Coastguard Worker                           this->queueIndex())) {
1404*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
1405*c8dee2aaSAndroid Build Coastguard Worker     }
1406*c8dee2aaSAndroid Build Coastguard Worker 
1407*c8dee2aaSAndroid Build Coastguard Worker     if (!check_tex_image_info(this->vkCaps(), imageInfo)) {
1408*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
1409*c8dee2aaSAndroid Build Coastguard Worker     }
1410*c8dee2aaSAndroid Build Coastguard Worker     // If sampleCnt is > 1 we will create an intermediate MSAA VkImage and then resolve into
1411*c8dee2aaSAndroid Build Coastguard Worker     // the wrapped VkImage.
1412*c8dee2aaSAndroid Build Coastguard Worker     bool resolveOnly = sampleCnt > 1;
1413*c8dee2aaSAndroid Build Coastguard Worker     if (!check_rt_image_info(this->vkCaps(), imageInfo, resolveOnly)) {
1414*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
1415*c8dee2aaSAndroid Build Coastguard Worker     }
1416*c8dee2aaSAndroid Build Coastguard Worker 
1417*c8dee2aaSAndroid Build Coastguard Worker     if (backendTex.isProtected() && (fProtectedContext == GrProtected::kNo)) {
1418*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
1419*c8dee2aaSAndroid Build Coastguard Worker     }
1420*c8dee2aaSAndroid Build Coastguard Worker 
1421*c8dee2aaSAndroid Build Coastguard Worker     sampleCnt = this->vkCaps().getRenderTargetSampleCount(sampleCnt, imageInfo.fFormat);
1422*c8dee2aaSAndroid Build Coastguard Worker 
1423*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<skgpu::MutableTextureState> mutableState = backendTex.getMutableState();
1424*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(mutableState);
1425*c8dee2aaSAndroid Build Coastguard Worker 
1426*c8dee2aaSAndroid Build Coastguard Worker     return GrVkTextureRenderTarget::MakeWrappedTextureRenderTarget(this, backendTex.dimensions(),
1427*c8dee2aaSAndroid Build Coastguard Worker                                                                    sampleCnt, ownership, cacheable,
1428*c8dee2aaSAndroid Build Coastguard Worker                                                                    imageInfo,
1429*c8dee2aaSAndroid Build Coastguard Worker                                                                    std::move(mutableState));
1430*c8dee2aaSAndroid Build Coastguard Worker }
1431*c8dee2aaSAndroid Build Coastguard Worker 
onWrapBackendRenderTarget(const GrBackendRenderTarget & backendRT)1432*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrRenderTarget> GrVkGpu::onWrapBackendRenderTarget(const GrBackendRenderTarget& backendRT) {
1433*c8dee2aaSAndroid Build Coastguard Worker     GrVkImageInfo info;
1434*c8dee2aaSAndroid Build Coastguard Worker     if (!GrBackendRenderTargets::GetVkImageInfo(backendRT, &info)) {
1435*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
1436*c8dee2aaSAndroid Build Coastguard Worker     }
1437*c8dee2aaSAndroid Build Coastguard Worker 
1438*c8dee2aaSAndroid Build Coastguard Worker     if (!check_image_info(this->vkCaps(), info, false, this->queueIndex())) {
1439*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
1440*c8dee2aaSAndroid Build Coastguard Worker     }
1441*c8dee2aaSAndroid Build Coastguard Worker 
1442*c8dee2aaSAndroid Build Coastguard Worker     // We will always render directly to this VkImage.
1443*c8dee2aaSAndroid Build Coastguard Worker     static bool kResolveOnly = false;
1444*c8dee2aaSAndroid Build Coastguard Worker     if (!check_rt_image_info(this->vkCaps(), info, kResolveOnly)) {
1445*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
1446*c8dee2aaSAndroid Build Coastguard Worker     }
1447*c8dee2aaSAndroid Build Coastguard Worker 
1448*c8dee2aaSAndroid Build Coastguard Worker     if (backendRT.isProtected() && (fProtectedContext == GrProtected::kNo)) {
1449*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
1450*c8dee2aaSAndroid Build Coastguard Worker     }
1451*c8dee2aaSAndroid Build Coastguard Worker 
1452*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<skgpu::MutableTextureState> mutableState = backendRT.getMutableState();
1453*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(mutableState);
1454*c8dee2aaSAndroid Build Coastguard Worker 
1455*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<GrVkRenderTarget> tgt = GrVkRenderTarget::MakeWrappedRenderTarget(
1456*c8dee2aaSAndroid Build Coastguard Worker             this, backendRT.dimensions(), backendRT.sampleCnt(), info, std::move(mutableState));
1457*c8dee2aaSAndroid Build Coastguard Worker 
1458*c8dee2aaSAndroid Build Coastguard Worker     // We don't allow the client to supply a premade stencil buffer. We always create one if needed.
1459*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!backendRT.stencilBits());
1460*c8dee2aaSAndroid Build Coastguard Worker     if (tgt) {
1461*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(tgt->canAttemptStencilAttachment(tgt->numSamples() > 1));
1462*c8dee2aaSAndroid Build Coastguard Worker     }
1463*c8dee2aaSAndroid Build Coastguard Worker 
1464*c8dee2aaSAndroid Build Coastguard Worker     return tgt;
1465*c8dee2aaSAndroid Build Coastguard Worker }
1466*c8dee2aaSAndroid Build Coastguard Worker 
onWrapVulkanSecondaryCBAsRenderTarget(const SkImageInfo & imageInfo,const GrVkDrawableInfo & vkInfo)1467*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrRenderTarget> GrVkGpu::onWrapVulkanSecondaryCBAsRenderTarget(
1468*c8dee2aaSAndroid Build Coastguard Worker         const SkImageInfo& imageInfo, const GrVkDrawableInfo& vkInfo) {
1469*c8dee2aaSAndroid Build Coastguard Worker     int maxSize = this->caps()->maxTextureSize();
1470*c8dee2aaSAndroid Build Coastguard Worker     if (imageInfo.width() > maxSize || imageInfo.height() > maxSize) {
1471*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
1472*c8dee2aaSAndroid Build Coastguard Worker     }
1473*c8dee2aaSAndroid Build Coastguard Worker 
1474*c8dee2aaSAndroid Build Coastguard Worker     GrBackendFormat backendFormat = GrBackendFormats::MakeVk(vkInfo.fFormat);
1475*c8dee2aaSAndroid Build Coastguard Worker     if (!backendFormat.isValid()) {
1476*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
1477*c8dee2aaSAndroid Build Coastguard Worker     }
1478*c8dee2aaSAndroid Build Coastguard Worker     int sampleCnt = this->vkCaps().getRenderTargetSampleCount(1, vkInfo.fFormat);
1479*c8dee2aaSAndroid Build Coastguard Worker     if (!sampleCnt) {
1480*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
1481*c8dee2aaSAndroid Build Coastguard Worker     }
1482*c8dee2aaSAndroid Build Coastguard Worker 
1483*c8dee2aaSAndroid Build Coastguard Worker     return GrVkRenderTarget::MakeSecondaryCBRenderTarget(this, imageInfo.dimensions(), vkInfo);
1484*c8dee2aaSAndroid Build Coastguard Worker }
1485*c8dee2aaSAndroid Build Coastguard Worker 
loadMSAAFromResolve(GrVkCommandBuffer * commandBuffer,const GrVkRenderPass & renderPass,GrAttachment * dst,GrVkImage * src,const SkIRect & srcRect)1486*c8dee2aaSAndroid Build Coastguard Worker bool GrVkGpu::loadMSAAFromResolve(GrVkCommandBuffer* commandBuffer,
1487*c8dee2aaSAndroid Build Coastguard Worker                                   const GrVkRenderPass& renderPass,
1488*c8dee2aaSAndroid Build Coastguard Worker                                   GrAttachment* dst,
1489*c8dee2aaSAndroid Build Coastguard Worker                                   GrVkImage* src,
1490*c8dee2aaSAndroid Build Coastguard Worker                                   const SkIRect& srcRect) {
1491*c8dee2aaSAndroid Build Coastguard Worker     return fMSAALoadManager.loadMSAAFromResolve(this, commandBuffer, renderPass, dst, src, srcRect);
1492*c8dee2aaSAndroid Build Coastguard Worker }
1493*c8dee2aaSAndroid Build Coastguard Worker 
onRegenerateMipMapLevels(GrTexture * tex)1494*c8dee2aaSAndroid Build Coastguard Worker bool GrVkGpu::onRegenerateMipMapLevels(GrTexture* tex) {
1495*c8dee2aaSAndroid Build Coastguard Worker     if (!this->currentCommandBuffer()) {
1496*c8dee2aaSAndroid Build Coastguard Worker         return false;
1497*c8dee2aaSAndroid Build Coastguard Worker     }
1498*c8dee2aaSAndroid Build Coastguard Worker     auto* vkTex = static_cast<GrVkTexture*>(tex)->textureImage();
1499*c8dee2aaSAndroid Build Coastguard Worker     // don't do anything for linearly tiled textures (can't have mipmaps)
1500*c8dee2aaSAndroid Build Coastguard Worker     if (vkTex->isLinearTiled()) {
1501*c8dee2aaSAndroid Build Coastguard Worker         SkDebugf("Trying to create mipmap for linear tiled texture");
1502*c8dee2aaSAndroid Build Coastguard Worker         return false;
1503*c8dee2aaSAndroid Build Coastguard Worker     }
1504*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(tex->textureType() == GrTextureType::k2D);
1505*c8dee2aaSAndroid Build Coastguard Worker 
1506*c8dee2aaSAndroid Build Coastguard Worker     // determine if we can blit to and from this format
1507*c8dee2aaSAndroid Build Coastguard Worker     const GrVkCaps& caps = this->vkCaps();
1508*c8dee2aaSAndroid Build Coastguard Worker     if (!caps.formatCanBeDstofBlit(vkTex->imageFormat(), false) ||
1509*c8dee2aaSAndroid Build Coastguard Worker         !caps.formatCanBeSrcofBlit(vkTex->imageFormat(), false) ||
1510*c8dee2aaSAndroid Build Coastguard Worker         !caps.mipmapSupport()) {
1511*c8dee2aaSAndroid Build Coastguard Worker         return false;
1512*c8dee2aaSAndroid Build Coastguard Worker     }
1513*c8dee2aaSAndroid Build Coastguard Worker 
1514*c8dee2aaSAndroid Build Coastguard Worker     int width = tex->width();
1515*c8dee2aaSAndroid Build Coastguard Worker     int height = tex->height();
1516*c8dee2aaSAndroid Build Coastguard Worker     VkImageBlit blitRegion;
1517*c8dee2aaSAndroid Build Coastguard Worker     memset(&blitRegion, 0, sizeof(VkImageBlit));
1518*c8dee2aaSAndroid Build Coastguard Worker 
1519*c8dee2aaSAndroid Build Coastguard Worker     // SkMipmap doesn't include the base level in the level count so we have to add 1
1520*c8dee2aaSAndroid Build Coastguard Worker     uint32_t levelCount = SkMipmap::ComputeLevelCount(tex->width(), tex->height()) + 1;
1521*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(levelCount == vkTex->mipLevels());
1522*c8dee2aaSAndroid Build Coastguard Worker 
1523*c8dee2aaSAndroid Build Coastguard Worker     // change layout of the layers so we can write to them.
1524*c8dee2aaSAndroid Build Coastguard Worker     vkTex->setImageLayout(this, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT,
1525*c8dee2aaSAndroid Build Coastguard Worker                           VK_PIPELINE_STAGE_TRANSFER_BIT, false);
1526*c8dee2aaSAndroid Build Coastguard Worker 
1527*c8dee2aaSAndroid Build Coastguard Worker     // setup memory barrier
1528*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(GrVkFormatIsSupported(vkTex->imageFormat()));
1529*c8dee2aaSAndroid Build Coastguard Worker     VkImageMemoryBarrier imageMemoryBarrier = {
1530*c8dee2aaSAndroid Build Coastguard Worker             VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,  // sType
1531*c8dee2aaSAndroid Build Coastguard Worker             nullptr,                                 // pNext
1532*c8dee2aaSAndroid Build Coastguard Worker             VK_ACCESS_TRANSFER_WRITE_BIT,            // srcAccessMask
1533*c8dee2aaSAndroid Build Coastguard Worker             VK_ACCESS_TRANSFER_READ_BIT,             // dstAccessMask
1534*c8dee2aaSAndroid Build Coastguard Worker             VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,    // oldLayout
1535*c8dee2aaSAndroid Build Coastguard Worker             VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,    // newLayout
1536*c8dee2aaSAndroid Build Coastguard Worker             VK_QUEUE_FAMILY_IGNORED,                 // srcQueueFamilyIndex
1537*c8dee2aaSAndroid Build Coastguard Worker             VK_QUEUE_FAMILY_IGNORED,                 // dstQueueFamilyIndex
1538*c8dee2aaSAndroid Build Coastguard Worker             vkTex->image(),                          // image
1539*c8dee2aaSAndroid Build Coastguard Worker             {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}  // subresourceRange
1540*c8dee2aaSAndroid Build Coastguard Worker     };
1541*c8dee2aaSAndroid Build Coastguard Worker 
1542*c8dee2aaSAndroid Build Coastguard Worker     // Blit the miplevels
1543*c8dee2aaSAndroid Build Coastguard Worker     uint32_t mipLevel = 1;
1544*c8dee2aaSAndroid Build Coastguard Worker     while (mipLevel < levelCount) {
1545*c8dee2aaSAndroid Build Coastguard Worker         int prevWidth = width;
1546*c8dee2aaSAndroid Build Coastguard Worker         int prevHeight = height;
1547*c8dee2aaSAndroid Build Coastguard Worker         width = std::max(1, width / 2);
1548*c8dee2aaSAndroid Build Coastguard Worker         height = std::max(1, height / 2);
1549*c8dee2aaSAndroid Build Coastguard Worker 
1550*c8dee2aaSAndroid Build Coastguard Worker         imageMemoryBarrier.subresourceRange.baseMipLevel = mipLevel - 1;
1551*c8dee2aaSAndroid Build Coastguard Worker         this->addImageMemoryBarrier(vkTex->resource(), VK_PIPELINE_STAGE_TRANSFER_BIT,
1552*c8dee2aaSAndroid Build Coastguard Worker                                     VK_PIPELINE_STAGE_TRANSFER_BIT, false, &imageMemoryBarrier);
1553*c8dee2aaSAndroid Build Coastguard Worker 
1554*c8dee2aaSAndroid Build Coastguard Worker         blitRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, mipLevel - 1, 0, 1 };
1555*c8dee2aaSAndroid Build Coastguard Worker         blitRegion.srcOffsets[0] = { 0, 0, 0 };
1556*c8dee2aaSAndroid Build Coastguard Worker         blitRegion.srcOffsets[1] = { prevWidth, prevHeight, 1 };
1557*c8dee2aaSAndroid Build Coastguard Worker         blitRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, mipLevel, 0, 1 };
1558*c8dee2aaSAndroid Build Coastguard Worker         blitRegion.dstOffsets[0] = { 0, 0, 0 };
1559*c8dee2aaSAndroid Build Coastguard Worker         blitRegion.dstOffsets[1] = { width, height, 1 };
1560*c8dee2aaSAndroid Build Coastguard Worker         this->currentCommandBuffer()->blitImage(this,
1561*c8dee2aaSAndroid Build Coastguard Worker                                                 vkTex->resource(),
1562*c8dee2aaSAndroid Build Coastguard Worker                                                 vkTex->image(),
1563*c8dee2aaSAndroid Build Coastguard Worker                                                 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1564*c8dee2aaSAndroid Build Coastguard Worker                                                 vkTex->resource(),
1565*c8dee2aaSAndroid Build Coastguard Worker                                                 vkTex->image(),
1566*c8dee2aaSAndroid Build Coastguard Worker                                                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1567*c8dee2aaSAndroid Build Coastguard Worker                                                 1,
1568*c8dee2aaSAndroid Build Coastguard Worker                                                 &blitRegion,
1569*c8dee2aaSAndroid Build Coastguard Worker                                                 VK_FILTER_LINEAR);
1570*c8dee2aaSAndroid Build Coastguard Worker         ++mipLevel;
1571*c8dee2aaSAndroid Build Coastguard Worker     }
1572*c8dee2aaSAndroid Build Coastguard Worker     if (levelCount > 1) {
1573*c8dee2aaSAndroid Build Coastguard Worker         // This barrier logically is not needed, but it changes the final level to the same layout
1574*c8dee2aaSAndroid Build Coastguard Worker         // as all the others, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL. This makes tracking of the
1575*c8dee2aaSAndroid Build Coastguard Worker         // layouts and future layout changes easier. The alternative here would be to track layout
1576*c8dee2aaSAndroid Build Coastguard Worker         // and memory accesses per layer which doesn't seem work it.
1577*c8dee2aaSAndroid Build Coastguard Worker         imageMemoryBarrier.subresourceRange.baseMipLevel = mipLevel - 1;
1578*c8dee2aaSAndroid Build Coastguard Worker         this->addImageMemoryBarrier(vkTex->resource(), VK_PIPELINE_STAGE_TRANSFER_BIT,
1579*c8dee2aaSAndroid Build Coastguard Worker                                     VK_PIPELINE_STAGE_TRANSFER_BIT, false, &imageMemoryBarrier);
1580*c8dee2aaSAndroid Build Coastguard Worker         vkTex->updateImageLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
1581*c8dee2aaSAndroid Build Coastguard Worker     }
1582*c8dee2aaSAndroid Build Coastguard Worker     return true;
1583*c8dee2aaSAndroid Build Coastguard Worker }
1584*c8dee2aaSAndroid Build Coastguard Worker 
1585*c8dee2aaSAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////
1586*c8dee2aaSAndroid Build Coastguard Worker 
makeStencilAttachment(const GrBackendFormat &,SkISize dimensions,int numStencilSamples)1587*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrAttachment> GrVkGpu::makeStencilAttachment(const GrBackendFormat& /*colorFormat*/,
1588*c8dee2aaSAndroid Build Coastguard Worker                                                    SkISize dimensions, int numStencilSamples) {
1589*c8dee2aaSAndroid Build Coastguard Worker     VkFormat sFmt = this->vkCaps().preferredStencilFormat();
1590*c8dee2aaSAndroid Build Coastguard Worker 
1591*c8dee2aaSAndroid Build Coastguard Worker     fStats.incStencilAttachmentCreates();
1592*c8dee2aaSAndroid Build Coastguard Worker     return GrVkImage::MakeStencil(this, dimensions, numStencilSamples, sFmt);
1593*c8dee2aaSAndroid Build Coastguard Worker }
1594*c8dee2aaSAndroid Build Coastguard Worker 
makeMSAAAttachment(SkISize dimensions,const GrBackendFormat & format,int numSamples,GrProtected isProtected,GrMemoryless memoryless)1595*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrAttachment> GrVkGpu::makeMSAAAttachment(SkISize dimensions,
1596*c8dee2aaSAndroid Build Coastguard Worker                                                 const GrBackendFormat& format,
1597*c8dee2aaSAndroid Build Coastguard Worker                                                 int numSamples,
1598*c8dee2aaSAndroid Build Coastguard Worker                                                 GrProtected isProtected,
1599*c8dee2aaSAndroid Build Coastguard Worker                                                 GrMemoryless memoryless) {
1600*c8dee2aaSAndroid Build Coastguard Worker     VkFormat pixelFormat;
1601*c8dee2aaSAndroid Build Coastguard Worker     SkAssertResult(GrBackendFormats::AsVkFormat(format, &pixelFormat));
1602*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!skgpu::VkFormatIsCompressed(pixelFormat));
1603*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(this->vkCaps().isFormatRenderable(pixelFormat, numSamples));
1604*c8dee2aaSAndroid Build Coastguard Worker 
1605*c8dee2aaSAndroid Build Coastguard Worker     fStats.incMSAAAttachmentCreates();
1606*c8dee2aaSAndroid Build Coastguard Worker     return GrVkImage::MakeMSAA(this, dimensions, numSamples, pixelFormat, isProtected, memoryless);
1607*c8dee2aaSAndroid Build Coastguard Worker }
1608*c8dee2aaSAndroid Build Coastguard Worker 
1609*c8dee2aaSAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////
1610*c8dee2aaSAndroid Build Coastguard Worker 
copy_src_data(char * mapPtr,VkFormat vkFormat,const TArray<size_t> & individualMipOffsets,const GrPixmap srcData[],int numMipLevels)1611*c8dee2aaSAndroid Build Coastguard Worker bool copy_src_data(char* mapPtr,
1612*c8dee2aaSAndroid Build Coastguard Worker                    VkFormat vkFormat,
1613*c8dee2aaSAndroid Build Coastguard Worker                    const TArray<size_t>& individualMipOffsets,
1614*c8dee2aaSAndroid Build Coastguard Worker                    const GrPixmap srcData[],
1615*c8dee2aaSAndroid Build Coastguard Worker                    int numMipLevels) {
1616*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(srcData && numMipLevels);
1617*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!skgpu::VkFormatIsCompressed(vkFormat));
1618*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(individualMipOffsets.size() == numMipLevels);
1619*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(mapPtr);
1620*c8dee2aaSAndroid Build Coastguard Worker 
1621*c8dee2aaSAndroid Build Coastguard Worker     size_t bytesPerPixel = skgpu::VkFormatBytesPerBlock(vkFormat);
1622*c8dee2aaSAndroid Build Coastguard Worker 
1623*c8dee2aaSAndroid Build Coastguard Worker     for (int level = 0; level < numMipLevels; ++level) {
1624*c8dee2aaSAndroid Build Coastguard Worker         const size_t trimRB = srcData[level].info().width() * bytesPerPixel;
1625*c8dee2aaSAndroid Build Coastguard Worker 
1626*c8dee2aaSAndroid Build Coastguard Worker         SkRectMemcpy(mapPtr + individualMipOffsets[level], trimRB,
1627*c8dee2aaSAndroid Build Coastguard Worker                      srcData[level].addr(), srcData[level].rowBytes(),
1628*c8dee2aaSAndroid Build Coastguard Worker                      trimRB, srcData[level].height());
1629*c8dee2aaSAndroid Build Coastguard Worker     }
1630*c8dee2aaSAndroid Build Coastguard Worker     return true;
1631*c8dee2aaSAndroid Build Coastguard Worker }
1632*c8dee2aaSAndroid Build Coastguard Worker 
createVkImageForBackendSurface(VkFormat vkFormat,SkISize dimensions,int sampleCnt,GrTexturable texturable,GrRenderable renderable,skgpu::Mipmapped mipmapped,GrVkImageInfo * info,GrProtected isProtected)1633*c8dee2aaSAndroid Build Coastguard Worker bool GrVkGpu::createVkImageForBackendSurface(VkFormat vkFormat,
1634*c8dee2aaSAndroid Build Coastguard Worker                                              SkISize dimensions,
1635*c8dee2aaSAndroid Build Coastguard Worker                                              int sampleCnt,
1636*c8dee2aaSAndroid Build Coastguard Worker                                              GrTexturable texturable,
1637*c8dee2aaSAndroid Build Coastguard Worker                                              GrRenderable renderable,
1638*c8dee2aaSAndroid Build Coastguard Worker                                              skgpu::Mipmapped mipmapped,
1639*c8dee2aaSAndroid Build Coastguard Worker                                              GrVkImageInfo* info,
1640*c8dee2aaSAndroid Build Coastguard Worker                                              GrProtected isProtected) {
1641*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(texturable == GrTexturable::kYes || renderable == GrRenderable::kYes);
1642*c8dee2aaSAndroid Build Coastguard Worker 
1643*c8dee2aaSAndroid Build Coastguard Worker     if (fProtectedContext != isProtected) {
1644*c8dee2aaSAndroid Build Coastguard Worker         return false;
1645*c8dee2aaSAndroid Build Coastguard Worker     }
1646*c8dee2aaSAndroid Build Coastguard Worker 
1647*c8dee2aaSAndroid Build Coastguard Worker     if (texturable == GrTexturable::kYes && !fVkCaps->isVkFormatTexturable(vkFormat)) {
1648*c8dee2aaSAndroid Build Coastguard Worker         return false;
1649*c8dee2aaSAndroid Build Coastguard Worker     }
1650*c8dee2aaSAndroid Build Coastguard Worker 
1651*c8dee2aaSAndroid Build Coastguard Worker     // MSAA images are only currently used by createTestingOnlyBackendRenderTarget.
1652*c8dee2aaSAndroid Build Coastguard Worker     if (sampleCnt > 1 && (texturable == GrTexturable::kYes || renderable == GrRenderable::kNo)) {
1653*c8dee2aaSAndroid Build Coastguard Worker         return false;
1654*c8dee2aaSAndroid Build Coastguard Worker     }
1655*c8dee2aaSAndroid Build Coastguard Worker 
1656*c8dee2aaSAndroid Build Coastguard Worker     if (renderable == GrRenderable::kYes) {
1657*c8dee2aaSAndroid Build Coastguard Worker         sampleCnt = fVkCaps->getRenderTargetSampleCount(sampleCnt, vkFormat);
1658*c8dee2aaSAndroid Build Coastguard Worker         if (!sampleCnt) {
1659*c8dee2aaSAndroid Build Coastguard Worker             return false;
1660*c8dee2aaSAndroid Build Coastguard Worker         }
1661*c8dee2aaSAndroid Build Coastguard Worker     }
1662*c8dee2aaSAndroid Build Coastguard Worker 
1663*c8dee2aaSAndroid Build Coastguard Worker 
1664*c8dee2aaSAndroid Build Coastguard Worker     int numMipLevels = 1;
1665*c8dee2aaSAndroid Build Coastguard Worker     if (mipmapped == skgpu::Mipmapped::kYes) {
1666*c8dee2aaSAndroid Build Coastguard Worker         numMipLevels = SkMipmap::ComputeLevelCount(dimensions.width(), dimensions.height()) + 1;
1667*c8dee2aaSAndroid Build Coastguard Worker     }
1668*c8dee2aaSAndroid Build Coastguard Worker 
1669*c8dee2aaSAndroid Build Coastguard Worker     VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
1670*c8dee2aaSAndroid Build Coastguard Worker                                    VK_IMAGE_USAGE_TRANSFER_DST_BIT;
1671*c8dee2aaSAndroid Build Coastguard Worker     if (texturable == GrTexturable::kYes) {
1672*c8dee2aaSAndroid Build Coastguard Worker         usageFlags |= VK_IMAGE_USAGE_SAMPLED_BIT;
1673*c8dee2aaSAndroid Build Coastguard Worker     }
1674*c8dee2aaSAndroid Build Coastguard Worker     if (renderable == GrRenderable::kYes) {
1675*c8dee2aaSAndroid Build Coastguard Worker         usageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
1676*c8dee2aaSAndroid Build Coastguard Worker         // We always make our render targets support being used as input attachments
1677*c8dee2aaSAndroid Build Coastguard Worker         usageFlags |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
1678*c8dee2aaSAndroid Build Coastguard Worker     }
1679*c8dee2aaSAndroid Build Coastguard Worker 
1680*c8dee2aaSAndroid Build Coastguard Worker     GrVkImage::ImageDesc imageDesc;
1681*c8dee2aaSAndroid Build Coastguard Worker     imageDesc.fImageType = VK_IMAGE_TYPE_2D;
1682*c8dee2aaSAndroid Build Coastguard Worker     imageDesc.fFormat = vkFormat;
1683*c8dee2aaSAndroid Build Coastguard Worker     imageDesc.fWidth = dimensions.width();
1684*c8dee2aaSAndroid Build Coastguard Worker     imageDesc.fHeight = dimensions.height();
1685*c8dee2aaSAndroid Build Coastguard Worker     imageDesc.fLevels = numMipLevels;
1686*c8dee2aaSAndroid Build Coastguard Worker     imageDesc.fSamples = sampleCnt;
1687*c8dee2aaSAndroid Build Coastguard Worker     imageDesc.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
1688*c8dee2aaSAndroid Build Coastguard Worker     imageDesc.fUsageFlags = usageFlags;
1689*c8dee2aaSAndroid Build Coastguard Worker     imageDesc.fMemProps = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
1690*c8dee2aaSAndroid Build Coastguard Worker     imageDesc.fIsProtected = fProtectedContext;
1691*c8dee2aaSAndroid Build Coastguard Worker 
1692*c8dee2aaSAndroid Build Coastguard Worker     if (!GrVkImage::InitImageInfo(this, imageDesc, info)) {
1693*c8dee2aaSAndroid Build Coastguard Worker         SkDebugf("Failed to init image info\n");
1694*c8dee2aaSAndroid Build Coastguard Worker         return false;
1695*c8dee2aaSAndroid Build Coastguard Worker     }
1696*c8dee2aaSAndroid Build Coastguard Worker 
1697*c8dee2aaSAndroid Build Coastguard Worker     return true;
1698*c8dee2aaSAndroid Build Coastguard Worker }
1699*c8dee2aaSAndroid Build Coastguard Worker 
onClearBackendTexture(const GrBackendTexture & backendTexture,sk_sp<skgpu::RefCntedCallback> finishedCallback,std::array<float,4> color)1700*c8dee2aaSAndroid Build Coastguard Worker bool GrVkGpu::onClearBackendTexture(const GrBackendTexture& backendTexture,
1701*c8dee2aaSAndroid Build Coastguard Worker                                     sk_sp<skgpu::RefCntedCallback> finishedCallback,
1702*c8dee2aaSAndroid Build Coastguard Worker                                     std::array<float, 4> color) {
1703*c8dee2aaSAndroid Build Coastguard Worker     GrVkImageInfo info;
1704*c8dee2aaSAndroid Build Coastguard Worker     SkAssertResult(GrBackendTextures::GetVkImageInfo(backendTexture, &info));
1705*c8dee2aaSAndroid Build Coastguard Worker 
1706*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<skgpu::MutableTextureState> mutableState = backendTexture.getMutableState();
1707*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(mutableState);
1708*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<GrVkTexture> texture =
1709*c8dee2aaSAndroid Build Coastguard Worker                 GrVkTexture::MakeWrappedTexture(this, backendTexture.dimensions(),
1710*c8dee2aaSAndroid Build Coastguard Worker                                                 kBorrow_GrWrapOwnership, GrWrapCacheable::kNo,
1711*c8dee2aaSAndroid Build Coastguard Worker                                                 kRW_GrIOType, info, std::move(mutableState));
1712*c8dee2aaSAndroid Build Coastguard Worker     if (!texture) {
1713*c8dee2aaSAndroid Build Coastguard Worker         return false;
1714*c8dee2aaSAndroid Build Coastguard Worker     }
1715*c8dee2aaSAndroid Build Coastguard Worker     GrVkImage* texImage = texture->textureImage();
1716*c8dee2aaSAndroid Build Coastguard Worker 
1717*c8dee2aaSAndroid Build Coastguard Worker     GrVkPrimaryCommandBuffer* cmdBuffer = this->currentCommandBuffer();
1718*c8dee2aaSAndroid Build Coastguard Worker     if (!cmdBuffer) {
1719*c8dee2aaSAndroid Build Coastguard Worker         return false;
1720*c8dee2aaSAndroid Build Coastguard Worker     }
1721*c8dee2aaSAndroid Build Coastguard Worker 
1722*c8dee2aaSAndroid Build Coastguard Worker     texImage->setImageLayout(this,
1723*c8dee2aaSAndroid Build Coastguard Worker                              VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1724*c8dee2aaSAndroid Build Coastguard Worker                              VK_ACCESS_TRANSFER_WRITE_BIT,
1725*c8dee2aaSAndroid Build Coastguard Worker                              VK_PIPELINE_STAGE_TRANSFER_BIT,
1726*c8dee2aaSAndroid Build Coastguard Worker                              false);
1727*c8dee2aaSAndroid Build Coastguard Worker 
1728*c8dee2aaSAndroid Build Coastguard Worker     // CmdClearColorImage doesn't work for compressed formats
1729*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!skgpu::VkFormatIsCompressed(info.fFormat));
1730*c8dee2aaSAndroid Build Coastguard Worker 
1731*c8dee2aaSAndroid Build Coastguard Worker     VkClearColorValue vkColor;
1732*c8dee2aaSAndroid Build Coastguard Worker     // If we ever support SINT or UINT formats this needs to be updated to use the int32 and
1733*c8dee2aaSAndroid Build Coastguard Worker     // uint32 union members in those cases.
1734*c8dee2aaSAndroid Build Coastguard Worker     vkColor.float32[0] = color[0];
1735*c8dee2aaSAndroid Build Coastguard Worker     vkColor.float32[1] = color[1];
1736*c8dee2aaSAndroid Build Coastguard Worker     vkColor.float32[2] = color[2];
1737*c8dee2aaSAndroid Build Coastguard Worker     vkColor.float32[3] = color[3];
1738*c8dee2aaSAndroid Build Coastguard Worker     VkImageSubresourceRange range;
1739*c8dee2aaSAndroid Build Coastguard Worker     range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
1740*c8dee2aaSAndroid Build Coastguard Worker     range.baseArrayLayer = 0;
1741*c8dee2aaSAndroid Build Coastguard Worker     range.baseMipLevel = 0;
1742*c8dee2aaSAndroid Build Coastguard Worker     range.layerCount = 1;
1743*c8dee2aaSAndroid Build Coastguard Worker     range.levelCount = info.fLevelCount;
1744*c8dee2aaSAndroid Build Coastguard Worker     cmdBuffer->clearColorImage(this, texImage, &vkColor, 1, &range);
1745*c8dee2aaSAndroid Build Coastguard Worker 
1746*c8dee2aaSAndroid Build Coastguard Worker     // Change image layout to shader read since if we use this texture as a borrowed
1747*c8dee2aaSAndroid Build Coastguard Worker     // texture within Ganesh we require that its layout be set to that
1748*c8dee2aaSAndroid Build Coastguard Worker     texImage->setImageLayout(this, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
1749*c8dee2aaSAndroid Build Coastguard Worker                                   VK_ACCESS_SHADER_READ_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
1750*c8dee2aaSAndroid Build Coastguard Worker                                   false);
1751*c8dee2aaSAndroid Build Coastguard Worker 
1752*c8dee2aaSAndroid Build Coastguard Worker     if (finishedCallback) {
1753*c8dee2aaSAndroid Build Coastguard Worker         this->addFinishedCallback(std::move(finishedCallback));
1754*c8dee2aaSAndroid Build Coastguard Worker     }
1755*c8dee2aaSAndroid Build Coastguard Worker     return true;
1756*c8dee2aaSAndroid Build Coastguard Worker }
1757*c8dee2aaSAndroid Build Coastguard Worker 
onCreateBackendTexture(SkISize dimensions,const GrBackendFormat & format,GrRenderable renderable,skgpu::Mipmapped mipmapped,GrProtected isProtected,std::string_view label)1758*c8dee2aaSAndroid Build Coastguard Worker GrBackendTexture GrVkGpu::onCreateBackendTexture(SkISize dimensions,
1759*c8dee2aaSAndroid Build Coastguard Worker                                                  const GrBackendFormat& format,
1760*c8dee2aaSAndroid Build Coastguard Worker                                                  GrRenderable renderable,
1761*c8dee2aaSAndroid Build Coastguard Worker                                                  skgpu::Mipmapped mipmapped,
1762*c8dee2aaSAndroid Build Coastguard Worker                                                  GrProtected isProtected,
1763*c8dee2aaSAndroid Build Coastguard Worker                                                  std::string_view label) {
1764*c8dee2aaSAndroid Build Coastguard Worker     const GrVkCaps& caps = this->vkCaps();
1765*c8dee2aaSAndroid Build Coastguard Worker 
1766*c8dee2aaSAndroid Build Coastguard Worker     if (fProtectedContext != isProtected) {
1767*c8dee2aaSAndroid Build Coastguard Worker         return {};
1768*c8dee2aaSAndroid Build Coastguard Worker     }
1769*c8dee2aaSAndroid Build Coastguard Worker 
1770*c8dee2aaSAndroid Build Coastguard Worker     VkFormat vkFormat;
1771*c8dee2aaSAndroid Build Coastguard Worker     if (!GrBackendFormats::AsVkFormat(format, &vkFormat)) {
1772*c8dee2aaSAndroid Build Coastguard Worker         return {};
1773*c8dee2aaSAndroid Build Coastguard Worker     }
1774*c8dee2aaSAndroid Build Coastguard Worker 
1775*c8dee2aaSAndroid Build Coastguard Worker     // TODO: move the texturability check up to GrGpu::createBackendTexture and just assert here
1776*c8dee2aaSAndroid Build Coastguard Worker     if (!caps.isVkFormatTexturable(vkFormat)) {
1777*c8dee2aaSAndroid Build Coastguard Worker         return {};
1778*c8dee2aaSAndroid Build Coastguard Worker     }
1779*c8dee2aaSAndroid Build Coastguard Worker 
1780*c8dee2aaSAndroid Build Coastguard Worker     if (skgpu::VkFormatNeedsYcbcrSampler(vkFormat)) {
1781*c8dee2aaSAndroid Build Coastguard Worker         return {};
1782*c8dee2aaSAndroid Build Coastguard Worker     }
1783*c8dee2aaSAndroid Build Coastguard Worker 
1784*c8dee2aaSAndroid Build Coastguard Worker     GrVkImageInfo info;
1785*c8dee2aaSAndroid Build Coastguard Worker     if (!this->createVkImageForBackendSurface(vkFormat, dimensions, 1, GrTexturable::kYes,
1786*c8dee2aaSAndroid Build Coastguard Worker                                               renderable, mipmapped, &info, isProtected)) {
1787*c8dee2aaSAndroid Build Coastguard Worker         return {};
1788*c8dee2aaSAndroid Build Coastguard Worker     }
1789*c8dee2aaSAndroid Build Coastguard Worker 
1790*c8dee2aaSAndroid Build Coastguard Worker     return GrBackendTextures::MakeVk(dimensions.width(), dimensions.height(), info);
1791*c8dee2aaSAndroid Build Coastguard Worker }
1792*c8dee2aaSAndroid Build Coastguard Worker 
onCreateCompressedBackendTexture(SkISize dimensions,const GrBackendFormat & format,skgpu::Mipmapped mipmapped,GrProtected isProtected)1793*c8dee2aaSAndroid Build Coastguard Worker GrBackendTexture GrVkGpu::onCreateCompressedBackendTexture(SkISize dimensions,
1794*c8dee2aaSAndroid Build Coastguard Worker                                                            const GrBackendFormat& format,
1795*c8dee2aaSAndroid Build Coastguard Worker                                                            skgpu::Mipmapped mipmapped,
1796*c8dee2aaSAndroid Build Coastguard Worker                                                            GrProtected isProtected) {
1797*c8dee2aaSAndroid Build Coastguard Worker     return this->onCreateBackendTexture(dimensions,
1798*c8dee2aaSAndroid Build Coastguard Worker                                         format,
1799*c8dee2aaSAndroid Build Coastguard Worker                                         GrRenderable::kNo,
1800*c8dee2aaSAndroid Build Coastguard Worker                                         mipmapped,
1801*c8dee2aaSAndroid Build Coastguard Worker                                         isProtected,
1802*c8dee2aaSAndroid Build Coastguard Worker                                         /*label=*/"VkGpu_CreateCompressedBackendTexture");
1803*c8dee2aaSAndroid Build Coastguard Worker }
1804*c8dee2aaSAndroid Build Coastguard Worker 
onUpdateCompressedBackendTexture(const GrBackendTexture & backendTexture,sk_sp<skgpu::RefCntedCallback> finishedCallback,const void * data,size_t size)1805*c8dee2aaSAndroid Build Coastguard Worker bool GrVkGpu::onUpdateCompressedBackendTexture(const GrBackendTexture& backendTexture,
1806*c8dee2aaSAndroid Build Coastguard Worker                                                sk_sp<skgpu::RefCntedCallback> finishedCallback,
1807*c8dee2aaSAndroid Build Coastguard Worker                                                const void* data,
1808*c8dee2aaSAndroid Build Coastguard Worker                                                size_t size) {
1809*c8dee2aaSAndroid Build Coastguard Worker     GrVkImageInfo info;
1810*c8dee2aaSAndroid Build Coastguard Worker     SkAssertResult(GrBackendTextures::GetVkImageInfo(backendTexture, &info));
1811*c8dee2aaSAndroid Build Coastguard Worker 
1812*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<skgpu::MutableTextureState> mutableState = backendTexture.getMutableState();
1813*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(mutableState);
1814*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<GrVkTexture> texture = GrVkTexture::MakeWrappedTexture(this,
1815*c8dee2aaSAndroid Build Coastguard Worker                                                                  backendTexture.dimensions(),
1816*c8dee2aaSAndroid Build Coastguard Worker                                                                  kBorrow_GrWrapOwnership,
1817*c8dee2aaSAndroid Build Coastguard Worker                                                                  GrWrapCacheable::kNo,
1818*c8dee2aaSAndroid Build Coastguard Worker                                                                  kRW_GrIOType,
1819*c8dee2aaSAndroid Build Coastguard Worker                                                                  info,
1820*c8dee2aaSAndroid Build Coastguard Worker                                                                  std::move(mutableState));
1821*c8dee2aaSAndroid Build Coastguard Worker     if (!texture) {
1822*c8dee2aaSAndroid Build Coastguard Worker         return false;
1823*c8dee2aaSAndroid Build Coastguard Worker     }
1824*c8dee2aaSAndroid Build Coastguard Worker 
1825*c8dee2aaSAndroid Build Coastguard Worker     GrVkPrimaryCommandBuffer* cmdBuffer = this->currentCommandBuffer();
1826*c8dee2aaSAndroid Build Coastguard Worker     if (!cmdBuffer) {
1827*c8dee2aaSAndroid Build Coastguard Worker         return false;
1828*c8dee2aaSAndroid Build Coastguard Worker     }
1829*c8dee2aaSAndroid Build Coastguard Worker     GrVkImage* image = texture->textureImage();
1830*c8dee2aaSAndroid Build Coastguard Worker     image->setImageLayout(this,
1831*c8dee2aaSAndroid Build Coastguard Worker                           VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1832*c8dee2aaSAndroid Build Coastguard Worker                           VK_ACCESS_TRANSFER_WRITE_BIT,
1833*c8dee2aaSAndroid Build Coastguard Worker                           VK_PIPELINE_STAGE_TRANSFER_BIT,
1834*c8dee2aaSAndroid Build Coastguard Worker                           false);
1835*c8dee2aaSAndroid Build Coastguard Worker 
1836*c8dee2aaSAndroid Build Coastguard Worker     SkTextureCompressionType compression =
1837*c8dee2aaSAndroid Build Coastguard Worker             GrBackendFormatToCompressionType(backendTexture.getBackendFormat());
1838*c8dee2aaSAndroid Build Coastguard Worker 
1839*c8dee2aaSAndroid Build Coastguard Worker     TArray<VkBufferImageCopy> regions;
1840*c8dee2aaSAndroid Build Coastguard Worker     TArray<size_t> individualMipOffsets;
1841*c8dee2aaSAndroid Build Coastguard Worker     GrStagingBufferManager::Slice slice;
1842*c8dee2aaSAndroid Build Coastguard Worker 
1843*c8dee2aaSAndroid Build Coastguard Worker     fill_in_compressed_regions(&fStagingBufferManager,
1844*c8dee2aaSAndroid Build Coastguard Worker                                &regions,
1845*c8dee2aaSAndroid Build Coastguard Worker                                &individualMipOffsets,
1846*c8dee2aaSAndroid Build Coastguard Worker                                &slice,
1847*c8dee2aaSAndroid Build Coastguard Worker                                compression,
1848*c8dee2aaSAndroid Build Coastguard Worker                                info.fFormat,
1849*c8dee2aaSAndroid Build Coastguard Worker                                backendTexture.dimensions(),
1850*c8dee2aaSAndroid Build Coastguard Worker                                backendTexture.fMipmapped);
1851*c8dee2aaSAndroid Build Coastguard Worker 
1852*c8dee2aaSAndroid Build Coastguard Worker     if (!slice.fBuffer) {
1853*c8dee2aaSAndroid Build Coastguard Worker         return false;
1854*c8dee2aaSAndroid Build Coastguard Worker     }
1855*c8dee2aaSAndroid Build Coastguard Worker 
1856*c8dee2aaSAndroid Build Coastguard Worker     memcpy(slice.fOffsetMapPtr, data, size);
1857*c8dee2aaSAndroid Build Coastguard Worker 
1858*c8dee2aaSAndroid Build Coastguard Worker     cmdBuffer->addGrSurface(texture);
1859*c8dee2aaSAndroid Build Coastguard Worker     // Copy the buffer to the image. This call takes the raw VkBuffer instead of a GrGpuBuffer
1860*c8dee2aaSAndroid Build Coastguard Worker     // because we don't need the command buffer to ref the buffer here. The reason being is that
1861*c8dee2aaSAndroid Build Coastguard Worker     // the buffer is coming from the staging manager and the staging manager will make sure the
1862*c8dee2aaSAndroid Build Coastguard Worker     // command buffer has a ref on the buffer. This avoids having to add and remove a ref for
1863*c8dee2aaSAndroid Build Coastguard Worker     // every upload in the frame.
1864*c8dee2aaSAndroid Build Coastguard Worker     cmdBuffer->copyBufferToImage(this,
1865*c8dee2aaSAndroid Build Coastguard Worker                                  static_cast<GrVkBuffer*>(slice.fBuffer)->vkBuffer(),
1866*c8dee2aaSAndroid Build Coastguard Worker                                  image,
1867*c8dee2aaSAndroid Build Coastguard Worker                                  image->currentLayout(),
1868*c8dee2aaSAndroid Build Coastguard Worker                                  regions.size(),
1869*c8dee2aaSAndroid Build Coastguard Worker                                  regions.begin());
1870*c8dee2aaSAndroid Build Coastguard Worker 
1871*c8dee2aaSAndroid Build Coastguard Worker     // Change image layout to shader read since if we use this texture as a borrowed
1872*c8dee2aaSAndroid Build Coastguard Worker     // texture within Ganesh we require that its layout be set to that
1873*c8dee2aaSAndroid Build Coastguard Worker     image->setImageLayout(this,
1874*c8dee2aaSAndroid Build Coastguard Worker                           VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
1875*c8dee2aaSAndroid Build Coastguard Worker                           VK_ACCESS_SHADER_READ_BIT,
1876*c8dee2aaSAndroid Build Coastguard Worker                           VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
1877*c8dee2aaSAndroid Build Coastguard Worker                           false);
1878*c8dee2aaSAndroid Build Coastguard Worker 
1879*c8dee2aaSAndroid Build Coastguard Worker     if (finishedCallback) {
1880*c8dee2aaSAndroid Build Coastguard Worker         this->addFinishedCallback(std::move(finishedCallback));
1881*c8dee2aaSAndroid Build Coastguard Worker     }
1882*c8dee2aaSAndroid Build Coastguard Worker     return true;
1883*c8dee2aaSAndroid Build Coastguard Worker }
1884*c8dee2aaSAndroid Build Coastguard Worker 
set_layout_and_queue_from_mutable_state(GrVkGpu * gpu,GrVkImage * image,VkImageLayout newLayout,uint32_t newQueueFamilyIndex)1885*c8dee2aaSAndroid Build Coastguard Worker void set_layout_and_queue_from_mutable_state(GrVkGpu* gpu, GrVkImage* image,
1886*c8dee2aaSAndroid Build Coastguard Worker                                              VkImageLayout newLayout,
1887*c8dee2aaSAndroid Build Coastguard Worker                                              uint32_t newQueueFamilyIndex) {
1888*c8dee2aaSAndroid Build Coastguard Worker     // Even though internally we use this helper for getting src access flags and stages they
1889*c8dee2aaSAndroid Build Coastguard Worker     // can also be used for general dst flags since we don't know exactly what the client
1890*c8dee2aaSAndroid Build Coastguard Worker     // plans on using the image for.
1891*c8dee2aaSAndroid Build Coastguard Worker     if (newLayout == VK_IMAGE_LAYOUT_UNDEFINED) {
1892*c8dee2aaSAndroid Build Coastguard Worker         newLayout = image->currentLayout();
1893*c8dee2aaSAndroid Build Coastguard Worker     }
1894*c8dee2aaSAndroid Build Coastguard Worker     VkPipelineStageFlags dstStage = GrVkImage::LayoutToPipelineSrcStageFlags(newLayout);
1895*c8dee2aaSAndroid Build Coastguard Worker     VkAccessFlags dstAccess = GrVkImage::LayoutToSrcAccessMask(newLayout);
1896*c8dee2aaSAndroid Build Coastguard Worker 
1897*c8dee2aaSAndroid Build Coastguard Worker     uint32_t currentQueueFamilyIndex = image->currentQueueFamilyIndex();
1898*c8dee2aaSAndroid Build Coastguard Worker     auto isSpecialQueue = [](uint32_t queueFamilyIndex) {
1899*c8dee2aaSAndroid Build Coastguard Worker         return queueFamilyIndex == VK_QUEUE_FAMILY_EXTERNAL ||
1900*c8dee2aaSAndroid Build Coastguard Worker                queueFamilyIndex == VK_QUEUE_FAMILY_FOREIGN_EXT;
1901*c8dee2aaSAndroid Build Coastguard Worker     };
1902*c8dee2aaSAndroid Build Coastguard Worker     if (isSpecialQueue(currentQueueFamilyIndex) && isSpecialQueue(newQueueFamilyIndex)) {
1903*c8dee2aaSAndroid Build Coastguard Worker         // It is illegal to have both the new and old queue be special queue families (i.e. external
1904*c8dee2aaSAndroid Build Coastguard Worker         // or foreign).
1905*c8dee2aaSAndroid Build Coastguard Worker         return;
1906*c8dee2aaSAndroid Build Coastguard Worker     }
1907*c8dee2aaSAndroid Build Coastguard Worker 
1908*c8dee2aaSAndroid Build Coastguard Worker     image->setImageLayoutAndQueueIndex(gpu, newLayout, dstAccess, dstStage, false,
1909*c8dee2aaSAndroid Build Coastguard Worker                                        newQueueFamilyIndex);
1910*c8dee2aaSAndroid Build Coastguard Worker }
1911*c8dee2aaSAndroid Build Coastguard Worker 
setBackendSurfaceState(GrVkImageInfo info,sk_sp<skgpu::MutableTextureState> currentState,SkISize dimensions,VkImageLayout newLayout,uint32_t newQueueFamilyIndex,skgpu::MutableTextureState * previousState,sk_sp<skgpu::RefCntedCallback> finishedCallback)1912*c8dee2aaSAndroid Build Coastguard Worker bool GrVkGpu::setBackendSurfaceState(GrVkImageInfo info,
1913*c8dee2aaSAndroid Build Coastguard Worker                                      sk_sp<skgpu::MutableTextureState> currentState,
1914*c8dee2aaSAndroid Build Coastguard Worker                                      SkISize dimensions,
1915*c8dee2aaSAndroid Build Coastguard Worker                                      VkImageLayout newLayout,
1916*c8dee2aaSAndroid Build Coastguard Worker                                      uint32_t newQueueFamilyIndex,
1917*c8dee2aaSAndroid Build Coastguard Worker                                      skgpu::MutableTextureState* previousState,
1918*c8dee2aaSAndroid Build Coastguard Worker                                      sk_sp<skgpu::RefCntedCallback> finishedCallback) {
1919*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<GrVkImage> texture = GrVkImage::MakeWrapped(this,
1920*c8dee2aaSAndroid Build Coastguard Worker                                                       dimensions,
1921*c8dee2aaSAndroid Build Coastguard Worker                                                       info,
1922*c8dee2aaSAndroid Build Coastguard Worker                                                       std::move(currentState),
1923*c8dee2aaSAndroid Build Coastguard Worker                                                       GrVkImage::UsageFlags::kColorAttachment,
1924*c8dee2aaSAndroid Build Coastguard Worker                                                       kBorrow_GrWrapOwnership,
1925*c8dee2aaSAndroid Build Coastguard Worker                                                       GrWrapCacheable::kNo,
1926*c8dee2aaSAndroid Build Coastguard Worker                                                       "VkGpu_SetBackendSurfaceState",
1927*c8dee2aaSAndroid Build Coastguard Worker                                                       /*forSecondaryCB=*/false);
1928*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(texture);
1929*c8dee2aaSAndroid Build Coastguard Worker     if (!texture) {
1930*c8dee2aaSAndroid Build Coastguard Worker         return false;
1931*c8dee2aaSAndroid Build Coastguard Worker     }
1932*c8dee2aaSAndroid Build Coastguard Worker     if (previousState) {
1933*c8dee2aaSAndroid Build Coastguard Worker         previousState->set(*texture->getMutableState());
1934*c8dee2aaSAndroid Build Coastguard Worker     }
1935*c8dee2aaSAndroid Build Coastguard Worker     set_layout_and_queue_from_mutable_state(this, texture.get(), newLayout, newQueueFamilyIndex);
1936*c8dee2aaSAndroid Build Coastguard Worker     if (finishedCallback) {
1937*c8dee2aaSAndroid Build Coastguard Worker         this->addFinishedCallback(std::move(finishedCallback));
1938*c8dee2aaSAndroid Build Coastguard Worker     }
1939*c8dee2aaSAndroid Build Coastguard Worker     return true;
1940*c8dee2aaSAndroid Build Coastguard Worker }
1941*c8dee2aaSAndroid Build Coastguard Worker 
setBackendTextureState(const GrBackendTexture & backendTeture,const skgpu::MutableTextureState & newState,skgpu::MutableTextureState * previousState,sk_sp<skgpu::RefCntedCallback> finishedCallback)1942*c8dee2aaSAndroid Build Coastguard Worker bool GrVkGpu::setBackendTextureState(const GrBackendTexture& backendTeture,
1943*c8dee2aaSAndroid Build Coastguard Worker                                      const skgpu::MutableTextureState& newState,
1944*c8dee2aaSAndroid Build Coastguard Worker                                      skgpu::MutableTextureState* previousState,
1945*c8dee2aaSAndroid Build Coastguard Worker                                      sk_sp<skgpu::RefCntedCallback> finishedCallback) {
1946*c8dee2aaSAndroid Build Coastguard Worker     GrVkImageInfo info;
1947*c8dee2aaSAndroid Build Coastguard Worker     SkAssertResult(GrBackendTextures::GetVkImageInfo(backendTeture, &info));
1948*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<skgpu::MutableTextureState> currentState = backendTeture.getMutableState();
1949*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(currentState);
1950*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(newState.isValid() && newState.backend() == skgpu::BackendApi::kVulkan);
1951*c8dee2aaSAndroid Build Coastguard Worker     return this->setBackendSurfaceState(info, std::move(currentState), backendTeture.dimensions(),
1952*c8dee2aaSAndroid Build Coastguard Worker                                         skgpu::MutableTextureStates::GetVkImageLayout(newState),
1953*c8dee2aaSAndroid Build Coastguard Worker                                         skgpu::MutableTextureStates::GetVkQueueFamilyIndex(newState),
1954*c8dee2aaSAndroid Build Coastguard Worker                                         previousState,
1955*c8dee2aaSAndroid Build Coastguard Worker                                         std::move(finishedCallback));
1956*c8dee2aaSAndroid Build Coastguard Worker }
1957*c8dee2aaSAndroid Build Coastguard Worker 
setBackendRenderTargetState(const GrBackendRenderTarget & backendRenderTarget,const skgpu::MutableTextureState & newState,skgpu::MutableTextureState * previousState,sk_sp<skgpu::RefCntedCallback> finishedCallback)1958*c8dee2aaSAndroid Build Coastguard Worker bool GrVkGpu::setBackendRenderTargetState(const GrBackendRenderTarget& backendRenderTarget,
1959*c8dee2aaSAndroid Build Coastguard Worker                                           const skgpu::MutableTextureState& newState,
1960*c8dee2aaSAndroid Build Coastguard Worker                                           skgpu::MutableTextureState* previousState,
1961*c8dee2aaSAndroid Build Coastguard Worker                                           sk_sp<skgpu::RefCntedCallback> finishedCallback) {
1962*c8dee2aaSAndroid Build Coastguard Worker     GrVkImageInfo info;
1963*c8dee2aaSAndroid Build Coastguard Worker     SkAssertResult(GrBackendRenderTargets::GetVkImageInfo(backendRenderTarget, &info));
1964*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<skgpu::MutableTextureState> currentState = backendRenderTarget.getMutableState();
1965*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(currentState);
1966*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(newState.backend() == skgpu::BackendApi::kVulkan);
1967*c8dee2aaSAndroid Build Coastguard Worker     return this->setBackendSurfaceState(info, std::move(currentState),
1968*c8dee2aaSAndroid Build Coastguard Worker                                         backendRenderTarget.dimensions(),
1969*c8dee2aaSAndroid Build Coastguard Worker                                         skgpu::MutableTextureStates::GetVkImageLayout(newState),
1970*c8dee2aaSAndroid Build Coastguard Worker                                         skgpu::MutableTextureStates::GetVkQueueFamilyIndex(newState),
1971*c8dee2aaSAndroid Build Coastguard Worker                                         previousState, std::move(finishedCallback));
1972*c8dee2aaSAndroid Build Coastguard Worker }
1973*c8dee2aaSAndroid Build Coastguard Worker 
xferBarrier(GrRenderTarget * rt,GrXferBarrierType barrierType)1974*c8dee2aaSAndroid Build Coastguard Worker void GrVkGpu::xferBarrier(GrRenderTarget* rt, GrXferBarrierType barrierType) {
1975*c8dee2aaSAndroid Build Coastguard Worker     GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(rt);
1976*c8dee2aaSAndroid Build Coastguard Worker     VkPipelineStageFlags dstStage;
1977*c8dee2aaSAndroid Build Coastguard Worker     VkAccessFlags dstAccess;
1978*c8dee2aaSAndroid Build Coastguard Worker     if (barrierType == kBlend_GrXferBarrierType) {
1979*c8dee2aaSAndroid Build Coastguard Worker         dstStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1980*c8dee2aaSAndroid Build Coastguard Worker         dstAccess = VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT;
1981*c8dee2aaSAndroid Build Coastguard Worker     } else {
1982*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(barrierType == kTexture_GrXferBarrierType);
1983*c8dee2aaSAndroid Build Coastguard Worker         dstStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
1984*c8dee2aaSAndroid Build Coastguard Worker         dstAccess = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
1985*c8dee2aaSAndroid Build Coastguard Worker     }
1986*c8dee2aaSAndroid Build Coastguard Worker     GrVkImage* image = vkRT->colorAttachment();
1987*c8dee2aaSAndroid Build Coastguard Worker     VkImageMemoryBarrier barrier;
1988*c8dee2aaSAndroid Build Coastguard Worker     barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
1989*c8dee2aaSAndroid Build Coastguard Worker     barrier.pNext = nullptr;
1990*c8dee2aaSAndroid Build Coastguard Worker     barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
1991*c8dee2aaSAndroid Build Coastguard Worker     barrier.dstAccessMask = dstAccess;
1992*c8dee2aaSAndroid Build Coastguard Worker     barrier.oldLayout = image->currentLayout();
1993*c8dee2aaSAndroid Build Coastguard Worker     barrier.newLayout = barrier.oldLayout;
1994*c8dee2aaSAndroid Build Coastguard Worker     barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1995*c8dee2aaSAndroid Build Coastguard Worker     barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1996*c8dee2aaSAndroid Build Coastguard Worker     barrier.image = image->image();
1997*c8dee2aaSAndroid Build Coastguard Worker     barrier.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, image->mipLevels(), 0, 1};
1998*c8dee2aaSAndroid Build Coastguard Worker     this->addImageMemoryBarrier(image->resource(),
1999*c8dee2aaSAndroid Build Coastguard Worker                                 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
2000*c8dee2aaSAndroid Build Coastguard Worker                                 dstStage, true, &barrier);
2001*c8dee2aaSAndroid Build Coastguard Worker }
2002*c8dee2aaSAndroid Build Coastguard Worker 
deleteBackendTexture(const GrBackendTexture & tex)2003*c8dee2aaSAndroid Build Coastguard Worker void GrVkGpu::deleteBackendTexture(const GrBackendTexture& tex) {
2004*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(GrBackendApi::kVulkan == tex.fBackend);
2005*c8dee2aaSAndroid Build Coastguard Worker 
2006*c8dee2aaSAndroid Build Coastguard Worker     GrVkImageInfo info;
2007*c8dee2aaSAndroid Build Coastguard Worker     if (GrBackendTextures::GetVkImageInfo(tex, &info)) {
2008*c8dee2aaSAndroid Build Coastguard Worker         GrVkImage::DestroyImageInfo(this, const_cast<GrVkImageInfo*>(&info));
2009*c8dee2aaSAndroid Build Coastguard Worker     }
2010*c8dee2aaSAndroid Build Coastguard Worker }
2011*c8dee2aaSAndroid Build Coastguard Worker 
compile(const GrProgramDesc & desc,const GrProgramInfo & programInfo)2012*c8dee2aaSAndroid Build Coastguard Worker bool GrVkGpu::compile(const GrProgramDesc& desc, const GrProgramInfo& programInfo) {
2013*c8dee2aaSAndroid Build Coastguard Worker     GrVkRenderPass::AttachmentsDescriptor attachmentsDescriptor;
2014*c8dee2aaSAndroid Build Coastguard Worker     GrVkRenderPass::AttachmentFlags attachmentFlags;
2015*c8dee2aaSAndroid Build Coastguard Worker     GrVkRenderTarget::ReconstructAttachmentsDescriptor(this->vkCaps(), programInfo,
2016*c8dee2aaSAndroid Build Coastguard Worker                                                        &attachmentsDescriptor, &attachmentFlags);
2017*c8dee2aaSAndroid Build Coastguard Worker 
2018*c8dee2aaSAndroid Build Coastguard Worker     GrVkRenderPass::SelfDependencyFlags selfDepFlags = GrVkRenderPass::SelfDependencyFlags::kNone;
2019*c8dee2aaSAndroid Build Coastguard Worker     if (programInfo.renderPassBarriers() & GrXferBarrierFlags::kBlend) {
2020*c8dee2aaSAndroid Build Coastguard Worker         selfDepFlags |= GrVkRenderPass::SelfDependencyFlags::kForNonCoherentAdvBlend;
2021*c8dee2aaSAndroid Build Coastguard Worker     }
2022*c8dee2aaSAndroid Build Coastguard Worker     if (programInfo.renderPassBarriers() & GrXferBarrierFlags::kTexture) {
2023*c8dee2aaSAndroid Build Coastguard Worker         selfDepFlags |= GrVkRenderPass::SelfDependencyFlags::kForInputAttachment;
2024*c8dee2aaSAndroid Build Coastguard Worker     }
2025*c8dee2aaSAndroid Build Coastguard Worker 
2026*c8dee2aaSAndroid Build Coastguard Worker     GrVkRenderPass::LoadFromResolve loadFromResolve = GrVkRenderPass::LoadFromResolve::kNo;
2027*c8dee2aaSAndroid Build Coastguard Worker     if (this->vkCaps().programInfoWillUseDiscardableMSAA(programInfo) &&
2028*c8dee2aaSAndroid Build Coastguard Worker         programInfo.colorLoadOp() == GrLoadOp::kLoad) {
2029*c8dee2aaSAndroid Build Coastguard Worker         loadFromResolve = GrVkRenderPass::LoadFromResolve::kLoad;
2030*c8dee2aaSAndroid Build Coastguard Worker     }
2031*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<const GrVkRenderPass> renderPass(this->resourceProvider().findCompatibleRenderPass(
2032*c8dee2aaSAndroid Build Coastguard Worker             &attachmentsDescriptor, attachmentFlags, selfDepFlags, loadFromResolve));
2033*c8dee2aaSAndroid Build Coastguard Worker     if (!renderPass) {
2034*c8dee2aaSAndroid Build Coastguard Worker         return false;
2035*c8dee2aaSAndroid Build Coastguard Worker     }
2036*c8dee2aaSAndroid Build Coastguard Worker 
2037*c8dee2aaSAndroid Build Coastguard Worker     GrThreadSafePipelineBuilder::Stats::ProgramCacheResult stat;
2038*c8dee2aaSAndroid Build Coastguard Worker 
2039*c8dee2aaSAndroid Build Coastguard Worker     auto pipelineState = this->resourceProvider().findOrCreateCompatiblePipelineState(
2040*c8dee2aaSAndroid Build Coastguard Worker                                     desc,
2041*c8dee2aaSAndroid Build Coastguard Worker                                     programInfo,
2042*c8dee2aaSAndroid Build Coastguard Worker                                     renderPass->vkRenderPass(),
2043*c8dee2aaSAndroid Build Coastguard Worker                                     &stat);
2044*c8dee2aaSAndroid Build Coastguard Worker     if (!pipelineState) {
2045*c8dee2aaSAndroid Build Coastguard Worker         return false;
2046*c8dee2aaSAndroid Build Coastguard Worker     }
2047*c8dee2aaSAndroid Build Coastguard Worker 
2048*c8dee2aaSAndroid Build Coastguard Worker     return stat != GrThreadSafePipelineBuilder::Stats::ProgramCacheResult::kHit;
2049*c8dee2aaSAndroid Build Coastguard Worker }
2050*c8dee2aaSAndroid Build Coastguard Worker 
2051*c8dee2aaSAndroid Build Coastguard Worker #if defined(GPU_TEST_UTILS)
isTestingOnlyBackendTexture(const GrBackendTexture & tex) const2052*c8dee2aaSAndroid Build Coastguard Worker bool GrVkGpu::isTestingOnlyBackendTexture(const GrBackendTexture& tex) const {
2053*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(GrBackendApi::kVulkan == tex.fBackend);
2054*c8dee2aaSAndroid Build Coastguard Worker 
2055*c8dee2aaSAndroid Build Coastguard Worker     GrVkImageInfo backend;
2056*c8dee2aaSAndroid Build Coastguard Worker     if (!GrBackendTextures::GetVkImageInfo(tex, &backend)) {
2057*c8dee2aaSAndroid Build Coastguard Worker         return false;
2058*c8dee2aaSAndroid Build Coastguard Worker     }
2059*c8dee2aaSAndroid Build Coastguard Worker 
2060*c8dee2aaSAndroid Build Coastguard Worker     if (backend.fImage && backend.fAlloc.fMemory) {
2061*c8dee2aaSAndroid Build Coastguard Worker         VkMemoryRequirements req;
2062*c8dee2aaSAndroid Build Coastguard Worker         memset(&req, 0, sizeof(req));
2063*c8dee2aaSAndroid Build Coastguard Worker         GR_VK_CALL(this->vkInterface(), GetImageMemoryRequirements(fDevice,
2064*c8dee2aaSAndroid Build Coastguard Worker                                                                    backend.fImage,
2065*c8dee2aaSAndroid Build Coastguard Worker                                                                    &req));
2066*c8dee2aaSAndroid Build Coastguard Worker         // TODO: find a better check
2067*c8dee2aaSAndroid Build Coastguard Worker         // This will probably fail with a different driver
2068*c8dee2aaSAndroid Build Coastguard Worker         return (req.size > 0) && (req.size <= 8192 * 8192);
2069*c8dee2aaSAndroid Build Coastguard Worker     }
2070*c8dee2aaSAndroid Build Coastguard Worker 
2071*c8dee2aaSAndroid Build Coastguard Worker     return false;
2072*c8dee2aaSAndroid Build Coastguard Worker }
2073*c8dee2aaSAndroid Build Coastguard Worker 
createTestingOnlyBackendRenderTarget(SkISize dimensions,GrColorType ct,int sampleCnt,GrProtected isProtected)2074*c8dee2aaSAndroid Build Coastguard Worker GrBackendRenderTarget GrVkGpu::createTestingOnlyBackendRenderTarget(SkISize dimensions,
2075*c8dee2aaSAndroid Build Coastguard Worker                                                                     GrColorType ct,
2076*c8dee2aaSAndroid Build Coastguard Worker                                                                     int sampleCnt,
2077*c8dee2aaSAndroid Build Coastguard Worker                                                                     GrProtected isProtected) {
2078*c8dee2aaSAndroid Build Coastguard Worker     if (dimensions.width()  > this->caps()->maxRenderTargetSize() ||
2079*c8dee2aaSAndroid Build Coastguard Worker         dimensions.height() > this->caps()->maxRenderTargetSize()) {
2080*c8dee2aaSAndroid Build Coastguard Worker         return {};
2081*c8dee2aaSAndroid Build Coastguard Worker     }
2082*c8dee2aaSAndroid Build Coastguard Worker 
2083*c8dee2aaSAndroid Build Coastguard Worker     VkFormat vkFormat = this->vkCaps().getFormatFromColorType(ct);
2084*c8dee2aaSAndroid Build Coastguard Worker 
2085*c8dee2aaSAndroid Build Coastguard Worker     GrVkImageInfo info;
2086*c8dee2aaSAndroid Build Coastguard Worker     if (!this->createVkImageForBackendSurface(vkFormat,
2087*c8dee2aaSAndroid Build Coastguard Worker                                               dimensions,
2088*c8dee2aaSAndroid Build Coastguard Worker                                               sampleCnt,
2089*c8dee2aaSAndroid Build Coastguard Worker                                               GrTexturable::kNo,
2090*c8dee2aaSAndroid Build Coastguard Worker                                               GrRenderable::kYes,
2091*c8dee2aaSAndroid Build Coastguard Worker                                               skgpu::Mipmapped::kNo,
2092*c8dee2aaSAndroid Build Coastguard Worker                                               &info,
2093*c8dee2aaSAndroid Build Coastguard Worker                                               isProtected)) {
2094*c8dee2aaSAndroid Build Coastguard Worker         return {};
2095*c8dee2aaSAndroid Build Coastguard Worker     }
2096*c8dee2aaSAndroid Build Coastguard Worker     return GrBackendRenderTargets::MakeVk(dimensions.width(), dimensions.height(), info);
2097*c8dee2aaSAndroid Build Coastguard Worker }
2098*c8dee2aaSAndroid Build Coastguard Worker 
deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget & rt)2099*c8dee2aaSAndroid Build Coastguard Worker void GrVkGpu::deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget& rt) {
2100*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(GrBackendApi::kVulkan == rt.fBackend);
2101*c8dee2aaSAndroid Build Coastguard Worker 
2102*c8dee2aaSAndroid Build Coastguard Worker     GrVkImageInfo info;
2103*c8dee2aaSAndroid Build Coastguard Worker     if (GrBackendRenderTargets::GetVkImageInfo(rt, &info)) {
2104*c8dee2aaSAndroid Build Coastguard Worker         // something in the command buffer may still be using this, so force submit
2105*c8dee2aaSAndroid Build Coastguard Worker         GrSubmitInfo submitInfo;
2106*c8dee2aaSAndroid Build Coastguard Worker         submitInfo.fSync = GrSyncCpu::kYes;
2107*c8dee2aaSAndroid Build Coastguard Worker         SkAssertResult(this->submitCommandBuffer(submitInfo));
2108*c8dee2aaSAndroid Build Coastguard Worker         GrVkImage::DestroyImageInfo(this, const_cast<GrVkImageInfo*>(&info));
2109*c8dee2aaSAndroid Build Coastguard Worker     }
2110*c8dee2aaSAndroid Build Coastguard Worker }
2111*c8dee2aaSAndroid Build Coastguard Worker #endif
2112*c8dee2aaSAndroid Build Coastguard Worker 
2113*c8dee2aaSAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////
2114*c8dee2aaSAndroid Build Coastguard Worker 
addBufferMemoryBarrier(const GrManagedResource * resource,VkPipelineStageFlags srcStageMask,VkPipelineStageFlags dstStageMask,bool byRegion,VkBufferMemoryBarrier * barrier) const2115*c8dee2aaSAndroid Build Coastguard Worker void GrVkGpu::addBufferMemoryBarrier(const GrManagedResource* resource,
2116*c8dee2aaSAndroid Build Coastguard Worker                                      VkPipelineStageFlags srcStageMask,
2117*c8dee2aaSAndroid Build Coastguard Worker                                      VkPipelineStageFlags dstStageMask,
2118*c8dee2aaSAndroid Build Coastguard Worker                                      bool byRegion,
2119*c8dee2aaSAndroid Build Coastguard Worker                                      VkBufferMemoryBarrier* barrier) const {
2120*c8dee2aaSAndroid Build Coastguard Worker     if (!this->currentCommandBuffer()) {
2121*c8dee2aaSAndroid Build Coastguard Worker         return;
2122*c8dee2aaSAndroid Build Coastguard Worker     }
2123*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(resource);
2124*c8dee2aaSAndroid Build Coastguard Worker     this->currentCommandBuffer()->pipelineBarrier(this,
2125*c8dee2aaSAndroid Build Coastguard Worker                                                   resource,
2126*c8dee2aaSAndroid Build Coastguard Worker                                                   srcStageMask,
2127*c8dee2aaSAndroid Build Coastguard Worker                                                   dstStageMask,
2128*c8dee2aaSAndroid Build Coastguard Worker                                                   byRegion,
2129*c8dee2aaSAndroid Build Coastguard Worker                                                   GrVkCommandBuffer::kBufferMemory_BarrierType,
2130*c8dee2aaSAndroid Build Coastguard Worker                                                   barrier);
2131*c8dee2aaSAndroid Build Coastguard Worker }
addBufferMemoryBarrier(VkPipelineStageFlags srcStageMask,VkPipelineStageFlags dstStageMask,bool byRegion,VkBufferMemoryBarrier * barrier) const2132*c8dee2aaSAndroid Build Coastguard Worker void GrVkGpu::addBufferMemoryBarrier(VkPipelineStageFlags srcStageMask,
2133*c8dee2aaSAndroid Build Coastguard Worker                                      VkPipelineStageFlags dstStageMask,
2134*c8dee2aaSAndroid Build Coastguard Worker                                      bool byRegion,
2135*c8dee2aaSAndroid Build Coastguard Worker                                      VkBufferMemoryBarrier* barrier) const {
2136*c8dee2aaSAndroid Build Coastguard Worker     if (!this->currentCommandBuffer()) {
2137*c8dee2aaSAndroid Build Coastguard Worker         return;
2138*c8dee2aaSAndroid Build Coastguard Worker     }
2139*c8dee2aaSAndroid Build Coastguard Worker     // We don't pass in a resource here to the command buffer. The command buffer only is using it
2140*c8dee2aaSAndroid Build Coastguard Worker     // to hold a ref, but every place where we add a buffer memory barrier we are doing some other
2141*c8dee2aaSAndroid Build Coastguard Worker     // command with the buffer on the command buffer. Thus those other commands will already cause
2142*c8dee2aaSAndroid Build Coastguard Worker     // the command buffer to be holding a ref to the buffer.
2143*c8dee2aaSAndroid Build Coastguard Worker     this->currentCommandBuffer()->pipelineBarrier(this,
2144*c8dee2aaSAndroid Build Coastguard Worker                                                   /*resource=*/nullptr,
2145*c8dee2aaSAndroid Build Coastguard Worker                                                   srcStageMask,
2146*c8dee2aaSAndroid Build Coastguard Worker                                                   dstStageMask,
2147*c8dee2aaSAndroid Build Coastguard Worker                                                   byRegion,
2148*c8dee2aaSAndroid Build Coastguard Worker                                                   GrVkCommandBuffer::kBufferMemory_BarrierType,
2149*c8dee2aaSAndroid Build Coastguard Worker                                                   barrier);
2150*c8dee2aaSAndroid Build Coastguard Worker }
2151*c8dee2aaSAndroid Build Coastguard Worker 
addImageMemoryBarrier(const GrManagedResource * resource,VkPipelineStageFlags srcStageMask,VkPipelineStageFlags dstStageMask,bool byRegion,VkImageMemoryBarrier * barrier) const2152*c8dee2aaSAndroid Build Coastguard Worker void GrVkGpu::addImageMemoryBarrier(const GrManagedResource* resource,
2153*c8dee2aaSAndroid Build Coastguard Worker                                     VkPipelineStageFlags srcStageMask,
2154*c8dee2aaSAndroid Build Coastguard Worker                                     VkPipelineStageFlags dstStageMask,
2155*c8dee2aaSAndroid Build Coastguard Worker                                     bool byRegion,
2156*c8dee2aaSAndroid Build Coastguard Worker                                     VkImageMemoryBarrier* barrier) const {
2157*c8dee2aaSAndroid Build Coastguard Worker     // If we are in the middle of destroying or abandoning the context we may hit a release proc
2158*c8dee2aaSAndroid Build Coastguard Worker     // that triggers the destruction of a GrVkImage. This could cause us to try and transfer the
2159*c8dee2aaSAndroid Build Coastguard Worker     // VkImage back to the original queue. In this state we don't submit anymore work and we may not
2160*c8dee2aaSAndroid Build Coastguard Worker     // have a current command buffer. Thus we won't do the queue transfer.
2161*c8dee2aaSAndroid Build Coastguard Worker     if (!this->currentCommandBuffer()) {
2162*c8dee2aaSAndroid Build Coastguard Worker         return;
2163*c8dee2aaSAndroid Build Coastguard Worker     }
2164*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(resource);
2165*c8dee2aaSAndroid Build Coastguard Worker     this->currentCommandBuffer()->pipelineBarrier(this,
2166*c8dee2aaSAndroid Build Coastguard Worker                                                   resource,
2167*c8dee2aaSAndroid Build Coastguard Worker                                                   srcStageMask,
2168*c8dee2aaSAndroid Build Coastguard Worker                                                   dstStageMask,
2169*c8dee2aaSAndroid Build Coastguard Worker                                                   byRegion,
2170*c8dee2aaSAndroid Build Coastguard Worker                                                   GrVkCommandBuffer::kImageMemory_BarrierType,
2171*c8dee2aaSAndroid Build Coastguard Worker                                                   barrier);
2172*c8dee2aaSAndroid Build Coastguard Worker }
2173*c8dee2aaSAndroid Build Coastguard Worker 
prepareSurfacesForBackendAccessAndStateUpdates(SkSpan<GrSurfaceProxy * > proxies,SkSurfaces::BackendSurfaceAccess access,const skgpu::MutableTextureState * newState)2174*c8dee2aaSAndroid Build Coastguard Worker void GrVkGpu::prepareSurfacesForBackendAccessAndStateUpdates(
2175*c8dee2aaSAndroid Build Coastguard Worker         SkSpan<GrSurfaceProxy*> proxies,
2176*c8dee2aaSAndroid Build Coastguard Worker         SkSurfaces::BackendSurfaceAccess access,
2177*c8dee2aaSAndroid Build Coastguard Worker         const skgpu::MutableTextureState* newState) {
2178*c8dee2aaSAndroid Build Coastguard Worker     // Submit the current command buffer to the Queue. Whether we inserted semaphores or not does
2179*c8dee2aaSAndroid Build Coastguard Worker     // not effect what we do here.
2180*c8dee2aaSAndroid Build Coastguard Worker     if (!proxies.empty() && (access == SkSurfaces::BackendSurfaceAccess::kPresent || newState)) {
2181*c8dee2aaSAndroid Build Coastguard Worker         // We currently don't support passing in new surface state for multiple proxies here. The
2182*c8dee2aaSAndroid Build Coastguard Worker         // only time we have multiple proxies is if we are flushing a yuv SkImage which won't have
2183*c8dee2aaSAndroid Build Coastguard Worker         // state updates anyways. Additionally if we have a newState than we must not have any
2184*c8dee2aaSAndroid Build Coastguard Worker         // BackendSurfaceAccess.
2185*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(!newState || proxies.size() == 1);
2186*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(!newState || access == SkSurfaces::BackendSurfaceAccess::kNoAccess);
2187*c8dee2aaSAndroid Build Coastguard Worker         GrVkImage* image;
2188*c8dee2aaSAndroid Build Coastguard Worker         for (GrSurfaceProxy* proxy : proxies) {
2189*c8dee2aaSAndroid Build Coastguard Worker             SkASSERT(proxy->isInstantiated());
2190*c8dee2aaSAndroid Build Coastguard Worker             if (GrTexture* tex = proxy->peekTexture()) {
2191*c8dee2aaSAndroid Build Coastguard Worker                 image = static_cast<GrVkTexture*>(tex)->textureImage();
2192*c8dee2aaSAndroid Build Coastguard Worker             } else {
2193*c8dee2aaSAndroid Build Coastguard Worker                 GrRenderTarget* rt = proxy->peekRenderTarget();
2194*c8dee2aaSAndroid Build Coastguard Worker                 SkASSERT(rt);
2195*c8dee2aaSAndroid Build Coastguard Worker                 GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(rt);
2196*c8dee2aaSAndroid Build Coastguard Worker                 image = vkRT->externalAttachment();
2197*c8dee2aaSAndroid Build Coastguard Worker             }
2198*c8dee2aaSAndroid Build Coastguard Worker             if (newState) {
2199*c8dee2aaSAndroid Build Coastguard Worker                 VkImageLayout newLayout =
2200*c8dee2aaSAndroid Build Coastguard Worker                     skgpu::MutableTextureStates::GetVkImageLayout(newState);
2201*c8dee2aaSAndroid Build Coastguard Worker                 uint32_t newIndex =
2202*c8dee2aaSAndroid Build Coastguard Worker                     skgpu::MutableTextureStates::GetVkQueueFamilyIndex(newState);
2203*c8dee2aaSAndroid Build Coastguard Worker                 set_layout_and_queue_from_mutable_state(this, image, newLayout, newIndex);
2204*c8dee2aaSAndroid Build Coastguard Worker             } else {
2205*c8dee2aaSAndroid Build Coastguard Worker                 SkASSERT(access == SkSurfaces::BackendSurfaceAccess::kPresent);
2206*c8dee2aaSAndroid Build Coastguard Worker                 image->prepareForPresent(this);
2207*c8dee2aaSAndroid Build Coastguard Worker             }
2208*c8dee2aaSAndroid Build Coastguard Worker         }
2209*c8dee2aaSAndroid Build Coastguard Worker     }
2210*c8dee2aaSAndroid Build Coastguard Worker }
2211*c8dee2aaSAndroid Build Coastguard Worker 
addFinishedCallback(sk_sp<skgpu::RefCntedCallback> finishedCallback)2212*c8dee2aaSAndroid Build Coastguard Worker void GrVkGpu::addFinishedCallback(sk_sp<skgpu::RefCntedCallback> finishedCallback) {
2213*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(finishedCallback);
2214*c8dee2aaSAndroid Build Coastguard Worker     fResourceProvider.addFinishedProcToActiveCommandBuffers(std::move(finishedCallback));
2215*c8dee2aaSAndroid Build Coastguard Worker }
2216*c8dee2aaSAndroid Build Coastguard Worker 
takeOwnershipOfBuffer(sk_sp<GrGpuBuffer> buffer)2217*c8dee2aaSAndroid Build Coastguard Worker void GrVkGpu::takeOwnershipOfBuffer(sk_sp<GrGpuBuffer> buffer) {
2218*c8dee2aaSAndroid Build Coastguard Worker     this->currentCommandBuffer()->addGrBuffer(std::move(buffer));
2219*c8dee2aaSAndroid Build Coastguard Worker }
2220*c8dee2aaSAndroid Build Coastguard Worker 
onSubmitToGpu(const GrSubmitInfo & info)2221*c8dee2aaSAndroid Build Coastguard Worker bool GrVkGpu::onSubmitToGpu(const GrSubmitInfo& info) {
2222*c8dee2aaSAndroid Build Coastguard Worker     return this->submitCommandBuffer(info);
2223*c8dee2aaSAndroid Build Coastguard Worker }
2224*c8dee2aaSAndroid Build Coastguard Worker 
finishOutstandingGpuWork()2225*c8dee2aaSAndroid Build Coastguard Worker void GrVkGpu::finishOutstandingGpuWork() {
2226*c8dee2aaSAndroid Build Coastguard Worker     VK_CALL(QueueWaitIdle(fQueue));
2227*c8dee2aaSAndroid Build Coastguard Worker 
2228*c8dee2aaSAndroid Build Coastguard Worker     if (this->vkCaps().mustSyncCommandBuffersWithQueue()) {
2229*c8dee2aaSAndroid Build Coastguard Worker         fResourceProvider.forceSyncAllCommandBuffers();
2230*c8dee2aaSAndroid Build Coastguard Worker     }
2231*c8dee2aaSAndroid Build Coastguard Worker }
2232*c8dee2aaSAndroid Build Coastguard Worker 
onReportSubmitHistograms()2233*c8dee2aaSAndroid Build Coastguard Worker void GrVkGpu::onReportSubmitHistograms() {
2234*c8dee2aaSAndroid Build Coastguard Worker #if SK_HISTOGRAMS_ENABLED
2235*c8dee2aaSAndroid Build Coastguard Worker     uint64_t allocatedMemory = 0, usedMemory = 0;
2236*c8dee2aaSAndroid Build Coastguard Worker     std::tie(allocatedMemory, usedMemory) = fMemoryAllocator->totalAllocatedAndUsedMemory();
2237*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(usedMemory <= allocatedMemory);
2238*c8dee2aaSAndroid Build Coastguard Worker     if (allocatedMemory > 0) {
2239*c8dee2aaSAndroid Build Coastguard Worker         SK_HISTOGRAM_PERCENTAGE("VulkanMemoryAllocator.PercentUsed",
2240*c8dee2aaSAndroid Build Coastguard Worker                                 (usedMemory * 100) / allocatedMemory);
2241*c8dee2aaSAndroid Build Coastguard Worker     }
2242*c8dee2aaSAndroid Build Coastguard Worker     // allocatedMemory is in bytes and need to be reported it in kilobytes. SK_HISTOGRAM_MEMORY_KB
2243*c8dee2aaSAndroid Build Coastguard Worker     // supports samples up to around 500MB which should support the amounts of memory we allocate.
2244*c8dee2aaSAndroid Build Coastguard Worker     SK_HISTOGRAM_MEMORY_KB("VulkanMemoryAllocator.AmountAllocated", allocatedMemory >> 10);
2245*c8dee2aaSAndroid Build Coastguard Worker #endif  // SK_HISTOGRAMS_ENABLED
2246*c8dee2aaSAndroid Build Coastguard Worker }
2247*c8dee2aaSAndroid Build Coastguard Worker 
copySurfaceAsCopyImage(GrSurface * dst,GrSurface * src,GrVkImage * dstImage,GrVkImage * srcImage,const SkIRect & srcRect,const SkIPoint & dstPoint)2248*c8dee2aaSAndroid Build Coastguard Worker void GrVkGpu::copySurfaceAsCopyImage(GrSurface* dst,
2249*c8dee2aaSAndroid Build Coastguard Worker                                      GrSurface* src,
2250*c8dee2aaSAndroid Build Coastguard Worker                                      GrVkImage* dstImage,
2251*c8dee2aaSAndroid Build Coastguard Worker                                      GrVkImage* srcImage,
2252*c8dee2aaSAndroid Build Coastguard Worker                                      const SkIRect& srcRect,
2253*c8dee2aaSAndroid Build Coastguard Worker                                      const SkIPoint& dstPoint) {
2254*c8dee2aaSAndroid Build Coastguard Worker     if (!this->currentCommandBuffer()) {
2255*c8dee2aaSAndroid Build Coastguard Worker         return;
2256*c8dee2aaSAndroid Build Coastguard Worker     }
2257*c8dee2aaSAndroid Build Coastguard Worker 
2258*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_DEBUG
2259*c8dee2aaSAndroid Build Coastguard Worker     int dstSampleCnt = dstImage->numSamples();
2260*c8dee2aaSAndroid Build Coastguard Worker     int srcSampleCnt = srcImage->numSamples();
2261*c8dee2aaSAndroid Build Coastguard Worker     bool dstHasYcbcr = dstImage->ycbcrConversionInfo().isValid();
2262*c8dee2aaSAndroid Build Coastguard Worker     bool srcHasYcbcr = srcImage->ycbcrConversionInfo().isValid();
2263*c8dee2aaSAndroid Build Coastguard Worker     VkFormat dstFormat = dstImage->imageFormat();
2264*c8dee2aaSAndroid Build Coastguard Worker     VkFormat srcFormat;
2265*c8dee2aaSAndroid Build Coastguard Worker     SkAssertResult(GrBackendFormats::AsVkFormat(dst->backendFormat(), &srcFormat));
2266*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(this->vkCaps().canCopyImage(dstFormat, dstSampleCnt, dstHasYcbcr,
2267*c8dee2aaSAndroid Build Coastguard Worker                                          srcFormat, srcSampleCnt, srcHasYcbcr));
2268*c8dee2aaSAndroid Build Coastguard Worker #endif
2269*c8dee2aaSAndroid Build Coastguard Worker     if (src->isProtected() && !dst->isProtected()) {
2270*c8dee2aaSAndroid Build Coastguard Worker         SkDebugf("Can't copy from protected memory to non-protected");
2271*c8dee2aaSAndroid Build Coastguard Worker         return;
2272*c8dee2aaSAndroid Build Coastguard Worker     }
2273*c8dee2aaSAndroid Build Coastguard Worker 
2274*c8dee2aaSAndroid Build Coastguard Worker     // These flags are for flushing/invalidating caches and for the dst image it doesn't matter if
2275*c8dee2aaSAndroid Build Coastguard Worker     // the cache is flushed since it is only being written to.
2276*c8dee2aaSAndroid Build Coastguard Worker     dstImage->setImageLayout(this,
2277*c8dee2aaSAndroid Build Coastguard Worker                              VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
2278*c8dee2aaSAndroid Build Coastguard Worker                              VK_ACCESS_TRANSFER_WRITE_BIT,
2279*c8dee2aaSAndroid Build Coastguard Worker                              VK_PIPELINE_STAGE_TRANSFER_BIT,
2280*c8dee2aaSAndroid Build Coastguard Worker                              false);
2281*c8dee2aaSAndroid Build Coastguard Worker 
2282*c8dee2aaSAndroid Build Coastguard Worker     srcImage->setImageLayout(this,
2283*c8dee2aaSAndroid Build Coastguard Worker                              VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
2284*c8dee2aaSAndroid Build Coastguard Worker                              VK_ACCESS_TRANSFER_READ_BIT,
2285*c8dee2aaSAndroid Build Coastguard Worker                              VK_PIPELINE_STAGE_TRANSFER_BIT,
2286*c8dee2aaSAndroid Build Coastguard Worker                              false);
2287*c8dee2aaSAndroid Build Coastguard Worker 
2288*c8dee2aaSAndroid Build Coastguard Worker     VkImageCopy copyRegion;
2289*c8dee2aaSAndroid Build Coastguard Worker     memset(&copyRegion, 0, sizeof(VkImageCopy));
2290*c8dee2aaSAndroid Build Coastguard Worker     copyRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
2291*c8dee2aaSAndroid Build Coastguard Worker     copyRegion.srcOffset = { srcRect.fLeft, srcRect.fTop, 0 };
2292*c8dee2aaSAndroid Build Coastguard Worker     copyRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
2293*c8dee2aaSAndroid Build Coastguard Worker     copyRegion.dstOffset = { dstPoint.fX, dstPoint.fY, 0 };
2294*c8dee2aaSAndroid Build Coastguard Worker     copyRegion.extent = { (uint32_t)srcRect.width(), (uint32_t)srcRect.height(), 1 };
2295*c8dee2aaSAndroid Build Coastguard Worker 
2296*c8dee2aaSAndroid Build Coastguard Worker     this->currentCommandBuffer()->addGrSurface(sk_ref_sp<const GrSurface>(src));
2297*c8dee2aaSAndroid Build Coastguard Worker     this->currentCommandBuffer()->addGrSurface(sk_ref_sp<const GrSurface>(dst));
2298*c8dee2aaSAndroid Build Coastguard Worker     this->currentCommandBuffer()->copyImage(this,
2299*c8dee2aaSAndroid Build Coastguard Worker                                             srcImage,
2300*c8dee2aaSAndroid Build Coastguard Worker                                             VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
2301*c8dee2aaSAndroid Build Coastguard Worker                                             dstImage,
2302*c8dee2aaSAndroid Build Coastguard Worker                                             VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
2303*c8dee2aaSAndroid Build Coastguard Worker                                             1,
2304*c8dee2aaSAndroid Build Coastguard Worker                                             &copyRegion);
2305*c8dee2aaSAndroid Build Coastguard Worker 
2306*c8dee2aaSAndroid Build Coastguard Worker     SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY,
2307*c8dee2aaSAndroid Build Coastguard Worker                                         srcRect.width(), srcRect.height());
2308*c8dee2aaSAndroid Build Coastguard Worker     // The rect is already in device space so we pass in kTopLeft so no flip is done.
2309*c8dee2aaSAndroid Build Coastguard Worker     this->didWriteToSurface(dst, kTopLeft_GrSurfaceOrigin, &dstRect);
2310*c8dee2aaSAndroid Build Coastguard Worker }
2311*c8dee2aaSAndroid Build Coastguard Worker 
copySurfaceAsBlit(GrSurface * dst,GrSurface * src,GrVkImage * dstImage,GrVkImage * srcImage,const SkIRect & srcRect,const SkIRect & dstRect,GrSamplerState::Filter filter)2312*c8dee2aaSAndroid Build Coastguard Worker void GrVkGpu::copySurfaceAsBlit(GrSurface* dst,
2313*c8dee2aaSAndroid Build Coastguard Worker                                 GrSurface* src,
2314*c8dee2aaSAndroid Build Coastguard Worker                                 GrVkImage* dstImage,
2315*c8dee2aaSAndroid Build Coastguard Worker                                 GrVkImage* srcImage,
2316*c8dee2aaSAndroid Build Coastguard Worker                                 const SkIRect& srcRect,
2317*c8dee2aaSAndroid Build Coastguard Worker                                 const SkIRect& dstRect,
2318*c8dee2aaSAndroid Build Coastguard Worker                                 GrSamplerState::Filter filter) {
2319*c8dee2aaSAndroid Build Coastguard Worker     if (!this->currentCommandBuffer()) {
2320*c8dee2aaSAndroid Build Coastguard Worker         return;
2321*c8dee2aaSAndroid Build Coastguard Worker     }
2322*c8dee2aaSAndroid Build Coastguard Worker 
2323*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_DEBUG
2324*c8dee2aaSAndroid Build Coastguard Worker     int dstSampleCnt = dstImage->numSamples();
2325*c8dee2aaSAndroid Build Coastguard Worker     int srcSampleCnt = srcImage->numSamples();
2326*c8dee2aaSAndroid Build Coastguard Worker     bool dstHasYcbcr = dstImage->ycbcrConversionInfo().isValid();
2327*c8dee2aaSAndroid Build Coastguard Worker     bool srcHasYcbcr = srcImage->ycbcrConversionInfo().isValid();
2328*c8dee2aaSAndroid Build Coastguard Worker     VkFormat dstFormat = dstImage->imageFormat();
2329*c8dee2aaSAndroid Build Coastguard Worker     VkFormat srcFormat;
2330*c8dee2aaSAndroid Build Coastguard Worker     SkAssertResult(GrBackendFormats::AsVkFormat(dst->backendFormat(), &srcFormat));
2331*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(this->vkCaps().canCopyAsBlit(dstFormat,
2332*c8dee2aaSAndroid Build Coastguard Worker                                           dstSampleCnt,
2333*c8dee2aaSAndroid Build Coastguard Worker                                           dstImage->isLinearTiled(),
2334*c8dee2aaSAndroid Build Coastguard Worker                                           dstHasYcbcr,
2335*c8dee2aaSAndroid Build Coastguard Worker                                           srcFormat,
2336*c8dee2aaSAndroid Build Coastguard Worker                                           srcSampleCnt,
2337*c8dee2aaSAndroid Build Coastguard Worker                                           srcImage->isLinearTiled(),
2338*c8dee2aaSAndroid Build Coastguard Worker                                           srcHasYcbcr));
2339*c8dee2aaSAndroid Build Coastguard Worker 
2340*c8dee2aaSAndroid Build Coastguard Worker #endif
2341*c8dee2aaSAndroid Build Coastguard Worker     if (src->isProtected() && !dst->isProtected()) {
2342*c8dee2aaSAndroid Build Coastguard Worker         SkDebugf("Can't copy from protected memory to non-protected");
2343*c8dee2aaSAndroid Build Coastguard Worker         return;
2344*c8dee2aaSAndroid Build Coastguard Worker     }
2345*c8dee2aaSAndroid Build Coastguard Worker 
2346*c8dee2aaSAndroid Build Coastguard Worker     dstImage->setImageLayout(this,
2347*c8dee2aaSAndroid Build Coastguard Worker                              VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
2348*c8dee2aaSAndroid Build Coastguard Worker                              VK_ACCESS_TRANSFER_WRITE_BIT,
2349*c8dee2aaSAndroid Build Coastguard Worker                              VK_PIPELINE_STAGE_TRANSFER_BIT,
2350*c8dee2aaSAndroid Build Coastguard Worker                              false);
2351*c8dee2aaSAndroid Build Coastguard Worker 
2352*c8dee2aaSAndroid Build Coastguard Worker     srcImage->setImageLayout(this,
2353*c8dee2aaSAndroid Build Coastguard Worker                              VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
2354*c8dee2aaSAndroid Build Coastguard Worker                              VK_ACCESS_TRANSFER_READ_BIT,
2355*c8dee2aaSAndroid Build Coastguard Worker                              VK_PIPELINE_STAGE_TRANSFER_BIT,
2356*c8dee2aaSAndroid Build Coastguard Worker                              false);
2357*c8dee2aaSAndroid Build Coastguard Worker 
2358*c8dee2aaSAndroid Build Coastguard Worker     VkImageBlit blitRegion;
2359*c8dee2aaSAndroid Build Coastguard Worker     memset(&blitRegion, 0, sizeof(VkImageBlit));
2360*c8dee2aaSAndroid Build Coastguard Worker     blitRegion.srcSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
2361*c8dee2aaSAndroid Build Coastguard Worker     blitRegion.srcOffsets[0] = { srcRect.fLeft, srcRect.fTop, 0 };
2362*c8dee2aaSAndroid Build Coastguard Worker     blitRegion.srcOffsets[1] = { srcRect.fRight, srcRect.fBottom, 1 };
2363*c8dee2aaSAndroid Build Coastguard Worker     blitRegion.dstSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
2364*c8dee2aaSAndroid Build Coastguard Worker     blitRegion.dstOffsets[0] = { dstRect.fLeft, dstRect.fTop, 0 };
2365*c8dee2aaSAndroid Build Coastguard Worker     blitRegion.dstOffsets[1] = { dstRect.fRight, dstRect.fBottom, 1 };
2366*c8dee2aaSAndroid Build Coastguard Worker 
2367*c8dee2aaSAndroid Build Coastguard Worker     this->currentCommandBuffer()->addGrSurface(sk_ref_sp<const GrSurface>(src));
2368*c8dee2aaSAndroid Build Coastguard Worker     this->currentCommandBuffer()->addGrSurface(sk_ref_sp<const GrSurface>(dst));
2369*c8dee2aaSAndroid Build Coastguard Worker     this->currentCommandBuffer()->blitImage(this,
2370*c8dee2aaSAndroid Build Coastguard Worker                                             *srcImage,
2371*c8dee2aaSAndroid Build Coastguard Worker                                             *dstImage,
2372*c8dee2aaSAndroid Build Coastguard Worker                                             1,
2373*c8dee2aaSAndroid Build Coastguard Worker                                             &blitRegion,
2374*c8dee2aaSAndroid Build Coastguard Worker                                             filter == GrSamplerState::Filter::kNearest ?
2375*c8dee2aaSAndroid Build Coastguard Worker                                                     VK_FILTER_NEAREST : VK_FILTER_LINEAR);
2376*c8dee2aaSAndroid Build Coastguard Worker 
2377*c8dee2aaSAndroid Build Coastguard Worker     // The rect is already in device space so we pass in kTopLeft so no flip is done.
2378*c8dee2aaSAndroid Build Coastguard Worker     this->didWriteToSurface(dst, kTopLeft_GrSurfaceOrigin, &dstRect);
2379*c8dee2aaSAndroid Build Coastguard Worker }
2380*c8dee2aaSAndroid Build Coastguard Worker 
copySurfaceAsResolve(GrSurface * dst,GrSurface * src,const SkIRect & srcRect,const SkIPoint & dstPoint)2381*c8dee2aaSAndroid Build Coastguard Worker void GrVkGpu::copySurfaceAsResolve(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
2382*c8dee2aaSAndroid Build Coastguard Worker                                    const SkIPoint& dstPoint) {
2383*c8dee2aaSAndroid Build Coastguard Worker     if (src->isProtected() && !dst->isProtected()) {
2384*c8dee2aaSAndroid Build Coastguard Worker         SkDebugf("Can't copy from protected memory to non-protected");
2385*c8dee2aaSAndroid Build Coastguard Worker         return;
2386*c8dee2aaSAndroid Build Coastguard Worker     }
2387*c8dee2aaSAndroid Build Coastguard Worker     GrVkRenderTarget* srcRT = static_cast<GrVkRenderTarget*>(src->asRenderTarget());
2388*c8dee2aaSAndroid Build Coastguard Worker     this->resolveImage(dst, srcRT, srcRect, dstPoint);
2389*c8dee2aaSAndroid Build Coastguard Worker     SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY,
2390*c8dee2aaSAndroid Build Coastguard Worker                                         srcRect.width(), srcRect.height());
2391*c8dee2aaSAndroid Build Coastguard Worker     // The rect is already in device space so we pass in kTopLeft so no flip is done.
2392*c8dee2aaSAndroid Build Coastguard Worker     this->didWriteToSurface(dst, kTopLeft_GrSurfaceOrigin, &dstRect);
2393*c8dee2aaSAndroid Build Coastguard Worker }
2394*c8dee2aaSAndroid Build Coastguard Worker 
onCopySurface(GrSurface * dst,const SkIRect & dstRect,GrSurface * src,const SkIRect & srcRect,GrSamplerState::Filter filter)2395*c8dee2aaSAndroid Build Coastguard Worker bool GrVkGpu::onCopySurface(GrSurface* dst, const SkIRect& dstRect,
2396*c8dee2aaSAndroid Build Coastguard Worker                             GrSurface* src, const SkIRect& srcRect,
2397*c8dee2aaSAndroid Build Coastguard Worker                             GrSamplerState::Filter filter) {
2398*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_DEBUG
2399*c8dee2aaSAndroid Build Coastguard Worker     if (GrVkRenderTarget* srcRT = static_cast<GrVkRenderTarget*>(src->asRenderTarget())) {
2400*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(!srcRT->wrapsSecondaryCommandBuffer());
2401*c8dee2aaSAndroid Build Coastguard Worker     }
2402*c8dee2aaSAndroid Build Coastguard Worker     if (GrVkRenderTarget* dstRT = static_cast<GrVkRenderTarget*>(dst->asRenderTarget())) {
2403*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(!dstRT->wrapsSecondaryCommandBuffer());
2404*c8dee2aaSAndroid Build Coastguard Worker     }
2405*c8dee2aaSAndroid Build Coastguard Worker #endif
2406*c8dee2aaSAndroid Build Coastguard Worker     if (src->isProtected() && !dst->isProtected()) {
2407*c8dee2aaSAndroid Build Coastguard Worker         SkDebugf("Can't copy from protected memory to non-protected");
2408*c8dee2aaSAndroid Build Coastguard Worker         return false;
2409*c8dee2aaSAndroid Build Coastguard Worker     }
2410*c8dee2aaSAndroid Build Coastguard Worker 
2411*c8dee2aaSAndroid Build Coastguard Worker     GrVkImage* dstImage;
2412*c8dee2aaSAndroid Build Coastguard Worker     GrVkImage* srcImage;
2413*c8dee2aaSAndroid Build Coastguard Worker     GrRenderTarget* dstRT = dst->asRenderTarget();
2414*c8dee2aaSAndroid Build Coastguard Worker     if (dstRT) {
2415*c8dee2aaSAndroid Build Coastguard Worker         GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(dstRT);
2416*c8dee2aaSAndroid Build Coastguard Worker         if (vkRT->wrapsSecondaryCommandBuffer()) {
2417*c8dee2aaSAndroid Build Coastguard Worker             return false;
2418*c8dee2aaSAndroid Build Coastguard Worker         }
2419*c8dee2aaSAndroid Build Coastguard Worker         // This will technically return true for single sample rts that used DMSAA in which case we
2420*c8dee2aaSAndroid Build Coastguard Worker         // don't have to pick the resolve attachment. But in that case the resolve and color
2421*c8dee2aaSAndroid Build Coastguard Worker         // attachments will be the same anyways.
2422*c8dee2aaSAndroid Build Coastguard Worker         if (this->vkCaps().renderTargetSupportsDiscardableMSAA(vkRT)) {
2423*c8dee2aaSAndroid Build Coastguard Worker             dstImage = vkRT->resolveAttachment();
2424*c8dee2aaSAndroid Build Coastguard Worker         } else {
2425*c8dee2aaSAndroid Build Coastguard Worker             dstImage = vkRT->colorAttachment();
2426*c8dee2aaSAndroid Build Coastguard Worker         }
2427*c8dee2aaSAndroid Build Coastguard Worker     } else if (dst->asTexture()) {
2428*c8dee2aaSAndroid Build Coastguard Worker         dstImage = static_cast<GrVkTexture*>(dst->asTexture())->textureImage();
2429*c8dee2aaSAndroid Build Coastguard Worker     } else {
2430*c8dee2aaSAndroid Build Coastguard Worker         // The surface in a GrAttachment already
2431*c8dee2aaSAndroid Build Coastguard Worker         dstImage = static_cast<GrVkImage*>(dst);
2432*c8dee2aaSAndroid Build Coastguard Worker     }
2433*c8dee2aaSAndroid Build Coastguard Worker     GrRenderTarget* srcRT = src->asRenderTarget();
2434*c8dee2aaSAndroid Build Coastguard Worker     if (srcRT) {
2435*c8dee2aaSAndroid Build Coastguard Worker         GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(srcRT);
2436*c8dee2aaSAndroid Build Coastguard Worker         // This will technically return true for single sample rts that used DMSAA in which case we
2437*c8dee2aaSAndroid Build Coastguard Worker         // don't have to pick the resolve attachment. But in that case the resolve and color
2438*c8dee2aaSAndroid Build Coastguard Worker         // attachments will be the same anyways.
2439*c8dee2aaSAndroid Build Coastguard Worker         if (this->vkCaps().renderTargetSupportsDiscardableMSAA(vkRT)) {
2440*c8dee2aaSAndroid Build Coastguard Worker             srcImage = vkRT->resolveAttachment();
2441*c8dee2aaSAndroid Build Coastguard Worker         } else {
2442*c8dee2aaSAndroid Build Coastguard Worker             srcImage = vkRT->colorAttachment();
2443*c8dee2aaSAndroid Build Coastguard Worker         }
2444*c8dee2aaSAndroid Build Coastguard Worker     } else if (src->asTexture()) {
2445*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(src->asTexture());
2446*c8dee2aaSAndroid Build Coastguard Worker         srcImage = static_cast<GrVkTexture*>(src->asTexture())->textureImage();
2447*c8dee2aaSAndroid Build Coastguard Worker     } else {
2448*c8dee2aaSAndroid Build Coastguard Worker         // The surface in a GrAttachment already
2449*c8dee2aaSAndroid Build Coastguard Worker         srcImage = static_cast<GrVkImage*>(src);
2450*c8dee2aaSAndroid Build Coastguard Worker     }
2451*c8dee2aaSAndroid Build Coastguard Worker 
2452*c8dee2aaSAndroid Build Coastguard Worker     VkFormat dstFormat = dstImage->imageFormat();
2453*c8dee2aaSAndroid Build Coastguard Worker     VkFormat srcFormat = srcImage->imageFormat();
2454*c8dee2aaSAndroid Build Coastguard Worker 
2455*c8dee2aaSAndroid Build Coastguard Worker     int dstSampleCnt = dstImage->numSamples();
2456*c8dee2aaSAndroid Build Coastguard Worker     int srcSampleCnt = srcImage->numSamples();
2457*c8dee2aaSAndroid Build Coastguard Worker 
2458*c8dee2aaSAndroid Build Coastguard Worker     bool dstHasYcbcr = dstImage->ycbcrConversionInfo().isValid();
2459*c8dee2aaSAndroid Build Coastguard Worker     bool srcHasYcbcr = srcImage->ycbcrConversionInfo().isValid();
2460*c8dee2aaSAndroid Build Coastguard Worker 
2461*c8dee2aaSAndroid Build Coastguard Worker     if (srcRect.size() == dstRect.size()) {
2462*c8dee2aaSAndroid Build Coastguard Worker         // Prefer resolves or copy-image commands when there is no scaling
2463*c8dee2aaSAndroid Build Coastguard Worker         const SkIPoint dstPoint = dstRect.topLeft();
2464*c8dee2aaSAndroid Build Coastguard Worker         if (this->vkCaps().canCopyAsResolve(dstFormat, dstSampleCnt, dstHasYcbcr,
2465*c8dee2aaSAndroid Build Coastguard Worker                                             srcFormat, srcSampleCnt, srcHasYcbcr)) {
2466*c8dee2aaSAndroid Build Coastguard Worker             this->copySurfaceAsResolve(dst, src, srcRect, dstPoint);
2467*c8dee2aaSAndroid Build Coastguard Worker             return true;
2468*c8dee2aaSAndroid Build Coastguard Worker         }
2469*c8dee2aaSAndroid Build Coastguard Worker 
2470*c8dee2aaSAndroid Build Coastguard Worker         if (this->vkCaps().canCopyImage(dstFormat, dstSampleCnt, dstHasYcbcr,
2471*c8dee2aaSAndroid Build Coastguard Worker                                         srcFormat, srcSampleCnt, srcHasYcbcr)) {
2472*c8dee2aaSAndroid Build Coastguard Worker             this->copySurfaceAsCopyImage(dst, src, dstImage, srcImage, srcRect, dstPoint);
2473*c8dee2aaSAndroid Build Coastguard Worker             return true;
2474*c8dee2aaSAndroid Build Coastguard Worker         }
2475*c8dee2aaSAndroid Build Coastguard Worker     }
2476*c8dee2aaSAndroid Build Coastguard Worker 
2477*c8dee2aaSAndroid Build Coastguard Worker     if (this->vkCaps().canCopyAsBlit(dstFormat,
2478*c8dee2aaSAndroid Build Coastguard Worker                                      dstSampleCnt,
2479*c8dee2aaSAndroid Build Coastguard Worker                                      dstImage->isLinearTiled(),
2480*c8dee2aaSAndroid Build Coastguard Worker                                      dstHasYcbcr,
2481*c8dee2aaSAndroid Build Coastguard Worker                                      srcFormat,
2482*c8dee2aaSAndroid Build Coastguard Worker                                      srcSampleCnt,
2483*c8dee2aaSAndroid Build Coastguard Worker                                      srcImage->isLinearTiled(),
2484*c8dee2aaSAndroid Build Coastguard Worker                                      srcHasYcbcr)) {
2485*c8dee2aaSAndroid Build Coastguard Worker         this->copySurfaceAsBlit(dst, src, dstImage, srcImage, srcRect, dstRect, filter);
2486*c8dee2aaSAndroid Build Coastguard Worker         return true;
2487*c8dee2aaSAndroid Build Coastguard Worker     }
2488*c8dee2aaSAndroid Build Coastguard Worker 
2489*c8dee2aaSAndroid Build Coastguard Worker     return false;
2490*c8dee2aaSAndroid Build Coastguard Worker }
2491*c8dee2aaSAndroid Build Coastguard Worker 
onReadPixels(GrSurface * surface,SkIRect rect,GrColorType surfaceColorType,GrColorType dstColorType,void * buffer,size_t rowBytes)2492*c8dee2aaSAndroid Build Coastguard Worker bool GrVkGpu::onReadPixels(GrSurface* surface,
2493*c8dee2aaSAndroid Build Coastguard Worker                            SkIRect rect,
2494*c8dee2aaSAndroid Build Coastguard Worker                            GrColorType surfaceColorType,
2495*c8dee2aaSAndroid Build Coastguard Worker                            GrColorType dstColorType,
2496*c8dee2aaSAndroid Build Coastguard Worker                            void* buffer,
2497*c8dee2aaSAndroid Build Coastguard Worker                            size_t rowBytes) {
2498*c8dee2aaSAndroid Build Coastguard Worker     if (surface->isProtected()) {
2499*c8dee2aaSAndroid Build Coastguard Worker         return false;
2500*c8dee2aaSAndroid Build Coastguard Worker     }
2501*c8dee2aaSAndroid Build Coastguard Worker 
2502*c8dee2aaSAndroid Build Coastguard Worker     if (!this->currentCommandBuffer()) {
2503*c8dee2aaSAndroid Build Coastguard Worker         return false;
2504*c8dee2aaSAndroid Build Coastguard Worker     }
2505*c8dee2aaSAndroid Build Coastguard Worker 
2506*c8dee2aaSAndroid Build Coastguard Worker     GrVkImage* image = nullptr;
2507*c8dee2aaSAndroid Build Coastguard Worker     GrVkRenderTarget* rt = static_cast<GrVkRenderTarget*>(surface->asRenderTarget());
2508*c8dee2aaSAndroid Build Coastguard Worker     if (rt) {
2509*c8dee2aaSAndroid Build Coastguard Worker         // Reading from render targets that wrap a secondary command buffer is not allowed since
2510*c8dee2aaSAndroid Build Coastguard Worker         // it would require us to know the VkImage, which we don't have, as well as need us to
2511*c8dee2aaSAndroid Build Coastguard Worker         // stop and start the VkRenderPass which we don't have access to.
2512*c8dee2aaSAndroid Build Coastguard Worker         if (rt->wrapsSecondaryCommandBuffer()) {
2513*c8dee2aaSAndroid Build Coastguard Worker             return false;
2514*c8dee2aaSAndroid Build Coastguard Worker         }
2515*c8dee2aaSAndroid Build Coastguard Worker         image = rt->nonMSAAAttachment();
2516*c8dee2aaSAndroid Build Coastguard Worker     } else {
2517*c8dee2aaSAndroid Build Coastguard Worker         image = static_cast<GrVkTexture*>(surface->asTexture())->textureImage();
2518*c8dee2aaSAndroid Build Coastguard Worker     }
2519*c8dee2aaSAndroid Build Coastguard Worker 
2520*c8dee2aaSAndroid Build Coastguard Worker     if (!image) {
2521*c8dee2aaSAndroid Build Coastguard Worker         return false;
2522*c8dee2aaSAndroid Build Coastguard Worker     }
2523*c8dee2aaSAndroid Build Coastguard Worker 
2524*c8dee2aaSAndroid Build Coastguard Worker     if (dstColorType == GrColorType::kUnknown ||
2525*c8dee2aaSAndroid Build Coastguard Worker         dstColorType != this->vkCaps().transferColorType(image->imageFormat(), surfaceColorType)) {
2526*c8dee2aaSAndroid Build Coastguard Worker         return false;
2527*c8dee2aaSAndroid Build Coastguard Worker     }
2528*c8dee2aaSAndroid Build Coastguard Worker 
2529*c8dee2aaSAndroid Build Coastguard Worker     // Change layout of our target so it can be used as copy
2530*c8dee2aaSAndroid Build Coastguard Worker     image->setImageLayout(this,
2531*c8dee2aaSAndroid Build Coastguard Worker                           VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
2532*c8dee2aaSAndroid Build Coastguard Worker                           VK_ACCESS_TRANSFER_READ_BIT,
2533*c8dee2aaSAndroid Build Coastguard Worker                           VK_PIPELINE_STAGE_TRANSFER_BIT,
2534*c8dee2aaSAndroid Build Coastguard Worker                           false);
2535*c8dee2aaSAndroid Build Coastguard Worker 
2536*c8dee2aaSAndroid Build Coastguard Worker     size_t bpp = GrColorTypeBytesPerPixel(dstColorType);
2537*c8dee2aaSAndroid Build Coastguard Worker     if (skgpu::VkFormatBytesPerBlock(image->imageFormat()) != bpp) {
2538*c8dee2aaSAndroid Build Coastguard Worker         return false;
2539*c8dee2aaSAndroid Build Coastguard Worker     }
2540*c8dee2aaSAndroid Build Coastguard Worker     size_t tightRowBytes = bpp*rect.width();
2541*c8dee2aaSAndroid Build Coastguard Worker 
2542*c8dee2aaSAndroid Build Coastguard Worker     VkBufferImageCopy region;
2543*c8dee2aaSAndroid Build Coastguard Worker     memset(&region, 0, sizeof(VkBufferImageCopy));
2544*c8dee2aaSAndroid Build Coastguard Worker     VkOffset3D offset = { rect.left(), rect.top(), 0 };
2545*c8dee2aaSAndroid Build Coastguard Worker     region.imageOffset = offset;
2546*c8dee2aaSAndroid Build Coastguard Worker     region.imageExtent = { (uint32_t)rect.width(), (uint32_t)rect.height(), 1 };
2547*c8dee2aaSAndroid Build Coastguard Worker 
2548*c8dee2aaSAndroid Build Coastguard Worker     size_t transBufferRowBytes = bpp * region.imageExtent.width;
2549*c8dee2aaSAndroid Build Coastguard Worker     size_t imageRows = region.imageExtent.height;
2550*c8dee2aaSAndroid Build Coastguard Worker     GrResourceProvider* resourceProvider = this->getContext()->priv().resourceProvider();
2551*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<GrGpuBuffer> transferBuffer = resourceProvider->createBuffer(
2552*c8dee2aaSAndroid Build Coastguard Worker             transBufferRowBytes * imageRows,
2553*c8dee2aaSAndroid Build Coastguard Worker             GrGpuBufferType::kXferGpuToCpu,
2554*c8dee2aaSAndroid Build Coastguard Worker             kDynamic_GrAccessPattern,
2555*c8dee2aaSAndroid Build Coastguard Worker             GrResourceProvider::ZeroInit::kNo);
2556*c8dee2aaSAndroid Build Coastguard Worker 
2557*c8dee2aaSAndroid Build Coastguard Worker     if (!transferBuffer) {
2558*c8dee2aaSAndroid Build Coastguard Worker         return false;
2559*c8dee2aaSAndroid Build Coastguard Worker     }
2560*c8dee2aaSAndroid Build Coastguard Worker 
2561*c8dee2aaSAndroid Build Coastguard Worker     GrVkBuffer* vkBuffer = static_cast<GrVkBuffer*>(transferBuffer.get());
2562*c8dee2aaSAndroid Build Coastguard Worker 
2563*c8dee2aaSAndroid Build Coastguard Worker     // Copy the image to a buffer so we can map it to cpu memory
2564*c8dee2aaSAndroid Build Coastguard Worker     region.bufferOffset = 0;
2565*c8dee2aaSAndroid Build Coastguard Worker     region.bufferRowLength = 0; // Forces RowLength to be width. We handle the rowBytes below.
2566*c8dee2aaSAndroid Build Coastguard Worker     region.bufferImageHeight = 0; // Forces height to be tightly packed. Only useful for 3d images.
2567*c8dee2aaSAndroid Build Coastguard Worker     region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
2568*c8dee2aaSAndroid Build Coastguard Worker 
2569*c8dee2aaSAndroid Build Coastguard Worker     this->currentCommandBuffer()->copyImageToBuffer(this,
2570*c8dee2aaSAndroid Build Coastguard Worker                                                     image,
2571*c8dee2aaSAndroid Build Coastguard Worker                                                     VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
2572*c8dee2aaSAndroid Build Coastguard Worker                                                     transferBuffer,
2573*c8dee2aaSAndroid Build Coastguard Worker                                                     1,
2574*c8dee2aaSAndroid Build Coastguard Worker                                                     &region);
2575*c8dee2aaSAndroid Build Coastguard Worker 
2576*c8dee2aaSAndroid Build Coastguard Worker     // make sure the copy to buffer has finished
2577*c8dee2aaSAndroid Build Coastguard Worker     vkBuffer->addMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT,
2578*c8dee2aaSAndroid Build Coastguard Worker                                VK_ACCESS_HOST_READ_BIT,
2579*c8dee2aaSAndroid Build Coastguard Worker                                VK_PIPELINE_STAGE_TRANSFER_BIT,
2580*c8dee2aaSAndroid Build Coastguard Worker                                VK_PIPELINE_STAGE_HOST_BIT,
2581*c8dee2aaSAndroid Build Coastguard Worker                                false);
2582*c8dee2aaSAndroid Build Coastguard Worker 
2583*c8dee2aaSAndroid Build Coastguard Worker     // We need to submit the current command buffer to the Queue and make sure it finishes before
2584*c8dee2aaSAndroid Build Coastguard Worker     // we can copy the data out of the buffer.
2585*c8dee2aaSAndroid Build Coastguard Worker     GrSubmitInfo submitInfo;
2586*c8dee2aaSAndroid Build Coastguard Worker     submitInfo.fSync = GrSyncCpu::kYes;
2587*c8dee2aaSAndroid Build Coastguard Worker     if (!this->submitCommandBuffer(submitInfo)) {
2588*c8dee2aaSAndroid Build Coastguard Worker         return false;
2589*c8dee2aaSAndroid Build Coastguard Worker     }
2590*c8dee2aaSAndroid Build Coastguard Worker     void* mappedMemory = transferBuffer->map();
2591*c8dee2aaSAndroid Build Coastguard Worker     if (!mappedMemory) {
2592*c8dee2aaSAndroid Build Coastguard Worker         return false;
2593*c8dee2aaSAndroid Build Coastguard Worker     }
2594*c8dee2aaSAndroid Build Coastguard Worker 
2595*c8dee2aaSAndroid Build Coastguard Worker     SkRectMemcpy(buffer, rowBytes, mappedMemory, transBufferRowBytes, tightRowBytes, rect.height());
2596*c8dee2aaSAndroid Build Coastguard Worker 
2597*c8dee2aaSAndroid Build Coastguard Worker     transferBuffer->unmap();
2598*c8dee2aaSAndroid Build Coastguard Worker     return true;
2599*c8dee2aaSAndroid Build Coastguard Worker }
2600*c8dee2aaSAndroid Build Coastguard Worker 
beginRenderPass(const GrVkRenderPass * renderPass,sk_sp<const GrVkFramebuffer> framebuffer,const VkClearValue * colorClear,const GrSurface * target,const SkIRect & renderPassBounds,bool forSecondaryCB)2601*c8dee2aaSAndroid Build Coastguard Worker bool GrVkGpu::beginRenderPass(const GrVkRenderPass* renderPass,
2602*c8dee2aaSAndroid Build Coastguard Worker                               sk_sp<const GrVkFramebuffer> framebuffer,
2603*c8dee2aaSAndroid Build Coastguard Worker                               const VkClearValue* colorClear,
2604*c8dee2aaSAndroid Build Coastguard Worker                               const GrSurface* target,
2605*c8dee2aaSAndroid Build Coastguard Worker                               const SkIRect& renderPassBounds,
2606*c8dee2aaSAndroid Build Coastguard Worker                               bool forSecondaryCB) {
2607*c8dee2aaSAndroid Build Coastguard Worker     if (!this->currentCommandBuffer()) {
2608*c8dee2aaSAndroid Build Coastguard Worker         return false;
2609*c8dee2aaSAndroid Build Coastguard Worker     }
2610*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT (!framebuffer->isExternal());
2611*c8dee2aaSAndroid Build Coastguard Worker 
2612*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_DEBUG
2613*c8dee2aaSAndroid Build Coastguard Worker     uint32_t index;
2614*c8dee2aaSAndroid Build Coastguard Worker     bool result = renderPass->colorAttachmentIndex(&index);
2615*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(result && 0 == index);
2616*c8dee2aaSAndroid Build Coastguard Worker     result = renderPass->stencilAttachmentIndex(&index);
2617*c8dee2aaSAndroid Build Coastguard Worker     if (result) {
2618*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(1 == index);
2619*c8dee2aaSAndroid Build Coastguard Worker     }
2620*c8dee2aaSAndroid Build Coastguard Worker #endif
2621*c8dee2aaSAndroid Build Coastguard Worker     VkClearValue clears[3];
2622*c8dee2aaSAndroid Build Coastguard Worker     int stencilIndex = renderPass->hasResolveAttachment() ? 2 : 1;
2623*c8dee2aaSAndroid Build Coastguard Worker     clears[0].color = colorClear->color;
2624*c8dee2aaSAndroid Build Coastguard Worker     clears[stencilIndex].depthStencil.depth = 0.0f;
2625*c8dee2aaSAndroid Build Coastguard Worker     clears[stencilIndex].depthStencil.stencil = 0;
2626*c8dee2aaSAndroid Build Coastguard Worker 
2627*c8dee2aaSAndroid Build Coastguard Worker    return this->currentCommandBuffer()->beginRenderPass(
2628*c8dee2aaSAndroid Build Coastguard Worker         this, renderPass, std::move(framebuffer), clears, target, renderPassBounds, forSecondaryCB);
2629*c8dee2aaSAndroid Build Coastguard Worker }
2630*c8dee2aaSAndroid Build Coastguard Worker 
endRenderPass(GrRenderTarget * target,GrSurfaceOrigin origin,const SkIRect & bounds)2631*c8dee2aaSAndroid Build Coastguard Worker void GrVkGpu::endRenderPass(GrRenderTarget* target, GrSurfaceOrigin origin,
2632*c8dee2aaSAndroid Build Coastguard Worker                             const SkIRect& bounds) {
2633*c8dee2aaSAndroid Build Coastguard Worker     // We had a command buffer when we started the render pass, we should have one now as well.
2634*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(this->currentCommandBuffer());
2635*c8dee2aaSAndroid Build Coastguard Worker     this->currentCommandBuffer()->endRenderPass(this);
2636*c8dee2aaSAndroid Build Coastguard Worker     this->didWriteToSurface(target, origin, &bounds);
2637*c8dee2aaSAndroid Build Coastguard Worker }
2638*c8dee2aaSAndroid Build Coastguard Worker 
checkVkResult(VkResult result)2639*c8dee2aaSAndroid Build Coastguard Worker bool GrVkGpu::checkVkResult(VkResult result) {
2640*c8dee2aaSAndroid Build Coastguard Worker     switch (result) {
2641*c8dee2aaSAndroid Build Coastguard Worker         case VK_SUCCESS:
2642*c8dee2aaSAndroid Build Coastguard Worker             return true;
2643*c8dee2aaSAndroid Build Coastguard Worker         case VK_ERROR_DEVICE_LOST:
2644*c8dee2aaSAndroid Build Coastguard Worker             if (!fDeviceIsLost) {
2645*c8dee2aaSAndroid Build Coastguard Worker                 // Callback should only be invoked once, and device should be marked as lost first.
2646*c8dee2aaSAndroid Build Coastguard Worker                 fDeviceIsLost = true;
2647*c8dee2aaSAndroid Build Coastguard Worker                 skgpu::InvokeDeviceLostCallback(vkInterface(),
2648*c8dee2aaSAndroid Build Coastguard Worker                                                 device(),
2649*c8dee2aaSAndroid Build Coastguard Worker                                                 fDeviceLostContext,
2650*c8dee2aaSAndroid Build Coastguard Worker                                                 fDeviceLostProc,
2651*c8dee2aaSAndroid Build Coastguard Worker                                                 vkCaps().supportsDeviceFaultInfo());
2652*c8dee2aaSAndroid Build Coastguard Worker             }
2653*c8dee2aaSAndroid Build Coastguard Worker             return false;
2654*c8dee2aaSAndroid Build Coastguard Worker         case VK_ERROR_OUT_OF_DEVICE_MEMORY:
2655*c8dee2aaSAndroid Build Coastguard Worker         case VK_ERROR_OUT_OF_HOST_MEMORY:
2656*c8dee2aaSAndroid Build Coastguard Worker             this->setOOMed();
2657*c8dee2aaSAndroid Build Coastguard Worker             return false;
2658*c8dee2aaSAndroid Build Coastguard Worker         default:
2659*c8dee2aaSAndroid Build Coastguard Worker             return false;
2660*c8dee2aaSAndroid Build Coastguard Worker     }
2661*c8dee2aaSAndroid Build Coastguard Worker }
2662*c8dee2aaSAndroid Build Coastguard Worker 
submitSecondaryCommandBuffer(std::unique_ptr<GrVkSecondaryCommandBuffer> buffer)2663*c8dee2aaSAndroid Build Coastguard Worker void GrVkGpu::submitSecondaryCommandBuffer(std::unique_ptr<GrVkSecondaryCommandBuffer> buffer) {
2664*c8dee2aaSAndroid Build Coastguard Worker     if (!this->currentCommandBuffer()) {
2665*c8dee2aaSAndroid Build Coastguard Worker         return;
2666*c8dee2aaSAndroid Build Coastguard Worker     }
2667*c8dee2aaSAndroid Build Coastguard Worker     this->currentCommandBuffer()->executeCommands(this, std::move(buffer));
2668*c8dee2aaSAndroid Build Coastguard Worker }
2669*c8dee2aaSAndroid Build Coastguard Worker 
submit(GrOpsRenderPass * renderPass)2670*c8dee2aaSAndroid Build Coastguard Worker void GrVkGpu::submit(GrOpsRenderPass* renderPass) {
2671*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(fCachedOpsRenderPass.get() == renderPass);
2672*c8dee2aaSAndroid Build Coastguard Worker 
2673*c8dee2aaSAndroid Build Coastguard Worker     fCachedOpsRenderPass->submit();
2674*c8dee2aaSAndroid Build Coastguard Worker     fCachedOpsRenderPass->reset();
2675*c8dee2aaSAndroid Build Coastguard Worker }
2676*c8dee2aaSAndroid Build Coastguard Worker 
makeSemaphore(bool isOwned)2677*c8dee2aaSAndroid Build Coastguard Worker [[nodiscard]] std::unique_ptr<GrSemaphore> GrVkGpu::makeSemaphore(bool isOwned) {
2678*c8dee2aaSAndroid Build Coastguard Worker     return GrVkSemaphore::Make(this, isOwned);
2679*c8dee2aaSAndroid Build Coastguard Worker }
2680*c8dee2aaSAndroid Build Coastguard Worker 
wrapBackendSemaphore(const GrBackendSemaphore & semaphore,GrSemaphoreWrapType wrapType,GrWrapOwnership ownership)2681*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<GrSemaphore> GrVkGpu::wrapBackendSemaphore(const GrBackendSemaphore& semaphore,
2682*c8dee2aaSAndroid Build Coastguard Worker                                                            GrSemaphoreWrapType wrapType,
2683*c8dee2aaSAndroid Build Coastguard Worker                                                            GrWrapOwnership ownership) {
2684*c8dee2aaSAndroid Build Coastguard Worker     return GrVkSemaphore::MakeWrapped(this, GrBackendSemaphores::GetVkSemaphore(semaphore),
2685*c8dee2aaSAndroid Build Coastguard Worker                                       wrapType, ownership);
2686*c8dee2aaSAndroid Build Coastguard Worker }
2687*c8dee2aaSAndroid Build Coastguard Worker 
insertSemaphore(GrSemaphore * semaphore)2688*c8dee2aaSAndroid Build Coastguard Worker void GrVkGpu::insertSemaphore(GrSemaphore* semaphore) {
2689*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(semaphore);
2690*c8dee2aaSAndroid Build Coastguard Worker 
2691*c8dee2aaSAndroid Build Coastguard Worker     GrVkSemaphore* vkSem = static_cast<GrVkSemaphore*>(semaphore);
2692*c8dee2aaSAndroid Build Coastguard Worker 
2693*c8dee2aaSAndroid Build Coastguard Worker     GrVkSemaphore::Resource* resource = vkSem->getResource();
2694*c8dee2aaSAndroid Build Coastguard Worker     if (resource->shouldSignal()) {
2695*c8dee2aaSAndroid Build Coastguard Worker         resource->ref();
2696*c8dee2aaSAndroid Build Coastguard Worker         fSemaphoresToSignal.push_back(resource);
2697*c8dee2aaSAndroid Build Coastguard Worker     }
2698*c8dee2aaSAndroid Build Coastguard Worker }
2699*c8dee2aaSAndroid Build Coastguard Worker 
waitSemaphore(GrSemaphore * semaphore)2700*c8dee2aaSAndroid Build Coastguard Worker void GrVkGpu::waitSemaphore(GrSemaphore* semaphore) {
2701*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(semaphore);
2702*c8dee2aaSAndroid Build Coastguard Worker 
2703*c8dee2aaSAndroid Build Coastguard Worker     GrVkSemaphore* vkSem = static_cast<GrVkSemaphore*>(semaphore);
2704*c8dee2aaSAndroid Build Coastguard Worker 
2705*c8dee2aaSAndroid Build Coastguard Worker     GrVkSemaphore::Resource* resource = vkSem->getResource();
2706*c8dee2aaSAndroid Build Coastguard Worker     if (resource->shouldWait()) {
2707*c8dee2aaSAndroid Build Coastguard Worker         resource->ref();
2708*c8dee2aaSAndroid Build Coastguard Worker         fSemaphoresToWaitOn.push_back(resource);
2709*c8dee2aaSAndroid Build Coastguard Worker     }
2710*c8dee2aaSAndroid Build Coastguard Worker }
2711*c8dee2aaSAndroid Build Coastguard Worker 
prepareTextureForCrossContextUsage(GrTexture * texture)2712*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<GrSemaphore> GrVkGpu::prepareTextureForCrossContextUsage(GrTexture* texture) {
2713*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(texture);
2714*c8dee2aaSAndroid Build Coastguard Worker     GrVkImage* vkTexture = static_cast<GrVkTexture*>(texture)->textureImage();
2715*c8dee2aaSAndroid Build Coastguard Worker     vkTexture->setImageLayout(this,
2716*c8dee2aaSAndroid Build Coastguard Worker                               VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
2717*c8dee2aaSAndroid Build Coastguard Worker                               VK_ACCESS_SHADER_READ_BIT,
2718*c8dee2aaSAndroid Build Coastguard Worker                               VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
2719*c8dee2aaSAndroid Build Coastguard Worker                               false);
2720*c8dee2aaSAndroid Build Coastguard Worker     // TODO: should we have a way to notify the caller that this has failed? Currently if the submit
2721*c8dee2aaSAndroid Build Coastguard Worker     // fails (caused by DEVICE_LOST) this will just cause us to fail the next use of the gpu.
2722*c8dee2aaSAndroid Build Coastguard Worker     // Eventually we will abandon the whole GPU if this fails.
2723*c8dee2aaSAndroid Build Coastguard Worker     this->submitToGpu();
2724*c8dee2aaSAndroid Build Coastguard Worker 
2725*c8dee2aaSAndroid Build Coastguard Worker     // The image layout change serves as a barrier, so no semaphore is needed.
2726*c8dee2aaSAndroid Build Coastguard Worker     // If we ever decide we need to return a semaphore here, we need to make sure GrVkSemaphore is
2727*c8dee2aaSAndroid Build Coastguard Worker     // thread safe so that only the first thread that tries to use the semaphore actually submits
2728*c8dee2aaSAndroid Build Coastguard Worker     // it. This additionally would also require thread safety in command buffer submissions to
2729*c8dee2aaSAndroid Build Coastguard Worker     // queues in general.
2730*c8dee2aaSAndroid Build Coastguard Worker     return nullptr;
2731*c8dee2aaSAndroid Build Coastguard Worker }
2732*c8dee2aaSAndroid Build Coastguard Worker 
addDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler> drawable)2733*c8dee2aaSAndroid Build Coastguard Worker void GrVkGpu::addDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler> drawable) {
2734*c8dee2aaSAndroid Build Coastguard Worker     fDrawables.emplace_back(std::move(drawable));
2735*c8dee2aaSAndroid Build Coastguard Worker }
2736*c8dee2aaSAndroid Build Coastguard Worker 
storeVkPipelineCacheData()2737*c8dee2aaSAndroid Build Coastguard Worker void GrVkGpu::storeVkPipelineCacheData() {
2738*c8dee2aaSAndroid Build Coastguard Worker     if (this->getContext()->priv().getPersistentCache()) {
2739*c8dee2aaSAndroid Build Coastguard Worker         this->resourceProvider().storePipelineCacheData();
2740*c8dee2aaSAndroid Build Coastguard Worker     }
2741*c8dee2aaSAndroid Build Coastguard Worker }
2742