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