1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2020 Google LLC
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "src/gpu/GrUniformDataManager.h"
9cb93a386Sopenharmony_ci
10cb93a386Sopenharmony_ci#include "include/private/SkHalf.h"
11cb93a386Sopenharmony_ci#include "src/gpu/GrShaderVar.h"
12cb93a386Sopenharmony_ci
13cb93a386Sopenharmony_ci// ensure that these types are the sizes the uniform data is expecting
14cb93a386Sopenharmony_cistatic_assert(sizeof(int32_t) == 4);
15cb93a386Sopenharmony_cistatic_assert(sizeof(float) == 4);
16cb93a386Sopenharmony_cistatic_assert(sizeof(short) == 2);
17cb93a386Sopenharmony_cistatic_assert(sizeof(SkHalf) == 2);
18cb93a386Sopenharmony_ci
19cb93a386Sopenharmony_ciGrUniformDataManager::GrUniformDataManager(uint32_t uniformCount, uint32_t uniformSize)
20cb93a386Sopenharmony_ci    : fUniformSize(uniformSize)
21cb93a386Sopenharmony_ci    , fUniformsDirty(false) {
22cb93a386Sopenharmony_ci    fUniformData.reset(uniformSize);
23cb93a386Sopenharmony_ci    fUniforms.push_back_n(uniformCount);
24cb93a386Sopenharmony_ci    // subclasses fill in the uniforms in their constructor
25cb93a386Sopenharmony_ci}
26cb93a386Sopenharmony_ci
27cb93a386Sopenharmony_civoid* GrUniformDataManager::getBufferPtrAndMarkDirty(const Uniform& uni) const {
28cb93a386Sopenharmony_ci    fUniformsDirty = true;
29cb93a386Sopenharmony_ci    return static_cast<char*>(fUniformData.get()) + uni.fOffset;
30cb93a386Sopenharmony_ci}
31cb93a386Sopenharmony_ci
32cb93a386Sopenharmony_ciint GrUniformDataManager::copyUniforms(void* dest,
33cb93a386Sopenharmony_ci                                       const void* src,
34cb93a386Sopenharmony_ci                                       int numUniforms,
35cb93a386Sopenharmony_ci                                       GrSLType uniformType) const {
36cb93a386Sopenharmony_ci    if (fWrite16BitUniforms) {
37cb93a386Sopenharmony_ci        switch (uniformType) {
38cb93a386Sopenharmony_ci            case kHalf_GrSLType:
39cb93a386Sopenharmony_ci            case kHalf2_GrSLType:
40cb93a386Sopenharmony_ci            case kHalf3_GrSLType:
41cb93a386Sopenharmony_ci            case kHalf4_GrSLType:
42cb93a386Sopenharmony_ci            case kHalf2x2_GrSLType:
43cb93a386Sopenharmony_ci            case kHalf3x3_GrSLType:
44cb93a386Sopenharmony_ci            case kHalf4x4_GrSLType: {
45cb93a386Sopenharmony_ci                const float* floatBits = static_cast<const float*>(src);
46cb93a386Sopenharmony_ci                SkHalf* halfBits = static_cast<SkHalf*>(dest);
47cb93a386Sopenharmony_ci                while (numUniforms-- > 0) {
48cb93a386Sopenharmony_ci                    *halfBits++ = SkFloatToHalf(*floatBits++);
49cb93a386Sopenharmony_ci                }
50cb93a386Sopenharmony_ci                return 2;
51cb93a386Sopenharmony_ci            }
52cb93a386Sopenharmony_ci
53cb93a386Sopenharmony_ci            case kShort_GrSLType:
54cb93a386Sopenharmony_ci            case kShort2_GrSLType:
55cb93a386Sopenharmony_ci            case kShort3_GrSLType:
56cb93a386Sopenharmony_ci            case kShort4_GrSLType:
57cb93a386Sopenharmony_ci            case kUShort_GrSLType:
58cb93a386Sopenharmony_ci            case kUShort2_GrSLType:
59cb93a386Sopenharmony_ci            case kUShort3_GrSLType:
60cb93a386Sopenharmony_ci            case kUShort4_GrSLType: {
61cb93a386Sopenharmony_ci                const int32_t* intBits = static_cast<const int32_t*>(src);
62cb93a386Sopenharmony_ci                short* shortBits = static_cast<short*>(dest);
63cb93a386Sopenharmony_ci                while (numUniforms-- > 0) {
64cb93a386Sopenharmony_ci                    *shortBits++ = (short)(*intBits++);
65cb93a386Sopenharmony_ci                }
66cb93a386Sopenharmony_ci                return 2;
67cb93a386Sopenharmony_ci            }
68cb93a386Sopenharmony_ci
69cb93a386Sopenharmony_ci            default:
70cb93a386Sopenharmony_ci                // Fall through to memcpy below.
71cb93a386Sopenharmony_ci                break;
72cb93a386Sopenharmony_ci        }
73cb93a386Sopenharmony_ci    }
74cb93a386Sopenharmony_ci
75cb93a386Sopenharmony_ci    memcpy(dest, src, numUniforms * 4);
76cb93a386Sopenharmony_ci    return 4;
77cb93a386Sopenharmony_ci}
78cb93a386Sopenharmony_ci
79cb93a386Sopenharmony_citemplate <int N, GrSLType FullType, GrSLType HalfType>
80cb93a386Sopenharmony_civoid GrUniformDataManager::set(UniformHandle u, const void* v) const {
81cb93a386Sopenharmony_ci    const Uniform& uni = fUniforms[u.toIndex()];
82cb93a386Sopenharmony_ci    SkASSERT(uni.fType == FullType || uni.fType == HalfType);
83cb93a386Sopenharmony_ci    SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
84cb93a386Sopenharmony_ci    void* buffer = this->getBufferPtrAndMarkDirty(uni);
85cb93a386Sopenharmony_ci    this->copyUniforms(buffer, v, N, uni.fType);
86cb93a386Sopenharmony_ci}
87cb93a386Sopenharmony_ci
88cb93a386Sopenharmony_citemplate <int N, GrSLType FullType, GrSLType HalfType>
89cb93a386Sopenharmony_civoid GrUniformDataManager::setv(UniformHandle u, int arrayCount, const void* v) const {
90cb93a386Sopenharmony_ci    const Uniform& uni = fUniforms[u.toIndex()];
91cb93a386Sopenharmony_ci    SkASSERT(uni.fType == FullType || uni.fType == HalfType);
92cb93a386Sopenharmony_ci    SkASSERT(arrayCount > 0);
93cb93a386Sopenharmony_ci    SkASSERT(arrayCount <= uni.fArrayCount ||
94cb93a386Sopenharmony_ci             (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount));
95cb93a386Sopenharmony_ci
96cb93a386Sopenharmony_ci    void* buffer = this->getBufferPtrAndMarkDirty(uni);
97cb93a386Sopenharmony_ci    if constexpr (N == 4) {
98cb93a386Sopenharmony_ci        this->copyUniforms(buffer, v, arrayCount * 4, uni.fType);
99cb93a386Sopenharmony_ci    } else {
100cb93a386Sopenharmony_ci        for (int i = 0; i < arrayCount; ++i) {
101cb93a386Sopenharmony_ci            int uniformSize = this->copyUniforms(buffer, v, N, uni.fType);
102cb93a386Sopenharmony_ci            buffer = SkTAddOffset<void>(buffer, /*numUniforms*/4 * uniformSize);
103cb93a386Sopenharmony_ci            v = static_cast<const char*>(v) + N * 4;
104cb93a386Sopenharmony_ci        }
105cb93a386Sopenharmony_ci    }
106cb93a386Sopenharmony_ci}
107cb93a386Sopenharmony_ci
108cb93a386Sopenharmony_civoid GrUniformDataManager::set1i(UniformHandle u, int32_t i0) const {
109cb93a386Sopenharmony_ci    this->set<1, kInt_GrSLType, kShort_GrSLType>(u, &i0);
110cb93a386Sopenharmony_ci}
111cb93a386Sopenharmony_ci
112cb93a386Sopenharmony_civoid GrUniformDataManager::set1iv(UniformHandle u,
113cb93a386Sopenharmony_ci                                  int arrayCount,
114cb93a386Sopenharmony_ci                                  const int32_t v[]) const {
115cb93a386Sopenharmony_ci    this->setv<1, kInt_GrSLType, kShort_GrSLType>(u, arrayCount, v);
116cb93a386Sopenharmony_ci}
117cb93a386Sopenharmony_ci
118cb93a386Sopenharmony_civoid GrUniformDataManager::set1f(UniformHandle u, float v0) const {
119cb93a386Sopenharmony_ci    this->set<1, kFloat_GrSLType, kHalf_GrSLType>(u, &v0);
120cb93a386Sopenharmony_ci}
121cb93a386Sopenharmony_ci
122cb93a386Sopenharmony_civoid GrUniformDataManager::set1fv(UniformHandle u,
123cb93a386Sopenharmony_ci                                  int arrayCount,
124cb93a386Sopenharmony_ci                                  const float v[]) const {
125cb93a386Sopenharmony_ci    this->setv<1, kFloat_GrSLType, kHalf_GrSLType>(u, arrayCount, v);
126cb93a386Sopenharmony_ci}
127cb93a386Sopenharmony_ci
128cb93a386Sopenharmony_civoid GrUniformDataManager::set2i(UniformHandle u, int32_t i0, int32_t i1) const {
129cb93a386Sopenharmony_ci    int32_t v[2] = { i0, i1 };
130cb93a386Sopenharmony_ci    this->set<2, kInt2_GrSLType, kShort2_GrSLType>(u, v);
131cb93a386Sopenharmony_ci}
132cb93a386Sopenharmony_ci
133cb93a386Sopenharmony_civoid GrUniformDataManager::set2iv(UniformHandle u,
134cb93a386Sopenharmony_ci                                  int arrayCount,
135cb93a386Sopenharmony_ci                                  const int32_t v[]) const {
136cb93a386Sopenharmony_ci    this->setv<2, kInt2_GrSLType, kShort2_GrSLType>(u, arrayCount, v);
137cb93a386Sopenharmony_ci}
138cb93a386Sopenharmony_ci
139cb93a386Sopenharmony_civoid GrUniformDataManager::set2f(UniformHandle u, float v0, float v1) const {
140cb93a386Sopenharmony_ci    float v[2] = { v0, v1 };
141cb93a386Sopenharmony_ci    this->set<2, kFloat2_GrSLType, kHalf2_GrSLType>(u, v);
142cb93a386Sopenharmony_ci}
143cb93a386Sopenharmony_ci
144cb93a386Sopenharmony_civoid GrUniformDataManager::set2fv(UniformHandle u,
145cb93a386Sopenharmony_ci                                  int arrayCount,
146cb93a386Sopenharmony_ci                                  const float v[]) const {
147cb93a386Sopenharmony_ci    this->setv<2, kFloat2_GrSLType, kHalf2_GrSLType>(u, arrayCount, v);
148cb93a386Sopenharmony_ci}
149cb93a386Sopenharmony_ci
150cb93a386Sopenharmony_civoid GrUniformDataManager::set3i(UniformHandle u,
151cb93a386Sopenharmony_ci                                 int32_t i0,
152cb93a386Sopenharmony_ci                                 int32_t i1,
153cb93a386Sopenharmony_ci                                 int32_t i2) const {
154cb93a386Sopenharmony_ci    int32_t v[3] = { i0, i1, i2 };
155cb93a386Sopenharmony_ci    this->set<3, kInt3_GrSLType, kShort3_GrSLType>(u, v);
156cb93a386Sopenharmony_ci}
157cb93a386Sopenharmony_ci
158cb93a386Sopenharmony_civoid GrUniformDataManager::set3iv(UniformHandle u,
159cb93a386Sopenharmony_ci                                  int arrayCount,
160cb93a386Sopenharmony_ci                                  const int32_t v[]) const {
161cb93a386Sopenharmony_ci    this->setv<3, kInt3_GrSLType, kShort3_GrSLType>(u, arrayCount, v);
162cb93a386Sopenharmony_ci}
163cb93a386Sopenharmony_ci
164cb93a386Sopenharmony_civoid GrUniformDataManager::set3f(UniformHandle u, float v0, float v1, float v2) const {
165cb93a386Sopenharmony_ci    float v[3] = { v0, v1, v2 };
166cb93a386Sopenharmony_ci    this->set<3, kFloat3_GrSLType, kHalf3_GrSLType>(u, v);
167cb93a386Sopenharmony_ci}
168cb93a386Sopenharmony_ci
169cb93a386Sopenharmony_civoid GrUniformDataManager::set3fv(UniformHandle u,
170cb93a386Sopenharmony_ci                                  int arrayCount,
171cb93a386Sopenharmony_ci                                  const float v[]) const {
172cb93a386Sopenharmony_ci    this->setv<3, kFloat3_GrSLType, kHalf3_GrSLType>(u, arrayCount, v);
173cb93a386Sopenharmony_ci}
174cb93a386Sopenharmony_ci
175cb93a386Sopenharmony_civoid GrUniformDataManager::set4i(UniformHandle u,
176cb93a386Sopenharmony_ci                                 int32_t i0,
177cb93a386Sopenharmony_ci                                 int32_t i1,
178cb93a386Sopenharmony_ci                                 int32_t i2,
179cb93a386Sopenharmony_ci                                 int32_t i3) const {
180cb93a386Sopenharmony_ci    int32_t v[4] = { i0, i1, i2, i3 };
181cb93a386Sopenharmony_ci    this->set<4, kInt4_GrSLType, kShort4_GrSLType>(u, v);
182cb93a386Sopenharmony_ci}
183cb93a386Sopenharmony_ci
184cb93a386Sopenharmony_civoid GrUniformDataManager::set4iv(UniformHandle u,
185cb93a386Sopenharmony_ci                                  int arrayCount,
186cb93a386Sopenharmony_ci                                  const int32_t v[]) const {
187cb93a386Sopenharmony_ci    this->setv<4, kInt4_GrSLType, kShort4_GrSLType>(u, arrayCount, v);
188cb93a386Sopenharmony_ci}
189cb93a386Sopenharmony_ci
190cb93a386Sopenharmony_civoid GrUniformDataManager::set4f(UniformHandle u,
191cb93a386Sopenharmony_ci                                 float v0,
192cb93a386Sopenharmony_ci                                 float v1,
193cb93a386Sopenharmony_ci                                 float v2,
194cb93a386Sopenharmony_ci                                 float v3) const {
195cb93a386Sopenharmony_ci    float v[4] = { v0, v1, v2, v3 };
196cb93a386Sopenharmony_ci    this->set<4, kFloat4_GrSLType, kHalf4_GrSLType>(u, v);
197cb93a386Sopenharmony_ci}
198cb93a386Sopenharmony_ci
199cb93a386Sopenharmony_civoid GrUniformDataManager::set4fv(UniformHandle u,
200cb93a386Sopenharmony_ci                                  int arrayCount,
201cb93a386Sopenharmony_ci                                  const float v[]) const {
202cb93a386Sopenharmony_ci    this->setv<4, kFloat4_GrSLType, kHalf4_GrSLType>(u, arrayCount, v);
203cb93a386Sopenharmony_ci}
204cb93a386Sopenharmony_ci
205cb93a386Sopenharmony_civoid GrUniformDataManager::setMatrix2f(UniformHandle u, const float matrix[]) const {
206cb93a386Sopenharmony_ci    this->setMatrices<2, kFloat2x2_GrSLType, kHalf2x2_GrSLType>(u, 1, matrix);
207cb93a386Sopenharmony_ci}
208cb93a386Sopenharmony_ci
209cb93a386Sopenharmony_civoid GrUniformDataManager::setMatrix2fv(UniformHandle u, int arrayCount, const float m[]) const {
210cb93a386Sopenharmony_ci    this->setMatrices<2, kFloat2x2_GrSLType, kHalf2x2_GrSLType>(u, arrayCount, m);
211cb93a386Sopenharmony_ci}
212cb93a386Sopenharmony_ci
213cb93a386Sopenharmony_civoid GrUniformDataManager::setMatrix3f(UniformHandle u, const float matrix[]) const {
214cb93a386Sopenharmony_ci    this->setMatrices<3, kFloat3x3_GrSLType, kHalf3x3_GrSLType>(u, 1, matrix);
215cb93a386Sopenharmony_ci}
216cb93a386Sopenharmony_ci
217cb93a386Sopenharmony_civoid GrUniformDataManager::setMatrix3fv(UniformHandle u, int arrayCount, const float m[]) const {
218cb93a386Sopenharmony_ci    this->setMatrices<3, kFloat3x3_GrSLType, kHalf3x3_GrSLType>(u, arrayCount, m);
219cb93a386Sopenharmony_ci}
220cb93a386Sopenharmony_ci
221cb93a386Sopenharmony_civoid GrUniformDataManager::setMatrix4f(UniformHandle u, const float matrix[]) const {
222cb93a386Sopenharmony_ci    this->setMatrices<4, kFloat4x4_GrSLType, kHalf4x4_GrSLType>(u, 1, matrix);
223cb93a386Sopenharmony_ci}
224cb93a386Sopenharmony_ci
225cb93a386Sopenharmony_civoid GrUniformDataManager::setMatrix4fv(UniformHandle u, int arrayCount, const float m[]) const {
226cb93a386Sopenharmony_ci    this->setMatrices<4, kFloat4x4_GrSLType, kHalf4x4_GrSLType>(u, arrayCount, m);
227cb93a386Sopenharmony_ci}
228cb93a386Sopenharmony_ci
229cb93a386Sopenharmony_citemplate <int N, GrSLType FullType, GrSLType HalfType>
230cb93a386Sopenharmony_ciinline void GrUniformDataManager::setMatrices(UniformHandle u,
231cb93a386Sopenharmony_ci                                              int arrayCount,
232cb93a386Sopenharmony_ci                                              const float matrices[]) const {
233cb93a386Sopenharmony_ci    const Uniform& uni = fUniforms[u.toIndex()];
234cb93a386Sopenharmony_ci    SkASSERT(uni.fType == FullType || uni.fType == HalfType);
235cb93a386Sopenharmony_ci    SkASSERT(arrayCount > 0);
236cb93a386Sopenharmony_ci    SkASSERT(arrayCount <= uni.fArrayCount ||
237cb93a386Sopenharmony_ci             (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount));
238cb93a386Sopenharmony_ci
239cb93a386Sopenharmony_ci    void* buffer = this->getBufferPtrAndMarkDirty(uni);
240cb93a386Sopenharmony_ci    if constexpr (N == 4) {
241cb93a386Sopenharmony_ci        this->copyUniforms(buffer, matrices, arrayCount * 16, uni.fType);
242cb93a386Sopenharmony_ci    } else {
243cb93a386Sopenharmony_ci        for (int i = 0; i < arrayCount; ++i) {
244cb93a386Sopenharmony_ci            const float* matrix = &matrices[N * N * i];
245cb93a386Sopenharmony_ci            for (int j = 0; j < N; ++j) {
246cb93a386Sopenharmony_ci                int uniformSize = this->copyUniforms(buffer, &matrix[j * N], N, uni.fType);
247cb93a386Sopenharmony_ci                buffer = SkTAddOffset<void>(buffer, /*numUniforms*/4 * uniformSize);
248cb93a386Sopenharmony_ci            }
249cb93a386Sopenharmony_ci        }
250cb93a386Sopenharmony_ci    }
251cb93a386Sopenharmony_ci}
252