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