1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2016 Google Inc.
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 "src/gpu/GrProgramDesc.h"
9cb93a386Sopenharmony_ci
10cb93a386Sopenharmony_ci#include "include/private/SkChecksum.h"
11cb93a386Sopenharmony_ci#include "include/private/SkTo.h"
12cb93a386Sopenharmony_ci#include "src/gpu/GrFragmentProcessor.h"
13cb93a386Sopenharmony_ci#include "src/gpu/GrGeometryProcessor.h"
14cb93a386Sopenharmony_ci#include "src/gpu/GrPipeline.h"
15cb93a386Sopenharmony_ci#include "src/gpu/GrProcessor.h"
16cb93a386Sopenharmony_ci#include "src/gpu/GrProgramInfo.h"
17cb93a386Sopenharmony_ci#include "src/gpu/GrRenderTarget.h"
18cb93a386Sopenharmony_ci#include "src/gpu/GrShaderCaps.h"
19cb93a386Sopenharmony_ci#include "src/gpu/GrTexture.h"
20cb93a386Sopenharmony_ci#include "src/gpu/effects/GrTextureEffect.h"
21cb93a386Sopenharmony_ci#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
22cb93a386Sopenharmony_ci
23cb93a386Sopenharmony_cienum {
24cb93a386Sopenharmony_ci    kSamplerOrImageTypeKeyBits = 4
25cb93a386Sopenharmony_ci};
26cb93a386Sopenharmony_ci
27cb93a386Sopenharmony_cistatic inline uint16_t texture_type_key(GrTextureType type) {
28cb93a386Sopenharmony_ci    int value = UINT16_MAX;
29cb93a386Sopenharmony_ci    switch (type) {
30cb93a386Sopenharmony_ci        case GrTextureType::k2D:
31cb93a386Sopenharmony_ci            value = 0;
32cb93a386Sopenharmony_ci            break;
33cb93a386Sopenharmony_ci        case GrTextureType::kExternal:
34cb93a386Sopenharmony_ci            value = 1;
35cb93a386Sopenharmony_ci            break;
36cb93a386Sopenharmony_ci        case GrTextureType::kRectangle:
37cb93a386Sopenharmony_ci            value = 2;
38cb93a386Sopenharmony_ci            break;
39cb93a386Sopenharmony_ci        default:
40cb93a386Sopenharmony_ci            SK_ABORT("Unexpected texture type");
41cb93a386Sopenharmony_ci            value = 3;
42cb93a386Sopenharmony_ci            break;
43cb93a386Sopenharmony_ci    }
44cb93a386Sopenharmony_ci    SkASSERT((value & ((1 << kSamplerOrImageTypeKeyBits) - 1)) == value);
45cb93a386Sopenharmony_ci    return SkToU16(value);
46cb93a386Sopenharmony_ci}
47cb93a386Sopenharmony_ci
48cb93a386Sopenharmony_cistatic uint32_t sampler_key(GrTextureType textureType, const GrSwizzle& swizzle,
49cb93a386Sopenharmony_ci                            const GrCaps& caps) {
50cb93a386Sopenharmony_ci    int samplerTypeKey = texture_type_key(textureType);
51cb93a386Sopenharmony_ci
52cb93a386Sopenharmony_ci    static_assert(2 == sizeof(swizzle.asKey()));
53cb93a386Sopenharmony_ci    uint16_t swizzleKey = swizzle.asKey();
54cb93a386Sopenharmony_ci    return SkToU32(samplerTypeKey | swizzleKey << kSamplerOrImageTypeKeyBits);
55cb93a386Sopenharmony_ci}
56cb93a386Sopenharmony_ci
57cb93a386Sopenharmony_cistatic void add_geomproc_sampler_keys(GrProcessorKeyBuilder* b,
58cb93a386Sopenharmony_ci                                      const GrGeometryProcessor& geomProc,
59cb93a386Sopenharmony_ci                                      const GrCaps& caps) {
60cb93a386Sopenharmony_ci    int numTextureSamplers = geomProc.numTextureSamplers();
61cb93a386Sopenharmony_ci    b->add32(numTextureSamplers, "ppNumSamplers");
62cb93a386Sopenharmony_ci    for (int i = 0; i < numTextureSamplers; ++i) {
63cb93a386Sopenharmony_ci        const GrGeometryProcessor::TextureSampler& sampler = geomProc.textureSampler(i);
64cb93a386Sopenharmony_ci        const GrBackendFormat& backendFormat = sampler.backendFormat();
65cb93a386Sopenharmony_ci
66cb93a386Sopenharmony_ci        uint32_t samplerKey = sampler_key(backendFormat.textureType(), sampler.swizzle(), caps);
67cb93a386Sopenharmony_ci        b->add32(samplerKey);
68cb93a386Sopenharmony_ci
69cb93a386Sopenharmony_ci        caps.addExtraSamplerKey(b, sampler.samplerState(), backendFormat);
70cb93a386Sopenharmony_ci    }
71cb93a386Sopenharmony_ci}
72cb93a386Sopenharmony_ci
73cb93a386Sopenharmony_ci// Currently we allow 8 bits for the class id
74cb93a386Sopenharmony_cistatic constexpr uint32_t kClassIDBits = 8;
75cb93a386Sopenharmony_ci
76cb93a386Sopenharmony_ci/**
77cb93a386Sopenharmony_ci * Functions which emit processor key info into the key builder.
78cb93a386Sopenharmony_ci * For every effect, we include the effect's class ID (different for every GrProcessor subclass),
79cb93a386Sopenharmony_ci * any information generated by the effect itself (addToKey), and some meta-information.
80cb93a386Sopenharmony_ci * Shader code may be dependent on properties of the effect not placed in the key by the effect
81cb93a386Sopenharmony_ci * (e.g. pixel format of textures used).
82cb93a386Sopenharmony_ci */
83cb93a386Sopenharmony_cistatic void gen_geomproc_key(const GrGeometryProcessor& geomProc,
84cb93a386Sopenharmony_ci                             const GrCaps& caps,
85cb93a386Sopenharmony_ci                             GrProcessorKeyBuilder* b) {
86cb93a386Sopenharmony_ci    b->appendComment(geomProc.name());
87cb93a386Sopenharmony_ci    b->addBits(kClassIDBits, geomProc.classID(), "geomProcClassID");
88cb93a386Sopenharmony_ci
89cb93a386Sopenharmony_ci    geomProc.addToKey(*caps.shaderCaps(), b);
90cb93a386Sopenharmony_ci    geomProc.getAttributeKey(b);
91cb93a386Sopenharmony_ci
92cb93a386Sopenharmony_ci    add_geomproc_sampler_keys(b, geomProc, caps);
93cb93a386Sopenharmony_ci}
94cb93a386Sopenharmony_ci
95cb93a386Sopenharmony_cistatic void gen_xp_key(const GrXferProcessor& xp,
96cb93a386Sopenharmony_ci                       const GrCaps& caps,
97cb93a386Sopenharmony_ci                       const GrPipeline& pipeline,
98cb93a386Sopenharmony_ci                       GrProcessorKeyBuilder* b) {
99cb93a386Sopenharmony_ci    b->appendComment(xp.name());
100cb93a386Sopenharmony_ci    b->addBits(kClassIDBits, xp.classID(), "xpClassID");
101cb93a386Sopenharmony_ci
102cb93a386Sopenharmony_ci    const GrSurfaceOrigin* originIfDstTexture = nullptr;
103cb93a386Sopenharmony_ci    GrSurfaceOrigin origin;
104cb93a386Sopenharmony_ci    if (pipeline.dstProxyView().proxy()) {
105cb93a386Sopenharmony_ci        origin = pipeline.dstProxyView().origin();
106cb93a386Sopenharmony_ci        originIfDstTexture = &origin;
107cb93a386Sopenharmony_ci    }
108cb93a386Sopenharmony_ci
109cb93a386Sopenharmony_ci    xp.addToKey(*caps.shaderCaps(),
110cb93a386Sopenharmony_ci                b,
111cb93a386Sopenharmony_ci                originIfDstTexture,
112cb93a386Sopenharmony_ci                pipeline.dstSampleFlags() & GrDstSampleFlags::kAsInputAttachment);
113cb93a386Sopenharmony_ci}
114cb93a386Sopenharmony_ci
115cb93a386Sopenharmony_cistatic void gen_fp_key(const GrFragmentProcessor& fp,
116cb93a386Sopenharmony_ci                       const GrCaps& caps,
117cb93a386Sopenharmony_ci                       GrProcessorKeyBuilder* b) {
118cb93a386Sopenharmony_ci    b->appendComment(fp.name());
119cb93a386Sopenharmony_ci    b->addBits(kClassIDBits, fp.classID(), "fpClassID");
120cb93a386Sopenharmony_ci    b->addBits(GrGeometryProcessor::kCoordTransformKeyBits,
121cb93a386Sopenharmony_ci               GrGeometryProcessor::ComputeCoordTransformsKey(fp), "fpTransforms");
122cb93a386Sopenharmony_ci
123cb93a386Sopenharmony_ci    if (auto* te = fp.asTextureEffect()) {
124cb93a386Sopenharmony_ci        const GrBackendFormat& backendFormat = te->view().proxy()->backendFormat();
125cb93a386Sopenharmony_ci        uint32_t samplerKey = sampler_key(backendFormat.textureType(), te->view().swizzle(), caps);
126cb93a386Sopenharmony_ci        b->add32(samplerKey, "fpSamplerKey");
127cb93a386Sopenharmony_ci        caps.addExtraSamplerKey(b, te->samplerState(), backendFormat);
128cb93a386Sopenharmony_ci    }
129cb93a386Sopenharmony_ci
130cb93a386Sopenharmony_ci    fp.addToKey(*caps.shaderCaps(), b);
131cb93a386Sopenharmony_ci    b->add32(fp.numChildProcessors(), "fpNumChildren");
132cb93a386Sopenharmony_ci
133cb93a386Sopenharmony_ci    for (int i = 0; i < fp.numChildProcessors(); ++i) {
134cb93a386Sopenharmony_ci        if (auto child = fp.childProcessor(i)) {
135cb93a386Sopenharmony_ci            gen_fp_key(*child, caps, b);
136cb93a386Sopenharmony_ci        } else {
137cb93a386Sopenharmony_ci            // Fold in a sentinel value as the "class ID" for any null children
138cb93a386Sopenharmony_ci            b->appendComment("Null");
139cb93a386Sopenharmony_ci            b->addBits(kClassIDBits, GrProcessor::ClassID::kNull_ClassID, "fpClassID");
140cb93a386Sopenharmony_ci        }
141cb93a386Sopenharmony_ci    }
142cb93a386Sopenharmony_ci}
143cb93a386Sopenharmony_ci
144cb93a386Sopenharmony_cistatic void gen_key(GrProcessorKeyBuilder* b,
145cb93a386Sopenharmony_ci                    const GrProgramInfo& programInfo,
146cb93a386Sopenharmony_ci                    const GrCaps& caps) {
147cb93a386Sopenharmony_ci    gen_geomproc_key(programInfo.geomProc(), caps, b);
148cb93a386Sopenharmony_ci
149cb93a386Sopenharmony_ci    const GrPipeline& pipeline = programInfo.pipeline();
150cb93a386Sopenharmony_ci    b->addBits(2, pipeline.numFragmentProcessors(),      "numFPs");
151cb93a386Sopenharmony_ci    b->addBits(1, pipeline.numColorFragmentProcessors(), "numColorFPs");
152cb93a386Sopenharmony_ci    for (int i = 0; i < pipeline.numFragmentProcessors(); ++i) {
153cb93a386Sopenharmony_ci        gen_fp_key(pipeline.getFragmentProcessor(i), caps, b);
154cb93a386Sopenharmony_ci    }
155cb93a386Sopenharmony_ci
156cb93a386Sopenharmony_ci    gen_xp_key(pipeline.getXferProcessor(), caps, pipeline, b);
157cb93a386Sopenharmony_ci
158cb93a386Sopenharmony_ci    b->addBits(16, pipeline.writeSwizzle().asKey(), "writeSwizzle");
159cb93a386Sopenharmony_ci    b->addBool(pipeline.snapVerticesToPixelCenters(), "snapVertices");
160cb93a386Sopenharmony_ci    // The base descriptor only stores whether or not the primitiveType is kPoints. Backend-
161cb93a386Sopenharmony_ci    // specific versions (e.g., Vulkan) require more detail
162cb93a386Sopenharmony_ci    b->addBool((programInfo.primitiveType() == GrPrimitiveType::kPoints), "isPoints");
163cb93a386Sopenharmony_ci    b->addBool(SkToBool(programInfo.renderPassBarriers() & GrXferBarrierFlags::kTexture), "useInput");
164cb93a386Sopenharmony_ci
165cb93a386Sopenharmony_ci    // Put a clean break between the "common" data written by this function, and any backend data
166cb93a386Sopenharmony_ci    // appended later. The initial key length will just be this portion (rounded to 4 bytes).
167cb93a386Sopenharmony_ci    b->flush();
168cb93a386Sopenharmony_ci}
169cb93a386Sopenharmony_ci
170cb93a386Sopenharmony_civoid GrProgramDesc::Build(GrProgramDesc* desc,
171cb93a386Sopenharmony_ci                          const GrProgramInfo& programInfo,
172cb93a386Sopenharmony_ci                          const GrCaps& caps) {
173cb93a386Sopenharmony_ci    desc->reset();
174cb93a386Sopenharmony_ci    GrProcessorKeyBuilder b(desc->key());
175cb93a386Sopenharmony_ci    gen_key(&b, programInfo, caps);
176cb93a386Sopenharmony_ci    desc->fInitialKeyLength = desc->keyLength();
177cb93a386Sopenharmony_ci}
178cb93a386Sopenharmony_ci
179cb93a386Sopenharmony_ciSkString GrProgramDesc::Describe(const GrProgramInfo& programInfo,
180cb93a386Sopenharmony_ci                                 const GrCaps& caps) {
181cb93a386Sopenharmony_ci    GrProgramDesc desc;
182cb93a386Sopenharmony_ci    GrProcessorStringKeyBuilder b(desc.key());
183cb93a386Sopenharmony_ci    gen_key(&b, programInfo, caps);
184cb93a386Sopenharmony_ci    b.flush();
185cb93a386Sopenharmony_ci    return b.description();
186cb93a386Sopenharmony_ci}
187