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#include "GrProgramDesc.h"
8#include "GrPipeline.h"
9#include "GrPrimitiveProcessor.h"
10#include "GrProcessor.h"
11#include "GrRenderTargetPriv.h"
12#include "GrShaderCaps.h"
13#include "GrTexturePriv.h"
14#include "SkChecksum.h"
15#include "glsl/GrGLSLFragmentProcessor.h"
16#include "glsl/GrGLSLFragmentShaderBuilder.h"
17
18enum {
19    kSamplerOrImageTypeKeyBits = 4
20};
21
22static inline uint16_t image_storage_or_sampler_uniform_type_key(GrSLType type ) {
23    int value = UINT16_MAX;
24    switch (type) {
25        case kTexture2DSampler_GrSLType:
26            value = 0;
27            break;
28        case kITexture2DSampler_GrSLType:
29            value = 1;
30            break;
31        case kTextureExternalSampler_GrSLType:
32            value = 2;
33            break;
34        case kTexture2DRectSampler_GrSLType:
35            value = 3;
36            break;
37        case kBufferSampler_GrSLType:
38            value = 4;
39            break;
40
41        default:
42            break;
43    }
44    SkASSERT((value & ((1 << kSamplerOrImageTypeKeyBits) - 1)) == value);
45    return value;
46}
47
48static uint16_t sampler_key(GrSLType samplerType, GrPixelConfig config, GrShaderFlags visibility,
49                            const GrShaderCaps& caps) {
50    int samplerTypeKey = image_storage_or_sampler_uniform_type_key(samplerType);
51
52    GR_STATIC_ASSERT(1 == sizeof(caps.configTextureSwizzle(config).asKey()));
53    return SkToU16(samplerTypeKey |
54                   caps.configTextureSwizzle(config).asKey() << kSamplerOrImageTypeKeyBits |
55                   (GrSLSamplerPrecision(config) << (8 + kSamplerOrImageTypeKeyBits)));
56}
57
58static void add_sampler_and_image_keys(GrProcessorKeyBuilder* b, const GrResourceIOProcessor& proc,
59                                       const GrShaderCaps& caps) {
60    int numTextureSamplers = proc.numTextureSamplers();
61    int numBuffers = proc.numBuffers();
62    int numUniforms = numTextureSamplers + numBuffers;
63    // Need two bytes per key.
64    int word32Count = (numUniforms + 1) / 2;
65    if (0 == word32Count) {
66        return;
67    }
68    uint16_t* k16 = SkTCast<uint16_t*>(b->add32n(word32Count));
69    int j = 0;
70    for (int i = 0; i < numTextureSamplers; ++i, ++j) {
71        const GrResourceIOProcessor::TextureSampler& sampler = proc.textureSampler(i);
72        const GrTexture* tex = sampler.peekTexture();
73
74        k16[j] = sampler_key(tex->texturePriv().samplerType(), tex->config(), sampler.visibility(),
75                             caps);
76    }
77    for (int i = 0; i < numBuffers; ++i, ++j) {
78        const GrResourceIOProcessor::BufferAccess& access = proc.bufferAccess(i);
79        k16[j] = sampler_key(kBufferSampler_GrSLType, access.texelConfig(), access.visibility(),
80                             caps);
81    }
82    // zero the last 16 bits if the number of uniforms for samplers and image storages is odd.
83    if (numUniforms & 0x1) {
84        k16[numUniforms] = 0;
85    }
86}
87
88/**
89 * A function which emits a meta key into the key builder.  This is required because shader code may
90 * be dependent on properties of the effect that the effect itself doesn't use
91 * in its key (e.g. the pixel format of textures used). So we create a meta-key for
92 * every effect using this function. It is also responsible for inserting the effect's class ID
93 * which must be different for every GrProcessor subclass. It can fail if an effect uses too many
94 * transforms, etc, for the space allotted in the meta-key.  NOTE, both FPs and GPs share this
95 * function because it is hairy, though FPs do not have attribs, and GPs do not have transforms
96 */
97static bool gen_meta_key(const GrResourceIOProcessor& proc,
98                         const GrShaderCaps& shaderCaps,
99                         uint32_t transformKey,
100                         GrProcessorKeyBuilder* b) {
101    size_t processorKeySize = b->size();
102    uint32_t classID = proc.classID();
103
104    // Currently we allow 16 bits for the class id and the overall processor key size.
105    static const uint32_t kMetaKeyInvalidMask = ~((uint32_t)SK_MaxU16);
106    if ((processorKeySize | classID) & kMetaKeyInvalidMask) {
107        return false;
108    }
109
110    add_sampler_and_image_keys(b, proc, shaderCaps);
111
112    uint32_t* key = b->add32n(2);
113    key[0] = (classID << 16) | SkToU32(processorKeySize);
114    key[1] = transformKey;
115    return true;
116}
117
118static bool gen_meta_key(const GrXferProcessor& xp,
119                         const GrShaderCaps& shaderCaps,
120                         GrProcessorKeyBuilder* b) {
121    size_t processorKeySize = b->size();
122    uint32_t classID = xp.classID();
123
124    // Currently we allow 16 bits for the class id and the overall processor key size.
125    static const uint32_t kMetaKeyInvalidMask = ~((uint32_t)SK_MaxU16);
126    if ((processorKeySize | classID) & kMetaKeyInvalidMask) {
127        return false;
128    }
129
130    b->add32((classID << 16) | SkToU32(processorKeySize));
131    return true;
132}
133
134static bool gen_frag_proc_and_meta_keys(const GrPrimitiveProcessor& primProc,
135                                        const GrFragmentProcessor& fp,
136                                        const GrShaderCaps& shaderCaps,
137                                        GrProcessorKeyBuilder* b) {
138    for (int i = 0; i < fp.numChildProcessors(); ++i) {
139        if (!gen_frag_proc_and_meta_keys(primProc, fp.childProcessor(i), shaderCaps, b)) {
140            return false;
141        }
142    }
143
144    fp.getGLSLProcessorKey(shaderCaps, b);
145
146    return gen_meta_key(fp, shaderCaps, primProc.getTransformKey(fp.coordTransforms(),
147                                                                 fp.numCoordTransforms()), b);
148}
149
150bool GrProgramDesc::Build(GrProgramDesc* desc,
151                          const GrPrimitiveProcessor& primProc,
152                          bool hasPointSize,
153                          const GrPipeline& pipeline,
154                          const GrShaderCaps& shaderCaps) {
155    // The descriptor is used as a cache key. Thus when a field of the
156    // descriptor will not affect program generation (because of the attribute
157    // bindings in use or other descriptor field settings) it should be set
158    // to a canonical value to avoid duplicate programs with different keys.
159
160    GR_STATIC_ASSERT(0 == kProcessorKeysOffset % sizeof(uint32_t));
161    // Make room for everything up to the effect keys.
162    desc->key().reset();
163    desc->key().push_back_n(kProcessorKeysOffset);
164
165    GrProcessorKeyBuilder b(&desc->key());
166
167    primProc.getGLSLProcessorKey(shaderCaps, &b);
168    if (!gen_meta_key(primProc, shaderCaps, 0, &b)) {
169        desc->key().reset();
170        return false;
171    }
172    GrProcessor::RequiredFeatures requiredFeatures = primProc.requiredFeatures();
173
174    for (int i = 0; i < pipeline.numFragmentProcessors(); ++i) {
175        const GrFragmentProcessor& fp = pipeline.getFragmentProcessor(i);
176        if (!gen_frag_proc_and_meta_keys(primProc, fp, shaderCaps, &b)) {
177            desc->key().reset();
178            return false;
179        }
180        requiredFeatures |= fp.requiredFeatures();
181    }
182
183    const GrXferProcessor& xp = pipeline.getXferProcessor();
184    const GrSurfaceOrigin* originIfDstTexture = nullptr;
185    GrSurfaceOrigin origin;
186    if (pipeline.dstTextureProxy()) {
187        origin = pipeline.dstTextureProxy()->origin();
188        originIfDstTexture = &origin;
189    }
190    xp.getGLSLProcessorKey(shaderCaps, &b, originIfDstTexture);
191    if (!gen_meta_key(xp, shaderCaps, &b)) {
192        desc->key().reset();
193        return false;
194    }
195    requiredFeatures |= xp.requiredFeatures();
196
197    // --------DO NOT MOVE HEADER ABOVE THIS LINE--------------------------------------------------
198    // Because header is a pointer into the dynamic array, we can't push any new data into the key
199    // below here.
200    KeyHeader* header = desc->atOffset<KeyHeader, kHeaderOffset>();
201
202    // make sure any padding in the header is zeroed.
203    memset(header, 0, kHeaderSize);
204
205    GrRenderTargetProxy* proxy = pipeline.proxy();
206
207    if (requiredFeatures & GrProcessor::kSampleLocations_RequiredFeature) {
208        SkASSERT(pipeline.isHWAntialiasState());
209
210        GrRenderTarget* rt = pipeline.renderTarget();
211        header->fSamplePatternKey =
212            rt->renderTargetPriv().getMultisampleSpecs(pipeline).fUniqueID;
213    } else {
214        header->fSamplePatternKey = 0;
215    }
216
217    header->fOutputSwizzle = shaderCaps.configOutputSwizzle(proxy->config()).asKey();
218
219    header->fSnapVerticesToPixelCenters = pipeline.snapVerticesToPixelCenters();
220    header->fColorFragmentProcessorCnt = pipeline.numColorFragmentProcessors();
221    header->fCoverageFragmentProcessorCnt = pipeline.numCoverageFragmentProcessors();
222    // Fail if the client requested more processors than the key can fit.
223    if (header->fColorFragmentProcessorCnt != pipeline.numColorFragmentProcessors() ||
224        header->fCoverageFragmentProcessorCnt != pipeline.numCoverageFragmentProcessors()) {
225        return false;
226    }
227    header->fHasPointSize = hasPointSize ? 1 : 0;
228    return true;
229}
230