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 uniformBufferSize)12 GrDawnProgramDataManager::GrDawnProgramDataManager(const UniformInfoArray& uniforms,
13                                                    uint32_t uniformBufferSize)
14     : fUniformBufferSize(uniformBufferSize)
15     , fUniformsDirty(false) {
16     fUniformData.reset(uniformBufferSize);
17     memset(fUniformData.get(), 0, fUniformBufferSize);
18     fUniforms.push_back_n(uniforms.count());
19     // We must add uniforms in same order is the UniformInfoArray so that UniformHandles already
20     // owned by other objects will still match up here.
21     int i = 0;
22     for (const auto& uniformInfo : uniforms.items()) {
23         Uniform& uniform = fUniforms[i];
24         SkDEBUGCODE(
25             uniform.fArrayCount = uniformInfo.fVar.getArrayCount();
26             uniform.fType = uniformInfo.fVar.getType();
27         )
28         uniform.fOffset = uniformInfo.fUBOOffset;
29         ++i;
30     }
31 }
32 
getBufferPtrAndMarkDirty(const Uniform & uni) const33 void* GrDawnProgramDataManager::getBufferPtrAndMarkDirty(const Uniform& uni) const {
34     fUniformsDirty = true;
35     return static_cast<char*>(fUniformData.get()) + uni.fOffset;
36 }
37 
set1i(UniformHandle u,int32_t i) const38 void GrDawnProgramDataManager::set1i(UniformHandle u, int32_t i) const {
39     const Uniform& uni = fUniforms[u.toIndex()];
40     void* buffer = this->getBufferPtrAndMarkDirty(uni);
41     memcpy(buffer, &i, sizeof(int32_t));
42 }
43 
set1iv(UniformHandle u,int arrayCount,const int32_t v[]) const44 void GrDawnProgramDataManager::set1iv(UniformHandle u, int arrayCount, const int32_t v[]) const {
45     const Uniform& uni = fUniforms[u.toIndex()];
46     uint32_t* buffer = static_cast<uint32_t*>(this->getBufferPtrAndMarkDirty(uni));
47     for (int i = 0; i < arrayCount; ++i) {
48         const int32_t* curVec = &v[i];
49         memcpy(buffer, curVec, sizeof(int32_t));
50         buffer += 4;
51     }
52 }
53 
set2i(UniformHandle u,int32_t i0,int32_t i1) const54 void GrDawnProgramDataManager::set2i(UniformHandle u, int32_t i0, int32_t i1) const {
55     const Uniform& uni = fUniforms[u.toIndex()];
56     void* buffer = this->getBufferPtrAndMarkDirty(uni);
57     int32_t v[2] = { i0, i1 };
58     memcpy(buffer, v, 2 * sizeof(int32_t));
59 }
60 
set2iv(UniformHandle u,int arrayCount,const int32_t v[]) const61 void GrDawnProgramDataManager::set2iv(UniformHandle u, int arrayCount, const int32_t v[]) const {
62     const Uniform& uni = fUniforms[u.toIndex()];
63     uint32_t* buffer = static_cast<uint32_t*>(this->getBufferPtrAndMarkDirty(uni));
64     for (int i = 0; i < arrayCount; ++i) {
65         const int32_t* curVec = &v[2 * i];
66         memcpy(buffer, curVec, 2 * sizeof(int32_t));
67         buffer += 4;
68     }
69 }
70 
set3i(UniformHandle u,int32_t i0,int32_t i1,int32_t i2) const71 void GrDawnProgramDataManager::set3i(UniformHandle u, int32_t i0, int32_t i1, int32_t i2) const {
72     const Uniform& uni = fUniforms[u.toIndex()];
73     void* buffer = this->getBufferPtrAndMarkDirty(uni);
74     int32_t v[3] = { i0, i1, i2 };
75     memcpy(buffer, v, 3 * sizeof(int32_t));
76 }
77 
set3iv(UniformHandle u,int arrayCount,const int32_t v[]) const78 void GrDawnProgramDataManager::set3iv(UniformHandle u, int arrayCount, const int32_t v[]) const {
79     const Uniform& uni = fUniforms[u.toIndex()];
80     uint32_t* buffer = static_cast<uint32_t*>(this->getBufferPtrAndMarkDirty(uni));
81     for (int i = 0; i < arrayCount; ++i) {
82         const int32_t* curVec = &v[3 * i];
83         memcpy(buffer, curVec, 3 * sizeof(int32_t));
84         buffer += 4;
85     }
86 }
87 
set4i(UniformHandle u,int32_t i0,int32_t i1,int32_t i2,int32_t i3) const88 void GrDawnProgramDataManager::set4i(UniformHandle u,
89                                      int32_t i0,
90                                      int32_t i1,
91                                      int32_t i2,
92                                      int32_t i3) const {
93     const Uniform& uni = fUniforms[u.toIndex()];
94     void* buffer = this->getBufferPtrAndMarkDirty(uni);
95     int32_t v[4] = { i0, i1, i2, i3 };
96     memcpy(buffer, v, sizeof(v));
97 }
98 
set4iv(UniformHandle u,int arrayCount,const int32_t v[]) const99 void GrDawnProgramDataManager::set4iv(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[4 * i];
104         memcpy(buffer, curVec, 4 * sizeof(int32_t));
105         buffer += 4;
106     }
107 }
108 
set1f(UniformHandle u,float v0) const109 void GrDawnProgramDataManager::set1f(UniformHandle u, float v0) const {
110     const Uniform& uni = fUniforms[u.toIndex()];
111     void* buffer = this->getBufferPtrAndMarkDirty(uni);
112     memcpy(buffer, &v0, sizeof(float));
113 }
114 
set1fv(UniformHandle u,int arrayCount,const float v[]) const115 void GrDawnProgramDataManager::set1fv(UniformHandle u, int arrayCount, const float v[]) const {
116     const Uniform& uni = fUniforms[u.toIndex()];
117     void* buffer = this->getBufferPtrAndMarkDirty(uni);
118     for (int i = 0; i < arrayCount; ++i) {
119         const float* curVec = &v[i];
120         memcpy(buffer, curVec, sizeof(float));
121         buffer = static_cast<char*>(buffer) + 4*sizeof(float);
122     }
123 }
124 
set2f(UniformHandle u,float v0,float v1) const125 void GrDawnProgramDataManager::set2f(UniformHandle u, float v0, float v1) const {
126     const Uniform& uni = fUniforms[u.toIndex()];
127     void* buffer = this->getBufferPtrAndMarkDirty(uni);
128     float v[2] = { v0, v1 };
129     memcpy(buffer, v, 2 * sizeof(float));
130 }
131 
set2fv(UniformHandle u,int arrayCount,const float v[]) const132 void GrDawnProgramDataManager::set2fv(UniformHandle u, int arrayCount, const float v[]) const {
133     const Uniform& uni = fUniforms[u.toIndex()];
134     void* buffer = this->getBufferPtrAndMarkDirty(uni);
135     for (int i = 0; i < arrayCount; ++i) {
136         const float* curVec = &v[2 * i];
137         memcpy(buffer, curVec, 2 * sizeof(float));
138         buffer = static_cast<char*>(buffer) + 4*sizeof(float);
139     }
140 }
141 
set3f(UniformHandle u,float v0,float v1,float v2) const142 void GrDawnProgramDataManager::set3f(UniformHandle u, float v0, float v1, float v2) const {
143     const Uniform& uni = fUniforms[u.toIndex()];
144     void* buffer = this->getBufferPtrAndMarkDirty(uni);
145     float v[3] = { v0, v1, v2 };
146     memcpy(buffer, v, 3 * sizeof(float));
147 }
148 
set3fv(UniformHandle u,int arrayCount,const float v[]) const149 void GrDawnProgramDataManager::set3fv(UniformHandle u, int arrayCount, const float v[]) const {
150     const Uniform& uni = fUniforms[u.toIndex()];
151     void* buffer = this->getBufferPtrAndMarkDirty(uni);
152     for (int i = 0; i < arrayCount; ++i) {
153         const float* curVec = &v[3 * i];
154         memcpy(buffer, curVec, 3 * sizeof(float));
155         buffer = static_cast<char*>(buffer) + 4*sizeof(float);
156     }
157 }
158 
set4f(UniformHandle u,float v0,float v1,float v2,float v3) const159 void GrDawnProgramDataManager::set4f(UniformHandle u,
160                                      float v0,
161                                      float v1,
162                                      float v2,
163                                      float v3) const {
164     const Uniform& uni = fUniforms[u.toIndex()];
165     void* buffer = this->getBufferPtrAndMarkDirty(uni);
166     float v[4] = { v0, v1, v2, v3 };
167     memcpy(buffer, v, 4 * sizeof(float));
168 }
169 
set4fv(UniformHandle u,int arrayCount,const float v[]) const170 void GrDawnProgramDataManager::set4fv(UniformHandle u, int arrayCount, const float v[]) const {
171     const Uniform& uni = fUniforms[u.toIndex()];
172     void* buffer = this->getBufferPtrAndMarkDirty(uni);
173     memcpy(buffer, v, arrayCount * 4 * sizeof(float));
174 }
175 
setMatrix2f(UniformHandle u,const float matrix[]) const176 void GrDawnProgramDataManager::setMatrix2f(UniformHandle u, const float matrix[]) const {
177     this->setMatrices<2>(u, 1, matrix);
178 }
179 
setMatrix2fv(UniformHandle u,int arrayCount,const float m[]) const180 void GrDawnProgramDataManager::setMatrix2fv(UniformHandle u,
181                                             int arrayCount,
182                                             const float m[]) const {
183     this->setMatrices<2>(u, arrayCount, m);
184 }
185 
setMatrix3f(UniformHandle u,const float matrix[]) const186 void GrDawnProgramDataManager::setMatrix3f(UniformHandle u, const float matrix[]) const {
187     this->setMatrices<3>(u, 1, matrix);
188 }
189 
setMatrix3fv(UniformHandle u,int arrayCount,const float m[]) const190 void GrDawnProgramDataManager::setMatrix3fv(UniformHandle u,
191                                             int arrayCount,
192                                             const float m[]) const {
193     this->setMatrices<3>(u, arrayCount, m);
194 }
195 
setMatrix4f(UniformHandle u,const float matrix[]) const196 void GrDawnProgramDataManager::setMatrix4f(UniformHandle u, const float matrix[]) const {
197     this->setMatrices<4>(u, 1, matrix);
198 }
199 
setMatrix4fv(UniformHandle u,int arrayCount,const float m[]) const200 void GrDawnProgramDataManager::setMatrix4fv(UniformHandle u,
201                                             int arrayCount,
202                                             const float m[]) const {
203     this->setMatrices<4>(u, arrayCount, m);
204 }
205 
206 template<int N> struct set_uniform_matrix;
207 
setMatrices(UniformHandle u,int arrayCount,const float matrices[]) const208 template<int N> inline void GrDawnProgramDataManager::setMatrices(UniformHandle u,
209                                                                   int arrayCount,
210                                                                   const float matrices[]) const {
211     const Uniform& uni = fUniforms[u.toIndex()];
212     fUniformsDirty = true;
213     set_uniform_matrix<N>::set(fUniformData.get(), uni.fOffset, arrayCount, matrices);
214 }
215 
216 template<int N> struct set_uniform_matrix {
setset_uniform_matrix217     inline static void set(void* buffer, int uniformOffset, int count, const float matrices[]) {
218         static_assert(sizeof(float) == 4);
219         buffer = static_cast<char*>(buffer) + uniformOffset;
220         for (int i = 0; i < count; ++i) {
221             const float* matrix = &matrices[N * N * i];
222             for (int j = 0; j < N; ++j) {
223                 memcpy(buffer, &matrix[j * N], N * sizeof(float));
224                 buffer = static_cast<char*>(buffer) + 4 * sizeof(float);
225             }
226         }
227     }
228 };
229 
230 template<> struct set_uniform_matrix<4> {
setset_uniform_matrix231     inline static void set(void* buffer, int uniformOffset, int count, const float matrices[]) {
232         static_assert(sizeof(float) == 4);
233         buffer = static_cast<char*>(buffer) + uniformOffset;
234         memcpy(buffer, matrices, count * 16 * sizeof(float));
235     }
236 };
237 
uploadUniformBuffers(void * dest) const238 void GrDawnProgramDataManager::uploadUniformBuffers(void* dest) const {
239     if (fUniformsDirty) {
240         memcpy(dest, fUniformData.get(), fUniformBufferSize);
241     }
242 }
243