1/* 2 * Copyright 2018 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 "GrMtlPipelineStateDataManager.h" 9 10#include "GrMtlBuffer.h" 11#include "GrMtlGpu.h" 12 13GrMtlPipelineStateDataManager::GrMtlPipelineStateDataManager(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 GrMtlUniformHandler::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 = GrMtlUniformHandler::kGeometryBinding; 38 } else { 39 SkASSERT(kFragment_GrShaderFlag == uniformInfo.fVisibility); 40 uniform.fBinding = GrMtlUniformHandler::kFragBinding; 41 } 42 uniform.fOffset = uniformInfo.fUBOffset; 43 } 44} 45 46void* GrMtlPipelineStateDataManager::getBufferPtrAndMarkDirty(const Uniform& uni) const { 47 void* buffer; 48 if (GrMtlUniformHandler::kGeometryBinding == uni.fBinding) { 49 buffer = fGeometryUniformData.get(); 50 fGeometryUniformsDirty = true; 51 } else { 52 SkASSERT(GrMtlUniformHandler::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 GrMtlPipelineStateDataManager::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 GrMtlPipelineStateDataManager::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 GrMtlPipelineStateDataManager::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 GrMtlPipelineStateDataManager::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 GrMtlPipelineStateDataManager::set2i(UniformHandle u, int32_t i0, int32_t i1) const { 114 const Uniform& uni = fUniforms[u.toIndex()]; 115 SkASSERT(uni.fType == kInt2_GrSLType || uni.fType == kShort2_GrSLType); 116 SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount); 117 void* buffer = this->getBufferPtrAndMarkDirty(uni); 118 int32_t v[2] = { i0, i1 }; 119 memcpy(buffer, v, 2 * sizeof(int32_t)); 120} 121 122void GrMtlPipelineStateDataManager::set2iv(UniformHandle u, 123 int arrayCount, 124 const int32_t v[]) const { 125 const Uniform& uni = fUniforms[u.toIndex()]; 126 SkASSERT(uni.fType == kInt2_GrSLType || uni.fType == kShort2_GrSLType); 127 SkASSERT(arrayCount > 0); 128 SkASSERT(arrayCount <= uni.fArrayCount || 129 (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount)); 130 131 void* buffer = this->getBufferPtrAndMarkDirty(uni); 132 SkASSERT(sizeof(int32_t) == 4); 133 for (int i = 0; i < arrayCount; ++i) { 134 const int32_t* curVec = &v[2 * i]; 135 memcpy(buffer, curVec, 2 * sizeof(int32_t)); 136 buffer = static_cast<char*>(buffer) + 4*sizeof(int32_t); 137 } 138} 139 140void GrMtlPipelineStateDataManager::set2f(UniformHandle u, float v0, float v1) const { 141 const Uniform& uni = fUniforms[u.toIndex()]; 142 SkASSERT(uni.fType == kFloat2_GrSLType || uni.fType == kHalf2_GrSLType); 143 SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount); 144 void* buffer = this->getBufferPtrAndMarkDirty(uni); 145 SkASSERT(sizeof(float) == 4); 146 float v[2] = { v0, v1 }; 147 memcpy(buffer, v, 2 * sizeof(float)); 148} 149 150void GrMtlPipelineStateDataManager::set2fv(UniformHandle u, 151 int arrayCount, 152 const float v[]) const { 153 const Uniform& uni = fUniforms[u.toIndex()]; 154 SkASSERT(uni.fType == kFloat2_GrSLType || uni.fType == kHalf2_GrSLType); 155 SkASSERT(arrayCount > 0); 156 SkASSERT(arrayCount <= uni.fArrayCount || 157 (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount)); 158 159 void* buffer = this->getBufferPtrAndMarkDirty(uni); 160 SkASSERT(sizeof(float) == 4); 161 for (int i = 0; i < arrayCount; ++i) { 162 const float* curVec = &v[2 * i]; 163 memcpy(buffer, curVec, 2 * sizeof(float)); 164 buffer = static_cast<char*>(buffer) + 4*sizeof(float); 165 } 166} 167 168void GrMtlPipelineStateDataManager::set3i(UniformHandle u, 169 int32_t i0, 170 int32_t i1, 171 int32_t i2) const { 172 const Uniform& uni = fUniforms[u.toIndex()]; 173 SkASSERT(uni.fType == kInt3_GrSLType || uni.fType == kShort3_GrSLType); 174 SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount); 175 void* buffer = this->getBufferPtrAndMarkDirty(uni); 176 int32_t v[3] = { i0, i1, i2 }; 177 memcpy(buffer, v, 3 * sizeof(int32_t)); 178} 179 180void GrMtlPipelineStateDataManager::set3iv(UniformHandle u, 181 int arrayCount, 182 const int32_t v[]) const { 183 const Uniform& uni = fUniforms[u.toIndex()]; 184 SkASSERT(uni.fType == kInt3_GrSLType || uni.fType == kShort3_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(int32_t) == 4); 191 for (int i = 0; i < arrayCount; ++i) { 192 const int32_t* curVec = &v[3 * i]; 193 memcpy(buffer, curVec, 3 * sizeof(int32_t)); 194 buffer = static_cast<char*>(buffer) + 4*sizeof(int32_t); 195 } 196} 197 198void GrMtlPipelineStateDataManager::set3f(UniformHandle u, float v0, float v1, float v2) const { 199 const Uniform& uni = fUniforms[u.toIndex()]; 200 SkASSERT(uni.fType == kFloat3_GrSLType || uni.fType == kHalf3_GrSLType); 201 SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount); 202 void* buffer = this->getBufferPtrAndMarkDirty(uni); 203 SkASSERT(sizeof(float) == 4); 204 float v[3] = { v0, v1, v2 }; 205 memcpy(buffer, v, 3 * sizeof(float)); 206} 207 208void GrMtlPipelineStateDataManager::set3fv(UniformHandle u, 209 int arrayCount, 210 const float v[]) const { 211 const Uniform& uni = fUniforms[u.toIndex()]; 212 SkASSERT(uni.fType == kFloat3_GrSLType || uni.fType == kHalf3_GrSLType); 213 SkASSERT(arrayCount > 0); 214 SkASSERT(arrayCount <= uni.fArrayCount || 215 (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount)); 216 217 void* buffer = this->getBufferPtrAndMarkDirty(uni); 218 SkASSERT(sizeof(float) == 4); 219 for (int i = 0; i < arrayCount; ++i) { 220 const float* curVec = &v[3 * i]; 221 memcpy(buffer, curVec, 3 * sizeof(float)); 222 buffer = static_cast<char*>(buffer) + 4*sizeof(float); 223 } 224} 225 226void GrMtlPipelineStateDataManager::set4i(UniformHandle u, 227 int32_t i0, 228 int32_t i1, 229 int32_t i2, 230 int32_t i3) const { 231 const Uniform& uni = fUniforms[u.toIndex()]; 232 SkASSERT(uni.fType == kInt4_GrSLType || uni.fType == kShort4_GrSLType); 233 SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount); 234 void* buffer = this->getBufferPtrAndMarkDirty(uni); 235 int32_t v[4] = { i0, i1, i2, i3 }; 236 memcpy(buffer, v, 4 * sizeof(int32_t)); 237} 238 239void GrMtlPipelineStateDataManager::set4iv(UniformHandle u, 240 int arrayCount, 241 const int32_t v[]) const { 242 const Uniform& uni = fUniforms[u.toIndex()]; 243 SkASSERT(uni.fType == kInt4_GrSLType || uni.fType == kShort4_GrSLType); 244 SkASSERT(arrayCount > 0); 245 SkASSERT(arrayCount <= uni.fArrayCount || 246 (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount)); 247 248 void* buffer = this->getBufferPtrAndMarkDirty(uni); 249 SkASSERT(sizeof(int32_t) == 4); 250 for (int i = 0; i < arrayCount; ++i) { 251 const int32_t* curVec = &v[4 * i]; 252 memcpy(buffer, curVec, 4 * sizeof(int32_t)); 253 buffer = static_cast<char*>(buffer) + 4*sizeof(int32_t); 254 } 255} 256 257void GrMtlPipelineStateDataManager::set4f(UniformHandle u, 258 float v0, 259 float v1, 260 float v2, 261 float v3) const { 262 const Uniform& uni = fUniforms[u.toIndex()]; 263 SkASSERT(uni.fType == kFloat4_GrSLType || uni.fType == kHalf4_GrSLType); 264 SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount); 265 void* buffer = this->getBufferPtrAndMarkDirty(uni); 266 SkASSERT(sizeof(float) == 4); 267 float v[4] = { v0, v1, v2, v3 }; 268 memcpy(buffer, v, 4 * sizeof(float)); 269} 270 271void GrMtlPipelineStateDataManager::set4fv(UniformHandle u, 272 int arrayCount, 273 const float v[]) const { 274 const Uniform& uni = fUniforms[u.toIndex()]; 275 SkASSERT(uni.fType == kFloat4_GrSLType || uni.fType == kHalf4_GrSLType); 276 SkASSERT(arrayCount > 0); 277 SkASSERT(arrayCount <= uni.fArrayCount || 278 (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount)); 279 280 void* buffer = this->getBufferPtrAndMarkDirty(uni); 281 SkASSERT(sizeof(float) == 4); 282 memcpy(buffer, v, arrayCount * 4 * sizeof(float)); 283} 284 285void GrMtlPipelineStateDataManager::setMatrix2f(UniformHandle u, const float matrix[]) const { 286 this->setMatrices<2>(u, 1, matrix); 287} 288 289void GrMtlPipelineStateDataManager::setMatrix2fv(UniformHandle u, 290 int arrayCount, 291 const float m[]) const { 292 this->setMatrices<2>(u, arrayCount, m); 293} 294 295void GrMtlPipelineStateDataManager::setMatrix3f(UniformHandle u, const float matrix[]) const { 296 this->setMatrices<3>(u, 1, matrix); 297} 298 299void GrMtlPipelineStateDataManager::setMatrix3fv(UniformHandle u, 300 int arrayCount, 301 const float m[]) const { 302 this->setMatrices<3>(u, arrayCount, m); 303} 304 305void GrMtlPipelineStateDataManager::setMatrix4f(UniformHandle u, const float matrix[]) const { 306 this->setMatrices<4>(u, 1, matrix); 307} 308 309void GrMtlPipelineStateDataManager::setMatrix4fv(UniformHandle u, 310 int arrayCount, 311 const float m[]) const { 312 this->setMatrices<4>(u, arrayCount, m); 313} 314 315template<int N> struct set_uniform_matrix; 316 317template<int N> inline void GrMtlPipelineStateDataManager::setMatrices( 318 UniformHandle u, 319 int arrayCount, 320 const float matrices[]) const { 321 const Uniform& uni = fUniforms[u.toIndex()]; 322 SkASSERT(uni.fType == kFloat2x2_GrSLType + (N - 2) || 323 uni.fType == kHalf2x2_GrSLType + (N - 2)); 324 SkASSERT(arrayCount > 0); 325 SkASSERT(arrayCount <= uni.fArrayCount || 326 (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount)); 327 328 void* buffer; 329 if (GrMtlUniformHandler::kGeometryBinding == uni.fBinding) { 330 buffer = fGeometryUniformData.get(); 331 fGeometryUniformsDirty = true; 332 } else { 333 SkASSERT(GrMtlUniformHandler::kFragBinding == uni.fBinding); 334 buffer = fFragmentUniformData.get(); 335 fFragmentUniformsDirty = true; 336 } 337 338 set_uniform_matrix<N>::set(buffer, uni.fOffset, arrayCount, matrices); 339} 340 341template<int N> struct set_uniform_matrix { 342 inline static void set(void* buffer, int uniformOffset, int count, const float matrices[]) { 343 GR_STATIC_ASSERT(sizeof(float) == 4); 344 buffer = static_cast<char*>(buffer) + uniformOffset; 345 for (int i = 0; i < count; ++i) { 346 const float* matrix = &matrices[N * N * i]; 347 for (int j = 0; j < N; ++j) { 348 memcpy(buffer, &matrix[j * N], N * sizeof(float)); 349 buffer = static_cast<char*>(buffer) + 4 * sizeof(float); 350 } 351 } 352 } 353}; 354 355template<> struct set_uniform_matrix<4> { 356 inline static void set(void* buffer, int uniformOffset, int count, const float matrices[]) { 357 GR_STATIC_ASSERT(sizeof(float) == 4); 358 buffer = static_cast<char*>(buffer) + uniformOffset; 359 memcpy(buffer, matrices, count * 16 * sizeof(float)); 360 } 361}; 362 363void GrMtlPipelineStateDataManager::uploadUniformBuffers(GrMtlGpu* gpu, 364 GrMtlBuffer* geometryBuffer, 365 GrMtlBuffer* fragmentBuffer) const { 366 if (geometryBuffer && fGeometryUniformsDirty) { 367 SkAssertResult(geometryBuffer->updateData(fGeometryUniformData.get(), 368 fGeometryUniformSize)); 369 fGeometryUniformsDirty = false; 370 } 371 if (fragmentBuffer && fFragmentUniformsDirty) { 372 SkAssertResult(fragmentBuffer->updateData(fFragmentUniformData.get(), 373 fFragmentUniformSize)); 374 fFragmentUniformsDirty = false; 375 } 376} 377