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