1 /*
2 * Copyright 2022 Google LLC
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "src/gpu/graphite/UploadBufferManager.h"
9
10 #include "include/gpu/graphite/Recording.h"
11 #include "include/private/base/SkAlign.h"
12 #include "src/gpu/graphite/Buffer.h"
13 #include "src/gpu/graphite/Caps.h"
14 #include "src/gpu/graphite/RecordingPriv.h"
15 #include "src/gpu/graphite/ResourceProvider.h"
16
17 namespace skgpu::graphite {
18
19 static constexpr size_t kReusedBufferSize = 64 << 10; // 64 KB
20
UploadBufferManager(ResourceProvider * resourceProvider,const Caps * caps)21 UploadBufferManager::UploadBufferManager(ResourceProvider* resourceProvider,
22 const Caps* caps)
23 : fResourceProvider(resourceProvider)
24 , fMinAlignment(caps->requiredTransferBufferAlignment()) {}
25
~UploadBufferManager()26 UploadBufferManager::~UploadBufferManager() {}
27
getUploadWriter(size_t requiredBytes,size_t requiredAlignment)28 std::tuple<UploadWriter, BindBufferInfo> UploadBufferManager::getUploadWriter(
29 size_t requiredBytes, size_t requiredAlignment) {
30 if (!requiredBytes) {
31 return {UploadWriter(), BindBufferInfo()};
32 }
33
34 requiredAlignment = std::max(requiredAlignment, fMinAlignment);
35 requiredBytes = SkAlignTo(requiredBytes, requiredAlignment);
36 if (requiredBytes > kReusedBufferSize) {
37 // Create a dedicated buffer for this request.
38 sk_sp<Buffer> buffer = fResourceProvider->findOrCreateBuffer(
39 requiredBytes, BufferType::kXferCpuToGpu, PrioritizeGpuReads::kNo);
40
41 BindBufferInfo bindInfo;
42 bindInfo.fBuffer = buffer.get();
43 bindInfo.fOffset = 0;
44
45 void* bufferMapPtr = buffer->map();
46 fUsedBuffers.push_back(std::move(buffer));
47 return {UploadWriter(bufferMapPtr, requiredBytes), bindInfo};
48 }
49
50 // Try to reuse an already-allocated buffer.
51 fReusedBufferOffset = SkAlignTo(fReusedBufferOffset, requiredAlignment);
52 if (fReusedBuffer && requiredBytes > fReusedBuffer->size() - fReusedBufferOffset) {
53 fUsedBuffers.push_back(std::move(fReusedBuffer));
54 }
55
56 if (!fReusedBuffer) {
57 fReusedBuffer = fResourceProvider->findOrCreateBuffer(
58 kReusedBufferSize, BufferType::kXferCpuToGpu, PrioritizeGpuReads::kNo);
59 fReusedBufferOffset = 0;
60 if (!fReusedBuffer) {
61 return {UploadWriter(), BindBufferInfo()};
62 }
63 }
64
65 BindBufferInfo bindInfo;
66 bindInfo.fBuffer = fReusedBuffer.get();
67 bindInfo.fOffset = fReusedBufferOffset;
68
69 void* bufferMapPtr = fReusedBuffer->map();
70 bufferMapPtr = SkTAddOffset<void>(bufferMapPtr, fReusedBufferOffset);
71
72 fReusedBufferOffset += requiredBytes;
73 return {UploadWriter(bufferMapPtr, requiredBytes), bindInfo};
74 }
75
transferToRecording(Recording * recording)76 void UploadBufferManager::transferToRecording(Recording* recording) {
77 for (sk_sp<Buffer>& buffer : fUsedBuffers) {
78 buffer->unmap();
79 recording->priv().addResourceRef(std::move(buffer));
80 }
81 fUsedBuffers.clear();
82
83 if (fReusedBuffer) {
84 fReusedBuffer->unmap();
85 recording->priv().addResourceRef(std::move(fReusedBuffer));
86 }
87 }
88
89 } // namespace skgpu::graphite
90