• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2021 Google Inc.
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 "experimental/graphite/src/DrawBufferManager.h"
9 
10 #include "experimental/graphite/src/Buffer.h"
11 #include "experimental/graphite/src/CommandBuffer.h"
12 #include "experimental/graphite/src/ResourceProvider.h"
13 
14 namespace skgpu {
15 
16 // TODO: Tune these values on real world data
17 static constexpr size_t kVertexBufferSize = 2 << 10;
18 static constexpr size_t kIndexBufferSize = 2 << 10;
19 static constexpr size_t kUniformBufferSize = 2 << 10;
20 
DrawBufferManager(ResourceProvider * resourceProvider,size_t uniformStartAlignment)21 DrawBufferManager::DrawBufferManager(ResourceProvider* resourceProvider,
22                                      size_t uniformStartAlignment)
23         : fResourceProvider(resourceProvider)
24         , fUniformStartAlignment(uniformStartAlignment) {}
25 
~DrawBufferManager()26 DrawBufferManager::~DrawBufferManager() {}
27 
can_fit(size_t requestedSize,Buffer * buffer,size_t currentOffset,size_t alignment)28 static bool can_fit(size_t requestedSize,
29                     Buffer* buffer,
30                     size_t currentOffset,
31                     size_t alignment) {
32     size_t startOffset = SkAlignTo(currentOffset, alignment);
33     return requestedSize <= (buffer->size() - startOffset);
34 }
35 
getVertexWriter(size_t requiredBytes)36 std::tuple<VertexWriter, BindBufferInfo> DrawBufferManager::getVertexWriter(size_t requiredBytes) {
37     if (!requiredBytes) {
38         BindBufferInfo bindInfo;
39         bindInfo.fBuffer = nullptr;
40         bindInfo.fOffset = 0;
41         return {VertexWriter(nullptr), bindInfo};
42     }
43     if (fCurrentVertexBuffer &&
44         !can_fit(requiredBytes, fCurrentVertexBuffer.get(), fVertexOffset, /*alignment=*/1)) {
45         fUsedBuffers.push_back(std::move(fCurrentVertexBuffer));
46     }
47 
48     if (!fCurrentVertexBuffer) {
49         SkASSERT(requiredBytes <= kVertexBufferSize);
50         fCurrentVertexBuffer = fResourceProvider->findOrCreateBuffer(kVertexBufferSize,
51                                                                      BufferType::kVertex,
52                                                                      PrioritizeGpuReads::kNo);
53         fVertexOffset = 0;
54         if (!fCurrentVertexBuffer) {
55             return {VertexWriter(), BindBufferInfo()};
56         }
57     }
58     BindBufferInfo bindInfo;
59     bindInfo.fBuffer = fCurrentVertexBuffer.get();
60     bindInfo.fOffset = fVertexOffset;
61     fVertexOffset += requiredBytes;
62     return {VertexWriter(fCurrentVertexBuffer->map()), bindInfo};
63 }
64 
getIndexWriter(size_t requiredBytes)65 std::tuple<IndexWriter, BindBufferInfo> DrawBufferManager::getIndexWriter(size_t requiredBytes) {
66     if (!requiredBytes) {
67         BindBufferInfo bindInfo;
68         bindInfo.fBuffer = nullptr;
69         bindInfo.fOffset = 0;
70         return {IndexWriter(nullptr), bindInfo};
71     }
72     if (fCurrentIndexBuffer &&
73         !can_fit(requiredBytes, fCurrentIndexBuffer.get(), fIndexOffset, /*alignment=*/1)) {
74         fUsedBuffers.push_back(std::move(fCurrentIndexBuffer));
75     }
76 
77     if (!fCurrentIndexBuffer) {
78         SkASSERT(requiredBytes <= kIndexBufferSize);
79         fCurrentIndexBuffer = fResourceProvider->findOrCreateBuffer(kIndexBufferSize,
80                                                                     BufferType::kIndex,
81                                                                     PrioritizeGpuReads::kNo);
82         fIndexOffset = 0;
83         if (!fCurrentIndexBuffer) {
84             return {IndexWriter(), BindBufferInfo()};
85         }
86     }
87     BindBufferInfo bindInfo;
88     bindInfo.fBuffer = fCurrentIndexBuffer.get();
89     bindInfo.fOffset = fIndexOffset;
90     fIndexOffset += requiredBytes;
91     return {IndexWriter(fCurrentIndexBuffer->map()), bindInfo};
92 }
93 
getUniformWriter(size_t requiredBytes)94 std::tuple<UniformWriter, BindBufferInfo> DrawBufferManager::getUniformWriter(
95         size_t requiredBytes) {
96     if (!requiredBytes) {
97         BindBufferInfo bindInfo;
98         bindInfo.fBuffer = nullptr;
99         bindInfo.fOffset = 0;
100         return {UniformWriter(nullptr), bindInfo};
101     }
102     if (fCurrentUniformBuffer &&
103         !can_fit(requiredBytes,
104                  fCurrentUniformBuffer.get(),
105                  fUniformOffset,
106                  fUniformStartAlignment)) {
107         fUsedBuffers.push_back(std::move(fCurrentUniformBuffer));
108     }
109 
110     if (!fCurrentUniformBuffer) {
111         SkASSERT(requiredBytes <= kUniformBufferSize);
112         fCurrentUniformBuffer = fResourceProvider->findOrCreateBuffer(kUniformBufferSize,
113                                                                       BufferType::kUniform,
114                                                                       PrioritizeGpuReads::kNo);
115         fUniformOffset = 0;
116         if (!fCurrentUniformBuffer) {
117             return {UniformWriter(), BindBufferInfo()};
118         }
119     }
120     fUniformOffset = SkAlignTo(fUniformOffset, fUniformStartAlignment);
121     BindBufferInfo bindInfo;
122     bindInfo.fBuffer = fCurrentUniformBuffer.get();
123     bindInfo.fOffset = fUniformOffset;
124     fUniformOffset += requiredBytes;
125     return {UniformWriter(fCurrentUniformBuffer->map()), bindInfo};
126 }
127 
transferToCommandBuffer(CommandBuffer * commandBuffer)128 void DrawBufferManager::transferToCommandBuffer(CommandBuffer* commandBuffer) {
129     for (auto& buffer : fUsedBuffers) {
130         buffer->unmap();
131         commandBuffer->trackResource(std::move(buffer));
132     }
133     fUsedBuffers.clear();
134 }
135 
136 } // namespace skgpu
137 
138