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