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 "GrSkSLFP.h" 9 10 #include "GrBaseContextPriv.h" 11 #include "GrContext_Base.h" 12 #include "GrTexture.h" 13 #include "SkSLUtil.h" 14 15 #include "glsl/GrGLSLFragmentProcessor.h" 16 #include "glsl/GrGLSLFragmentShaderBuilder.h" 17 #include "glsl/GrGLSLProgramBuilder.h" 18 19 GrSkSLFPFactory::GrSkSLFPFactory(const char* name, const GrShaderCaps* shaderCaps, const char* sksl) 20 : fName(name) { 21 SkSL::Program::Settings settings; 22 settings.fCaps = shaderCaps; 23 fBaseProgram = fCompiler.convertProgram(SkSL::Program::kPipelineStage_Kind, 24 SkSL::String(sksl), 25 settings); 26 if (fCompiler.errorCount()) { 27 SkDebugf("%s\n", fCompiler.errorText().c_str()); 28 } 29 SkASSERT(fBaseProgram); 30 SkASSERT(!fCompiler.errorCount()); 31 for (const auto& e : *fBaseProgram) { 32 if (e.fKind == SkSL::ProgramElement::kVar_Kind) { 33 SkSL::VarDeclarations& v = (SkSL::VarDeclarations&) e; 34 for (const auto& varStatement : v.fVars) { 35 const SkSL::Variable& var = *((SkSL::VarDeclaration&) *varStatement).fVar; 36 if (var.fModifiers.fFlags & SkSL::Modifiers::kIn_Flag) { 37 fInputVars.push_back(&var); 38 } 39 if (var.fModifiers.fLayout.fKey) { 40 fKeyVars.push_back(&var); 41 } 42 } 43 } 44 } 45 } 46 47 const SkSL::Program* GrSkSLFPFactory::getSpecialization(const SkSL::String& key, const void* inputs, 48 size_t inputSize) { 49 const auto& found = fSpecializations.find(key); 50 if (found != fSpecializations.end()) { 51 return found->second.get(); 52 } 53 54 std::unordered_map<SkSL::String, SkSL::Program::Settings::Value> inputMap; 55 size_t offset = 0; 56 for (const auto& v : fInputVars) { 57 SkSL::String name(v->fName); 58 if (&v->fType == fCompiler.context().fInt_Type.get()) { 59 offset = SkAlign4(offset); 60 int32_t v = *(int32_t*) (((uint8_t*) inputs) + offset); 61 inputMap.insert(std::make_pair(name, SkSL::Program::Settings::Value(v))); 62 offset += sizeof(int32_t); 63 } else if (&v->fType == fCompiler.context().fFloat_Type.get()) { 64 offset = SkAlign4(offset); 65 float v = *(float*) (((uint8_t*) inputs) + offset); 66 inputMap.insert(std::make_pair(name, SkSL::Program::Settings::Value(v))); 67 offset += sizeof(float); 68 } else if (&v->fType == fCompiler.context().fBool_Type.get()) { 69 bool v = *(((bool*) inputs) + offset); 70 inputMap.insert(std::make_pair(name, SkSL::Program::Settings::Value(v))); 71 offset += sizeof(bool); 72 } else if (&v->fType == fCompiler.context().fFloat4_Type.get() || 73 &v->fType == fCompiler.context().fHalf4_Type.get()) { 74 offset = SkAlign4(offset) + sizeof(float) * 4; 75 } else if (&v->fType == fCompiler.context().fFragmentProcessor_Type.get()) { 76 // do nothing 77 } else { 78 printf("can't handle input var: %s\n", SkSL::String(v->fType.fName).c_str()); 79 SkASSERT(false); 80 } 81 } 82 83 std::unique_ptr<SkSL::Program> specialized = fCompiler.specialize(*fBaseProgram, inputMap); 84 SkAssertResult(fCompiler.optimize(*specialized)); 85 const SkSL::Program* result = specialized.get(); 86 fSpecializations.insert(std::make_pair(key, std::move(specialized))); 87 return result; 88 } 89 90 class GrGLSLSkSLFP : public GrGLSLFragmentProcessor { 91 public: 92 GrGLSLSkSLFP(const SkSL::Context* context, const std::vector<const SkSL::Variable*>* inputVars, 93 SkSL::String glsl, std::vector<SkSL::Compiler::FormatArg> formatArgs) 94 : fContext(*context) 95 , fInputVars(*inputVars) 96 , fGLSL(glsl) 97 , fFormatArgs(formatArgs) {} 98 99 GrSLType uniformType(const SkSL::Type& type) { 100 if (type == *fContext.fFloat_Type) { 101 return kFloat_GrSLType; 102 } else if (type == *fContext.fHalf_Type) { 103 return kHalf_GrSLType; 104 } else if (type == *fContext.fFloat2_Type) { 105 return kFloat2_GrSLType; 106 } else if (type == *fContext.fHalf2_Type) { 107 return kHalf2_GrSLType; 108 } else if (type == *fContext.fFloat4_Type) { 109 return kFloat4_GrSLType; 110 } else if (type == *fContext.fHalf4_Type) { 111 return kHalf4_GrSLType; 112 } else if (type == *fContext.fFloat4x4_Type) { 113 return kFloat4x4_GrSLType; 114 } else if (type == *fContext.fHalf4x4_Type) { 115 return kHalf4x4_GrSLType; 116 } else if (type == *fContext.fBool_Type) { 117 return kBool_GrSLType; 118 } else if (type == *fContext.fInt_Type) { 119 return kInt_GrSLType; 120 } 121 printf("%s\n", SkSL::String(type.fName).c_str()); 122 SK_ABORT("unsupported uniform type"); 123 return kFloat_GrSLType; 124 } 125 126 void emitCode(EmitArgs& args) override { 127 for (const auto& v : fInputVars) { 128 if (v->fModifiers.fFlags & SkSL::Modifiers::kUniform_Flag && v->fType != 129 *fContext.fFragmentProcessor_Type) { 130 fUniformHandles.push_back(args.fUniformHandler->addUniform( 131 kFragment_GrShaderFlag, 132 this->uniformType(v->fType), 133 SkSL::String(v->fName).c_str())); 134 } 135 } 136 std::vector<SkString> childNames; 137 for (int i = 0; i < this->numChildProcessors(); ++i) { 138 childNames.push_back(SkStringPrintf("_child%d", i)); 139 this->emitChild(i, &childNames[i], args); 140 } 141 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; 142 int substringStartIndex = 0; 143 int formatArgIndex = 0; 144 for (size_t i = 0; i < fGLSL.length(); ++i) { 145 char c = fGLSL[i]; 146 if (c == '%') { 147 fragBuilder->codeAppend(fGLSL.c_str() + substringStartIndex, 148 i - substringStartIndex); 149 ++i; 150 c = fGLSL[i]; 151 switch (c) { 152 case 's': { 153 SkSL::Compiler::FormatArg& arg = fFormatArgs[formatArgIndex++]; 154 switch (arg.fKind) { 155 case SkSL::Compiler::FormatArg::Kind::kInput: 156 fragBuilder->codeAppend(args.fInputColor); 157 break; 158 case SkSL::Compiler::FormatArg::Kind::kOutput: 159 fragBuilder->codeAppend(args.fOutputColor); 160 break; 161 case SkSL::Compiler::FormatArg::Kind::kUniform: 162 fragBuilder->codeAppend(args.fUniformHandler->getUniformCStr( 163 fUniformHandles[arg.fIndex])); 164 break; 165 case SkSL::Compiler::FormatArg::Kind::kChildProcessor: 166 fragBuilder->codeAppend(childNames[arg.fIndex].c_str()); 167 break; 168 } 169 break; 170 } 171 default: 172 fragBuilder->codeAppendf("%c", c); 173 } 174 substringStartIndex = i + 1; 175 } 176 } 177 fragBuilder->codeAppend(fGLSL.c_str() + substringStartIndex, 178 fGLSL.length() - substringStartIndex); 179 } 180 181 void onSetData(const GrGLSLProgramDataManager& pdman, 182 const GrFragmentProcessor& _proc) override { 183 size_t uniformIndex = 0; 184 size_t offset = 0; 185 const GrSkSLFP& outer = _proc.cast<GrSkSLFP>(); 186 char* inputs = (char*) outer.fInputs.get(); 187 const SkSL::Context& context = outer.fFactory->fCompiler.context(); 188 for (const auto& v : outer.fFactory->fInputVars) { 189 if (&v->fType == context.fFloat4_Type.get() || 190 &v->fType == context.fHalf4_Type.get()) { 191 float f1, f2, f3, f4; 192 switch (v->fModifiers.fLayout.fCType) { 193 case SkSL::Layout::CType::kSkPMColor: 194 f1 = ((uint8_t*) inputs)[offset++] / 255.0; 195 f2 = ((uint8_t*) inputs)[offset++] / 255.0; 196 f3 = ((uint8_t*) inputs)[offset++] / 255.0; 197 f4 = ((uint8_t*) inputs)[offset++] / 255.0; 198 break; 199 case SkSL::Layout::CType::kSkRect: // fall through 200 case SkSL::Layout::CType::kDefault: 201 offset = SkAlign4(offset); 202 f1 = *(float*) (inputs + offset); 203 offset += sizeof(float); 204 f2 = *(float*) (inputs + offset); 205 offset += sizeof(float); 206 f3 = *(float*) (inputs + offset); 207 offset += sizeof(float); 208 f4 = *(float*) (inputs + offset); 209 offset += sizeof(float); 210 break; 211 default: 212 SK_ABORT("unsupported uniform ctype"); 213 } 214 if (v->fModifiers.fFlags & SkSL::Modifiers::kUniform_Flag) { 215 pdman.set4f(fUniformHandles[uniformIndex++], f1, f2, f3, f4); 216 } 217 } else if (&v->fType == context.fInt_Type.get()) { 218 int32_t i = *(int32_t*) (inputs + offset); 219 offset += sizeof(int32_t); 220 if (v->fModifiers.fFlags & SkSL::Modifiers::kUniform_Flag) { 221 pdman.set1i(fUniformHandles[uniformIndex++], i); 222 } 223 } else if (&v->fType == context.fFloat_Type.get()) { 224 float f = *(float*) (inputs + offset); 225 offset += sizeof(float); 226 if (v->fModifiers.fFlags & SkSL::Modifiers::kUniform_Flag) { 227 pdman.set1f(fUniformHandles[uniformIndex++], f); 228 } 229 } else if (&v->fType == context.fBool_Type.get()) { 230 SkASSERT(!(v->fModifiers.fFlags & SkSL::Modifiers::kUniform_Flag)); 231 ++offset; 232 } else { 233 SkASSERT(&v->fType == context.fFragmentProcessor_Type.get()); 234 } 235 } 236 } 237 238 const SkSL::Context& fContext; 239 const std::vector<const SkSL::Variable*>& fInputVars; 240 // nearly-finished GLSL; still contains printf-style "%s" format tokens 241 const SkSL::String fGLSL; 242 std::vector<SkSL::Compiler::FormatArg> fFormatArgs; 243 std::vector<UniformHandle> fUniformHandles; 244 }; 245 246 std::unique_ptr<GrSkSLFP> GrSkSLFP::Make(GrContext_Base* context, int index, const char* name, 247 const char* sksl, const void* inputs, 248 size_t inputSize) { 249 return std::unique_ptr<GrSkSLFP>(new GrSkSLFP(context->priv().fpFactoryCache(), 250 context->priv().caps()->shaderCaps(), 251 index, name, sksl, SkString(), inputs, 252 inputSize)); 253 } 254 255 std::unique_ptr<GrSkSLFP> GrSkSLFP::Make(GrContext_Base* context, int index, const char* name, 256 SkString sksl, const void* inputs, size_t inputSize) { 257 return std::unique_ptr<GrSkSLFP>(new GrSkSLFP(context->priv().fpFactoryCache(), 258 context->priv().caps()->shaderCaps(), 259 index, name, nullptr, std::move(sksl), inputs, 260 inputSize)); 261 } 262 263 GrSkSLFP::GrSkSLFP(sk_sp<GrSkSLFPFactoryCache> factoryCache, const GrShaderCaps* shaderCaps, 264 int index, const char* name, const char* sksl, SkString skslString, 265 const void* inputs, size_t inputSize) 266 : INHERITED(kGrSkSLFP_ClassID, kNone_OptimizationFlags) 267 , fFactoryCache(factoryCache) 268 , fShaderCaps(sk_ref_sp(shaderCaps)) 269 , fIndex(index) 270 , fName(name) 271 , fSkSLString(skslString) 272 , fSkSL(sksl ? sksl : fSkSLString.c_str()) 273 , fInputs(new int8_t[inputSize]) 274 , fInputSize(inputSize) { 275 memcpy(fInputs.get(), inputs, inputSize); 276 } 277 278 GrSkSLFP::GrSkSLFP(const GrSkSLFP& other) 279 : INHERITED(kGrSkSLFP_ClassID, kNone_OptimizationFlags) 280 , fFactoryCache(other.fFactoryCache) 281 , fShaderCaps(other.fShaderCaps) 282 , fFactory(other.fFactory) 283 , fIndex(other.fIndex) 284 , fName(other.fName) 285 , fSkSLString(other.fSkSLString) 286 , fSkSL(other.fSkSL) 287 , fInputs(new int8_t[other.fInputSize]) 288 , fInputSize(other.fInputSize) { 289 memcpy(fInputs.get(), other.fInputs.get(), fInputSize); 290 } 291 292 const char* GrSkSLFP::name() const { 293 return fName; 294 } 295 296 void GrSkSLFP::createFactory() const { 297 if (!fFactory) { 298 fFactory = fFactoryCache->get(fIndex); 299 if (!fFactory) { 300 fFactory = sk_sp<GrSkSLFPFactory>(new GrSkSLFPFactory(fName, fShaderCaps.get(), fSkSL)); 301 fFactoryCache->set(fIndex, fFactory); 302 } 303 } 304 } 305 306 void GrSkSLFP::addChild(std::unique_ptr<GrFragmentProcessor> child) { 307 this->registerChildProcessor(std::move(child)); 308 } 309 310 GrGLSLFragmentProcessor* GrSkSLFP::onCreateGLSLInstance() const { 311 this->createFactory(); 312 const SkSL::Program* specialized = fFactory->getSpecialization(fKey, fInputs.get(), fInputSize); 313 SkSL::String glsl; 314 std::vector<SkSL::Compiler::FormatArg> formatArgs; 315 if (!fFactory->fCompiler.toPipelineStage(*specialized, &glsl, &formatArgs)) { 316 printf("%s\n", fFactory->fCompiler.errorText().c_str()); 317 SkASSERT(false); 318 } 319 return new GrGLSLSkSLFP(specialized->fContext.get(), &fFactory->fInputVars, glsl, formatArgs); 320 } 321 322 void GrSkSLFP::onGetGLSLProcessorKey(const GrShaderCaps& caps, 323 GrProcessorKeyBuilder* b) const { 324 this->createFactory(); 325 size_t offset = 0; 326 char* inputs = (char*) fInputs.get(); 327 const SkSL::Context& context = fFactory->fCompiler.context(); 328 for (const auto& v : fFactory->fInputVars) { 329 if (&v->fType == context.fInt_Type.get()) { 330 offset = SkAlign4(offset); 331 if (v->fModifiers.fLayout.fKey) { 332 fKey += inputs[offset + 0]; 333 fKey += inputs[offset + 1]; 334 fKey += inputs[offset + 2]; 335 fKey += inputs[offset + 3]; 336 b->add32(*(int32_t*) (inputs + offset)); 337 } 338 offset += sizeof(int32_t); 339 } else if (&v->fType == context.fFloat_Type.get()) { 340 offset = SkAlign4(offset); 341 if (v->fModifiers.fLayout.fKey) { 342 fKey += inputs[offset + 0]; 343 fKey += inputs[offset + 1]; 344 fKey += inputs[offset + 2]; 345 fKey += inputs[offset + 3]; 346 b->add32(*(float*) (inputs + offset)); 347 } 348 offset += sizeof(float); 349 } else if (&v->fType == context.fFloat4_Type.get() || 350 &v->fType == context.fHalf4_Type.get()) { 351 if (v->fModifiers.fLayout.fKey) { 352 for (size_t i = 0; i < sizeof(float) * 4; ++i) { 353 fKey += inputs[offset + i]; 354 } 355 b->add32(*(int32_t*) (inputs + offset)); 356 offset += sizeof(float); 357 b->add32(*(int32_t*) (inputs + offset)); 358 offset += sizeof(float); 359 b->add32(*(int32_t*) (inputs + offset)); 360 offset += sizeof(float); 361 b->add32(*(int32_t*) (inputs + offset)); 362 offset += sizeof(float); 363 } else { 364 offset += sizeof(float) * 4; 365 } 366 } else if (&v->fType == context.fBool_Type.get()) { 367 if (v->fModifiers.fLayout.fKey) { 368 fKey += inputs[offset]; 369 b->add32(inputs[offset]); 370 } 371 ++offset; 372 } else if (&v->fType == context.fFragmentProcessor_Type.get()) { 373 continue; 374 } else { 375 // unsupported input var type 376 printf("%s\n", SkSL::String(v->fType.fName).c_str()); 377 SkASSERT(false); 378 } 379 } 380 } 381 382 bool GrSkSLFP::onIsEqual(const GrFragmentProcessor& other) const { 383 const GrSkSLFP& sk = other.cast<GrSkSLFP>(); 384 SkASSERT(fIndex != sk.fIndex || fInputSize == sk.fInputSize); 385 return fIndex == sk.fIndex && 386 !memcmp(fInputs.get(), sk.fInputs.get(), fInputSize); 387 } 388 389 std::unique_ptr<GrFragmentProcessor> GrSkSLFP::clone() const { 390 std::unique_ptr<GrSkSLFP> result(new GrSkSLFP(*this)); 391 for (int i = 0; i < this->numChildProcessors(); ++i) { 392 result->registerChildProcessor(this->childProcessor(i).clone()); 393 } 394 return std::unique_ptr<GrFragmentProcessor>(result.release()); 395 } 396 397 // We have to do a bit of manual refcounting in the cache methods below. Ideally, we could just 398 // define fFactories to contain sk_sp<GrSkSLFPFactory> rather than GrSkSLFPFactory*, but that would 399 // require GrContext to include GrSkSLFP, which creates much bigger headaches than a few manual 400 // refcounts. 401 402 sk_sp<GrSkSLFPFactory> GrSkSLFPFactoryCache::get(int index) { 403 if (index >= (int) fFactories.size()) { 404 return nullptr; 405 } 406 GrSkSLFPFactory* result = fFactories[index]; 407 SkSafeRef(result); 408 return sk_sp<GrSkSLFPFactory>(result); 409 } 410 411 void GrSkSLFPFactoryCache::set(int index, sk_sp<GrSkSLFPFactory> factory) { 412 while (index >= (int) fFactories.size()) { 413 fFactories.emplace_back(); 414 } 415 factory->ref(); 416 SkASSERT(!fFactories[index]); 417 fFactories[index] = factory.get(); 418 } 419 420 GrSkSLFPFactoryCache::~GrSkSLFPFactoryCache() { 421 for (GrSkSLFPFactory* factory : fFactories) { 422 if (factory) { 423 factory->unref(); 424 } 425 } 426 } 427 428 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrSkSLFP); 429 430 #if GR_TEST_UTILS 431 432 #include "GrConstColorProcessor.h" 433 #include "GrContext.h" 434 #include "SkArithmeticImageFilter.h" 435 436 extern const char* SKSL_ARITHMETIC_SRC; 437 extern const char* SKSL_DITHER_SRC; 438 extern const char* SKSL_OVERDRAW_SRC; 439 440 using Value = SkSL::Program::Settings::Value; 441 442 std::unique_ptr<GrFragmentProcessor> GrSkSLFP::TestCreate(GrProcessorTestData* d) { 443 int type = d->fRandom->nextULessThan(3); 444 switch (type) { 445 case 0: { 446 static int ditherIndex = NewIndex(); 447 int rangeType = d->fRandom->nextULessThan(3); 448 std::unique_ptr<GrSkSLFP> result = GrSkSLFP::Make(d->context(), ditherIndex, "Dither", 449 SKSL_DITHER_SRC, &rangeType, 450 sizeof(rangeType)); 451 return std::unique_ptr<GrFragmentProcessor>(result.release()); 452 } 453 case 1: { 454 static int arithmeticIndex = NewIndex(); 455 ArithmeticFPInputs inputs; 456 inputs.k[0] = d->fRandom->nextF(); 457 inputs.k[1] = d->fRandom->nextF(); 458 inputs.k[2] = d->fRandom->nextF(); 459 inputs.k[3] = d->fRandom->nextF(); 460 inputs.enforcePMColor = d->fRandom->nextBool(); 461 std::unique_ptr<GrSkSLFP> result = GrSkSLFP::Make(d->context(), arithmeticIndex, 462 "Arithmetic", SKSL_ARITHMETIC_SRC, 463 &inputs, sizeof(inputs)); 464 result->addChild(GrConstColorProcessor::Make( 465 SK_PMColor4fWHITE, 466 GrConstColorProcessor::InputMode::kIgnore)); 467 return std::unique_ptr<GrFragmentProcessor>(result.release()); 468 } 469 case 2: { 470 static int overdrawIndex = NewIndex(); 471 SkPMColor inputs[6]; 472 for (int i = 0; i < 6; ++i) { 473 inputs[i] = d->fRandom->nextU(); 474 } 475 std::unique_ptr<GrSkSLFP> result = GrSkSLFP::Make(d->context(), overdrawIndex, 476 "Overdraw", SKSL_OVERDRAW_SRC, 477 &inputs, sizeof(inputs)); 478 return std::unique_ptr<GrFragmentProcessor>(result.release()); 479 } 480 } 481 SK_ABORT("unreachable"); 482 return nullptr; 483 } 484 485 #endif 486