1/*
2* Copyright 2016 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 "GrVkPipelineStateDataManager.h"
9
10#include "GrVkGpu.h"
11#include "GrVkUniformBuffer.h"
12
13GrVkPipelineStateDataManager::GrVkPipelineStateDataManager(const UniformInfoArray& uniforms,
14                                                           uint32_t geometryUniformSize,
15                                                           uint32_t fragmentUniformSize)
16    : fGeometryUniformSize(geometryUniformSize)
17    , fFragmentUniformSize(fragmentUniformSize)
18    , fGeometryUniformsDirty(false)
19    , fFragmentUniformsDirty(false) {
20    fGeometryUniformData.reset(geometryUniformSize);
21    fFragmentUniformData.reset(fragmentUniformSize);
22    int count = uniforms.count();
23    fUniforms.push_back_n(count);
24    // We must add uniforms in same order is the UniformInfoArray so that UniformHandles already
25    // owned by other objects will still match up here.
26    for (int i = 0; i < count; i++) {
27        Uniform& uniform = fUniforms[i];
28        const GrVkUniformHandler::UniformInfo uniformInfo = uniforms[i];
29        SkASSERT(GrShaderVar::kNonArray == uniformInfo.fVariable.getArrayCount() ||
30                 uniformInfo.fVariable.getArrayCount() > 0);
31        SkDEBUGCODE(
32            uniform.fArrayCount = uniformInfo.fVariable.getArrayCount();
33            uniform.fType = uniformInfo.fVariable.getType();
34        );
35
36        if (!(kFragment_GrShaderFlag & uniformInfo.fVisibility)) {
37            uniform.fBinding = GrVkUniformHandler::kGeometryBinding;
38        } else {
39            SkASSERT(kFragment_GrShaderFlag == uniformInfo.fVisibility);
40            uniform.fBinding = GrVkUniformHandler::kFragBinding;
41        }
42        uniform.fOffset = uniformInfo.fUBOffset;
43    }
44}
45
46void* GrVkPipelineStateDataManager::getBufferPtrAndMarkDirty(const Uniform& uni) const {
47    void* buffer;
48    if (GrVkUniformHandler::kGeometryBinding == uni.fBinding) {
49        buffer = fGeometryUniformData.get();
50        fGeometryUniformsDirty = true;
51    } else {
52        SkASSERT(GrVkUniformHandler::kFragBinding == uni.fBinding);
53        buffer = fFragmentUniformData.get();
54        fFragmentUniformsDirty = true;
55    }
56    buffer = static_cast<char*>(buffer)+uni.fOffset;
57    return buffer;
58}
59
60void GrVkPipelineStateDataManager::set1i(UniformHandle u, int32_t i) const {
61    const Uniform& uni = fUniforms[u.toIndex()];
62    SkASSERT(uni.fType == kInt_GrSLType || uni.fType == kShort_GrSLType);
63    SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
64    void* buffer = this->getBufferPtrAndMarkDirty(uni);
65    memcpy(buffer, &i, sizeof(int32_t));
66}
67
68void GrVkPipelineStateDataManager::set1iv(UniformHandle u,
69                                          int arrayCount,
70                                          const int32_t v[]) const {
71    const Uniform& uni = fUniforms[u.toIndex()];
72    SkASSERT(uni.fType == kInt_GrSLType || uni.fType == kShort_GrSLType);
73    SkASSERT(arrayCount > 0);
74    SkASSERT(arrayCount <= uni.fArrayCount ||
75             (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount));
76
77    void* buffer = this->getBufferPtrAndMarkDirty(uni);
78    SkASSERT(sizeof(int32_t) == 4);
79    for (int i = 0; i < arrayCount; ++i) {
80        const int32_t* curVec = &v[i];
81        memcpy(buffer, curVec, sizeof(int32_t));
82        buffer = static_cast<char*>(buffer) + 4*sizeof(int32_t);
83    }
84}
85
86void GrVkPipelineStateDataManager::set1f(UniformHandle u, float v0) const {
87    const Uniform& uni = fUniforms[u.toIndex()];
88    SkASSERT(uni.fType == kFloat_GrSLType || uni.fType == kHalf_GrSLType);
89    SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
90    void* buffer = this->getBufferPtrAndMarkDirty(uni);
91    SkASSERT(sizeof(float) == 4);
92    memcpy(buffer, &v0, sizeof(float));
93}
94
95void GrVkPipelineStateDataManager::set1fv(UniformHandle u,
96                                          int arrayCount,
97                                          const float v[]) const {
98    const Uniform& uni = fUniforms[u.toIndex()];
99    SkASSERT(uni.fType == kFloat_GrSLType || uni.fType == kHalf_GrSLType);
100    SkASSERT(arrayCount > 0);
101    SkASSERT(arrayCount <= uni.fArrayCount ||
102             (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount));
103
104    void* buffer = this->getBufferPtrAndMarkDirty(uni);
105    SkASSERT(sizeof(float) == 4);
106    for (int i = 0; i < arrayCount; ++i) {
107        const float* curVec = &v[i];
108        memcpy(buffer, curVec, sizeof(float));
109        buffer = static_cast<char*>(buffer) + 4*sizeof(float);
110    }
111}
112
113void GrVkPipelineStateDataManager::set2f(UniformHandle u, float v0, float v1) const {
114    const Uniform& uni = fUniforms[u.toIndex()];
115    SkASSERT(uni.fType == kFloat2_GrSLType || uni.fType == kHalf2_GrSLType);
116    SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
117    void* buffer = this->getBufferPtrAndMarkDirty(uni);
118    SkASSERT(sizeof(float) == 4);
119    float v[2] = { v0, v1 };
120    memcpy(buffer, v, 2 * sizeof(float));
121}
122
123void GrVkPipelineStateDataManager::set2fv(UniformHandle u,
124                                          int arrayCount,
125                                          const float v[]) const {
126    const Uniform& uni = fUniforms[u.toIndex()];
127    SkASSERT(uni.fType == kFloat2_GrSLType || uni.fType == kHalf2_GrSLType);
128    SkASSERT(arrayCount > 0);
129    SkASSERT(arrayCount <= uni.fArrayCount ||
130             (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount));
131
132    void* buffer = this->getBufferPtrAndMarkDirty(uni);
133    SkASSERT(sizeof(float) == 4);
134    for (int i = 0; i < arrayCount; ++i) {
135        const float* curVec = &v[2 * i];
136        memcpy(buffer, curVec, 2 * sizeof(float));
137        buffer = static_cast<char*>(buffer) + 4*sizeof(float);
138    }
139}
140
141void GrVkPipelineStateDataManager::set3f(UniformHandle u, float v0, float v1, float v2) const {
142    const Uniform& uni = fUniforms[u.toIndex()];
143    SkASSERT(uni.fType == kFloat3_GrSLType || uni.fType == kHalf3_GrSLType);
144    SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
145    void* buffer = this->getBufferPtrAndMarkDirty(uni);
146    SkASSERT(sizeof(float) == 4);
147    float v[3] = { v0, v1, v2 };
148    memcpy(buffer, v, 3 * sizeof(float));
149}
150
151void GrVkPipelineStateDataManager::set3fv(UniformHandle u,
152                                          int arrayCount,
153                                          const float v[]) const {
154    const Uniform& uni = fUniforms[u.toIndex()];
155    SkASSERT(uni.fType == kFloat3_GrSLType || uni.fType == kHalf3_GrSLType);
156    SkASSERT(arrayCount > 0);
157    SkASSERT(arrayCount <= uni.fArrayCount ||
158             (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount));
159
160    void* buffer = this->getBufferPtrAndMarkDirty(uni);
161    SkASSERT(sizeof(float) == 4);
162    for (int i = 0; i < arrayCount; ++i) {
163        const float* curVec = &v[3 * i];
164        memcpy(buffer, curVec, 3 * sizeof(float));
165        buffer = static_cast<char*>(buffer) + 4*sizeof(float);
166    }
167}
168
169void GrVkPipelineStateDataManager::set4f(UniformHandle u,
170                                         float v0,
171                                         float v1,
172                                         float v2,
173                                         float v3) const {
174    const Uniform& uni = fUniforms[u.toIndex()];
175    SkASSERT(uni.fType == kFloat4_GrSLType || uni.fType == kHalf4_GrSLType);
176    SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
177    void* buffer = this->getBufferPtrAndMarkDirty(uni);
178    SkASSERT(sizeof(float) == 4);
179    float v[4] = { v0, v1, v2, v3 };
180    memcpy(buffer, v, 4 * sizeof(float));
181}
182
183void GrVkPipelineStateDataManager::set4fv(UniformHandle u,
184                                          int arrayCount,
185                                          const float v[]) const {
186    const Uniform& uni = fUniforms[u.toIndex()];
187    SkASSERT(uni.fType == kFloat4_GrSLType || uni.fType == kHalf4_GrSLType);
188    SkASSERT(arrayCount > 0);
189    SkASSERT(arrayCount <= uni.fArrayCount ||
190             (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount));
191
192    void* buffer = this->getBufferPtrAndMarkDirty(uni);
193    SkASSERT(sizeof(float) == 4);
194    memcpy(buffer, v, arrayCount * 4 * sizeof(float));
195}
196
197void GrVkPipelineStateDataManager::setMatrix2f(UniformHandle u, const float matrix[]) const {
198    this->setMatrices<2>(u, 1, matrix);
199}
200
201void GrVkPipelineStateDataManager::setMatrix2fv(UniformHandle u,
202                                                int arrayCount,
203                                                const float m[]) const {
204    this->setMatrices<2>(u, arrayCount, m);
205}
206
207void GrVkPipelineStateDataManager::setMatrix3f(UniformHandle u, const float matrix[]) const {
208    this->setMatrices<3>(u, 1, matrix);
209}
210
211void GrVkPipelineStateDataManager::setMatrix3fv(UniformHandle u,
212                                                int arrayCount,
213                                                const float m[]) const {
214    this->setMatrices<3>(u, arrayCount, m);
215}
216
217void GrVkPipelineStateDataManager::setMatrix4f(UniformHandle u, const float matrix[]) const {
218    this->setMatrices<4>(u, 1, matrix);
219}
220
221void GrVkPipelineStateDataManager::setMatrix4fv(UniformHandle u,
222                                                int arrayCount,
223                                                const float m[]) const {
224    this->setMatrices<4>(u, arrayCount, m);
225}
226
227template<int N> struct set_uniform_matrix;
228
229template<int N> inline void GrVkPipelineStateDataManager::setMatrices(UniformHandle u,
230                                                                      int arrayCount,
231                                                                     const float matrices[]) const {
232    const Uniform& uni = fUniforms[u.toIndex()];
233    SkASSERT(uni.fType == kFloat2x2_GrSLType + (N - 2) ||
234             uni.fType == kHalf2x2_GrSLType + (N - 2));
235    SkASSERT(arrayCount > 0);
236    SkASSERT(arrayCount <= uni.fArrayCount ||
237             (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount));
238
239    void* buffer;
240    if (GrVkUniformHandler::kGeometryBinding == uni.fBinding) {
241        buffer = fGeometryUniformData.get();
242        fGeometryUniformsDirty = true;
243    } else {
244        SkASSERT(GrVkUniformHandler::kFragBinding == uni.fBinding);
245        buffer = fFragmentUniformData.get();
246        fFragmentUniformsDirty = true;
247    }
248
249    set_uniform_matrix<N>::set(buffer, uni.fOffset, arrayCount, matrices);
250}
251
252template<int N> struct set_uniform_matrix {
253    inline static void set(void* buffer, int uniformOffset, int count, const float matrices[]) {
254        GR_STATIC_ASSERT(sizeof(float) == 4);
255        buffer = static_cast<char*>(buffer) + uniformOffset;
256        for (int i = 0; i < count; ++i) {
257            const float* matrix = &matrices[N * N * i];
258            for (int j = 0; j < N; ++j) {
259                memcpy(buffer, &matrix[j * N], N * sizeof(float));
260                buffer = static_cast<char*>(buffer) + 4 * sizeof(float);
261            }
262        }
263    }
264};
265
266template<> struct set_uniform_matrix<4> {
267    inline static void set(void* buffer, int uniformOffset, int count, const float matrices[]) {
268        GR_STATIC_ASSERT(sizeof(float) == 4);
269        buffer = static_cast<char*>(buffer) + uniformOffset;
270        memcpy(buffer, matrices, count * 16 * sizeof(float));
271    }
272};
273
274bool GrVkPipelineStateDataManager::uploadUniformBuffers(GrVkGpu* gpu,
275                                                        GrVkUniformBuffer* geometryBuffer,
276                                                        GrVkUniformBuffer* fragmentBuffer) const {
277    bool updatedBuffer = false;
278    if (geometryBuffer && fGeometryUniformsDirty) {
279        SkAssertResult(geometryBuffer->updateData(gpu, fGeometryUniformData.get(),
280                                                  fGeometryUniformSize, &updatedBuffer));
281        fGeometryUniformsDirty = false;
282    }
283    if (fragmentBuffer && fFragmentUniformsDirty) {
284        SkAssertResult(fragmentBuffer->updateData(gpu, fFragmentUniformData.get(),
285                                                  fFragmentUniformSize, &updatedBuffer));
286        fFragmentUniformsDirty = false;
287    }
288
289    return updatedBuffer;
290}
291