• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/GrPipeline.h"
13 #include "src/gpu/GrPrimitiveProcessor.h"
14 #include "src/gpu/GrProcessor.h"
15 #include "src/gpu/GrRenderTargetPriv.h"
16 #include "src/gpu/GrShaderCaps.h"
17 #include "src/gpu/GrTexturePriv.h"
18 #include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
19 #include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
20 
21 enum {
22     kSamplerOrImageTypeKeyBits = 4
23 };
24 
texture_type_key(GrTextureType type)25 static inline uint16_t texture_type_key(GrTextureType type) {
26     int value = UINT16_MAX;
27     switch (type) {
28         case GrTextureType::k2D:
29             value = 0;
30             break;
31         case GrTextureType::kExternal:
32             value = 1;
33             break;
34         case GrTextureType::kRectangle:
35             value = 2;
36             break;
37         default:
38             SK_ABORT("Unexpected texture type");
39             value = 3;
40             break;
41     }
42     SkASSERT((value & ((1 << kSamplerOrImageTypeKeyBits) - 1)) == value);
43     return SkToU16(value);
44 }
45 
sampler_key(GrTextureType textureType,const GrSwizzle & swizzle,const GrShaderCaps & caps)46 static uint32_t sampler_key(GrTextureType textureType, const GrSwizzle& swizzle,
47                             const GrShaderCaps& caps) {
48     int samplerTypeKey = texture_type_key(textureType);
49 
50     GR_STATIC_ASSERT(2 == sizeof(swizzle.asKey()));
51     uint16_t swizzleKey = 0;
52     if (caps.textureSwizzleAppliedInShader()) {
53         swizzleKey = swizzle.asKey();
54     }
55     return SkToU32(samplerTypeKey | swizzleKey << kSamplerOrImageTypeKeyBits);
56 }
57 
add_sampler_keys(GrProcessorKeyBuilder * b,const GrFragmentProcessor & fp,GrGpu * gpu,const GrShaderCaps & caps)58 static void add_sampler_keys(GrProcessorKeyBuilder* b, const GrFragmentProcessor& fp,
59                              GrGpu* gpu, const GrShaderCaps& caps) {
60     int numTextureSamplers = fp.numTextureSamplers();
61     if (!numTextureSamplers) {
62         return;
63     }
64     for (int i = 0; i < numTextureSamplers; ++i) {
65         const GrFragmentProcessor::TextureSampler& sampler = fp.textureSampler(i);
66         const GrTexture* tex = sampler.peekTexture();
67         uint32_t samplerKey = sampler_key(
68                 tex->texturePriv().textureType(), sampler.swizzle(), caps);
69         uint32_t extraSamplerKey = gpu->getExtraSamplerKeyForProgram(
70                 sampler.samplerState(), sampler.proxy()->backendFormat());
71         if (extraSamplerKey) {
72             // We first mark the normal sampler key with last bit to flag that it has an extra
73             // sampler key. We then add both keys.
74             SkASSERT((samplerKey & (1 << 31)) == 0);
75             b->add32(samplerKey | (1 << 31));
76             b->add32(extraSamplerKey);
77         } else {
78             b->add32(samplerKey);
79         }
80     }
81 }
82 
add_sampler_keys(GrProcessorKeyBuilder * b,const GrPrimitiveProcessor & pp,const GrShaderCaps & caps)83 static void add_sampler_keys(GrProcessorKeyBuilder* b, const GrPrimitiveProcessor& pp,
84                              const GrShaderCaps& caps) {
85     int numTextureSamplers = pp.numTextureSamplers();
86     if (!numTextureSamplers) {
87         return;
88     }
89     for (int i = 0; i < numTextureSamplers; ++i) {
90         const GrPrimitiveProcessor::TextureSampler& sampler = pp.textureSampler(i);
91         uint32_t samplerKey = sampler_key(
92                 sampler.textureType(), sampler.swizzle(), caps);
93         uint32_t extraSamplerKey = sampler.extraSamplerKey();
94         if (extraSamplerKey) {
95             // We first mark the normal sampler key with last bit to flag that it has an extra
96             // sampler key. We then add both keys.
97             SkASSERT((samplerKey & (1 << 31)) == 0);
98             b->add32(samplerKey | (1 << 31));
99             b->add32(extraSamplerKey);
100         } else {
101             b->add32(samplerKey);
102         }
103     }
104 }
105 
106 /**
107  * A function which emits a meta key into the key builder.  This is required because shader code may
108  * be dependent on properties of the effect that the effect itself doesn't use
109  * in its key (e.g. the pixel format of textures used). So we create a meta-key for
110  * every effect using this function. It is also responsible for inserting the effect's class ID
111  * which must be different for every GrProcessor subclass. It can fail if an effect uses too many
112  * transforms, etc, for the space allotted in the meta-key.  NOTE, both FPs and GPs share this
113  * function because it is hairy, though FPs do not have attribs, and GPs do not have transforms
114  */
gen_meta_key(const GrFragmentProcessor & fp,GrGpu * gpu,const GrShaderCaps & shaderCaps,uint32_t transformKey,GrProcessorKeyBuilder * b)115 static bool gen_meta_key(const GrFragmentProcessor& fp,
116                          GrGpu* gpu,
117                          const GrShaderCaps& shaderCaps,
118                          uint32_t transformKey,
119                          GrProcessorKeyBuilder* b) {
120     size_t processorKeySize = b->size();
121     uint32_t classID = fp.classID();
122 
123     // Currently we allow 16 bits for the class id and the overall processor key size.
124     static const uint32_t kMetaKeyInvalidMask = ~((uint32_t)UINT16_MAX);
125     if ((processorKeySize | classID) & kMetaKeyInvalidMask) {
126         return false;
127     }
128 
129     add_sampler_keys(b, fp, gpu, shaderCaps);
130 
131     uint32_t* key = b->add32n(2);
132     key[0] = (classID << 16) | SkToU32(processorKeySize);
133     key[1] = transformKey;
134     return true;
135 }
136 
gen_meta_key(const GrPrimitiveProcessor & pp,const GrShaderCaps & shaderCaps,uint32_t transformKey,GrProcessorKeyBuilder * b)137 static bool gen_meta_key(const GrPrimitiveProcessor& pp,
138                          const GrShaderCaps& shaderCaps,
139                          uint32_t transformKey,
140                          GrProcessorKeyBuilder* b) {
141     size_t processorKeySize = b->size();
142     uint32_t classID = pp.classID();
143 
144     // Currently we allow 16 bits for the class id and the overall processor key size.
145     static const uint32_t kMetaKeyInvalidMask = ~((uint32_t)UINT16_MAX);
146     if ((processorKeySize | classID) & kMetaKeyInvalidMask) {
147         return false;
148     }
149 
150     add_sampler_keys(b, pp, shaderCaps);
151 
152     uint32_t* key = b->add32n(2);
153     key[0] = (classID << 16) | SkToU32(processorKeySize);
154     key[1] = transformKey;
155     return true;
156 }
157 
gen_meta_key(const GrXferProcessor & xp,const GrShaderCaps & shaderCaps,GrProcessorKeyBuilder * b)158 static bool gen_meta_key(const GrXferProcessor& xp,
159                          const GrShaderCaps& shaderCaps,
160                          GrProcessorKeyBuilder* b) {
161     size_t processorKeySize = b->size();
162     uint32_t classID = xp.classID();
163 
164     // Currently we allow 16 bits for the class id and the overall processor key size.
165     static const uint32_t kMetaKeyInvalidMask = ~((uint32_t)UINT16_MAX);
166     if ((processorKeySize | classID) & kMetaKeyInvalidMask) {
167         return false;
168     }
169 
170     b->add32((classID << 16) | SkToU32(processorKeySize));
171     return true;
172 }
173 
gen_frag_proc_and_meta_keys(const GrPrimitiveProcessor & primProc,const GrFragmentProcessor & fp,GrGpu * gpu,const GrShaderCaps & shaderCaps,GrProcessorKeyBuilder * b)174 static bool gen_frag_proc_and_meta_keys(const GrPrimitiveProcessor& primProc,
175                                         const GrFragmentProcessor& fp,
176                                         GrGpu* gpu,
177                                         const GrShaderCaps& shaderCaps,
178                                         GrProcessorKeyBuilder* b) {
179     for (int i = 0; i < fp.numChildProcessors(); ++i) {
180         if (!gen_frag_proc_and_meta_keys(primProc, fp.childProcessor(i), gpu, shaderCaps, b)) {
181             return false;
182         }
183     }
184 
185     fp.getGLSLProcessorKey(shaderCaps, b);
186 
187     return gen_meta_key(fp, gpu, shaderCaps, primProc.getTransformKey(fp.coordTransforms(),
188                                                                       fp.numCoordTransforms()), b);
189 }
190 
Build(GrProgramDesc * desc,const GrRenderTarget * renderTarget,const GrPrimitiveProcessor & primProc,bool hasPointSize,const GrPipeline & pipeline,GrGpu * gpu)191 bool GrProgramDesc::Build(
192         GrProgramDesc* desc, const GrRenderTarget* renderTarget,
193         const GrPrimitiveProcessor& primProc, bool hasPointSize, const GrPipeline& pipeline,
194         GrGpu* gpu) {
195     // The descriptor is used as a cache key. Thus when a field of the
196     // descriptor will not affect program generation (because of the attribute
197     // bindings in use or other descriptor field settings) it should be set
198     // to a canonical value to avoid duplicate programs with different keys.
199 
200     const GrShaderCaps& shaderCaps = *gpu->caps()->shaderCaps();
201 
202     GR_STATIC_ASSERT(0 == kProcessorKeysOffset % sizeof(uint32_t));
203     // Make room for everything up to the effect keys.
204     desc->key().reset();
205     desc->key().push_back_n(kProcessorKeysOffset);
206 
207     GrProcessorKeyBuilder b(&desc->key());
208 
209     primProc.getGLSLProcessorKey(shaderCaps, &b);
210     primProc.getAttributeKey(&b);
211     if (!gen_meta_key(primProc, shaderCaps, 0, &b)) {
212         desc->key().reset();
213         return false;
214     }
215     GrProcessor::CustomFeatures processorFeatures = primProc.requestedFeatures();
216 
217     for (int i = 0; i < pipeline.numFragmentProcessors(); ++i) {
218         const GrFragmentProcessor& fp = pipeline.getFragmentProcessor(i);
219         if (!gen_frag_proc_and_meta_keys(primProc, fp, gpu, shaderCaps, &b)) {
220             desc->key().reset();
221             return false;
222         }
223         processorFeatures |= fp.requestedFeatures();
224     }
225 
226     const GrXferProcessor& xp = pipeline.getXferProcessor();
227     const GrSurfaceOrigin* originIfDstTexture = nullptr;
228     GrSurfaceOrigin origin;
229     if (pipeline.dstTextureProxy()) {
230         origin = pipeline.dstTextureProxy()->origin();
231         originIfDstTexture = &origin;
232     }
233     xp.getGLSLProcessorKey(shaderCaps, &b, originIfDstTexture);
234     if (!gen_meta_key(xp, shaderCaps, &b)) {
235         desc->key().reset();
236         return false;
237     }
238     processorFeatures |= xp.requestedFeatures();
239 
240     if (processorFeatures & GrProcessor::CustomFeatures::kSampleLocations) {
241         SkASSERT(pipeline.isHWAntialiasState());
242         b.add32(renderTarget->renderTargetPriv().getSamplePatternKey());
243     }
244 
245     // --------DO NOT MOVE HEADER ABOVE THIS LINE--------------------------------------------------
246     // Because header is a pointer into the dynamic array, we can't push any new data into the key
247     // below here.
248     KeyHeader* header = desc->atOffset<KeyHeader, kHeaderOffset>();
249 
250     // make sure any padding in the header is zeroed.
251     memset(header, 0, kHeaderSize);
252     header->fOutputSwizzle = pipeline.outputSwizzle().asKey();
253     header->fColorFragmentProcessorCnt = pipeline.numColorFragmentProcessors();
254     header->fCoverageFragmentProcessorCnt = pipeline.numCoverageFragmentProcessors();
255     // Fail if the client requested more processors than the key can fit.
256     if (header->fColorFragmentProcessorCnt != pipeline.numColorFragmentProcessors() ||
257         header->fCoverageFragmentProcessorCnt != pipeline.numCoverageFragmentProcessors()) {
258         return false;
259     }
260     header->fProcessorFeatures = (uint8_t)processorFeatures;
261     SkASSERT(header->processorFeatures() == processorFeatures);  // Ensure enough bits.
262     header->fSnapVerticesToPixelCenters = pipeline.snapVerticesToPixelCenters();
263     header->fHasPointSize = hasPointSize ? 1 : 0;
264     header->fClampBlendInput =
265             GrClampType::kManual == GrPixelConfigClampType(renderTarget->config()) ? 1 : 0;
266     return true;
267 }
268