• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2015 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 "GrVkProgramDesc.h"
8 
9 //#include "GrVkProcessor.h"
10 #include "GrProcessor.h"
11 #include "GrPipeline.h"
12 #include "GrVkGpu.h"
13 #include "GrVkUtil.h"
14 #include "SkChecksum.h"
15 #include "glsl/GrGLSLFragmentProcessor.h"
16 #include "glsl/GrGLSLFragmentShaderBuilder.h"
17 #include "glsl/GrGLSLCaps.h"
18 
19 #include "shaderc/shaderc.h"
20 
add_texture_key(GrProcessorKeyBuilder * b,const GrProcessor & proc,const GrGLSLCaps & caps)21 static void add_texture_key(GrProcessorKeyBuilder* b, const GrProcessor& proc,
22                             const GrGLSLCaps& caps) {
23     int numTextures = proc.numTextures();
24     // Need two bytes per key (swizzle and target).
25     int word32Count = (proc.numTextures() + 1) / 2;
26     if (0 == word32Count) {
27         return;
28     }
29     uint16_t* k16 = SkTCast<uint16_t*>(b->add32n(word32Count));
30     for (int i = 0; i < numTextures; ++i) {
31         const GrTextureAccess& access = proc.textureAccess(i);
32         GrTexture* texture = access.getTexture();
33         k16[i] = SkToU16(caps.configTextureSwizzle(texture->config()).asKey());
34     }
35     // zero the last 16 bits if the number of textures is odd.
36     if (numTextures & 0x1) {
37         k16[numTextures] = 0;
38     }
39 }
40 
41 /**
42 * A function which emits a meta key into the key builder.  This is required because shader code may
43 * be dependent on properties of the effect that the effect itself doesn't use
44 * in its key (e.g. the pixel format of textures used). So we create a meta-key for
45 * every effect using this function. It is also responsible for inserting the effect's class ID
46 * which must be different for every GrProcessor subclass. It can fail if an effect uses too many
47 * transforms, etc, for the space allotted in the meta-key.  NOTE, both FPs and GPs share this
48 * function because it is hairy, though FPs do not have attribs, and GPs do not have transforms
49 */
gen_meta_key(const GrProcessor & proc,const GrGLSLCaps & glslCaps,uint32_t transformKey,GrProcessorKeyBuilder * b)50 static bool gen_meta_key(const GrProcessor& proc,
51                          const GrGLSLCaps& glslCaps,
52                          uint32_t transformKey,
53                          GrProcessorKeyBuilder* b) {
54     size_t processorKeySize = b->size();
55     uint32_t classID = proc.classID();
56 
57     // Currently we allow 16 bits for the class id and the overall processor key size.
58     static const uint32_t kMetaKeyInvalidMask = ~((uint32_t)SK_MaxU16);
59     if ((processorKeySize | classID) & kMetaKeyInvalidMask) {
60         return false;
61     }
62 
63     add_texture_key(b, proc, glslCaps);
64 
65     uint32_t* key = b->add32n(2);
66     key[0] = (classID << 16) | SkToU32(processorKeySize);
67     key[1] = transformKey;
68     return true;
69 }
70 
gen_frag_proc_and_meta_keys(const GrPrimitiveProcessor & primProc,const GrFragmentProcessor & fp,const GrGLSLCaps & glslCaps,GrProcessorKeyBuilder * b)71 static bool gen_frag_proc_and_meta_keys(const GrPrimitiveProcessor& primProc,
72                                         const GrFragmentProcessor& fp,
73                                         const GrGLSLCaps& glslCaps,
74                                         GrProcessorKeyBuilder* b) {
75     for (int i = 0; i < fp.numChildProcessors(); ++i) {
76         if (!gen_frag_proc_and_meta_keys(primProc, fp.childProcessor(i), glslCaps, b)) {
77             return false;
78         }
79     }
80 
81     fp.getGLSLProcessorKey(glslCaps, b);
82 
83     return gen_meta_key(fp, glslCaps, primProc.getTransformKey(fp.coordTransforms(),
84         fp.numTransformsExclChildren()), b);
85 }
86 
Build(GrProgramDesc * desc,const GrPrimitiveProcessor & primProc,const GrPipeline & pipeline,const GrGLSLCaps & glslCaps)87 bool GrVkProgramDescBuilder::Build(GrProgramDesc* desc,
88                                    const GrPrimitiveProcessor& primProc,
89                                    const GrPipeline& pipeline,
90                                    const GrGLSLCaps& glslCaps) {
91     // The descriptor is used as a cache key. Thus when a field of the
92     // descriptor will not affect program generation (because of the attribute
93     // bindings in use or other descriptor field settings) it should be set
94     // to a canonical value to avoid duplicate programs with different keys.
95 
96     GrVkProgramDesc* vkDesc = (GrVkProgramDesc*)desc;
97 
98     GR_STATIC_ASSERT(0 == kProcessorKeysOffset % sizeof(uint32_t));
99     // Make room for everything up to the effect keys.
100     vkDesc->key().reset();
101     vkDesc->key().push_back_n(kProcessorKeysOffset);
102 
103     GrProcessorKeyBuilder b(&vkDesc->key());
104 
105     primProc.getGLSLProcessorKey(glslCaps, &b);
106     if (!gen_meta_key(primProc, glslCaps, 0, &b)) {
107         vkDesc->key().reset();
108         return false;
109     }
110 
111     for (int i = 0; i < pipeline.numFragmentProcessors(); ++i) {
112         const GrFragmentProcessor& fp = pipeline.getFragmentProcessor(i);
113         if (!gen_frag_proc_and_meta_keys(primProc, fp, glslCaps, &b)) {
114             vkDesc->key().reset();
115             return false;
116         }
117     }
118 
119     const GrXferProcessor& xp = pipeline.getXferProcessor();
120     xp.getGLSLProcessorKey(glslCaps, &b);
121     if (!gen_meta_key(xp, glslCaps, 0, &b)) {
122         vkDesc->key().reset();
123         return false;
124     }
125 
126     // --------DO NOT MOVE HEADER ABOVE THIS LINE--------------------------------------------------
127     // Because header is a pointer into the dynamic array, we can't push any new data into the key
128     // below here.
129     KeyHeader* header = vkDesc->atOffset<KeyHeader, kHeaderOffset>();
130 
131     // make sure any padding in the header is zeroed.
132     memset(header, 0, kHeaderSize);
133 
134     if (pipeline.readsFragPosition()) {
135         header->fFragPosKey =
136             GrGLSLFragmentShaderBuilder::KeyForFragmentPosition(pipeline.getRenderTarget());
137     } else {
138         header->fFragPosKey = 0;
139     }
140 
141     header->fOutputSwizzle =
142         glslCaps.configOutputSwizzle(pipeline.getRenderTarget()->config()).asKey();
143 
144     if (pipeline.ignoresCoverage()) {
145         header->fIgnoresCoverage = 1;
146     } else {
147         header->fIgnoresCoverage = 0;
148     }
149 
150     header->fSnapVerticesToPixelCenters = pipeline.snapVerticesToPixelCenters();
151     header->fColorEffectCnt = pipeline.numColorFragmentProcessors();
152     header->fCoverageEffectCnt = pipeline.numCoverageFragmentProcessors();
153     vkDesc->finalize();
154     return true;
155 }
156