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