xref: /aosp_15_r20/external/skia/src/gpu/graphite/vk/VulkanBuffer.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2022 Google LLC
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker 
8*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/vk/VulkanBuffer.h"
9*c8dee2aaSAndroid Build Coastguard Worker 
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/vk/VulkanMemoryAllocator.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/vk/VulkanCommandBuffer.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/vk/VulkanGraphiteUtilsPriv.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/vk/VulkanMemory.h"
14*c8dee2aaSAndroid Build Coastguard Worker 
15*c8dee2aaSAndroid Build Coastguard Worker namespace skgpu::graphite {
16*c8dee2aaSAndroid Build Coastguard Worker 
Make(const VulkanSharedContext * sharedContext,size_t size,BufferType type,AccessPattern accessPattern)17*c8dee2aaSAndroid Build Coastguard Worker sk_sp<Buffer> VulkanBuffer::Make(const VulkanSharedContext* sharedContext,
18*c8dee2aaSAndroid Build Coastguard Worker                                  size_t size,
19*c8dee2aaSAndroid Build Coastguard Worker                                  BufferType type,
20*c8dee2aaSAndroid Build Coastguard Worker                                  AccessPattern accessPattern) {
21*c8dee2aaSAndroid Build Coastguard Worker     if (size <= 0) {
22*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
23*c8dee2aaSAndroid Build Coastguard Worker     }
24*c8dee2aaSAndroid Build Coastguard Worker     VkBuffer buffer;
25*c8dee2aaSAndroid Build Coastguard Worker     skgpu::VulkanAlloc alloc;
26*c8dee2aaSAndroid Build Coastguard Worker 
27*c8dee2aaSAndroid Build Coastguard Worker     // TODO (b/374749633): We can't use protected buffers in the vertex shader. The checks below
28*c8dee2aaSAndroid Build Coastguard Worker     // make sure we don't use it for vertex or index buffers. But we currently don't have a way to
29*c8dee2aaSAndroid Build Coastguard Worker     // check here if it is a uniform or storage buffer that is used in the vertex shader. If we hit
30*c8dee2aaSAndroid Build Coastguard Worker     // that issue and need those GpuOnly buffers, we'll need to pass in some information to the
31*c8dee2aaSAndroid Build Coastguard Worker     // factory to say what stage the buffer is for. Maybe expand AccessPattern to be
32*c8dee2aaSAndroid Build Coastguard Worker     // GpuOnly_NotVertex or some better name like that.
33*c8dee2aaSAndroid Build Coastguard Worker     bool isProtected = sharedContext->isProtected() == Protected::kYes &&
34*c8dee2aaSAndroid Build Coastguard Worker                        accessPattern == AccessPattern::kGpuOnly &&
35*c8dee2aaSAndroid Build Coastguard Worker                        type != BufferType::kVertex &&
36*c8dee2aaSAndroid Build Coastguard Worker                        type != BufferType::kIndex;
37*c8dee2aaSAndroid Build Coastguard Worker 
38*c8dee2aaSAndroid Build Coastguard Worker     // Protected memory _never_ uses mappable buffers.
39*c8dee2aaSAndroid Build Coastguard Worker     // Otherwise, the only time we don't require mappable buffers is when we're on a device
40*c8dee2aaSAndroid Build Coastguard Worker     // where gpu only memory has faster reads on the gpu than memory that is also mappable
41*c8dee2aaSAndroid Build Coastguard Worker     // on the cpu.
42*c8dee2aaSAndroid Build Coastguard Worker     bool requiresMappable = !isProtected &&
43*c8dee2aaSAndroid Build Coastguard Worker                             (accessPattern == AccessPattern::kHostVisible ||
44*c8dee2aaSAndroid Build Coastguard Worker                              !sharedContext->vulkanCaps().gpuOnlyBuffersMorePerformant());
45*c8dee2aaSAndroid Build Coastguard Worker 
46*c8dee2aaSAndroid Build Coastguard Worker     using BufferUsage = skgpu::VulkanMemoryAllocator::BufferUsage;
47*c8dee2aaSAndroid Build Coastguard Worker 
48*c8dee2aaSAndroid Build Coastguard Worker     BufferUsage allocUsage;
49*c8dee2aaSAndroid Build Coastguard Worker     if (type == BufferType::kXferCpuToGpu) {
50*c8dee2aaSAndroid Build Coastguard Worker         allocUsage = BufferUsage::kTransfersFromCpuToGpu;
51*c8dee2aaSAndroid Build Coastguard Worker     } else if (type == BufferType::kXferGpuToCpu) {
52*c8dee2aaSAndroid Build Coastguard Worker         allocUsage = BufferUsage::kTransfersFromGpuToCpu;
53*c8dee2aaSAndroid Build Coastguard Worker     } else {
54*c8dee2aaSAndroid Build Coastguard Worker         // GPU-only buffers are preferred unless mappability is required.
55*c8dee2aaSAndroid Build Coastguard Worker         allocUsage = requiresMappable ? BufferUsage::kCpuWritesGpuReads : BufferUsage::kGpuOnly;
56*c8dee2aaSAndroid Build Coastguard Worker     }
57*c8dee2aaSAndroid Build Coastguard Worker 
58*c8dee2aaSAndroid Build Coastguard Worker     // Create the buffer object
59*c8dee2aaSAndroid Build Coastguard Worker     VkBufferCreateInfo bufInfo;
60*c8dee2aaSAndroid Build Coastguard Worker     memset(&bufInfo, 0, sizeof(VkBufferCreateInfo));
61*c8dee2aaSAndroid Build Coastguard Worker     bufInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
62*c8dee2aaSAndroid Build Coastguard Worker     bufInfo.flags = isProtected ? VK_BUFFER_CREATE_PROTECTED_BIT : 0;
63*c8dee2aaSAndroid Build Coastguard Worker     bufInfo.size = size;
64*c8dee2aaSAndroid Build Coastguard Worker 
65*c8dee2aaSAndroid Build Coastguard Worker     // To support SkMesh buffer updates we make Vertex and Index buffers capable of being transfer
66*c8dee2aaSAndroid Build Coastguard Worker     // dsts. To support rtAdjust uniform buffer updates, we make host-visible uniform buffers also
67*c8dee2aaSAndroid Build Coastguard Worker     // capable of being transfer dsts.
68*c8dee2aaSAndroid Build Coastguard Worker     switch (type) {
69*c8dee2aaSAndroid Build Coastguard Worker         case BufferType::kVertex:
70*c8dee2aaSAndroid Build Coastguard Worker             bufInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
71*c8dee2aaSAndroid Build Coastguard Worker             break;
72*c8dee2aaSAndroid Build Coastguard Worker         case BufferType::kIndex:
73*c8dee2aaSAndroid Build Coastguard Worker             bufInfo.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
74*c8dee2aaSAndroid Build Coastguard Worker             break;
75*c8dee2aaSAndroid Build Coastguard Worker         case BufferType::kStorage:
76*c8dee2aaSAndroid Build Coastguard Worker             bufInfo.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
77*c8dee2aaSAndroid Build Coastguard Worker             break;
78*c8dee2aaSAndroid Build Coastguard Worker         case BufferType::kQuery:
79*c8dee2aaSAndroid Build Coastguard Worker             SK_ABORT("Query buffers not supported on Vulkan");
80*c8dee2aaSAndroid Build Coastguard Worker             break;
81*c8dee2aaSAndroid Build Coastguard Worker         case BufferType::kIndirect:
82*c8dee2aaSAndroid Build Coastguard Worker             bufInfo.usage =
83*c8dee2aaSAndroid Build Coastguard Worker                     VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
84*c8dee2aaSAndroid Build Coastguard Worker             break;
85*c8dee2aaSAndroid Build Coastguard Worker         case BufferType::kVertexStorage:
86*c8dee2aaSAndroid Build Coastguard Worker             bufInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
87*c8dee2aaSAndroid Build Coastguard Worker             break;
88*c8dee2aaSAndroid Build Coastguard Worker         case BufferType::kIndexStorage:
89*c8dee2aaSAndroid Build Coastguard Worker             bufInfo.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
90*c8dee2aaSAndroid Build Coastguard Worker             break;
91*c8dee2aaSAndroid Build Coastguard Worker         case BufferType::kUniform:
92*c8dee2aaSAndroid Build Coastguard Worker             bufInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
93*c8dee2aaSAndroid Build Coastguard Worker             break;
94*c8dee2aaSAndroid Build Coastguard Worker         case BufferType::kXferCpuToGpu:
95*c8dee2aaSAndroid Build Coastguard Worker             bufInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
96*c8dee2aaSAndroid Build Coastguard Worker             break;
97*c8dee2aaSAndroid Build Coastguard Worker         case BufferType::kXferGpuToCpu:
98*c8dee2aaSAndroid Build Coastguard Worker             bufInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
99*c8dee2aaSAndroid Build Coastguard Worker             break;
100*c8dee2aaSAndroid Build Coastguard Worker     }
101*c8dee2aaSAndroid Build Coastguard Worker 
102*c8dee2aaSAndroid Build Coastguard Worker     // We may not always get a mappable buffer for non-dynamic access buffers. Thus we set the
103*c8dee2aaSAndroid Build Coastguard Worker     // transfer dst usage bit in case we need to do a copy to write data. It doesn't really hurt
104*c8dee2aaSAndroid Build Coastguard Worker     // to set this extra usage flag, but we could narrow the scope of buffers we set it on more than
105*c8dee2aaSAndroid Build Coastguard Worker     // just not dynamic.
106*c8dee2aaSAndroid Build Coastguard Worker     if (!requiresMappable || accessPattern == AccessPattern::kGpuOnly) {
107*c8dee2aaSAndroid Build Coastguard Worker         bufInfo.usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
108*c8dee2aaSAndroid Build Coastguard Worker     }
109*c8dee2aaSAndroid Build Coastguard Worker 
110*c8dee2aaSAndroid Build Coastguard Worker     bufInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
111*c8dee2aaSAndroid Build Coastguard Worker     bufInfo.queueFamilyIndexCount = 0;
112*c8dee2aaSAndroid Build Coastguard Worker     bufInfo.pQueueFamilyIndices = nullptr;
113*c8dee2aaSAndroid Build Coastguard Worker 
114*c8dee2aaSAndroid Build Coastguard Worker     VkResult result;
115*c8dee2aaSAndroid Build Coastguard Worker     VULKAN_CALL_RESULT(sharedContext,
116*c8dee2aaSAndroid Build Coastguard Worker                        result,
117*c8dee2aaSAndroid Build Coastguard Worker                        CreateBuffer(sharedContext->device(),
118*c8dee2aaSAndroid Build Coastguard Worker                                     &bufInfo,
119*c8dee2aaSAndroid Build Coastguard Worker                                     nullptr, /*const VkAllocationCallbacks*/
120*c8dee2aaSAndroid Build Coastguard Worker                                     &buffer));
121*c8dee2aaSAndroid Build Coastguard Worker     if (result != VK_SUCCESS) {
122*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
123*c8dee2aaSAndroid Build Coastguard Worker     }
124*c8dee2aaSAndroid Build Coastguard Worker 
125*c8dee2aaSAndroid Build Coastguard Worker     auto allocator = sharedContext->memoryAllocator();
126*c8dee2aaSAndroid Build Coastguard Worker     bool shouldPersistentlyMapCpuToGpu =
127*c8dee2aaSAndroid Build Coastguard Worker         sharedContext->vulkanCaps().shouldPersistentlyMapCpuToGpuBuffers();
128*c8dee2aaSAndroid Build Coastguard Worker     //AllocBufferMemory
129*c8dee2aaSAndroid Build Coastguard Worker     auto checkResult = [](VkResult result) {
130*c8dee2aaSAndroid Build Coastguard Worker         return result == VK_SUCCESS;
131*c8dee2aaSAndroid Build Coastguard Worker     };
132*c8dee2aaSAndroid Build Coastguard Worker     if (!skgpu::VulkanMemory::AllocBufferMemory(allocator,
133*c8dee2aaSAndroid Build Coastguard Worker                                                 buffer,
134*c8dee2aaSAndroid Build Coastguard Worker                                                 skgpu::Protected(isProtected),
135*c8dee2aaSAndroid Build Coastguard Worker                                                 allocUsage,
136*c8dee2aaSAndroid Build Coastguard Worker                                                 shouldPersistentlyMapCpuToGpu,
137*c8dee2aaSAndroid Build Coastguard Worker                                                 checkResult,
138*c8dee2aaSAndroid Build Coastguard Worker                                                 &alloc)) {
139*c8dee2aaSAndroid Build Coastguard Worker         VULKAN_CALL(sharedContext->interface(),
140*c8dee2aaSAndroid Build Coastguard Worker                     DestroyBuffer(sharedContext->device(),
141*c8dee2aaSAndroid Build Coastguard Worker                                   buffer,
142*c8dee2aaSAndroid Build Coastguard Worker                                   /*const VkAllocationCallbacks*=*/nullptr));
143*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
144*c8dee2aaSAndroid Build Coastguard Worker     }
145*c8dee2aaSAndroid Build Coastguard Worker 
146*c8dee2aaSAndroid Build Coastguard Worker     // Bind buffer
147*c8dee2aaSAndroid Build Coastguard Worker     VULKAN_CALL_RESULT(
148*c8dee2aaSAndroid Build Coastguard Worker             sharedContext,
149*c8dee2aaSAndroid Build Coastguard Worker             result,
150*c8dee2aaSAndroid Build Coastguard Worker             BindBufferMemory(sharedContext->device(), buffer, alloc.fMemory, alloc.fOffset));
151*c8dee2aaSAndroid Build Coastguard Worker     if (result != VK_SUCCESS) {
152*c8dee2aaSAndroid Build Coastguard Worker         skgpu::VulkanMemory::FreeBufferMemory(allocator, alloc);
153*c8dee2aaSAndroid Build Coastguard Worker         VULKAN_CALL(sharedContext->interface(), DestroyBuffer(sharedContext->device(),
154*c8dee2aaSAndroid Build Coastguard Worker                 buffer,
155*c8dee2aaSAndroid Build Coastguard Worker                 /*const VkAllocationCallbacks*=*/nullptr));
156*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
157*c8dee2aaSAndroid Build Coastguard Worker     }
158*c8dee2aaSAndroid Build Coastguard Worker 
159*c8dee2aaSAndroid Build Coastguard Worker     return sk_sp<Buffer>(new VulkanBuffer(
160*c8dee2aaSAndroid Build Coastguard Worker             sharedContext, size, type, accessPattern, std::move(buffer), alloc, bufInfo.usage,
161*c8dee2aaSAndroid Build Coastguard Worker             Protected(isProtected)));
162*c8dee2aaSAndroid Build Coastguard Worker }
163*c8dee2aaSAndroid Build Coastguard Worker 
VulkanBuffer(const VulkanSharedContext * sharedContext,size_t size,BufferType type,AccessPattern accessPattern,VkBuffer buffer,const skgpu::VulkanAlloc & alloc,const VkBufferUsageFlags usageFlags,Protected isProtected)164*c8dee2aaSAndroid Build Coastguard Worker VulkanBuffer::VulkanBuffer(const VulkanSharedContext* sharedContext,
165*c8dee2aaSAndroid Build Coastguard Worker                            size_t size,
166*c8dee2aaSAndroid Build Coastguard Worker                            BufferType type,
167*c8dee2aaSAndroid Build Coastguard Worker                            AccessPattern accessPattern,
168*c8dee2aaSAndroid Build Coastguard Worker                            VkBuffer buffer,
169*c8dee2aaSAndroid Build Coastguard Worker                            const skgpu::VulkanAlloc& alloc,
170*c8dee2aaSAndroid Build Coastguard Worker                            const VkBufferUsageFlags usageFlags,
171*c8dee2aaSAndroid Build Coastguard Worker                            Protected isProtected)
172*c8dee2aaSAndroid Build Coastguard Worker         : Buffer(sharedContext, size, isProtected)
173*c8dee2aaSAndroid Build Coastguard Worker         , fBuffer(std::move(buffer))
174*c8dee2aaSAndroid Build Coastguard Worker         , fAlloc(alloc)
175*c8dee2aaSAndroid Build Coastguard Worker         , fBufferUsageFlags(usageFlags)
176*c8dee2aaSAndroid Build Coastguard Worker         // We assume a buffer is used for CPU reads only in the case of GPU->CPU transfer buffers.
177*c8dee2aaSAndroid Build Coastguard Worker         , fBufferUsedForCPURead(type == BufferType::kXferGpuToCpu) {}
178*c8dee2aaSAndroid Build Coastguard Worker 
freeGpuData()179*c8dee2aaSAndroid Build Coastguard Worker void VulkanBuffer::freeGpuData() {
180*c8dee2aaSAndroid Build Coastguard Worker     if (fMapPtr) {
181*c8dee2aaSAndroid Build Coastguard Worker         this->internalUnmap(0, this->size());
182*c8dee2aaSAndroid Build Coastguard Worker         fMapPtr = nullptr;
183*c8dee2aaSAndroid Build Coastguard Worker     }
184*c8dee2aaSAndroid Build Coastguard Worker 
185*c8dee2aaSAndroid Build Coastguard Worker     const VulkanSharedContext* sharedContext =
186*c8dee2aaSAndroid Build Coastguard Worker             static_cast<const VulkanSharedContext*>(this->sharedContext());
187*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(fBuffer);
188*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(fAlloc.fMemory && fAlloc.fBackendMemory);
189*c8dee2aaSAndroid Build Coastguard Worker     VULKAN_CALL(sharedContext->interface(),
190*c8dee2aaSAndroid Build Coastguard Worker                 DestroyBuffer(sharedContext->device(), fBuffer, nullptr));
191*c8dee2aaSAndroid Build Coastguard Worker     fBuffer = VK_NULL_HANDLE;
192*c8dee2aaSAndroid Build Coastguard Worker 
193*c8dee2aaSAndroid Build Coastguard Worker     skgpu::VulkanMemory::FreeBufferMemory(sharedContext->memoryAllocator(), fAlloc);
194*c8dee2aaSAndroid Build Coastguard Worker     fAlloc.fMemory = VK_NULL_HANDLE;
195*c8dee2aaSAndroid Build Coastguard Worker     fAlloc.fBackendMemory = 0;
196*c8dee2aaSAndroid Build Coastguard Worker }
197*c8dee2aaSAndroid Build Coastguard Worker 
internalMap(size_t readOffset,size_t readSize)198*c8dee2aaSAndroid Build Coastguard Worker void VulkanBuffer::internalMap(size_t readOffset, size_t readSize) {
199*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!fMapPtr);
200*c8dee2aaSAndroid Build Coastguard Worker     if (this->isMappable()) {
201*c8dee2aaSAndroid Build Coastguard Worker         // Not every buffer will use command buffer usage refs. Instead, the command buffer just
202*c8dee2aaSAndroid Build Coastguard Worker         // holds normal refs. Systems higher up in Graphite should be making sure not to reuse a
203*c8dee2aaSAndroid Build Coastguard Worker         // buffer that currently has a ref held by something else. However, we do need to make sure
204*c8dee2aaSAndroid Build Coastguard Worker         // there isn't a buffer with just a command buffer usage that is trying to be mapped.
205*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_DEBUG
206*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(!this->debugHasCommandBufferRef());
207*c8dee2aaSAndroid Build Coastguard Worker #endif
208*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(fAlloc.fSize > 0);
209*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(fAlloc.fSize >= readOffset + readSize);
210*c8dee2aaSAndroid Build Coastguard Worker 
211*c8dee2aaSAndroid Build Coastguard Worker         const VulkanSharedContext* sharedContext = this->vulkanSharedContext();
212*c8dee2aaSAndroid Build Coastguard Worker 
213*c8dee2aaSAndroid Build Coastguard Worker         auto allocator = sharedContext->memoryAllocator();
214*c8dee2aaSAndroid Build Coastguard Worker         auto checkResult = [sharedContext](VkResult result) {
215*c8dee2aaSAndroid Build Coastguard Worker             VULKAN_LOG_IF_NOT_SUCCESS(sharedContext, result, "skgpu::VulkanMemory::MapAlloc");
216*c8dee2aaSAndroid Build Coastguard Worker             return sharedContext->checkVkResult(result);
217*c8dee2aaSAndroid Build Coastguard Worker         };
218*c8dee2aaSAndroid Build Coastguard Worker         fMapPtr = skgpu::VulkanMemory::MapAlloc(allocator, fAlloc, checkResult);
219*c8dee2aaSAndroid Build Coastguard Worker         if (fMapPtr && readSize != 0) {
220*c8dee2aaSAndroid Build Coastguard Worker             auto checkResult_invalidate = [sharedContext, readOffset, readSize](VkResult result) {
221*c8dee2aaSAndroid Build Coastguard Worker                 VULKAN_LOG_IF_NOT_SUCCESS(sharedContext,
222*c8dee2aaSAndroid Build Coastguard Worker                                           result,
223*c8dee2aaSAndroid Build Coastguard Worker                                           "skgpu::VulkanMemory::InvalidateMappedAlloc "
224*c8dee2aaSAndroid Build Coastguard Worker                                           "(readOffset:%zu, readSize:%zu)",
225*c8dee2aaSAndroid Build Coastguard Worker                                           readOffset,
226*c8dee2aaSAndroid Build Coastguard Worker                                           readSize);
227*c8dee2aaSAndroid Build Coastguard Worker                 return sharedContext->checkVkResult(result);
228*c8dee2aaSAndroid Build Coastguard Worker             };
229*c8dee2aaSAndroid Build Coastguard Worker             // "Invalidate" here means make device writes visible to the host. That is, it makes
230*c8dee2aaSAndroid Build Coastguard Worker             // sure any GPU writes are finished in the range we might read from.
231*c8dee2aaSAndroid Build Coastguard Worker             skgpu::VulkanMemory::InvalidateMappedAlloc(allocator,
232*c8dee2aaSAndroid Build Coastguard Worker                                                        fAlloc,
233*c8dee2aaSAndroid Build Coastguard Worker                                                        readOffset,
234*c8dee2aaSAndroid Build Coastguard Worker                                                        readSize,
235*c8dee2aaSAndroid Build Coastguard Worker                                                        checkResult_invalidate);
236*c8dee2aaSAndroid Build Coastguard Worker         }
237*c8dee2aaSAndroid Build Coastguard Worker     }
238*c8dee2aaSAndroid Build Coastguard Worker }
239*c8dee2aaSAndroid Build Coastguard Worker 
internalUnmap(size_t flushOffset,size_t flushSize)240*c8dee2aaSAndroid Build Coastguard Worker void VulkanBuffer::internalUnmap(size_t flushOffset, size_t flushSize) {
241*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(fMapPtr && this->isMappable());
242*c8dee2aaSAndroid Build Coastguard Worker 
243*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(fAlloc.fSize > 0);
244*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(fAlloc.fSize >= flushOffset + flushSize);
245*c8dee2aaSAndroid Build Coastguard Worker 
246*c8dee2aaSAndroid Build Coastguard Worker     const VulkanSharedContext* sharedContext = this->vulkanSharedContext();
247*c8dee2aaSAndroid Build Coastguard Worker     auto checkResult = [sharedContext, flushOffset, flushSize](VkResult result) {
248*c8dee2aaSAndroid Build Coastguard Worker         VULKAN_LOG_IF_NOT_SUCCESS(sharedContext,
249*c8dee2aaSAndroid Build Coastguard Worker                                   result,
250*c8dee2aaSAndroid Build Coastguard Worker                                   "skgpu::VulkanMemory::FlushMappedAlloc "
251*c8dee2aaSAndroid Build Coastguard Worker                                   "(flushOffset:%zu, flushSize:%zu)",
252*c8dee2aaSAndroid Build Coastguard Worker                                   flushOffset,
253*c8dee2aaSAndroid Build Coastguard Worker                                   flushSize);
254*c8dee2aaSAndroid Build Coastguard Worker         return sharedContext->checkVkResult(result);
255*c8dee2aaSAndroid Build Coastguard Worker     };
256*c8dee2aaSAndroid Build Coastguard Worker 
257*c8dee2aaSAndroid Build Coastguard Worker     auto allocator = sharedContext->memoryAllocator();
258*c8dee2aaSAndroid Build Coastguard Worker     skgpu::VulkanMemory::FlushMappedAlloc(allocator, fAlloc, flushOffset, flushSize, checkResult);
259*c8dee2aaSAndroid Build Coastguard Worker     skgpu::VulkanMemory::UnmapAlloc(allocator, fAlloc);
260*c8dee2aaSAndroid Build Coastguard Worker }
261*c8dee2aaSAndroid Build Coastguard Worker 
onMap()262*c8dee2aaSAndroid Build Coastguard Worker void VulkanBuffer::onMap() {
263*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(fBuffer);
264*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!this->isMapped());
265*c8dee2aaSAndroid Build Coastguard Worker 
266*c8dee2aaSAndroid Build Coastguard Worker     this->internalMap(0, fBufferUsedForCPURead ? this->size() : 0);
267*c8dee2aaSAndroid Build Coastguard Worker }
268*c8dee2aaSAndroid Build Coastguard Worker 
onUnmap()269*c8dee2aaSAndroid Build Coastguard Worker void VulkanBuffer::onUnmap() {
270*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(fBuffer);
271*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(this->isMapped());
272*c8dee2aaSAndroid Build Coastguard Worker     this->internalUnmap(0, fBufferUsedForCPURead ? 0 : this->size());
273*c8dee2aaSAndroid Build Coastguard Worker }
274*c8dee2aaSAndroid Build Coastguard Worker 
setBufferAccess(VulkanCommandBuffer * cmdBuffer,VkAccessFlags dstAccessMask,VkPipelineStageFlags dstStageMask) const275*c8dee2aaSAndroid Build Coastguard Worker void VulkanBuffer::setBufferAccess(VulkanCommandBuffer* cmdBuffer,
276*c8dee2aaSAndroid Build Coastguard Worker                                    VkAccessFlags dstAccessMask,
277*c8dee2aaSAndroid Build Coastguard Worker                                    VkPipelineStageFlags dstStageMask) const {
278*c8dee2aaSAndroid Build Coastguard Worker     // TODO: fill out other cases where we need a barrier
279*c8dee2aaSAndroid Build Coastguard Worker     if (dstAccessMask == VK_ACCESS_HOST_READ_BIT      ||
280*c8dee2aaSAndroid Build Coastguard Worker         dstAccessMask == VK_ACCESS_TRANSFER_WRITE_BIT ||
281*c8dee2aaSAndroid Build Coastguard Worker         dstAccessMask == VK_ACCESS_UNIFORM_READ_BIT) {
282*c8dee2aaSAndroid Build Coastguard Worker         VkPipelineStageFlags srcStageMask =
283*c8dee2aaSAndroid Build Coastguard Worker             VulkanBuffer::AccessMaskToPipelineSrcStageFlags(fCurrentAccessMask);
284*c8dee2aaSAndroid Build Coastguard Worker 
285*c8dee2aaSAndroid Build Coastguard Worker         VkBufferMemoryBarrier bufferMemoryBarrier = {
286*c8dee2aaSAndroid Build Coastguard Worker                  VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,  // sType
287*c8dee2aaSAndroid Build Coastguard Worker                  nullptr,                                  // pNext
288*c8dee2aaSAndroid Build Coastguard Worker                  fCurrentAccessMask,                       // srcAccessMask
289*c8dee2aaSAndroid Build Coastguard Worker                  dstAccessMask,                            // dstAccessMask
290*c8dee2aaSAndroid Build Coastguard Worker                  VK_QUEUE_FAMILY_IGNORED,                  // srcQueueFamilyIndex
291*c8dee2aaSAndroid Build Coastguard Worker                  VK_QUEUE_FAMILY_IGNORED,                  // dstQueueFamilyIndex
292*c8dee2aaSAndroid Build Coastguard Worker                  fBuffer,                                  // buffer
293*c8dee2aaSAndroid Build Coastguard Worker                  0,                                        // offset
294*c8dee2aaSAndroid Build Coastguard Worker                  this->size(),                             // size
295*c8dee2aaSAndroid Build Coastguard Worker         };
296*c8dee2aaSAndroid Build Coastguard Worker         cmdBuffer->addBufferMemoryBarrier(srcStageMask, dstStageMask, &bufferMemoryBarrier);
297*c8dee2aaSAndroid Build Coastguard Worker     }
298*c8dee2aaSAndroid Build Coastguard Worker 
299*c8dee2aaSAndroid Build Coastguard Worker     fCurrentAccessMask = dstAccessMask;
300*c8dee2aaSAndroid Build Coastguard Worker }
301*c8dee2aaSAndroid Build Coastguard Worker 
AccessMaskToPipelineSrcStageFlags(const VkAccessFlags srcMask)302*c8dee2aaSAndroid Build Coastguard Worker VkPipelineStageFlags VulkanBuffer::AccessMaskToPipelineSrcStageFlags(const VkAccessFlags srcMask) {
303*c8dee2aaSAndroid Build Coastguard Worker     if (srcMask == 0) {
304*c8dee2aaSAndroid Build Coastguard Worker         return VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
305*c8dee2aaSAndroid Build Coastguard Worker     }
306*c8dee2aaSAndroid Build Coastguard Worker     VkPipelineStageFlags flags = 0;
307*c8dee2aaSAndroid Build Coastguard Worker 
308*c8dee2aaSAndroid Build Coastguard Worker     if (srcMask & VK_ACCESS_TRANSFER_WRITE_BIT || srcMask & VK_ACCESS_TRANSFER_READ_BIT) {
309*c8dee2aaSAndroid Build Coastguard Worker         flags |= VK_PIPELINE_STAGE_TRANSFER_BIT;
310*c8dee2aaSAndroid Build Coastguard Worker     }
311*c8dee2aaSAndroid Build Coastguard Worker     if (srcMask & VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT ||
312*c8dee2aaSAndroid Build Coastguard Worker         srcMask & VK_ACCESS_COLOR_ATTACHMENT_READ_BIT) {
313*c8dee2aaSAndroid Build Coastguard Worker         flags |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
314*c8dee2aaSAndroid Build Coastguard Worker     }
315*c8dee2aaSAndroid Build Coastguard Worker     if (srcMask & VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT ||
316*c8dee2aaSAndroid Build Coastguard Worker         srcMask & VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT) {
317*c8dee2aaSAndroid Build Coastguard Worker         flags |= VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
318*c8dee2aaSAndroid Build Coastguard Worker     }
319*c8dee2aaSAndroid Build Coastguard Worker     if (srcMask & VK_ACCESS_INPUT_ATTACHMENT_READ_BIT) {
320*c8dee2aaSAndroid Build Coastguard Worker         flags |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
321*c8dee2aaSAndroid Build Coastguard Worker     }
322*c8dee2aaSAndroid Build Coastguard Worker     if (srcMask & VK_ACCESS_SHADER_READ_BIT ||
323*c8dee2aaSAndroid Build Coastguard Worker         srcMask & VK_ACCESS_UNIFORM_READ_BIT) {
324*c8dee2aaSAndroid Build Coastguard Worker         // TODO(b/307577875): It is possible that uniforms could have simply been used in the vertex
325*c8dee2aaSAndroid Build Coastguard Worker         // shader and not the fragment shader, so using the fragment shader pipeline stage bit
326*c8dee2aaSAndroid Build Coastguard Worker         // indiscriminately is a bit overkill. This call should be modified to check & allow for
327*c8dee2aaSAndroid Build Coastguard Worker         // selecting VK_PIPELINE_STAGE_VERTEX_SHADER_BIT when appropriate.
328*c8dee2aaSAndroid Build Coastguard Worker         flags |= (VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
329*c8dee2aaSAndroid Build Coastguard Worker     }
330*c8dee2aaSAndroid Build Coastguard Worker     if (srcMask & VK_ACCESS_SHADER_WRITE_BIT) {
331*c8dee2aaSAndroid Build Coastguard Worker         flags |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
332*c8dee2aaSAndroid Build Coastguard Worker     }
333*c8dee2aaSAndroid Build Coastguard Worker     if (srcMask & VK_ACCESS_INDEX_READ_BIT ||
334*c8dee2aaSAndroid Build Coastguard Worker         srcMask & VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT) {
335*c8dee2aaSAndroid Build Coastguard Worker         flags |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
336*c8dee2aaSAndroid Build Coastguard Worker     }
337*c8dee2aaSAndroid Build Coastguard Worker     if (srcMask & VK_ACCESS_INDIRECT_COMMAND_READ_BIT) {
338*c8dee2aaSAndroid Build Coastguard Worker         flags |= VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT;
339*c8dee2aaSAndroid Build Coastguard Worker     }
340*c8dee2aaSAndroid Build Coastguard Worker     if (srcMask & VK_ACCESS_HOST_READ_BIT || srcMask & VK_ACCESS_HOST_WRITE_BIT) {
341*c8dee2aaSAndroid Build Coastguard Worker         flags |= VK_PIPELINE_STAGE_HOST_BIT;
342*c8dee2aaSAndroid Build Coastguard Worker     }
343*c8dee2aaSAndroid Build Coastguard Worker 
344*c8dee2aaSAndroid Build Coastguard Worker     return flags;
345*c8dee2aaSAndroid Build Coastguard Worker }
346*c8dee2aaSAndroid Build Coastguard Worker 
347*c8dee2aaSAndroid Build Coastguard Worker } // namespace skgpu::graphite
348