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 "src/gpu/mtl/GrMtlPipelineStateDataManager.h" 9 10#include "src/gpu/mtl/GrMtlBuffer.h" 11#include "src/gpu/mtl/GrMtlGpu.h" 12 13#if !__has_feature(objc_arc) 14#error This file must be compiled with Arc. Use -fobjc-arc flag 15#endif 16 17GrMtlPipelineStateDataManager::GrMtlPipelineStateDataManager(const UniformInfoArray& uniforms, 18 uint32_t uniformSize) 19 : fUniformSize(uniformSize) 20 , fUniformsDirty(false) { 21 fUniformData.reset(uniformSize); 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 uniform.fOffset = uniformInfo.fUBOffset; 36 } 37} 38 39void* GrMtlPipelineStateDataManager::getBufferPtrAndMarkDirty(const Uniform& uni) const { 40 fUniformsDirty = true; 41 return static_cast<char*>(fUniformData.get())+uni.fOffset; 42} 43 44void GrMtlPipelineStateDataManager::set1i(UniformHandle u, int32_t i) const { 45 const Uniform& uni = fUniforms[u.toIndex()]; 46 SkASSERT(uni.fType == kInt_GrSLType || uni.fType == kShort_GrSLType); 47 SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount); 48 void* buffer = this->getBufferPtrAndMarkDirty(uni); 49 memcpy(buffer, &i, sizeof(int32_t)); 50} 51 52void GrMtlPipelineStateDataManager::set1iv(UniformHandle u, 53 int arrayCount, 54 const int32_t v[]) const { 55 const Uniform& uni = fUniforms[u.toIndex()]; 56 SkASSERT(uni.fType == kInt_GrSLType || uni.fType == kShort_GrSLType); 57 SkASSERT(arrayCount > 0); 58 SkASSERT(arrayCount <= uni.fArrayCount || 59 (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount)); 60 61 void* buffer = this->getBufferPtrAndMarkDirty(uni); 62 SkASSERT(sizeof(int32_t) == 4); 63 for (int i = 0; i < arrayCount; ++i) { 64 const int32_t* curVec = &v[i]; 65 memcpy(buffer, curVec, sizeof(int32_t)); 66 buffer = static_cast<char*>(buffer) + 4*sizeof(int32_t); 67 } 68} 69 70void GrMtlPipelineStateDataManager::set1f(UniformHandle u, float v0) const { 71 const Uniform& uni = fUniforms[u.toIndex()]; 72 SkASSERT(uni.fType == kFloat_GrSLType || uni.fType == kHalf_GrSLType); 73 SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount); 74 void* buffer = this->getBufferPtrAndMarkDirty(uni); 75 SkASSERT(sizeof(float) == 4); 76 memcpy(buffer, &v0, sizeof(float)); 77} 78 79void GrMtlPipelineStateDataManager::set1fv(UniformHandle u, 80 int arrayCount, 81 const float v[]) const { 82 const Uniform& uni = fUniforms[u.toIndex()]; 83 SkASSERT(uni.fType == kFloat_GrSLType || uni.fType == kHalf_GrSLType); 84 SkASSERT(arrayCount > 0); 85 SkASSERT(arrayCount <= uni.fArrayCount || 86 (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount)); 87 88 void* buffer = this->getBufferPtrAndMarkDirty(uni); 89 SkASSERT(sizeof(float) == 4); 90 memcpy(buffer, v, arrayCount * sizeof(float)); 91} 92 93void GrMtlPipelineStateDataManager::set2i(UniformHandle u, int32_t i0, int32_t i1) const { 94 const Uniform& uni = fUniforms[u.toIndex()]; 95 SkASSERT(uni.fType == kInt2_GrSLType || uni.fType == kShort2_GrSLType); 96 SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount); 97 void* buffer = this->getBufferPtrAndMarkDirty(uni); 98 int32_t v[2] = { i0, i1 }; 99 memcpy(buffer, v, 2 * sizeof(int32_t)); 100} 101 102void GrMtlPipelineStateDataManager::set2iv(UniformHandle u, 103 int arrayCount, 104 const int32_t v[]) const { 105 const Uniform& uni = fUniforms[u.toIndex()]; 106 SkASSERT(uni.fType == kInt2_GrSLType || uni.fType == kShort2_GrSLType); 107 SkASSERT(arrayCount > 0); 108 SkASSERT(arrayCount <= uni.fArrayCount || 109 (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount)); 110 111 void* buffer = this->getBufferPtrAndMarkDirty(uni); 112 SkASSERT(sizeof(int32_t) == 4); 113 memcpy(buffer, v, arrayCount*sizeof(int32_t)); 114} 115 116void GrMtlPipelineStateDataManager::set2f(UniformHandle u, float v0, float v1) const { 117 const Uniform& uni = fUniforms[u.toIndex()]; 118 SkASSERT(uni.fType == kFloat2_GrSLType || uni.fType == kHalf2_GrSLType); 119 SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount); 120 void* buffer = this->getBufferPtrAndMarkDirty(uni); 121 SkASSERT(sizeof(float) == 4); 122 float v[2] = { v0, v1 }; 123 memcpy(buffer, v, 2 * sizeof(float)); 124} 125 126void GrMtlPipelineStateDataManager::set2fv(UniformHandle u, 127 int arrayCount, 128 const float v[]) const { 129 const Uniform& uni = fUniforms[u.toIndex()]; 130 SkASSERT(uni.fType == kFloat2_GrSLType || uni.fType == kHalf2_GrSLType); 131 SkASSERT(arrayCount > 0); 132 SkASSERT(arrayCount <= uni.fArrayCount || 133 (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount)); 134 135 void* buffer = this->getBufferPtrAndMarkDirty(uni); 136 SkASSERT(sizeof(float) == 4); 137 memcpy(buffer, v, arrayCount * 2 * sizeof(float)); 138} 139 140void GrMtlPipelineStateDataManager::set3i(UniformHandle u, 141 int32_t i0, 142 int32_t i1, 143 int32_t i2) const { 144 const Uniform& uni = fUniforms[u.toIndex()]; 145 SkASSERT(uni.fType == kInt3_GrSLType || uni.fType == kShort3_GrSLType); 146 SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount); 147 void* buffer = this->getBufferPtrAndMarkDirty(uni); 148 int32_t v[3] = { i0, i1, i2 }; 149 memcpy(buffer, v, 3 * sizeof(int32_t)); 150} 151 152void GrMtlPipelineStateDataManager::set3iv(UniformHandle u, 153 int arrayCount, 154 const int32_t v[]) const { 155 const Uniform& uni = fUniforms[u.toIndex()]; 156 SkASSERT(uni.fType == kInt3_GrSLType || uni.fType == kShort3_GrSLType); 157 SkASSERT(arrayCount > 0); 158 SkASSERT(arrayCount <= uni.fArrayCount || 159 (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount)); 160 161 void* buffer = this->getBufferPtrAndMarkDirty(uni); 162 SkASSERT(sizeof(int32_t) == 4); 163 for (int i = 0; i < arrayCount; ++i) { 164 const int32_t* curVec = &v[3 * i]; 165 memcpy(buffer, curVec, 3 * sizeof(int32_t)); 166 buffer = static_cast<char*>(buffer) + 4*sizeof(int32_t); 167 } 168} 169 170void GrMtlPipelineStateDataManager::set3f(UniformHandle u, float v0, float v1, float v2) const { 171 const Uniform& uni = fUniforms[u.toIndex()]; 172 SkASSERT(uni.fType == kFloat3_GrSLType || uni.fType == kHalf3_GrSLType); 173 SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount); 174 void* buffer = this->getBufferPtrAndMarkDirty(uni); 175 SkASSERT(sizeof(float) == 4); 176 float v[3] = { v0, v1, v2 }; 177 memcpy(buffer, v, 3 * sizeof(float)); 178} 179 180void GrMtlPipelineStateDataManager::set3fv(UniformHandle u, 181 int arrayCount, 182 const float v[]) const { 183 const Uniform& uni = fUniforms[u.toIndex()]; 184 SkASSERT(uni.fType == kFloat3_GrSLType || uni.fType == kHalf3_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 for (int i = 0; i < arrayCount; ++i) { 192 const float* curVec = &v[3 * i]; 193 memcpy(buffer, curVec, 3 * sizeof(float)); 194 buffer = static_cast<char*>(buffer) + 4*sizeof(float); 195 } 196} 197 198void GrMtlPipelineStateDataManager::set4i(UniformHandle u, 199 int32_t i0, 200 int32_t i1, 201 int32_t i2, 202 int32_t i3) const { 203 const Uniform& uni = fUniforms[u.toIndex()]; 204 SkASSERT(uni.fType == kInt4_GrSLType || uni.fType == kShort4_GrSLType); 205 SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount); 206 void* buffer = this->getBufferPtrAndMarkDirty(uni); 207 int32_t v[4] = { i0, i1, i2, i3 }; 208 memcpy(buffer, v, 4 * sizeof(int32_t)); 209} 210 211void GrMtlPipelineStateDataManager::set4iv(UniformHandle u, 212 int arrayCount, 213 const int32_t v[]) const { 214 const Uniform& uni = fUniforms[u.toIndex()]; 215 SkASSERT(uni.fType == kInt4_GrSLType || uni.fType == kShort4_GrSLType); 216 SkASSERT(arrayCount > 0); 217 SkASSERT(arrayCount <= uni.fArrayCount || 218 (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount)); 219 220 void* buffer = this->getBufferPtrAndMarkDirty(uni); 221 SkASSERT(sizeof(int32_t) == 4); 222 memcpy(buffer, v, arrayCount * 4 * sizeof(int32_t)); 223} 224 225void GrMtlPipelineStateDataManager::set4f(UniformHandle u, 226 float v0, 227 float v1, 228 float v2, 229 float v3) const { 230 const Uniform& uni = fUniforms[u.toIndex()]; 231 SkASSERT(uni.fType == kFloat4_GrSLType || uni.fType == kHalf4_GrSLType); 232 SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount); 233 void* buffer = this->getBufferPtrAndMarkDirty(uni); 234 SkASSERT(sizeof(float) == 4); 235 float v[4] = { v0, v1, v2, v3 }; 236 memcpy(buffer, v, 4 * sizeof(float)); 237} 238 239void GrMtlPipelineStateDataManager::set4fv(UniformHandle u, 240 int arrayCount, 241 const float v[]) const { 242 const Uniform& uni = fUniforms[u.toIndex()]; 243 SkASSERT(uni.fType == kFloat4_GrSLType || uni.fType == kHalf4_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(float) == 4); 250 memcpy(buffer, v, arrayCount * 4 * sizeof(float)); 251} 252 253void GrMtlPipelineStateDataManager::setMatrix2f(UniformHandle u, const float matrix[]) const { 254 this->setMatrices<2>(u, 1, matrix); 255} 256 257void GrMtlPipelineStateDataManager::setMatrix2fv(UniformHandle u, 258 int arrayCount, 259 const float m[]) const { 260 this->setMatrices<2>(u, arrayCount, m); 261} 262 263void GrMtlPipelineStateDataManager::setMatrix3f(UniformHandle u, const float matrix[]) const { 264 this->setMatrices<3>(u, 1, matrix); 265} 266 267void GrMtlPipelineStateDataManager::setMatrix3fv(UniformHandle u, 268 int arrayCount, 269 const float m[]) const { 270 this->setMatrices<3>(u, arrayCount, m); 271} 272 273void GrMtlPipelineStateDataManager::setMatrix4f(UniformHandle u, const float matrix[]) const { 274 this->setMatrices<4>(u, 1, matrix); 275} 276 277void GrMtlPipelineStateDataManager::setMatrix4fv(UniformHandle u, 278 int arrayCount, 279 const float m[]) const { 280 this->setMatrices<4>(u, arrayCount, m); 281} 282 283template<int N> struct set_uniform_matrix; 284 285template<int N> inline void GrMtlPipelineStateDataManager::setMatrices( 286 UniformHandle u, 287 int arrayCount, 288 const float matrices[]) const { 289 const Uniform& uni = fUniforms[u.toIndex()]; 290 SkASSERT(uni.fType == kFloat2x2_GrSLType + (N - 2) || 291 uni.fType == kHalf2x2_GrSLType + (N - 2)); 292 SkASSERT(arrayCount > 0); 293 SkASSERT(arrayCount <= uni.fArrayCount || 294 (1 == arrayCount && GrShaderVar::kNonArray == uni.fArrayCount)); 295 296 fUniformsDirty = true; 297 set_uniform_matrix<N>::set(fUniformData.get(), uni.fOffset, arrayCount, matrices); 298} 299 300template<> struct set_uniform_matrix<2> { 301 inline static void set(void* buffer, int uniformOffset, int count, const float matrices[]) { 302 GR_STATIC_ASSERT(sizeof(float) == 4); 303 buffer = static_cast<char*>(buffer) + uniformOffset; 304 memcpy(buffer, matrices, count * 4 * sizeof(float)); 305 } 306}; 307 308template<> struct set_uniform_matrix<3> { 309 inline static void set(void* buffer, int uniformOffset, int count, const float matrices[]) { 310 GR_STATIC_ASSERT(sizeof(float) == 4); 311 buffer = static_cast<char*>(buffer) + uniformOffset; 312 for (int i = 0; i < count; ++i) { 313 const float* matrix = &matrices[3 * 3 * i]; 314 for (int j = 0; j < 3; ++j) { 315 memcpy(buffer, &matrix[j * 3], 3 * sizeof(float)); 316 buffer = static_cast<char*>(buffer) + 4 * sizeof(float); 317 } 318 } 319 } 320}; 321 322template<> struct set_uniform_matrix<4> { 323 inline static void set(void* buffer, int uniformOffset, int count, const float matrices[]) { 324 GR_STATIC_ASSERT(sizeof(float) == 4); 325 buffer = static_cast<char*>(buffer) + uniformOffset; 326 memcpy(buffer, matrices, count * 16 * sizeof(float)); 327 } 328}; 329 330void GrMtlPipelineStateDataManager::uploadAndBindUniformBuffers( 331 GrMtlGpu* gpu, 332 id<MTLRenderCommandEncoder> renderCmdEncoder) const { 333 if (fUniformSize && fUniformsDirty) { 334 SkASSERT(fUniformSize < 4*1024); 335 [renderCmdEncoder setVertexBytes: fUniformData.get() 336 length: fUniformSize 337 atIndex: GrMtlUniformHandler::kUniformBinding]; 338 [renderCmdEncoder setFragmentBytes: fUniformData.get() 339 length: fUniformSize 340 atIndex: GrMtlUniformHandler::kUniformBinding]; 341 fUniformsDirty = false; 342 } 343} 344 345void GrMtlPipelineStateDataManager::resetDirtyBits() { 346 fUniformsDirty = true; 347} 348