xref: /third_party/skia/src/gpu/vk/GrVkBuffer.cpp (revision cb93a386)
1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2021 Google LLC
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/GrVkBuffer.h"
9cb93a386Sopenharmony_ci
10cb93a386Sopenharmony_ci#include "include/gpu/GrDirectContext.h"
11cb93a386Sopenharmony_ci#include "src/gpu/GrDirectContextPriv.h"
12cb93a386Sopenharmony_ci#include "src/gpu/GrResourceProvider.h"
13cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkDescriptorSet.h"
14cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkGpu.h"
15cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkMemory.h"
16cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkMemoryReclaimer.h"
17cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkUtil.h"
18cb93a386Sopenharmony_ci
19cb93a386Sopenharmony_ci#define VK_CALL(GPU, X) GR_VK_CALL(GPU->vkInterface(), X)
20cb93a386Sopenharmony_ci
21cb93a386Sopenharmony_ciGrVkBuffer::GrVkBuffer(GrVkGpu* gpu,
22cb93a386Sopenharmony_ci                         size_t sizeInBytes,
23cb93a386Sopenharmony_ci                         GrGpuBufferType bufferType,
24cb93a386Sopenharmony_ci                         GrAccessPattern accessPattern,
25cb93a386Sopenharmony_ci                         VkBuffer buffer,
26cb93a386Sopenharmony_ci                         const GrVkAlloc& alloc,
27cb93a386Sopenharmony_ci                         const GrVkDescriptorSet* uniformDescriptorSet)
28cb93a386Sopenharmony_ci        : GrGpuBuffer(gpu, sizeInBytes, bufferType, accessPattern)
29cb93a386Sopenharmony_ci        , fBuffer(buffer)
30cb93a386Sopenharmony_ci        , fAlloc(alloc)
31cb93a386Sopenharmony_ci        , fUniformDescriptorSet(uniformDescriptorSet) {
32cb93a386Sopenharmony_ci    // We always require dynamic buffers to be mappable
33cb93a386Sopenharmony_ci    SkASSERT(accessPattern != kDynamic_GrAccessPattern || this->isVkMappable());
34cb93a386Sopenharmony_ci    SkASSERT(bufferType != GrGpuBufferType::kUniform || uniformDescriptorSet);
35cb93a386Sopenharmony_ci    this->setRealAlloc(true); // OH ISSUE: set real alloc flag
36cb93a386Sopenharmony_ci    this->setRealAllocSize(sizeInBytes); // OH ISSUE: set real alloc size
37cb93a386Sopenharmony_ci    this->registerWithCache(SkBudgeted::kYes);
38cb93a386Sopenharmony_ci}
39cb93a386Sopenharmony_ci
40cb93a386Sopenharmony_cistatic const GrVkDescriptorSet* make_uniform_desc_set(GrVkGpu* gpu, VkBuffer buffer, size_t size) {
41cb93a386Sopenharmony_ci    const GrVkDescriptorSet* descriptorSet = gpu->resourceProvider().getUniformDescriptorSet();
42cb93a386Sopenharmony_ci    if (!descriptorSet) {
43cb93a386Sopenharmony_ci        return nullptr;
44cb93a386Sopenharmony_ci    }
45cb93a386Sopenharmony_ci
46cb93a386Sopenharmony_ci    VkDescriptorBufferInfo bufferInfo;
47cb93a386Sopenharmony_ci    memset(&bufferInfo, 0, sizeof(VkDescriptorBufferInfo));
48cb93a386Sopenharmony_ci    bufferInfo.buffer = buffer;
49cb93a386Sopenharmony_ci    bufferInfo.offset = 0;
50cb93a386Sopenharmony_ci    bufferInfo.range = size;
51cb93a386Sopenharmony_ci
52cb93a386Sopenharmony_ci    VkWriteDescriptorSet descriptorWrite;
53cb93a386Sopenharmony_ci    memset(&descriptorWrite, 0, sizeof(VkWriteDescriptorSet));
54cb93a386Sopenharmony_ci    descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
55cb93a386Sopenharmony_ci    descriptorWrite.pNext = nullptr;
56cb93a386Sopenharmony_ci    descriptorWrite.dstSet = *descriptorSet->descriptorSet();
57cb93a386Sopenharmony_ci    descriptorWrite.dstBinding = GrVkUniformHandler::kUniformBinding;
58cb93a386Sopenharmony_ci    descriptorWrite.dstArrayElement = 0;
59cb93a386Sopenharmony_ci    descriptorWrite.descriptorCount = 1;
60cb93a386Sopenharmony_ci    descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
61cb93a386Sopenharmony_ci    descriptorWrite.pImageInfo = nullptr;
62cb93a386Sopenharmony_ci    descriptorWrite.pBufferInfo = &bufferInfo;
63cb93a386Sopenharmony_ci    descriptorWrite.pTexelBufferView = nullptr;
64cb93a386Sopenharmony_ci
65cb93a386Sopenharmony_ci    GR_VK_CALL(gpu->vkInterface(),
66cb93a386Sopenharmony_ci               UpdateDescriptorSets(gpu->device(), 1, &descriptorWrite, 0, nullptr));
67cb93a386Sopenharmony_ci    return descriptorSet;
68cb93a386Sopenharmony_ci}
69cb93a386Sopenharmony_ci
70cb93a386Sopenharmony_cisk_sp<GrVkBuffer> GrVkBuffer::Make(GrVkGpu* gpu,
71cb93a386Sopenharmony_ci                                     size_t size,
72cb93a386Sopenharmony_ci                                     GrGpuBufferType bufferType,
73cb93a386Sopenharmony_ci                                     GrAccessPattern accessPattern) {
74cb93a386Sopenharmony_ci    VkBuffer buffer;
75cb93a386Sopenharmony_ci    GrVkAlloc alloc;
76cb93a386Sopenharmony_ci
77cb93a386Sopenharmony_ci    // The only time we don't require mappable buffers is when we have a static access pattern and
78cb93a386Sopenharmony_ci    // we're on a device where gpu only memory has faster reads on the gpu than memory that is also
79cb93a386Sopenharmony_ci    // mappable on the cpu. Protected memory always uses mappable buffers.
80cb93a386Sopenharmony_ci    bool requiresMappable = gpu->protectedContext() ||
81cb93a386Sopenharmony_ci                            accessPattern == kDynamic_GrAccessPattern ||
82cb93a386Sopenharmony_ci                            accessPattern == kStream_GrAccessPattern ||
83cb93a386Sopenharmony_ci                            !gpu->vkCaps().gpuOnlyBuffersMorePerformant();
84cb93a386Sopenharmony_ci
85cb93a386Sopenharmony_ci    using BufferUsage = GrVkMemoryAllocator::BufferUsage;
86cb93a386Sopenharmony_ci    BufferUsage allocUsage;
87cb93a386Sopenharmony_ci
88cb93a386Sopenharmony_ci    // create the buffer object
89cb93a386Sopenharmony_ci    VkBufferCreateInfo bufInfo;
90cb93a386Sopenharmony_ci    memset(&bufInfo, 0, sizeof(VkBufferCreateInfo));
91cb93a386Sopenharmony_ci    bufInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
92cb93a386Sopenharmony_ci    bufInfo.flags = 0;
93cb93a386Sopenharmony_ci    bufInfo.size = size;
94cb93a386Sopenharmony_ci    switch (bufferType) {
95cb93a386Sopenharmony_ci        case GrGpuBufferType::kVertex:
96cb93a386Sopenharmony_ci            bufInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
97cb93a386Sopenharmony_ci            allocUsage = requiresMappable ? BufferUsage::kCpuWritesGpuReads : BufferUsage::kGpuOnly;
98cb93a386Sopenharmony_ci            break;
99cb93a386Sopenharmony_ci        case GrGpuBufferType::kIndex:
100cb93a386Sopenharmony_ci            bufInfo.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
101cb93a386Sopenharmony_ci            allocUsage = requiresMappable ? BufferUsage::kCpuWritesGpuReads : BufferUsage::kGpuOnly;
102cb93a386Sopenharmony_ci            break;
103cb93a386Sopenharmony_ci        case GrGpuBufferType::kDrawIndirect:
104cb93a386Sopenharmony_ci            bufInfo.usage = VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT;
105cb93a386Sopenharmony_ci            allocUsage = requiresMappable ? BufferUsage::kCpuWritesGpuReads : BufferUsage::kGpuOnly;
106cb93a386Sopenharmony_ci            break;
107cb93a386Sopenharmony_ci        case GrGpuBufferType::kUniform:
108cb93a386Sopenharmony_ci            bufInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
109cb93a386Sopenharmony_ci            allocUsage = BufferUsage::kCpuWritesGpuReads;
110cb93a386Sopenharmony_ci            break;
111cb93a386Sopenharmony_ci        case GrGpuBufferType::kXferCpuToGpu:
112cb93a386Sopenharmony_ci            bufInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
113cb93a386Sopenharmony_ci            allocUsage = BufferUsage::kTransfersFromCpuToGpu;
114cb93a386Sopenharmony_ci            break;
115cb93a386Sopenharmony_ci        case GrGpuBufferType::kXferGpuToCpu:
116cb93a386Sopenharmony_ci            bufInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
117cb93a386Sopenharmony_ci            allocUsage = BufferUsage::kTransfersFromGpuToCpu;
118cb93a386Sopenharmony_ci            break;
119cb93a386Sopenharmony_ci    }
120cb93a386Sopenharmony_ci    // We may not always get a mappable buffer for non dynamic access buffers. Thus we set the
121cb93a386Sopenharmony_ci    // transfer dst usage bit in case we need to do a copy to write data.
122cb93a386Sopenharmony_ci    // TODO: It doesn't really hurt setting this extra usage flag, but maybe we can narrow the scope
123cb93a386Sopenharmony_ci    // of buffers we set it on more than just not dynamic.
124cb93a386Sopenharmony_ci    if (!requiresMappable) {
125cb93a386Sopenharmony_ci        bufInfo.usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
126cb93a386Sopenharmony_ci    }
127cb93a386Sopenharmony_ci
128cb93a386Sopenharmony_ci    bufInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
129cb93a386Sopenharmony_ci    bufInfo.queueFamilyIndexCount = 0;
130cb93a386Sopenharmony_ci    bufInfo.pQueueFamilyIndices = nullptr;
131cb93a386Sopenharmony_ci
132cb93a386Sopenharmony_ci    VkResult err;
133cb93a386Sopenharmony_ci    err = VK_CALL(gpu, CreateBuffer(gpu->device(), &bufInfo, nullptr, &buffer));
134cb93a386Sopenharmony_ci    if (err) {
135cb93a386Sopenharmony_ci        return nullptr;
136cb93a386Sopenharmony_ci    }
137cb93a386Sopenharmony_ci
138cb93a386Sopenharmony_ci#ifdef SKIA_DFX_FOR_OHOS
139cb93a386Sopenharmony_ci    if (!GrVkMemory::AllocAndBindBufferMemory(gpu, buffer, allocUsage, &alloc, size)) {
140cb93a386Sopenharmony_ci#else
141cb93a386Sopenharmony_ci    if (!GrVkMemory::AllocAndBindBufferMemory(gpu, buffer, allocUsage, &alloc)) {
142cb93a386Sopenharmony_ci#endif
143cb93a386Sopenharmony_ci        VK_CALL(gpu, DestroyBuffer(gpu->device(), buffer, nullptr));
144cb93a386Sopenharmony_ci        return nullptr;
145cb93a386Sopenharmony_ci    }
146cb93a386Sopenharmony_ci
147cb93a386Sopenharmony_ci    // If this is a uniform buffer we must setup a descriptor set
148cb93a386Sopenharmony_ci    const GrVkDescriptorSet* uniformDescSet = nullptr;
149cb93a386Sopenharmony_ci    if (bufferType == GrGpuBufferType::kUniform) {
150cb93a386Sopenharmony_ci        uniformDescSet = make_uniform_desc_set(gpu, buffer, size);
151cb93a386Sopenharmony_ci        if (!uniformDescSet) {
152cb93a386Sopenharmony_ci            DestroyAndFreeBufferMemory(gpu, alloc, buffer);
153cb93a386Sopenharmony_ci            return nullptr;
154cb93a386Sopenharmony_ci        }
155cb93a386Sopenharmony_ci    }
156cb93a386Sopenharmony_ci
157cb93a386Sopenharmony_ci    return sk_sp<GrVkBuffer>(new GrVkBuffer(gpu, size, bufferType, accessPattern, buffer, alloc,
158cb93a386Sopenharmony_ci                                              uniformDescSet));
159cb93a386Sopenharmony_ci}
160cb93a386Sopenharmony_ci
161cb93a386Sopenharmony_cisk_sp<GrVkBuffer> GrVkBuffer::MakeFromOHNativeBuffer(GrVkGpu* gpu,
162cb93a386Sopenharmony_ci                                                     OH_NativeBuffer *nativeBuffer,
163cb93a386Sopenharmony_ci                                                     size_t bufferSize,
164cb93a386Sopenharmony_ci                                                     GrGpuBufferType bufferType,
165cb93a386Sopenharmony_ci                                                     GrAccessPattern accessPattern) {
166cb93a386Sopenharmony_ci    SkASSERT(gpu);
167cb93a386Sopenharmony_ci    SkASSERT(nativeBuffer);
168cb93a386Sopenharmony_ci
169cb93a386Sopenharmony_ci    VkBuffer buffer;
170cb93a386Sopenharmony_ci    GrVkAlloc alloc;
171cb93a386Sopenharmony_ci
172cb93a386Sopenharmony_ci    // create the buffer object
173cb93a386Sopenharmony_ci    VkBufferCreateInfo bufInfo{};
174cb93a386Sopenharmony_ci    bufInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
175cb93a386Sopenharmony_ci    bufInfo.flags = 0;
176cb93a386Sopenharmony_ci    bufInfo.size = bufferSize;
177cb93a386Sopenharmony_ci    switch (bufferType) {
178cb93a386Sopenharmony_ci        case GrGpuBufferType::kVertex:
179cb93a386Sopenharmony_ci            bufInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
180cb93a386Sopenharmony_ci            break;
181cb93a386Sopenharmony_ci        case GrGpuBufferType::kIndex:
182cb93a386Sopenharmony_ci            bufInfo.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
183cb93a386Sopenharmony_ci            break;
184cb93a386Sopenharmony_ci        case GrGpuBufferType::kDrawIndirect:
185cb93a386Sopenharmony_ci            bufInfo.usage = VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT;
186cb93a386Sopenharmony_ci            break;
187cb93a386Sopenharmony_ci        case GrGpuBufferType::kUniform:
188cb93a386Sopenharmony_ci            bufInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
189cb93a386Sopenharmony_ci            break;
190cb93a386Sopenharmony_ci        case GrGpuBufferType::kXferCpuToGpu:
191cb93a386Sopenharmony_ci            bufInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
192cb93a386Sopenharmony_ci            break;
193cb93a386Sopenharmony_ci        case GrGpuBufferType::kXferGpuToCpu:
194cb93a386Sopenharmony_ci            bufInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
195cb93a386Sopenharmony_ci            break;
196cb93a386Sopenharmony_ci    }
197cb93a386Sopenharmony_ci
198cb93a386Sopenharmony_ci    bool requiresMappable = gpu->protectedContext() ||
199cb93a386Sopenharmony_ci                            accessPattern == kDynamic_GrAccessPattern ||
200cb93a386Sopenharmony_ci                            accessPattern == kStream_GrAccessPattern ||
201cb93a386Sopenharmony_ci                            !gpu->vkCaps().gpuOnlyBuffersMorePerformant();
202cb93a386Sopenharmony_ci    if (!requiresMappable) {
203cb93a386Sopenharmony_ci        bufInfo.usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
204cb93a386Sopenharmony_ci    }
205cb93a386Sopenharmony_ci
206cb93a386Sopenharmony_ci    bufInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
207cb93a386Sopenharmony_ci    bufInfo.queueFamilyIndexCount = 0;
208cb93a386Sopenharmony_ci    bufInfo.pQueueFamilyIndices = nullptr;
209cb93a386Sopenharmony_ci
210cb93a386Sopenharmony_ci    VkResult err = VK_CALL(gpu, CreateBuffer(gpu->device(), &bufInfo, nullptr, &buffer));
211cb93a386Sopenharmony_ci    if (err) {
212cb93a386Sopenharmony_ci        return nullptr;
213cb93a386Sopenharmony_ci    }
214cb93a386Sopenharmony_ci
215cb93a386Sopenharmony_ci    if (!GrVkMemory::ImportAndBindBufferMemory(gpu, nativeBuffer, buffer, &alloc)) {
216cb93a386Sopenharmony_ci        VK_CALL(gpu, DestroyBuffer(gpu->device(), buffer, nullptr));
217cb93a386Sopenharmony_ci        return nullptr;
218cb93a386Sopenharmony_ci    }
219cb93a386Sopenharmony_ci
220cb93a386Sopenharmony_ci    return sk_sp<GrVkBuffer>(new GrVkBuffer(gpu, bufferSize, bufferType, accessPattern, buffer, alloc, nullptr));
221cb93a386Sopenharmony_ci}
222cb93a386Sopenharmony_ci
223cb93a386Sopenharmony_ci// OH ISSUE: Integrate Destroy and Free
224cb93a386Sopenharmony_civoid GrVkBuffer::DestroyAndFreeBufferMemory(const GrVkGpu* gpu, const GrVkAlloc& alloc, const VkBuffer& buffer)
225cb93a386Sopenharmony_ci{
226cb93a386Sopenharmony_ci    VK_CALL(gpu, DestroyBuffer(gpu->device(), buffer, nullptr));
227cb93a386Sopenharmony_ci    GrVkMemory::FreeBufferMemory(gpu, alloc);
228cb93a386Sopenharmony_ci}
229cb93a386Sopenharmony_ci
230cb93a386Sopenharmony_civoid GrVkBuffer::vkMap(size_t size) {
231cb93a386Sopenharmony_ci    SkASSERT(!fMapPtr);
232cb93a386Sopenharmony_ci    if (this->isVkMappable()) {
233cb93a386Sopenharmony_ci        // Not every buffer will use command buffer usage refs and instead the command buffer just
234cb93a386Sopenharmony_ci        // holds normal refs. Systems higher up in Ganesh should be making sure not to reuse a
235cb93a386Sopenharmony_ci        // buffer that currently has a ref held by something else. However, we do need to make sure
236cb93a386Sopenharmony_ci        // there isn't a buffer with just a command buffer usage that is trying to be mapped.
237cb93a386Sopenharmony_ci        SkASSERT(this->internalHasNoCommandBufferUsages());
238cb93a386Sopenharmony_ci        SkASSERT(fAlloc.fSize > 0);
239cb93a386Sopenharmony_ci        SkASSERT(fAlloc.fSize >= size);
240cb93a386Sopenharmony_ci        fMapPtr = GrVkMemory::MapAlloc(this->getVkGpu(), fAlloc);
241cb93a386Sopenharmony_ci        if (fMapPtr && this->intendedType() == GrGpuBufferType::kXferGpuToCpu) {
242cb93a386Sopenharmony_ci            GrVkMemory::InvalidateMappedAlloc(this->getVkGpu(), fAlloc, 0, size);
243cb93a386Sopenharmony_ci        }
244cb93a386Sopenharmony_ci    }
245cb93a386Sopenharmony_ci}
246cb93a386Sopenharmony_ci
247cb93a386Sopenharmony_civoid GrVkBuffer::vkUnmap(size_t size) {
248cb93a386Sopenharmony_ci    SkASSERT(fMapPtr && this->isVkMappable());
249cb93a386Sopenharmony_ci
250cb93a386Sopenharmony_ci    SkASSERT(fAlloc.fSize > 0);
251cb93a386Sopenharmony_ci    SkASSERT(fAlloc.fSize >= size);
252cb93a386Sopenharmony_ci
253cb93a386Sopenharmony_ci    GrVkGpu* gpu = this->getVkGpu();
254cb93a386Sopenharmony_ci    GrVkMemory::FlushMappedAlloc(gpu, fAlloc, 0, size);
255cb93a386Sopenharmony_ci    GrVkMemory::UnmapAlloc(gpu, fAlloc);
256cb93a386Sopenharmony_ci}
257cb93a386Sopenharmony_ci
258cb93a386Sopenharmony_cistatic VkAccessFlags buffer_type_to_access_flags(GrGpuBufferType type) {
259cb93a386Sopenharmony_ci    switch (type) {
260cb93a386Sopenharmony_ci        case GrGpuBufferType::kIndex:
261cb93a386Sopenharmony_ci            return VK_ACCESS_INDEX_READ_BIT;
262cb93a386Sopenharmony_ci        case GrGpuBufferType::kVertex:
263cb93a386Sopenharmony_ci            return VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
264cb93a386Sopenharmony_ci        default:
265cb93a386Sopenharmony_ci            // This helper is only called for static buffers so we should only ever see index or
266cb93a386Sopenharmony_ci            // vertex buffers types
267cb93a386Sopenharmony_ci            SkUNREACHABLE;
268cb93a386Sopenharmony_ci    }
269cb93a386Sopenharmony_ci}
270cb93a386Sopenharmony_ci
271cb93a386Sopenharmony_civoid GrVkBuffer::copyCpuDataToGpuBuffer(const void* src, size_t size) {
272cb93a386Sopenharmony_ci    SkASSERT(src);
273cb93a386Sopenharmony_ci
274cb93a386Sopenharmony_ci    GrVkGpu* gpu = this->getVkGpu();
275cb93a386Sopenharmony_ci
276cb93a386Sopenharmony_ci    // We should never call this method in protected contexts.
277cb93a386Sopenharmony_ci    SkASSERT(!gpu->protectedContext());
278cb93a386Sopenharmony_ci
279cb93a386Sopenharmony_ci    // The vulkan api restricts the use of vkCmdUpdateBuffer to updates that are less than or equal
280cb93a386Sopenharmony_ci    // to 65536 bytes and a size the is 4 byte aligned.
281cb93a386Sopenharmony_ci    if ((size <= 65536) && (0 == (size & 0x3)) && !gpu->vkCaps().avoidUpdateBuffers()) {
282cb93a386Sopenharmony_ci        gpu->updateBuffer(sk_ref_sp(this), src, /*offset=*/0, size);
283cb93a386Sopenharmony_ci    } else {
284cb93a386Sopenharmony_ci        GrResourceProvider* resourceProvider = gpu->getContext()->priv().resourceProvider();
285cb93a386Sopenharmony_ci        sk_sp<GrGpuBuffer> transferBuffer = resourceProvider->createBuffer(
286cb93a386Sopenharmony_ci                size, GrGpuBufferType::kXferCpuToGpu, kDynamic_GrAccessPattern, src);
287cb93a386Sopenharmony_ci        if (!transferBuffer) {
288cb93a386Sopenharmony_ci            return;
289cb93a386Sopenharmony_ci        }
290cb93a386Sopenharmony_ci
291cb93a386Sopenharmony_ci        gpu->copyBuffer(std::move(transferBuffer), sk_ref_sp(this), /*srcOffset=*/0,
292cb93a386Sopenharmony_ci                        /*dstOffset=*/0, size);
293cb93a386Sopenharmony_ci    }
294cb93a386Sopenharmony_ci
295cb93a386Sopenharmony_ci    this->addMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT,
296cb93a386Sopenharmony_ci                           buffer_type_to_access_flags(this->intendedType()),
297cb93a386Sopenharmony_ci                           VK_PIPELINE_STAGE_TRANSFER_BIT,
298cb93a386Sopenharmony_ci                           VK_PIPELINE_STAGE_VERTEX_INPUT_BIT,
299cb93a386Sopenharmony_ci                           /*byRegion=*/false);
300cb93a386Sopenharmony_ci}
301cb93a386Sopenharmony_ci
302cb93a386Sopenharmony_civoid GrVkBuffer::addMemoryBarrier(VkAccessFlags srcAccessMask,
303cb93a386Sopenharmony_ci                                  VkAccessFlags dstAccesMask,
304cb93a386Sopenharmony_ci                                  VkPipelineStageFlags srcStageMask,
305cb93a386Sopenharmony_ci                                  VkPipelineStageFlags dstStageMask,
306cb93a386Sopenharmony_ci                                  bool byRegion) const {
307cb93a386Sopenharmony_ci    VkBufferMemoryBarrier bufferMemoryBarrier = {
308cb93a386Sopenharmony_ci            VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,  // sType
309cb93a386Sopenharmony_ci            nullptr,                                  // pNext
310cb93a386Sopenharmony_ci            srcAccessMask,                            // srcAccessMask
311cb93a386Sopenharmony_ci            dstAccesMask,                             // dstAccessMask
312cb93a386Sopenharmony_ci            VK_QUEUE_FAMILY_IGNORED,                  // srcQueueFamilyIndex
313cb93a386Sopenharmony_ci            VK_QUEUE_FAMILY_IGNORED,                  // dstQueueFamilyIndex
314cb93a386Sopenharmony_ci            fBuffer,                                  // buffer
315cb93a386Sopenharmony_ci            0,                                        // offset
316cb93a386Sopenharmony_ci            this->size(),                             // size
317cb93a386Sopenharmony_ci    };
318cb93a386Sopenharmony_ci
319cb93a386Sopenharmony_ci    // TODO: restrict to area of buffer we're interested in
320cb93a386Sopenharmony_ci    this->getVkGpu()->addBufferMemoryBarrier(srcStageMask, dstStageMask, byRegion,
321cb93a386Sopenharmony_ci                                             &bufferMemoryBarrier);
322cb93a386Sopenharmony_ci}
323cb93a386Sopenharmony_ci
324cb93a386Sopenharmony_civoid GrVkBuffer::vkRelease() {
325cb93a386Sopenharmony_ci    if (this->wasDestroyed()) {
326cb93a386Sopenharmony_ci        return;
327cb93a386Sopenharmony_ci    }
328cb93a386Sopenharmony_ci
329cb93a386Sopenharmony_ci    if (fMapPtr) {
330cb93a386Sopenharmony_ci        this->vkUnmap(this->size());
331cb93a386Sopenharmony_ci        fMapPtr = nullptr;
332cb93a386Sopenharmony_ci    }
333cb93a386Sopenharmony_ci
334cb93a386Sopenharmony_ci    if (fUniformDescriptorSet) {
335cb93a386Sopenharmony_ci        fUniformDescriptorSet->recycle();
336cb93a386Sopenharmony_ci        fUniformDescriptorSet = nullptr;
337cb93a386Sopenharmony_ci    }
338cb93a386Sopenharmony_ci
339cb93a386Sopenharmony_ci    SkASSERT(fBuffer);
340cb93a386Sopenharmony_ci    SkASSERT(fAlloc.fMemory && fAlloc.fBackendMemory);
341cb93a386Sopenharmony_ci
342cb93a386Sopenharmony_ci    // OH ISSUE: asyn memory reclaimer
343cb93a386Sopenharmony_ci    auto reclaimer = this->getVkGpu()->memoryReclaimer();
344cb93a386Sopenharmony_ci    if (!reclaimer || !reclaimer->addMemoryToWaitQueue(this->getVkGpu(), fAlloc, fBuffer)) {
345cb93a386Sopenharmony_ci        DestroyAndFreeBufferMemory(this->getVkGpu(), fAlloc, fBuffer);
346cb93a386Sopenharmony_ci    }
347cb93a386Sopenharmony_ci
348cb93a386Sopenharmony_ci    fBuffer = VK_NULL_HANDLE;
349cb93a386Sopenharmony_ci    fAlloc.fMemory = VK_NULL_HANDLE;
350cb93a386Sopenharmony_ci    fAlloc.fBackendMemory = 0;
351cb93a386Sopenharmony_ci}
352cb93a386Sopenharmony_ci
353cb93a386Sopenharmony_civoid GrVkBuffer::onRelease() {
354cb93a386Sopenharmony_ci    this->vkRelease();
355cb93a386Sopenharmony_ci    this->GrGpuBuffer::onRelease();
356cb93a386Sopenharmony_ci}
357cb93a386Sopenharmony_ci
358cb93a386Sopenharmony_civoid GrVkBuffer::onAbandon() {
359cb93a386Sopenharmony_ci    this->vkRelease();
360cb93a386Sopenharmony_ci    this->GrGpuBuffer::onAbandon();
361cb93a386Sopenharmony_ci}
362cb93a386Sopenharmony_ci
363cb93a386Sopenharmony_civoid GrVkBuffer::onMap() {
364cb93a386Sopenharmony_ci    if (!this->wasDestroyed()) {
365cb93a386Sopenharmony_ci        this->vkMap(this->size());
366cb93a386Sopenharmony_ci    }
367cb93a386Sopenharmony_ci}
368cb93a386Sopenharmony_ci
369cb93a386Sopenharmony_civoid GrVkBuffer::onUnmap() {
370cb93a386Sopenharmony_ci    if (!this->wasDestroyed()) {
371cb93a386Sopenharmony_ci        this->vkUnmap(this->size());
372cb93a386Sopenharmony_ci    }
373cb93a386Sopenharmony_ci}
374cb93a386Sopenharmony_ci
375cb93a386Sopenharmony_cibool GrVkBuffer::onUpdateData(const void* src, size_t srcSizeInBytes) {
376cb93a386Sopenharmony_ci    if (this->wasDestroyed()) {
377cb93a386Sopenharmony_ci        return false;
378cb93a386Sopenharmony_ci    }
379cb93a386Sopenharmony_ci
380cb93a386Sopenharmony_ci    if (srcSizeInBytes > this->size()) {
381cb93a386Sopenharmony_ci        return false;
382cb93a386Sopenharmony_ci    }
383cb93a386Sopenharmony_ci
384cb93a386Sopenharmony_ci    if (this->isVkMappable()) {
385cb93a386Sopenharmony_ci        this->vkMap(srcSizeInBytes);
386cb93a386Sopenharmony_ci        if (!fMapPtr) {
387cb93a386Sopenharmony_ci            return false;
388cb93a386Sopenharmony_ci        }
389cb93a386Sopenharmony_ci        memcpy(fMapPtr, src, srcSizeInBytes);
390cb93a386Sopenharmony_ci        this->vkUnmap(srcSizeInBytes);
391cb93a386Sopenharmony_ci        fMapPtr = nullptr;
392cb93a386Sopenharmony_ci    } else {
393cb93a386Sopenharmony_ci        this->copyCpuDataToGpuBuffer(src, srcSizeInBytes);
394cb93a386Sopenharmony_ci    }
395cb93a386Sopenharmony_ci    return true;
396cb93a386Sopenharmony_ci}
397cb93a386Sopenharmony_ci
398cb93a386Sopenharmony_ciGrVkGpu* GrVkBuffer::getVkGpu() const {
399cb93a386Sopenharmony_ci    SkASSERT(!this->wasDestroyed());
400cb93a386Sopenharmony_ci    return static_cast<GrVkGpu*>(this->getGpu());
401cb93a386Sopenharmony_ci}
402cb93a386Sopenharmony_ci
403cb93a386Sopenharmony_ciconst VkDescriptorSet* GrVkBuffer::uniformDescriptorSet() const {
404cb93a386Sopenharmony_ci    SkASSERT(fUniformDescriptorSet);
405cb93a386Sopenharmony_ci    return fUniformDescriptorSet->descriptorSet();
406cb93a386Sopenharmony_ci}
407cb93a386Sopenharmony_ci
408