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