1 /*
2 * Copyright 2019 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 "src/gpu/dawn/GrDawnProgramDataManager.h"
9
10 #include "src/gpu/dawn/GrDawnGpu.h"
11
GrDawnProgramDataManager(const UniformInfoArray & uniforms,uint32_t geometryUniformSize,uint32_t fragmentUniformSize)12 GrDawnProgramDataManager::GrDawnProgramDataManager(const UniformInfoArray& uniforms,
13 uint32_t geometryUniformSize,
14 uint32_t fragmentUniformSize)
15 : fGeometryUniformSize(geometryUniformSize)
16 , fFragmentUniformSize(fragmentUniformSize)
17 , fGeometryUniformsDirty(false)
18 , fFragmentUniformsDirty(false) {
19 fGeometryUniformData.reset(geometryUniformSize);
20 fFragmentUniformData.reset(fragmentUniformSize);
21 memset(fGeometryUniformData.get(), 0, fGeometryUniformSize);
22 memset(fFragmentUniformData.get(), 0, fFragmentUniformSize);
23 int count = uniforms.count();
24 fUniforms.push_back_n(count);
25 // We must add uniforms in same order is the UniformInfoArray so that UniformHandles already
26 // owned by other objects will still match up here.
27 for (int i = 0; i < count; i++) {
28 Uniform& uniform = fUniforms[i];
29 const GrDawnUniformHandler::UniformInfo uniformInfo = uniforms[i];
30 SkDEBUGCODE(
31 uniform.fArrayCount = uniformInfo.fVar.getArrayCount();
32 uniform.fType = uniformInfo.fVar.getType();
33 );
34
35 if (!(kFragment_GrShaderFlag & uniformInfo.fVisibility)) {
36 uniform.fBinding = GrDawnUniformHandler::kGeometryBinding;
37 } else {
38 SkASSERT(kFragment_GrShaderFlag == uniformInfo.fVisibility);
39 uniform.fBinding = GrDawnUniformHandler::kFragBinding;
40 }
41 uniform.fOffset = uniformInfo.fUBOOffset;
42 }
43 }
44
getBufferPtrAndMarkDirty(const Uniform & uni) const45 void* GrDawnProgramDataManager::getBufferPtrAndMarkDirty(const Uniform& uni) const {
46 void* buffer;
47 if (GrDawnUniformHandler::kGeometryBinding == uni.fBinding) {
48 buffer = fGeometryUniformData.get();
49 fGeometryUniformsDirty = true;
50 } else {
51 SkASSERT(GrDawnUniformHandler::kFragBinding == uni.fBinding);
52 buffer = fFragmentUniformData.get();
53 fFragmentUniformsDirty = true;
54 }
55 buffer = static_cast<char*>(buffer)+uni.fOffset;
56 return buffer;
57 }
58
set1i(UniformHandle u,int32_t i) const59 void GrDawnProgramDataManager::set1i(UniformHandle u, int32_t i) const {
60 const Uniform& uni = fUniforms[u.toIndex()];
61 void* buffer = this->getBufferPtrAndMarkDirty(uni);
62 memcpy(buffer, &i, sizeof(int32_t));
63 }
64
set1iv(UniformHandle u,int arrayCount,const int32_t v[]) const65 void GrDawnProgramDataManager::set1iv(UniformHandle u, int arrayCount, const int32_t v[]) const {
66 const Uniform& uni = fUniforms[u.toIndex()];
67 uint32_t* buffer = static_cast<uint32_t*>(this->getBufferPtrAndMarkDirty(uni));
68 for (int i = 0; i < arrayCount; ++i) {
69 const int32_t* curVec = &v[i];
70 memcpy(buffer, curVec, sizeof(int32_t));
71 buffer += 4;
72 }
73 }
74
set2i(UniformHandle u,int32_t i0,int32_t i1) const75 void GrDawnProgramDataManager::set2i(UniformHandle u, int32_t i0, int32_t i1) const {
76 const Uniform& uni = fUniforms[u.toIndex()];
77 void* buffer = this->getBufferPtrAndMarkDirty(uni);
78 int32_t v[2] = { i0, i1 };
79 memcpy(buffer, v, 2 * sizeof(int32_t));
80 }
81
set2iv(UniformHandle u,int arrayCount,const int32_t v[]) const82 void GrDawnProgramDataManager::set2iv(UniformHandle u, int arrayCount, const int32_t v[]) const {
83 const Uniform& uni = fUniforms[u.toIndex()];
84 uint32_t* buffer = static_cast<uint32_t*>(this->getBufferPtrAndMarkDirty(uni));
85 for (int i = 0; i < arrayCount; ++i) {
86 const int32_t* curVec = &v[2 * i];
87 memcpy(buffer, curVec, 2 * sizeof(int32_t));
88 buffer += 4;
89 }
90 }
91
set3i(UniformHandle u,int32_t i0,int32_t i1,int32_t i2) const92 void GrDawnProgramDataManager::set3i(UniformHandle u, int32_t i0, int32_t i1, int32_t i2) const {
93 const Uniform& uni = fUniforms[u.toIndex()];
94 void* buffer = this->getBufferPtrAndMarkDirty(uni);
95 int32_t v[3] = { i0, i1, i2 };
96 memcpy(buffer, v, 3 * sizeof(int32_t));
97 }
98
set3iv(UniformHandle u,int arrayCount,const int32_t v[]) const99 void GrDawnProgramDataManager::set3iv(UniformHandle u, int arrayCount, const int32_t v[]) const {
100 const Uniform& uni = fUniforms[u.toIndex()];
101 uint32_t* buffer = static_cast<uint32_t*>(this->getBufferPtrAndMarkDirty(uni));
102 for (int i = 0; i < arrayCount; ++i) {
103 const int32_t* curVec = &v[3 * i];
104 memcpy(buffer, curVec, 3 * sizeof(int32_t));
105 buffer += 4;
106 }
107 }
108
set4i(UniformHandle u,int32_t i0,int32_t i1,int32_t i2,int32_t i3) const109 void GrDawnProgramDataManager::set4i(UniformHandle u,
110 int32_t i0,
111 int32_t i1,
112 int32_t i2,
113 int32_t i3) const {
114 const Uniform& uni = fUniforms[u.toIndex()];
115 void* buffer = this->getBufferPtrAndMarkDirty(uni);
116 int32_t v[4] = { i0, i1, i2, i3 };
117 memcpy(buffer, v, sizeof(v));
118 }
119
set4iv(UniformHandle u,int arrayCount,const int32_t v[]) const120 void GrDawnProgramDataManager::set4iv(UniformHandle u, int arrayCount, const int32_t v[]) const {
121 const Uniform& uni = fUniforms[u.toIndex()];
122 uint32_t* buffer = static_cast<uint32_t*>(this->getBufferPtrAndMarkDirty(uni));
123 for (int i = 0; i < arrayCount; ++i) {
124 const int32_t* curVec = &v[4 * i];
125 memcpy(buffer, curVec, 4 * sizeof(int32_t));
126 buffer += 4;
127 }
128 }
129
set1f(UniformHandle u,float v0) const130 void GrDawnProgramDataManager::set1f(UniformHandle u, float v0) const {
131 const Uniform& uni = fUniforms[u.toIndex()];
132 void* buffer = this->getBufferPtrAndMarkDirty(uni);
133 memcpy(buffer, &v0, sizeof(float));
134 }
135
set1fv(UniformHandle u,int arrayCount,const float v[]) const136 void GrDawnProgramDataManager::set1fv(UniformHandle u, int arrayCount, const float v[]) const {
137 const Uniform& uni = fUniforms[u.toIndex()];
138 void* buffer = this->getBufferPtrAndMarkDirty(uni);
139 for (int i = 0; i < arrayCount; ++i) {
140 const float* curVec = &v[i];
141 memcpy(buffer, curVec, sizeof(float));
142 buffer = static_cast<char*>(buffer) + 4*sizeof(float);
143 }
144 }
145
set2f(UniformHandle u,float v0,float v1) const146 void GrDawnProgramDataManager::set2f(UniformHandle u, float v0, float v1) const {
147 const Uniform& uni = fUniforms[u.toIndex()];
148 void* buffer = this->getBufferPtrAndMarkDirty(uni);
149 float v[2] = { v0, v1 };
150 memcpy(buffer, v, 2 * sizeof(float));
151 }
152
set2fv(UniformHandle u,int arrayCount,const float v[]) const153 void GrDawnProgramDataManager::set2fv(UniformHandle u, int arrayCount, const float v[]) const {
154 const Uniform& uni = fUniforms[u.toIndex()];
155 void* buffer = this->getBufferPtrAndMarkDirty(uni);
156 for (int i = 0; i < arrayCount; ++i) {
157 const float* curVec = &v[2 * i];
158 memcpy(buffer, curVec, 2 * sizeof(float));
159 buffer = static_cast<char*>(buffer) + 4*sizeof(float);
160 }
161 }
162
set3f(UniformHandle u,float v0,float v1,float v2) const163 void GrDawnProgramDataManager::set3f(UniformHandle u, float v0, float v1, float v2) const {
164 const Uniform& uni = fUniforms[u.toIndex()];
165 void* buffer = this->getBufferPtrAndMarkDirty(uni);
166 float v[3] = { v0, v1, v2 };
167 memcpy(buffer, v, 3 * sizeof(float));
168 }
169
set3fv(UniformHandle u,int arrayCount,const float v[]) const170 void GrDawnProgramDataManager::set3fv(UniformHandle u, int arrayCount, const float v[]) const {
171 const Uniform& uni = fUniforms[u.toIndex()];
172 void* buffer = this->getBufferPtrAndMarkDirty(uni);
173 for (int i = 0; i < arrayCount; ++i) {
174 const float* curVec = &v[3 * i];
175 memcpy(buffer, curVec, 3 * sizeof(float));
176 buffer = static_cast<char*>(buffer) + 4*sizeof(float);
177 }
178 }
179
set4f(UniformHandle u,float v0,float v1,float v2,float v3) const180 void GrDawnProgramDataManager::set4f(UniformHandle u,
181 float v0,
182 float v1,
183 float v2,
184 float v3) const {
185 const Uniform& uni = fUniforms[u.toIndex()];
186 void* buffer = this->getBufferPtrAndMarkDirty(uni);
187 float v[4] = { v0, v1, v2, v3 };
188 memcpy(buffer, v, 4 * sizeof(float));
189 }
190
set4fv(UniformHandle u,int arrayCount,const float v[]) const191 void GrDawnProgramDataManager::set4fv(UniformHandle u, int arrayCount, const float v[]) const {
192 const Uniform& uni = fUniforms[u.toIndex()];
193 void* buffer = this->getBufferPtrAndMarkDirty(uni);
194 memcpy(buffer, v, arrayCount * 4 * sizeof(float));
195 }
196
setMatrix2f(UniformHandle u,const float matrix[]) const197 void GrDawnProgramDataManager::setMatrix2f(UniformHandle u, const float matrix[]) const {
198 this->setMatrices<2>(u, 1, matrix);
199 }
200
setMatrix2fv(UniformHandle u,int arrayCount,const float m[]) const201 void GrDawnProgramDataManager::setMatrix2fv(UniformHandle u,
202 int arrayCount,
203 const float m[]) const {
204 this->setMatrices<2>(u, arrayCount, m);
205 }
206
setMatrix3f(UniformHandle u,const float matrix[]) const207 void GrDawnProgramDataManager::setMatrix3f(UniformHandle u, const float matrix[]) const {
208 this->setMatrices<3>(u, 1, matrix);
209 }
210
setMatrix3fv(UniformHandle u,int arrayCount,const float m[]) const211 void GrDawnProgramDataManager::setMatrix3fv(UniformHandle u,
212 int arrayCount,
213 const float m[]) const {
214 this->setMatrices<3>(u, arrayCount, m);
215 }
216
setMatrix4f(UniformHandle u,const float matrix[]) const217 void GrDawnProgramDataManager::setMatrix4f(UniformHandle u, const float matrix[]) const {
218 this->setMatrices<4>(u, 1, matrix);
219 }
220
setMatrix4fv(UniformHandle u,int arrayCount,const float m[]) const221 void GrDawnProgramDataManager::setMatrix4fv(UniformHandle u,
222 int arrayCount,
223 const float m[]) const {
224 this->setMatrices<4>(u, arrayCount, m);
225 }
226
227 template<int N> struct set_uniform_matrix;
228
setMatrices(UniformHandle u,int arrayCount,const float matrices[]) const229 template<int N> inline void GrDawnProgramDataManager::setMatrices(UniformHandle u,
230 int arrayCount,
231 const float matrices[]) const {
232 const Uniform& uni = fUniforms[u.toIndex()];
233 void* buffer;
234 if (GrDawnUniformHandler::kGeometryBinding == uni.fBinding) {
235 buffer = fGeometryUniformData.get();
236 fGeometryUniformsDirty = true;
237 } else {
238 SkASSERT(GrDawnUniformHandler::kFragBinding == uni.fBinding);
239 buffer = fFragmentUniformData.get();
240 fFragmentUniformsDirty = true;
241 }
242
243 set_uniform_matrix<N>::set(buffer, uni.fOffset, arrayCount, matrices);
244 }
245
246 template<int N> struct set_uniform_matrix {
setset_uniform_matrix247 inline static void set(void* buffer, int uniformOffset, int count, const float matrices[]) {
248 GR_STATIC_ASSERT(sizeof(float) == 4);
249 buffer = static_cast<char*>(buffer) + uniformOffset;
250 for (int i = 0; i < count; ++i) {
251 const float* matrix = &matrices[N * N * i];
252 for (int j = 0; j < N; ++j) {
253 memcpy(buffer, &matrix[j * N], N * sizeof(float));
254 buffer = static_cast<char*>(buffer) + 4 * sizeof(float);
255 }
256 }
257 }
258 };
259
260 template<> struct set_uniform_matrix<4> {
setset_uniform_matrix261 inline static void set(void* buffer, int uniformOffset, int count, const float matrices[]) {
262 GR_STATIC_ASSERT(sizeof(float) == 4);
263 buffer = static_cast<char*>(buffer) + uniformOffset;
264 memcpy(buffer, matrices, count * 16 * sizeof(float));
265 }
266 };
267
uploadUniformBuffers(GrDawnGpu * gpu,GrDawnRingBuffer::Slice geometryBuffer,GrDawnRingBuffer::Slice fragmentBuffer) const268 void GrDawnProgramDataManager::uploadUniformBuffers(GrDawnGpu* gpu,
269 GrDawnRingBuffer::Slice geometryBuffer,
270 GrDawnRingBuffer::Slice fragmentBuffer) const {
271 dawn::Buffer geom = geometryBuffer.fBuffer;
272 uint32_t geomOffset = geometryBuffer.fOffset;
273 dawn::Buffer frag = fragmentBuffer.fBuffer;
274 uint32_t fragOffset = fragmentBuffer.fOffset;
275 auto copyEncoder = gpu->getCopyEncoder();
276 if (geom && fGeometryUniformsDirty) {
277 GrDawnStagingBuffer* stagingBuffer = gpu->getStagingBuffer(fGeometryUniformSize);
278 memcpy(stagingBuffer->fData, fGeometryUniformData.get(), fGeometryUniformSize);
279 stagingBuffer->fBuffer.Unmap();
280 copyEncoder
281 .CopyBufferToBuffer(stagingBuffer->fBuffer, 0, geom, geomOffset, fGeometryUniformSize);
282 }
283 if (frag && fFragmentUniformsDirty) {
284 GrDawnStagingBuffer* stagingBuffer = gpu->getStagingBuffer(fFragmentUniformSize);
285 memcpy(stagingBuffer->fData, fFragmentUniformData.get(), fFragmentUniformSize);
286 stagingBuffer->fBuffer.Unmap();
287 copyEncoder
288 .CopyBufferToBuffer(stagingBuffer->fBuffer, 0, frag, fragOffset, fFragmentUniformSize);
289 }
290 }
291