1/* 2 * Copyright 2021 Google LLC 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 "experimental/graphite/src/ProgramCache.h" 9 10namespace skgpu { 11 12//////////////////////////////////////////////////////////////////////////////////////////////////// 13ProgramCache::ProgramInfo::ProgramInfo(uint32_t uniqueID, Combination c) 14 : fID(uniqueID) 15 , fCombination(c) { 16} 17 18ProgramCache::ProgramInfo::~ProgramInfo() {} 19 20std::string ProgramCache::ProgramInfo::getMSL() const { 21 std::string msl = GetMSLUniformStruct(fCombination.fShaderType); 22 23 switch (fCombination.fShaderType) { 24 case ShaderCombo::ShaderType::kLinearGradient: 25 // TODO: this MSL uses a 'rtSize' uniform that, presumably, we'll be getting from the 26 // vertex shader side of things (still somewhat TBD) 27 msl += std::string( 28 "fragment float4 fragmentShader(VertexOut interpolated [[stage_in]],\n" 29 " constant FragmentUniforms &uniforms [[buffer(0)]])\n" 30 "{" 31 "float2 screenPos = float2(2*interpolated.pos.x/uniforms.rtSize[0] - 1,\n" 32 " 2*interpolated.pos.y/uniforms.rtSize[1] - 1);\n" 33 "float2 delta = uniforms.point1 - uniforms.point0;\n" 34 "float2 pt = screenPos - uniforms.point0;\n" 35 "float t = dot(pt, delta) / dot(delta, delta);\n" 36 "float4 result = uniforms.colors[0];\n" 37 "result = mix(result, uniforms.colors[1],\n" 38 " clamp((t-uniforms.offsets[0])/(uniforms.offsets[1]-uniforms.offsets[0]),\n" 39 " 0, 1));\n" 40 "result = mix(result, uniforms.colors[2],\n" 41 " clamp((t-uniforms.offsets[1])/(uniforms.offsets[2]-uniforms.offsets[1]),\n" 42 " 0, 1));\n" 43 "result = mix(result, uniforms.colors[3],\n" 44 " clamp((t-uniforms.offsets[2])/(uniforms.offsets[3]-uniforms.offsets[2]),\n" 45 " 0, 1));\n" 46 "return result;\n" 47 "}\n"); 48 break; 49 case ShaderCombo::ShaderType::kRadialGradient: 50 case ShaderCombo::ShaderType::kSweepGradient: 51 case ShaderCombo::ShaderType::kConicalGradient: 52 case ShaderCombo::ShaderType::kNone: 53 default: 54 msl += std::string( 55 "fragment float4 fragmentShader(VertexOut interpolated [[stage_in]],\n" 56 " constant FragmentUniforms &uniforms [[buffer(0)]])\n" 57 "{\n" 58 "return float4(uniforms.color);\n" 59 "}\n"); 60 break; 61 } 62 63 return msl; 64} 65 66//////////////////////////////////////////////////////////////////////////////////////////////////// 67ProgramCache::ProgramCache() { 68 // kInvalidProgramID (aka 0) is reserved 69 fProgramVector.push_back(nullptr); 70} 71 72size_t ProgramCache::Hash::operator()(Combination c) const { 73 return static_cast<int>(c.fShaderType) + 74 static_cast<int>(c.fTileMode) + 75 static_cast<int>(c.fBlendMode); 76} 77 78sk_sp<ProgramCache::ProgramInfo> ProgramCache::findOrCreateProgram(Combination c) { 79 auto iter = fProgramHash.find(c); 80 if (iter != fProgramHash.end()) { 81 SkASSERT(iter->second->id() != kInvalidProgramID); 82 return iter->second; 83 } 84 85 sk_sp<ProgramInfo> pi(new ProgramInfo(fNextUniqueID++, c)); 86 fProgramHash.insert(std::make_pair(c, pi)); 87 fProgramVector.push_back(pi); 88 SkASSERT(fProgramVector[pi->id()] == pi); 89 return pi; 90} 91 92sk_sp<ProgramCache::ProgramInfo> ProgramCache::lookup(uint32_t uniqueID) { 93 SkASSERT(uniqueID < fProgramVector.size()); 94 return fProgramVector[uniqueID]; 95} 96 97} // namespace skgpu 98