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