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