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