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