1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 //    names, trademarks, service marks, or product names of the Licensor
11 //    and its affiliates, except as required to comply with Section 4(c) of
12 //    the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 //     http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 #include "pxr/imaging/glf/contextCaps.h"
25 #include "pxr/imaging/glf/simpleShadowArray.h"
26 
27 #include "pxr/imaging/hdSt/codeGen.h"
28 #include "pxr/imaging/hdSt/geometricShader.h"
29 #include "pxr/imaging/hdSt/glConversions.h"
30 #include "pxr/imaging/hdSt/glslProgram.h"
31 #include "pxr/imaging/hdSt/package.h"
32 #include "pxr/imaging/hdSt/resourceBinder.h"
33 #include "pxr/imaging/hdSt/shaderCode.h"
34 #include "pxr/imaging/hdSt/tokens.h"
35 
36 #include "pxr/imaging/hd/binding.h"
37 #include "pxr/imaging/hd/instanceRegistry.h"
38 #include "pxr/imaging/hd/resourceRegistry.h"
39 #include "pxr/imaging/hd/tokens.h"
40 #include "pxr/imaging/hd/vtBufferSource.h"
41 
42 #include "pxr/imaging/hio/glslfx.h"
43 
44 #include "pxr/base/tf/iterator.h"
45 #include "pxr/base/tf/staticTokens.h"
46 
47 #include <boost/functional/hash.hpp>
48 
49 #include <sstream>
50 
51 #include <opensubdiv/osd/glslPatchShaderSource.h>
52 
53 PXR_NAMESPACE_OPEN_SCOPE
54 
55 
56 TF_DEFINE_PRIVATE_TOKENS(
57     _tokens,
58     ((_double, "double"))
59     ((_float, "float"))
60     ((_int, "int"))
61     ((_uint, "uint"))
62     (hd_vec3)
63     (hd_vec3_get)
64     (hd_vec3_set)
65     (hd_ivec3)
66     (hd_ivec3_get)
67     (hd_ivec3_set)
68     (hd_dvec3)
69     (hd_dvec3_get)
70     (hd_dvec3_set)
71     (hd_mat3)
72     (hd_mat3_get)
73     (hd_mat3_set)
74     (hd_dmat3)
75     (hd_dmat3_get)
76     (hd_dmat3_set)
77     (hd_vec4_2_10_10_10_get)
78     (hd_vec4_2_10_10_10_set)
79     (hd_half2_get)
80     (hd_half2_set)
81     (hd_half4_get)
82     (hd_half4_set)
83     (inPrimvars)
84     (uvec2)
85     (uvec3)
86     (uvec4)
87     (ivec2)
88     (ivec3)
89     (ivec4)
90     (outPrimvars)
91     (vec2)
92     (vec3)
93     (vec4)
94     (dvec2)
95     (dvec3)
96     (dvec4)
97     (mat3)
98     (mat4)
99     (dmat3)
100     (dmat4)
101     (packed_2_10_10_10)
102     (packed_half2)
103     (packed_half4)
104     ((ptexTextureSampler, "ptexTextureSampler"))
105     (isamplerBuffer)
106     (samplerBuffer)
107 );
108 
HdSt_CodeGen(HdSt_GeometricShaderPtr const & geometricShader,HdStShaderCodeSharedPtrVector const & shaders,TfToken const & materialTag)109 HdSt_CodeGen::HdSt_CodeGen(HdSt_GeometricShaderPtr const &geometricShader,
110                        HdStShaderCodeSharedPtrVector const &shaders,
111                        TfToken const &materialTag)
112     : _geometricShader(geometricShader), _shaders(shaders),
113       _materialTag(materialTag)
114 {
115     TF_VERIFY(geometricShader);
116 }
117 
HdSt_CodeGen(HdStShaderCodeSharedPtrVector const & shaders)118 HdSt_CodeGen::HdSt_CodeGen(HdStShaderCodeSharedPtrVector const &shaders)
119     : _geometricShader(), _shaders(shaders)
120 {
121 }
122 
123 HdSt_CodeGen::ID
ComputeHash() const124 HdSt_CodeGen::ComputeHash() const
125 {
126     HD_TRACE_FUNCTION();
127     HF_MALLOC_TAG_FUNCTION();
128 
129     ID hash = _geometricShader ? _geometricShader->ComputeHash() : 0;
130     boost::hash_combine(hash, _metaData.ComputeHash());
131     boost::hash_combine(hash, HdStShaderCode::ComputeHash(_shaders));
132     boost::hash_combine(hash, _materialTag.Hash());
133 
134     return hash;
135 }
136 
137 static
138 std::string
_GetPtexTextureShaderSource()139 _GetPtexTextureShaderSource()
140 {
141     static std::string source =
142         HioGlslfx(HdStPackagePtexTextureShader()).GetSource(
143             _tokens->ptexTextureSampler);
144     return source;
145 }
146 
147 // TODO: Shuffle code to remove these declarations.
148 static void _EmitDeclaration(std::stringstream &str,
149                              TfToken const &name,
150                              TfToken const &type,
151                              HdBinding const &binding,
152                              int arraySize=0);
153 
154 static void _EmitStructAccessor(std::stringstream &str,
155                                 TfToken const &structName,
156                                 TfToken const &name,
157                                 TfToken const &type,
158                                 int arraySize,
159                                 const char *index);
160 
161 static void _EmitComputeAccessor(std::stringstream &str,
162                                  TfToken const &name,
163                                  TfToken const &type,
164                                  HdBinding const &binding,
165                                  const char *index);
166 
167 static void _EmitComputeMutator(std::stringstream &str,
168                                 TfToken const &name,
169                                 TfToken const &type,
170                                 HdBinding const &binding,
171                                 const char *index);
172 
173 static void _EmitAccessor(std::stringstream &str,
174                           TfToken const &name,
175                           TfToken const &type,
176                           HdBinding const &binding,
177                           const char *index=NULL);
178 /*
179   1. If the member is a scalar consuming N basic machine units,
180   the base alignment is N.
181   2. If the member is a two- or four-component vector with components
182   consuming N basic machine units, the base alignment is 2N or 4N,
183   respectively.
184   3. If the member is a three-component vector with components
185   consuming N basic machine units, the base alignment is 4N.
186   4. If the member is an array of scalars or vectors, the base
187   alignment and array stride are set to match the base alignment of
188   a single array element, according to rules (1), (2), and (3), and
189   rounded up to the base alignment of a vec4. The array may have
190   padding at the end; the base offset of the member following the
191   array is rounded up to the next multiple of the base alignment.
192 
193   9. If the member is a structure, the base alignment of the structure
194   is <N>, where <N> is the largest base alignment value of any of its
195   members, and rounded up to the base alignment of a vec4. The
196   individual members of this sub-structure are then assigned offsets
197   by applying this set of rules recursively, where the base offset of
198   the first member of the sub-structure is equal to the aligned offset
199   of the structure. The structure may have padding at the end; the
200   base offset of the member following the sub-structure is rounded up
201   to the next multiple of the base alignment of the structure.
202 
203   When using the std430 storage layout, shader storage blocks will be
204   laid out in buffer storage identically to uniform and shader storage
205   blocks using the std140 layout, except that the base alignment and
206   stride of arrays of scalars and vectors in rule 4 and of structures
207   in rule 9 are not rounded up a multiple of the base alignment of a
208   vec4.
209 
210   i.e. rule 3 is still applied in std430. we use an array of 3-element
211   struct instead of vec3/dvec3 to avoid this undesirable padding.
212 
213   struct instanceData0 {
214     float x, y, z;
215   }
216   buffer buffer0 {
217     instanceData0 data[];
218   };
219 */
220 
221 static const char *
_GetPackedTypeDefinitions()222 _GetPackedTypeDefinitions()
223 {
224     return "struct hd_ivec3 { int    x, y, z; };\n"
225            "struct hd_vec3  { float  x, y, z; };\n"
226            "struct hd_dvec3 { double x, y, z; };\n"
227            "struct hd_mat3  { float  m00, m01, m02,\n"
228            "                         m10, m11, m12,\n"
229            "                         m20, m21, m22; };\n"
230            "struct hd_dmat3 { double m00, m01, m02,\n"
231            "                         m10, m11, m12,\n"
232            "                         m20, m21, m22; };\n"
233            "ivec3 hd_ivec3_get(hd_ivec3 v) { return ivec3(v.x, v.y, v.z); }\n"
234            "ivec3 hd_ivec3_get(ivec3 v)    { return v; }\n"
235            "vec3  hd_vec3_get(hd_vec3 v)   { return vec3(v.x, v.y, v.z); }\n"
236            "vec3  hd_vec3_get(vec3 v)      { return v; }\n"
237            "dvec3 hd_dvec3_get(hd_dvec3 v) { return dvec3(v.x, v.y, v.z); }\n"
238            "dvec3 hd_dvec3_get(dvec3 v)    { return v; }\n"
239            "mat3  hd_mat3_get(hd_mat3 v)   { return mat3(v.m00, v.m01, v.m02,\n"
240            "                                             v.m10, v.m11, v.m12,\n"
241            "                                             v.m20, v.m21, v.m22); }\n"
242            "mat3  hd_mat3_get(mat3 v)      { return v; }\n"
243            "dmat3 hd_dmat3_get(hd_dmat3 v) { return dmat3(v.m00, v.m01, v.m02,\n"
244            "                                              v.m10, v.m11, v.m12,\n"
245            "                                              v.m20, v.m21, v.m22); }\n"
246            "dmat3 hd_dmat3_get(dmat3 v)    { return v; }\n"
247            "hd_ivec3 hd_ivec3_set(hd_ivec3 v) { return v; }\n"
248            "hd_ivec3 hd_ivec3_set(ivec3 v)    { return hd_ivec3(v.x, v.y, v.z); }\n"
249            "hd_vec3 hd_vec3_set(hd_vec3 v)    { return v; }\n"
250            "hd_vec3 hd_vec3_set(vec3 v)       { return hd_vec3(v.x, v.y, v.z); }\n"
251            "hd_dvec3 hd_dvec3_set(hd_dvec3 v) { return v; }\n"
252            "hd_dvec3 hd_dvec3_set(dvec3 v)    { return hd_dvec3(v.x, v.y, v.z); }\n"
253            "hd_mat3  hd_mat3_set(hd_mat3 v)   { return v; }\n"
254            "hd_mat3  hd_mat3_set(mat3 v)      { return hd_mat3(v[0][0], v[0][1], v[0][2],\n"
255            "                                                   v[1][0], v[1][1], v[1][2],\n"
256            "                                                   v[2][0], v[2][1], v[2][2]); }\n"
257            "hd_dmat3 hd_dmat3_set(hd_dmat3 v) { return v; }\n"
258            "hd_dmat3 hd_dmat3_set(dmat3 v)    { return hd_dmat3(v[0][0], v[0][1], v[0][2],\n"
259            "                                                    v[1][0], v[1][1], v[1][2],\n"
260            "                                                    v[2][0], v[2][1], v[2][2]); }\n"
261         // helper functions for 410 specification
262         // applying a swizzle operator on int and float is not allowed in 410.
263            "int hd_int_get(int v)          { return v; }\n"
264            "int hd_int_get(ivec2 v)        { return v.x; }\n"
265            "int hd_int_get(ivec3 v)        { return v.x; }\n"
266            "int hd_int_get(ivec4 v)        { return v.x; }\n"
267         // udim helper function
268             "vec3 hd_sample_udim(vec2 v) {\n"
269             "vec2 vf = floor(v);\n"
270             "return vec3(v.x - vf.x, v.y - vf.y, clamp(vf.x, 0.0, 10.0) + 10.0 * vf.y);\n"
271             "}\n"
272 
273         // -------------------------------------------------------------------
274         // Packed HdType implementation.
275 
276         // XXX: this could be improved!
277            "vec4 hd_vec4_2_10_10_10_get(int v) {\n"
278            "    ivec4 unpacked = ivec4((v & 0x3ff) << 22, (v & 0xffc00) << 12,\n"
279            "                           (v & 0x3ff00000) << 2, (v & 0xc0000000));\n"
280            "    return vec4(unpacked) / 2147483647.0; }\n"
281            "int hd_vec4_2_10_10_10_set(vec4 v) {\n"
282            "    return ( (int(v.x * 511.0) & 0x3ff) |\n"
283            "            ((int(v.y * 511.0) & 0x3ff) << 10) |\n"
284            "            ((int(v.z * 511.0) & 0x3ff) << 20) |\n"
285            "            ((int(v.w) & 0x1) << 30)); }\n"
286         // half2 and half4 accessors (note that half and half3 are unsupported)
287            "vec2 hd_half2_get(uint v) {\n"
288            "    return unpackHalf2x16(v); }\n"
289            "uint hd_half2_set(vec2 v) {\n"
290            "    return packHalf2x16(v); }\n"
291            "vec4 hd_half4_get(uvec2 v) {\n"
292            "    return vec4(unpackHalf2x16(v.x), unpackHalf2x16(v.y)); }\n"
293            "uvec2 hd_half4_set(vec4 v) {\n"
294            "    return uvec2(packHalf2x16(v.xy), packHalf2x16(v.zw)); }\n"
295            ;
296 }
297 
298 static TfToken const &
_GetPackedType(TfToken const & token,bool packedAlignment)299 _GetPackedType(TfToken const &token, bool packedAlignment)
300 {
301     if (packedAlignment) {
302         if (token == _tokens->ivec3) {
303             return _tokens->hd_ivec3;
304         } else if (token == _tokens->vec3) {
305             return _tokens->hd_vec3;
306         } else if (token == _tokens->dvec3) {
307             return _tokens->hd_dvec3;
308         } else if (token == _tokens->mat3) {
309             return _tokens->hd_mat3;
310         } else if (token == _tokens->dmat3) {
311             return _tokens->hd_dmat3;
312         }
313     }
314     if (token == _tokens->packed_2_10_10_10) {
315         return _tokens->_int;
316     }
317     if (token == _tokens->packed_half2) {
318         return _tokens->_uint;
319     }
320     if (token == _tokens->packed_half4) {
321         return _tokens->uvec2;
322     }
323     return token;
324 }
325 
326 static TfToken const &
_GetUnpackedType(TfToken const & token,bool packedAlignment)327 _GetUnpackedType(TfToken const &token, bool packedAlignment)
328 {
329     if (token == _tokens->packed_2_10_10_10) {
330         return _tokens->vec4;
331     }
332     if (token == _tokens->packed_half2) {
333         return _tokens->vec2;
334     }
335     if (token == _tokens->packed_half4) {
336         return _tokens->vec4;
337     }
338     return token;
339 }
340 
341 static TfToken const &
_GetPackedTypeAccessor(TfToken const & token,bool packedAlignment)342 _GetPackedTypeAccessor(TfToken const &token, bool packedAlignment)
343 {
344     if (packedAlignment) {
345         if (token == _tokens->ivec3) {
346             return _tokens->hd_ivec3_get;
347         } else if (token == _tokens->vec3) {
348             return _tokens->hd_vec3_get;
349         } else if (token == _tokens->dvec3) {
350             return _tokens->hd_dvec3_get;
351         } else if (token == _tokens->mat3) {
352             return _tokens->hd_mat3_get;
353         } else if (token == _tokens->dmat3) {
354             return _tokens->hd_dmat3_get;
355         }
356     }
357     if (token == _tokens->packed_2_10_10_10) {
358         return _tokens->hd_vec4_2_10_10_10_get;
359     }
360     if (token == _tokens->packed_half2) {
361         return _tokens->hd_half2_get;
362     }
363     if (token == _tokens->packed_half4) {
364         return _tokens->hd_half4_get;
365     }
366     return token;
367 }
368 
369 static TfToken const &
_GetPackedTypeMutator(TfToken const & token,bool packedAlignment)370 _GetPackedTypeMutator(TfToken const &token, bool packedAlignment)
371 {
372     if (packedAlignment) {
373         if (token == _tokens->ivec3) {
374             return _tokens->hd_ivec3_set;
375         } else if (token == _tokens->vec3) {
376             return _tokens->hd_vec3_set;
377         } else if (token == _tokens->dvec3) {
378             return _tokens->hd_dvec3_set;
379         } else if (token == _tokens->mat3) {
380             return _tokens->hd_mat3_set;
381         } else if (token == _tokens->dmat3) {
382             return _tokens->hd_dmat3_set;
383         }
384     }
385     if (token == _tokens->packed_2_10_10_10) {
386         return _tokens->hd_vec4_2_10_10_10_set;
387     }
388     if (token == _tokens->packed_half2) {
389         return _tokens->hd_half2_set;
390     }
391     if (token == _tokens->packed_half4) {
392         return _tokens->hd_half4_set;
393     }
394     return token;
395 }
396 
397 static TfToken const &
_GetFlatType(TfToken const & token)398 _GetFlatType(TfToken const &token)
399 {
400     if (token == _tokens->ivec2) {
401         return _tokens->_int;
402     } else if (token == _tokens->ivec3) {
403         return _tokens->_int;
404     } else if (token == _tokens->ivec4) {
405         return _tokens->_int;
406     } else if (token == _tokens->vec2) {
407         return _tokens->_float;
408     } else if (token == _tokens->vec3) {
409         return _tokens->_float;
410     } else if (token == _tokens->vec4) {
411         return _tokens->_float;
412     } else if (token == _tokens->dvec2) {
413         return _tokens->_double;
414     } else if (token == _tokens->dvec3) {
415         return _tokens->_double;
416     } else if (token == _tokens->dvec4) {
417         return _tokens->_double;
418     } else if (token == _tokens->mat3) {
419         return _tokens->_float;
420     } else if (token == _tokens->mat4) {
421         return _tokens->_float;
422     } else if (token == _tokens->dmat3) {
423         return _tokens->_double;
424     } else if (token == _tokens->dmat4) {
425         return _tokens->_double;
426     }
427     return token;
428 }
429 
430 namespace {
431     struct LayoutQualifier {
LayoutQualifier__anon82e156170111::LayoutQualifier432         LayoutQualifier(HdBinding const &binding) :
433             binding(binding) {
434         }
435         friend std::ostream & operator << (std::ostream & out,
436                                            const LayoutQualifier &lq);
437         HdBinding binding;
438     };
operator <<(std::ostream & out,const LayoutQualifier & lq)439     std::ostream & operator << (std::ostream & out, const LayoutQualifier &lq)
440     {
441         GlfContextCaps const &caps = GlfContextCaps::GetInstance();
442         int location = lq.binding.GetLocation();
443 
444         switch (lq.binding.GetType()) {
445         case HdBinding::VERTEX_ATTR:
446         case HdBinding::DRAW_INDEX:
447         case HdBinding::DRAW_INDEX_INSTANCE:
448         case HdBinding::DRAW_INDEX_INSTANCE_ARRAY:
449             // ARB_explicit_attrib_location is supported since GL 3.3
450             out << "layout (location = " << location << ") ";
451             break;
452         case HdBinding::UNIFORM:
453         case HdBinding::UNIFORM_ARRAY:
454         case HdBinding::BINDLESS_UNIFORM:
455         case HdBinding::BINDLESS_SSBO_RANGE:
456             if (caps.explicitUniformLocation) {
457                 out << "layout (location = " << location << ") ";
458             }
459             break;
460         case HdBinding::TEXTURE_2D:
461         case HdBinding::BINDLESS_TEXTURE_2D:
462         case HdBinding::TEXTURE_FIELD:
463         case HdBinding::BINDLESS_TEXTURE_FIELD:
464         case HdBinding::TEXTURE_UDIM_ARRAY:
465         case HdBinding::BINDLESS_TEXTURE_UDIM_ARRAY:
466         case HdBinding::TEXTURE_UDIM_LAYOUT:
467         case HdBinding::BINDLESS_TEXTURE_UDIM_LAYOUT:
468         case HdBinding::TEXTURE_PTEX_TEXEL:
469         case HdBinding::BINDLESS_TEXTURE_PTEX_TEXEL:
470         case HdBinding::TEXTURE_PTEX_LAYOUT:
471         case HdBinding::BINDLESS_TEXTURE_PTEX_LAYOUT:
472             if (caps.shadingLanguage420pack) {
473                 out << "layout (binding = "
474                     << lq.binding.GetTextureUnit() << ") ";
475             } else if (caps.explicitUniformLocation) {
476                 out << "layout (location = " << location << ") ";
477             }
478             break;
479         case HdBinding::SSBO:
480             out << "layout (std430, binding = " << location << ") ";
481             break;
482         case HdBinding::UBO:
483             if (caps.shadingLanguage420pack) {
484                 out << "layout (std140, binding = " << location << ") ";
485             } else {
486                 out << "layout (std140)";
487             }
488             break;
489         default:
490             break;
491         }
492         return out;
493     }
494 }
495 
496 HdStGLSLProgramSharedPtr
Compile(HdStResourceRegistry * const registry)497 HdSt_CodeGen::Compile(HdStResourceRegistry*const registry)
498 {
499     HD_TRACE_FUNCTION();
500     HF_MALLOC_TAG_FUNCTION();
501 
502     // shader sources
503     // geometric shader owns main()
504     std::string vertexShader =
505         _geometricShader->GetSource(HdShaderTokens->vertexShader);
506     std::string tessControlShader =
507         _geometricShader->GetSource(HdShaderTokens->tessControlShader);
508     std::string tessEvalShader =
509         _geometricShader->GetSource(HdShaderTokens->tessEvalShader);
510     std::string geometryShader =
511         _geometricShader->GetSource(HdShaderTokens->geometryShader);
512     std::string fragmentShader =
513         _geometricShader->GetSource(HdShaderTokens->fragmentShader);
514 
515     bool hasVS  = (!vertexShader.empty());
516     bool hasTCS = (!tessControlShader.empty());
517     bool hasTES = (!tessEvalShader.empty());
518     bool hasGS  = (!geometryShader.empty());
519     bool hasFS  = (!fragmentShader.empty());
520 
521     // create GLSL program.
522     HdStGLSLProgramSharedPtr glslProgram =
523         std::make_shared<HdStGLSLProgram>(HdTokens->drawingShader, registry);
524 
525     // initialize autogen source buckets
526     _genCommon.str(""); _genVS.str(""); _genTCS.str(""); _genTES.str("");
527     _genGS.str(""); _genFS.str(""); _genCS.str("");
528     _procVS.str(""); _procTCS.str(""), _procTES.str(""), _procGS.str("");
529 
530     // GLSL version.
531     GlfContextCaps const &caps = GlfContextCaps::GetInstance();
532     _genCommon << "#version " << caps.glslVersion << "\n";
533 
534     if (caps.bindlessBufferEnabled) {
535         _genCommon << "#extension GL_NV_shader_buffer_load : require\n"
536                    << "#extension GL_NV_gpu_shader5 : require\n";
537     }
538     if (caps.bindlessTextureEnabled) {
539         _genCommon << "#extension GL_ARB_bindless_texture : require\n";
540     }
541     // XXX: Skip checking the context caps for whether the bindless texture
542     // extension is available when bindless shadow maps are enabled. This needs
543     // to be done because GlfSimpleShadowArray is used internally in a manner
544     // wherein context caps initialization might not have happened.
545     if (GlfSimpleShadowArray::GetBindlessShadowMapsEnabled()) {
546         _genCommon << "#extension GL_ARB_bindless_texture : require\n";
547     }
548     if (caps.glslVersion < 460 && caps.shaderDrawParametersEnabled) {
549         _genCommon << "#extension GL_ARB_shader_draw_parameters : require\n";
550     }
551     if (caps.glslVersion < 430 && caps.explicitUniformLocation) {
552         _genCommon << "#extension GL_ARB_explicit_uniform_location : require\n";
553     }
554     if (caps.glslVersion < 420 && caps.shadingLanguage420pack) {
555         _genCommon << "#extension GL_ARB_shading_language_420pack : require\n";
556     }
557 
558     // Used in glslfx files to determine if it is using new/old
559     // imaging system. It can also be used as API guards when
560     // we need new versions of Storm shading.
561     _genCommon << "#define HD_SHADER_API " << HD_SHADER_API << "\n";
562 
563     // XXX: this is a hacky workaround for experimental support of GL 3.3
564     //      the double is used in hd_dvec3 akin, so we are likely able to
565     //      refactor that helper functions.
566     if (caps.glslVersion < 400) {
567         _genCommon << "#define double float\n"
568                    << "#define dvec2 vec2\n"
569                    << "#define dvec3 vec3\n"
570                    << "#define dvec4 vec4\n"
571                    << "#define dmat4 mat4\n";
572     }
573 
574     // XXX: this macro is still used in GlobalUniform.
575     _genCommon << "#define MAT4 " <<
576         HdStGLConversions::GetGLSLTypename(
577             HdVtBufferSource::GetDefaultMatrixType()) << "\n";
578     // a trick to tightly pack unaligned data (vec3, etc) into SSBO/UBO.
579     _genCommon << _GetPackedTypeDefinitions();
580 
581     if (_materialTag == HdStMaterialTagTokens->masked) {
582         _genFS << "#define HD_MATERIAL_TAG_MASKED 1\n";
583     }
584 
585     // ------------------
586     // Custom Buffer Bindings
587     // ----------------------
588     // For custom buffer bindings, more code can be generated; a full spec is
589     // emitted based on the binding declaration.
590     TF_FOR_ALL(binDecl, _metaData.customBindings) {
591         _genCommon << "#define "
592                    << binDecl->name << "_Binding "
593                    << binDecl->binding.GetLocation() << "\n";
594         _genCommon << "#define HD_HAS_" << binDecl->name << " 1\n";
595 
596         // typeless binding doesn't need declaration nor accessor.
597         if (binDecl->dataType.IsEmpty()) continue;
598 
599         _EmitDeclaration(_genCommon,
600                      binDecl->name,
601                      binDecl->dataType,
602                      binDecl->binding);
603         _EmitAccessor(_genCommon,
604                       binDecl->name,
605                       binDecl->dataType,
606                       binDecl->binding,
607                       (binDecl->binding.GetType() == HdBinding::UNIFORM)
608                       ? NULL : "localIndex");
609     }
610 
611     std::stringstream declarations;
612     std::stringstream accessors;
613     TF_FOR_ALL(it, _metaData.customInterleavedBindings) {
614         // note: _constantData has been sorted by offset in HdSt_ResourceBinder.
615         // XXX: not robust enough, should consider padding and layouting rules
616         // to match with the logic in HdInterleavedMemoryManager if we
617         // want to use a layouting policy other than default padding.
618 
619         HdBinding binding = it->first;
620         TfToken typeName(TfStringPrintf("CustomBlockData%d", binding.GetValue()));
621         TfToken varName = it->second.blockName;
622 
623         declarations << "struct " << typeName << " {\n";
624 
625         // dbIt is StructEntry { name, dataType, offset, numElements }
626         TF_FOR_ALL (dbIt, it->second.entries) {
627             _genCommon << "#define HD_HAS_" << dbIt->name << " 1\n";
628             declarations << "  " << _GetPackedType(dbIt->dataType, false)
629                          << " " << dbIt->name;
630             if (dbIt->arraySize > 1) {
631                 _genCommon << "#define HD_NUM_" << dbIt->name
632                            << " " << dbIt->arraySize << "\n";
633                 declarations << "[" << dbIt->arraySize << "]";
634             }
635             declarations <<  ";\n";
636 
637             _EmitStructAccessor(accessors, varName,
638                                 dbIt->name, dbIt->dataType, dbIt->arraySize,
639                                 NULL);
640         }
641 
642         declarations << "};\n";
643         _EmitDeclaration(declarations, varName, typeName, binding);
644     }
645     _genCommon << declarations.str()
646                << accessors.str();
647 
648     // HD_NUM_PATCH_VERTS, HD_NUM_PRIMTIIVE_VERTS
649     if (_geometricShader->IsPrimTypePatches()) {
650         _genCommon << "#define HD_NUM_PATCH_VERTS "
651                    << _geometricShader->GetPrimitiveIndexSize() << "\n";
652         _genCommon << "#define HD_NUM_PATCH_EVAL_VERTS "
653                    << _geometricShader->GetNumPatchEvalVerts() << "\n";
654     }
655     _genCommon << "#define HD_NUM_PRIMITIVE_VERTS "
656                << _geometricShader->GetNumPrimitiveVertsForGeometryShader()
657                << "\n";
658 
659     // include ptex utility (if needed)
660     TF_FOR_ALL (it, _metaData.shaderParameterBinding) {
661         HdBinding::Type bindingType = it->first.GetType();
662         if (bindingType == HdBinding::TEXTURE_PTEX_TEXEL ||
663             bindingType == HdBinding::BINDLESS_TEXTURE_PTEX_TEXEL) {
664             _genCommon << _GetPtexTextureShaderSource();
665             break;
666         }
667     }
668 
669     TF_FOR_ALL (it, _metaData.topologyVisibilityData) {
670         TF_FOR_ALL (pIt, it->second.entries) {
671             _genCommon << "#define HD_HAS_" << pIt->name  << " 1\n";
672         }
673     }
674 
675     // primvar existence macros
676 
677     // XXX: this is temporary, until we implement the fallback value definition
678     // for any primvars used in glslfx.
679     // Note that this #define has to be considered in the hash computation
680     // since it changes the source code. However we have already combined the
681     // entries of instanceData into the hash value, so it's not needed to be
682     // added separately, at least in current usage.
683     TF_FOR_ALL (it, _metaData.constantData) {
684         TF_FOR_ALL (pIt, it->second.entries) {
685             _genCommon << "#define HD_HAS_" << pIt->name << " 1\n";
686         }
687     }
688     TF_FOR_ALL (it, _metaData.instanceData) {
689         _genCommon << "#define HD_HAS_INSTANCE_" << it->second.name << " 1\n";
690         _genCommon << "#define HD_HAS_"
691                    << it->second.name << "_" << it->second.level << " 1\n";
692     }
693     _genCommon << "#define HD_INSTANCER_NUM_LEVELS "
694                << _metaData.instancerNumLevels << "\n"
695                << "#define HD_INSTANCE_INDEX_WIDTH "
696                << (_metaData.instancerNumLevels+1) << "\n";
697    if (!_geometricShader->IsPrimTypePoints()) {
698       TF_FOR_ALL (it, _metaData.elementData) {
699         _genCommon << "#define HD_HAS_" << it->second.name << " 1\n";
700       }
701       if (hasGS) {
702         TF_FOR_ALL (it, _metaData.fvarData) {
703            _genCommon << "#define HD_HAS_" << it->second.name << " 1\n";
704         }
705       }
706     }
707     TF_FOR_ALL (it, _metaData.vertexData) {
708         _genCommon << "#define HD_HAS_" << it->second.name << " 1\n";
709     }
710     TF_FOR_ALL (it, _metaData.varyingData) {
711         _genCommon << "#define HD_HAS_" << it->second.name << " 1\n";
712     }
713     TF_FOR_ALL (it, _metaData.shaderParameterBinding) {
714         // XXX: HdBinding::PRIMVAR_REDIRECT won't define an accessor if it's
715         // an alias of like-to-like, so we want to suppress the HD_HAS_* flag
716         // as well.
717 
718         // For PRIMVAR_REDIRECT, the HD_HAS_* flag will be defined after
719         // the corresponding HdGet_* function.
720 
721         // XXX: (HYD-1882) The #define HD_HAS_... for a primvar
722         // redirect will be defined immediately after the primvar
723         // redirect HdGet_... in the loop over
724         // _metaData.shaderParameterBinding below.  Given that this
725         // loop is not running in a canonical order (e.g., textures
726         // first, then primvar redirects, ...) and that the texture is
727         // picking up the HD_HAS_... flag, the answer to the following
728         // question is random:
729         //
730         // If there is a texture trying to use a primvar called NAME
731         // for coordinates and there is a primvar redirect called NAME,
732         // will the texture use it or not?
733         //
734         HdBinding::Type bindingType = it->first.GetType();
735         if (bindingType != HdBinding::PRIMVAR_REDIRECT) {
736             _genCommon << "#define HD_HAS_" << it->second.name << " 1\n";
737         }
738 
739         // For any texture shader parameter we also emit the texture
740         // coordinates associated with it
741         if (bindingType == HdBinding::TEXTURE_2D ||
742             bindingType == HdBinding::BINDLESS_TEXTURE_2D ||
743             bindingType == HdBinding::TEXTURE_UDIM_ARRAY ||
744             bindingType == HdBinding::BINDLESS_TEXTURE_UDIM_ARRAY) {
745             _genCommon
746                 << "#define HD_HAS_COORD_" << it->second.name << " 1\n";
747         }
748     }
749 
750     // mixin shaders
751     _genCommon << _geometricShader->GetSource(HdShaderTokens->commonShaderSource);
752     TF_FOR_ALL(it, _shaders) {
753         _genCommon << (*it)->GetSource(HdShaderTokens->commonShaderSource);
754     }
755 
756     // Needed for patch-based face-varying primvar refinement
757     if (_geometricShader->GetFvarPatchType() ==
758         HdSt_GeometricShader::FvarPatchType::PATCH_BSPLINE ||
759         _geometricShader->GetFvarPatchType() ==
760         HdSt_GeometricShader::FvarPatchType::PATCH_BOXSPLINETRIANGLE) {
761         _genGS << "#define OSD_PATCH_BASIS_GLSL\n";
762         _genGS <<
763             OpenSubdiv::Osd::GLSLPatchShaderSource::GetPatchBasisShaderSource();
764     }
765 
766     // Barycentric coordinates
767     if (hasGS) {
768         _genGS << "noperspective out vec3 hd_barycentricCoord;\n";
769         _genFS << "noperspective in vec3 hd_barycentricCoord;\n"
770                   "vec3 GetBarycentricCoord() {\n"
771                   "  return hd_barycentricCoord;\n"
772                   "}\n";
773     }
774 
775     // prep interstage plumbing function
776     _procVS  << "void ProcessPrimvars() {\n";
777     _procTCS << "void ProcessPrimvars() {\n";
778     _procTES << "float ProcessPrimvar(float inPv0, float inPv1, float inPv2, float inPv3, vec4 basis, vec2 uv);\n";
779     _procTES << "vec2 ProcessPrimvar(vec2 inPv0, vec2 inPv1, vec2 inPv2, vec2 inPv3, vec4 basis, vec2 uv);\n";
780     _procTES << "vec3 ProcessPrimvar(vec3 inPv0, vec3 inPv1, vec3 inPv2, vec3 inPv3, vec4 basis, vec2 uv);\n";
781     _procTES << "vec4 ProcessPrimvar(vec4 inPv0, vec4 inPv1, vec4 inPv3, vec4 inPv3, vec4 basis, vec2 uv);\n";
782     _procTES << "void ProcessPrimvars(vec4 basis, int i0, int i1, int i2, int i3, vec2 uv) {\n";
783     // geometry shader plumbing
784     switch(_geometricShader->GetPrimitiveType())
785     {
786         case HdSt_GeometricShader::PrimitiveType::PRIM_MESH_COARSE_QUADS:
787         case HdSt_GeometricShader::PrimitiveType::PRIM_MESH_COARSE_TRIANGLES:
788         case HdSt_GeometricShader::PrimitiveType::PRIM_MESH_REFINED_QUADS:
789         case HdSt_GeometricShader::PrimitiveType::PRIM_MESH_REFINED_TRIANGLES:
790         {
791             _procGS << "vec4 GetPatchCoord(int index);\n"
792                     << "void ProcessPrimvars(int index) {\n"
793                     << "  vec2 localST = GetPatchCoord(index).xy;\n";
794             break;
795         }
796         case HdSt_GeometricShader::PrimitiveType::PRIM_MESH_BSPLINE:
797         case HdSt_GeometricShader::PrimitiveType::PRIM_MESH_BOXSPLINETRIANGLE:
798         {
799             _procGS << "void ProcessPrimvars(int index, vec2 tessST) {\n"
800                     << "  vec2 localST = tessST;\n";
801             break;
802         }
803         default: // points, basis curves
804             // do nothing. no additional code needs to be generated.
805             ;
806     }
807     switch(_geometricShader->GetPrimitiveType())
808     {
809         case HdSt_GeometricShader::PrimitiveType::PRIM_MESH_COARSE_QUADS:
810         case HdSt_GeometricShader::PrimitiveType::PRIM_MESH_REFINED_QUADS:
811         case HdSt_GeometricShader::PrimitiveType::PRIM_MESH_BSPLINE:
812         {
813             // These correspond to built-in fragment shader barycentric coords
814             // except reversed for the second triangle in the quad. Each quad is
815             // split into two triangles with indices (3,0,2) and (1,2,0).
816             _procGS << "  const vec3 coords[4] = vec3[](\n"
817                     << "   vec3(0,0,1), vec3(1,0,0), vec3(0,1,0), vec3(1,0,0)\n"
818                     << "  );\n"
819                     << "  hd_barycentricCoord = coords[index];\n";
820             break;
821         }
822         case HdSt_GeometricShader::PrimitiveType::PRIM_MESH_COARSE_TRIANGLES:
823         case HdSt_GeometricShader::PrimitiveType::PRIM_MESH_REFINED_TRIANGLES:
824         case HdSt_GeometricShader::PrimitiveType::PRIM_MESH_BOXSPLINETRIANGLE:
825         {
826             // These correspond to built-in fragment shader barycentric coords.
827             _procGS << "  const vec3 coords[3] = vec3[](\n"
828                     << "   vec3(1,0,0), vec3(0,1,0), vec3(0,0,1)\n"
829                     << "  );\n"
830                     << "  hd_barycentricCoord = coords[index];\n";
831             break;
832         }
833         default: // points, basis curves
834             // do nothing. no additional code needs to be generated.
835             ;
836     }
837 
838     // generate drawing coord and accessors
839     _GenerateDrawingCoord();
840 
841     // generate primvars
842     _GenerateConstantPrimvar();
843     _GenerateInstancePrimvar();
844     _GenerateElementPrimvar();
845     _GenerateVertexAndFaceVaryingPrimvar(hasGS);
846 
847     _GenerateTopologyVisibilityParameters();
848 
849     //generate shader parameters (is going last since it has primvar redirects)
850     _GenerateShaderParameters();
851 
852     // finalize buckets
853     _procVS  << "}\n";
854     _procGS  << "}\n";
855     _procTCS << "}\n";
856     _procTES << "}\n";
857 
858     // insert interstage primvar plumbing procs into genVS/TCS/TES/GS
859     _genVS  << _procVS.str();
860     _genTCS << _procTCS.str();
861     _genTES << _procTES.str();
862     _genGS  << _procGS.str();
863 
864 
865     // other shaders (renderpass, lighting, surface) first
866     TF_FOR_ALL(it, _shaders) {
867         HdStShaderCodeSharedPtr const &shader = *it;
868         if (hasVS)
869             _genVS  << shader->GetSource(HdShaderTokens->vertexShader);
870         if (hasTCS)
871             _genTCS << shader->GetSource(HdShaderTokens->tessControlShader);
872         if (hasTES)
873             _genTES << shader->GetSource(HdShaderTokens->tessEvalShader);
874         if (hasGS)
875             _genGS  << shader->GetSource(HdShaderTokens->geometryShader);
876         if (hasFS)
877             _genFS  << shader->GetSource(HdShaderTokens->fragmentShader);
878     }
879 
880     // OpenSubdiv tessellation shader (if required)
881     if (tessControlShader.find("OsdPerPatchVertexBezier") != std::string::npos) {
882         _genTCS << OpenSubdiv::Osd::GLSLPatchShaderSource::GetCommonShaderSource();
883         _genTCS << "MAT4 GetWorldToViewMatrix();\n";
884         _genTCS << "MAT4 GetProjectionMatrix();\n";
885         _genTCS << "float GetTessLevel();\n";
886         // we apply modelview in the vertex shader, so the osd shaders doesn't need
887         // to apply again.
888         _genTCS << "mat4 OsdModelViewMatrix() { return mat4(1); }\n";
889         _genTCS << "mat4 OsdProjectionMatrix() { return mat4(GetProjectionMatrix()); }\n";
890         _genTCS << "int OsdPrimitiveIdBase() { return 0; }\n";
891         _genTCS << "float OsdTessLevel() { return GetTessLevel(); }\n";
892     }
893     if (tessEvalShader.find("OsdPerPatchVertexBezier") != std::string::npos) {
894         _genTES << OpenSubdiv::Osd::GLSLPatchShaderSource::GetCommonShaderSource();
895         _genTES << "mat4 OsdModelViewMatrix() { return mat4(1); }\n";
896     }
897     if (geometryShader.find("OsdInterpolatePatchCoord") != std::string::npos) {
898         _genGS <<  OpenSubdiv::Osd::GLSLPatchShaderSource::GetCommonShaderSource();
899     }
900 
901     // geometric shader
902     _genVS  << vertexShader;
903     _genTCS << tessControlShader;
904     _genTES << tessEvalShader;
905     _genGS  << geometryShader;
906     _genFS  << fragmentShader;
907 
908     // Sanity check that if you provide a control shader, you have also provided
909     // an evaluation shader (and vice versa)
910     if (hasTCS ^ hasTES) {
911         TF_CODING_ERROR(
912             "tessControlShader and tessEvalShader must be provided together.");
913         hasTCS = hasTES = false;
914     };
915 
916     bool shaderCompiled = false;
917     // compile shaders
918     // note: _vsSource, _fsSource etc are used for diagnostics (see header)
919     if (hasVS) {
920         _vsSource = _genCommon.str() + _genVS.str();
921         if (!glslProgram->CompileShader(HgiShaderStageVertex, _vsSource)) {
922             return HdStGLSLProgramSharedPtr();
923         }
924         shaderCompiled = true;
925     }
926     if (hasFS) {
927         _fsSource = _genCommon.str() + _genFS.str();
928         if (!glslProgram->CompileShader(HgiShaderStageFragment, _fsSource)) {
929             return HdStGLSLProgramSharedPtr();
930         }
931         shaderCompiled = true;
932     }
933     if (hasTCS) {
934         _tcsSource = _genCommon.str() + _genTCS.str();
935         if (!glslProgram->CompileShader(
936                 HgiShaderStageTessellationControl, _tcsSource)) {
937             return HdStGLSLProgramSharedPtr();
938         }
939         shaderCompiled = true;
940     }
941     if (hasTES) {
942         _tesSource = _genCommon.str() + _genTES.str();
943         if (!glslProgram->CompileShader(
944                 HgiShaderStageTessellationEval, _tesSource)) {
945             return HdStGLSLProgramSharedPtr();
946         }
947         shaderCompiled = true;
948     }
949     if (hasGS) {
950         _gsSource = _genCommon.str() + _genGS.str();
951         if (!glslProgram->CompileShader(HgiShaderStageGeometry, _gsSource)) {
952             return HdStGLSLProgramSharedPtr();
953         }
954         shaderCompiled = true;
955     }
956 
957     if (!shaderCompiled) {
958         return HdStGLSLProgramSharedPtr();
959     }
960 
961     return glslProgram;
962 }
963 
964 HdStGLSLProgramSharedPtr
CompileComputeProgram(HdStResourceRegistry * const registry)965 HdSt_CodeGen::CompileComputeProgram(HdStResourceRegistry*const registry)
966 {
967     HD_TRACE_FUNCTION();
968     HF_MALLOC_TAG_FUNCTION();
969 
970     // initialize autogen source buckets
971     _genCommon.str(""); _genVS.str(""); _genTCS.str(""); _genTES.str("");
972     _genGS.str(""); _genFS.str(""); _genCS.str("");
973     _procVS.str(""); _procTCS.str(""), _procTES.str(""), _procGS.str("");
974 
975     // GLSL version.
976     GlfContextCaps const &caps = GlfContextCaps::GetInstance();
977     _genCommon << "#version " << caps.glslVersion << "\n";
978 
979     if (caps.bindlessBufferEnabled) {
980         _genCommon << "#extension GL_NV_shader_buffer_load : require\n"
981                    << "#extension GL_NV_gpu_shader5 : require\n";
982     }
983     if (caps.bindlessTextureEnabled) {
984         _genCommon << "#extension GL_ARB_bindless_texture : require\n";
985     }
986     if (caps.glslVersion < 430 && caps.explicitUniformLocation) {
987         _genCommon << "#extension GL_ARB_explicit_uniform_location : require\n";
988     }
989     if (caps.glslVersion < 420 && caps.shadingLanguage420pack) {
990         _genCommon << "#extension GL_ARB_shading_language_420pack : require\n";
991     }
992 
993     // default workgroup size (must follow #extension directives)
994     _genCommon << "layout(local_size_x = 1, local_size_y = 1) in;\n";
995 
996     // Used in glslfx files to determine if it is using new/old
997     // imaging system. It can also be used as API guards when
998     // we need new versions of Storm shading.
999     _genCommon << "#define HD_SHADER_API " << HD_SHADER_API << "\n";
1000 
1001     // a trick to tightly pack unaligned data (vec3, etc) into SSBO/UBO.
1002     _genCommon << _GetPackedTypeDefinitions();
1003 
1004     std::stringstream uniforms;
1005     std::stringstream declarations;
1006     std::stringstream accessors;
1007 
1008     uniforms << "// Uniform block\n";
1009 
1010     HdBinding uboBinding(HdBinding::UBO, 0);
1011     uniforms << LayoutQualifier(uboBinding);
1012     uniforms << "uniform ubo_" << uboBinding.GetLocation() << " {\n";
1013 
1014     accessors << "// Read-Write Accessors & Mutators\n";
1015     uniforms << "    int vertexOffset;       // offset in aggregated buffer\n";
1016     TF_FOR_ALL(it, _metaData.computeReadWriteData) {
1017         TfToken const &name = it->second.name;
1018         HdBinding const &binding = it->first;
1019         TfToken const &dataType = it->second.dataType;
1020 
1021         // For now, SSBO bindings use a flat type encoding.
1022         TfToken declDataType =
1023             (binding.GetType() == HdBinding::SSBO
1024                 ? _GetFlatType(dataType) : dataType);
1025 
1026         uniforms << "    int " << name << "Offset;\n";
1027         uniforms << "    int " << name << "Stride;\n";
1028 
1029         _EmitDeclaration(declarations,
1030                 name,
1031                 declDataType,
1032                 binding, 0);
1033         // getter & setter
1034         {
1035             std::stringstream indexing;
1036             indexing << "(localIndex + vertexOffset)"
1037                      << " * " << name << "Stride"
1038                      << " + " << name << "Offset";
1039             _EmitComputeAccessor(accessors, name, dataType, binding,
1040                     indexing.str().c_str());
1041             _EmitComputeMutator(accessors, name, dataType, binding,
1042                     indexing.str().c_str());
1043         }
1044     }
1045     accessors << "// Read-Only Accessors\n";
1046     // no vertex offset for constant data
1047     TF_FOR_ALL(it, _metaData.computeReadOnlyData) {
1048         TfToken const &name = it->second.name;
1049         HdBinding const &binding = it->first;
1050         TfToken const &dataType = it->second.dataType;
1051 
1052         // For now, SSBO bindings use a flat type encoding.
1053         TfToken declDataType =
1054             (binding.GetType() == HdBinding::SSBO
1055                 ? _GetFlatType(dataType) : dataType);
1056 
1057         uniforms << "    int " << name << "Offset;\n";
1058         uniforms << "    int " << name << "Stride;\n";
1059 
1060         _EmitDeclaration(declarations,
1061                 name,
1062                 declDataType,
1063                 binding, 0);
1064         // getter
1065         {
1066             std::stringstream indexing;
1067             // no vertex offset for constant data
1068             indexing << "(localIndex)"
1069                      << " * " << name << "Stride"
1070                      << " + " << name << "Offset";
1071             _EmitComputeAccessor(accessors, name, dataType, binding,
1072                     indexing.str().c_str());
1073         }
1074     }
1075     uniforms << "};\n";
1076 
1077     _genCommon << uniforms.str()
1078                << declarations.str()
1079                << accessors.str();
1080 
1081     // other shaders (renderpass, lighting, surface) first
1082     TF_FOR_ALL(it, _shaders) {
1083         HdStShaderCodeSharedPtr const &shader = *it;
1084         _genCS  << shader->GetSource(HdShaderTokens->computeShader);
1085     }
1086 
1087     // main
1088     _genCS << "void main() {\n";
1089     _genCS << "  int computeCoordinate = int(gl_GlobalInvocationID.x);\n";
1090     _genCS << "  compute(computeCoordinate);\n";
1091     _genCS << "}\n";
1092 
1093     // create GLSL program.
1094     HdStGLSLProgramSharedPtr glslProgram =
1095         std::make_shared<HdStGLSLProgram>(HdTokens->computeShader, registry);
1096 
1097     // compile shaders
1098     {
1099         _csSource = _genCommon.str() + _genCS.str();
1100         if (!glslProgram->CompileShader(HgiShaderStageCompute, _csSource)) {
1101             HgiShaderProgramHandle const& prg = glslProgram->GetProgram();
1102             std::string const& logString = prg->GetCompileErrors();
1103             TF_WARN("Failed to compile compute shader: %s",
1104                     logString.c_str());
1105             return HdStGLSLProgramSharedPtr();
1106         }
1107     }
1108 
1109     return glslProgram;
1110 }
1111 
_EmitDeclaration(std::stringstream & str,TfToken const & name,TfToken const & type,HdBinding const & binding,int arraySize)1112 static void _EmitDeclaration(std::stringstream &str,
1113                              TfToken const &name,
1114                              TfToken const &type,
1115                              HdBinding const &binding,
1116                              int arraySize)
1117 {
1118     /*
1119       [vertex attribute]
1120          layout (location = <location>) in <type> <name>;
1121       [uniform]
1122          layout (location = <location>) uniform <type> <name>;
1123       [SSBO]
1124          layout (std430, binding = <location>) buffer buffer_<location> {
1125             <type> <name>[];
1126          };
1127       [Bindless Uniform]
1128          layout (location = <location>) uniform <type> *<name>;
1129 
1130      */
1131     HdBinding::Type bindingType = binding.GetType();
1132 
1133     if (!TF_VERIFY(!name.IsEmpty())) return;
1134     if (!TF_VERIFY(!type.IsEmpty(),
1135                       "Unknown dataType for %s",
1136                       name.GetText())) return;
1137 
1138     if (arraySize > 0) {
1139         if (!TF_VERIFY(bindingType == HdBinding::UNIFORM_ARRAY                ||
1140                           bindingType == HdBinding::DRAW_INDEX_INSTANCE_ARRAY ||
1141                           bindingType == HdBinding::UBO                       ||
1142                           bindingType == HdBinding::SSBO                      ||
1143                           bindingType == HdBinding::BINDLESS_SSBO_RANGE       ||
1144                           bindingType == HdBinding::BINDLESS_UNIFORM)) {
1145             // XXX: SSBO and BINDLESS_UNIFORM don't need arraySize, but for the
1146             // workaround of UBO allocation we're passing arraySize = 2
1147             // for all bindingType.
1148             return;
1149         }
1150     }
1151 
1152     // layout qualifier (if exists)
1153     str << LayoutQualifier(binding);
1154 
1155     switch (bindingType) {
1156     case HdBinding::VERTEX_ATTR:
1157     case HdBinding::DRAW_INDEX:
1158     case HdBinding::DRAW_INDEX_INSTANCE:
1159         str << "in " << _GetPackedType(type, false) << " " << name << ";\n";
1160         break;
1161     case HdBinding::DRAW_INDEX_INSTANCE_ARRAY:
1162         str << "in " << _GetPackedType(type, false) << " " << name
1163             << "[" << arraySize << "];\n";
1164         break;
1165     case HdBinding::UNIFORM:
1166         str << "uniform " << _GetPackedType(type, false) << " " << name << ";\n";
1167         break;
1168     case HdBinding::UNIFORM_ARRAY:
1169         str << "uniform " << _GetPackedType(type, false) << " " << name
1170             << "[" << arraySize << "];\n";
1171         break;
1172     case HdBinding::UBO:
1173         // note: ubo_ prefix is used in HdResourceBinder::IntrospectBindings.
1174         str << "uniform ubo_" << name <<  " {\n"
1175             << "  " << _GetPackedType(type, true)
1176             << " " << name;
1177         if (arraySize > 0) {
1178             str << "[" << arraySize << "];\n";
1179         } else {
1180             str << ";\n";
1181         }
1182         str << "};\n";
1183         break;
1184     case HdBinding::SSBO:
1185         str << "buffer buffer_" << binding.GetLocation() << " {\n"
1186             << "  " << _GetPackedType(type, true)
1187             << " " << name << "[];\n"
1188             << "};\n";
1189         break;
1190     case HdBinding::BINDLESS_SSBO_RANGE:
1191         str << "uniform " << _GetPackedType(type, true)
1192             << " *" << name << ";\n";
1193         break;
1194     case HdBinding::BINDLESS_UNIFORM:
1195         str << "uniform " << _GetPackedType(type, true)
1196             << " *" << name << ";\n";
1197         break;
1198     default:
1199         TF_CODING_ERROR("Unknown binding type %d, for %s\n",
1200                         binding.GetType(), name.GetText());
1201         break;
1202     }
1203 }
1204 
_EmitDeclaration(std::stringstream & str,HdSt_ResourceBinder::MetaData::BindingDeclaration const & bindingDeclaration,int arraySize=0)1205 static void _EmitDeclaration(
1206     std::stringstream &str,
1207     HdSt_ResourceBinder::MetaData::BindingDeclaration const &bindingDeclaration,
1208     int arraySize=0)
1209 {
1210     _EmitDeclaration(str,
1211          bindingDeclaration.name,
1212          bindingDeclaration.dataType,
1213          bindingDeclaration.binding,
1214          arraySize);
1215 }
1216 
_EmitStructAccessor(std::stringstream & str,TfToken const & structName,TfToken const & name,TfToken const & type,int arraySize,const char * index=NULL)1217 static void _EmitStructAccessor(std::stringstream &str,
1218                                 TfToken const &structName,
1219                                 TfToken const &name,
1220                                 TfToken const &type,
1221                                 int arraySize,
1222                                 const char *index = NULL)
1223 {
1224     // index != NULL  if the struct is an array
1225     // arraySize > 1  if the struct entry is an array.
1226     if (index) {
1227         if (arraySize > 1) {
1228             str << _GetUnpackedType(type, false) << " HdGet_" << name
1229                 << "(int arrayIndex, int localIndex) {\n"
1230                 // storing to a local variable to avoid the nvidia-driver
1231                 // bug #1561110 (fixed in 346.59)
1232                 << "  int index = " << index << ";\n"
1233                 << "  return "
1234                 << _GetPackedTypeAccessor(type, false) << "("
1235                 << structName << "[index]." << name << "[arrayIndex]);\n}\n";
1236         } else {
1237             str << _GetUnpackedType(type, false) << " HdGet_" << name
1238                 << "(int localIndex) {\n"
1239                 << "  int index = " << index << ";\n"
1240                 << "  return "
1241                 << _GetPackedTypeAccessor(type, false) << "("
1242                 << structName << "[index]." << name << ");\n}\n";
1243         }
1244     } else {
1245         if (arraySize > 1) {
1246             str << _GetUnpackedType(type, false) << " HdGet_" << name
1247                 << "(int arrayIndex, int localIndex) { return "
1248                 << _GetPackedTypeAccessor(type, false) << "("
1249                 << structName << "." << name << "[arrayIndex]);}\n";
1250         } else {
1251             str << _GetUnpackedType(type, false) << " HdGet_" << name
1252                 << "(int localIndex) { return "
1253                 << _GetPackedTypeAccessor(type, false) << "("
1254                 << structName << "." << name << ");}\n";
1255         }
1256     }
1257     // GLSL spec doesn't allow default parameter. use function overload instead.
1258     // default to localIndex=0
1259     if (arraySize > 1) {
1260         str << _GetUnpackedType(type, false) << " HdGet_" << name
1261             << "(int arrayIndex)"
1262             << " { return HdGet_" << name << "(arrayIndex, 0); }\n";
1263     } else {
1264         str << _GetUnpackedType(type, false) << " HdGet_" << name << "()"
1265             << " { return HdGet_" << name << "(0); }\n";
1266     }
1267 }
1268 
_EmitBufferAccessor(std::stringstream & str,TfToken const & name,TfToken const & type,const char * index)1269 static void _EmitBufferAccessor(std::stringstream &str,
1270                                 TfToken const &name,
1271                                 TfToken const &type,
1272                                 const char *index)
1273 {
1274     if (index) {
1275         str << _GetUnpackedType(type, false) << " HdGet_" << name
1276             << "(int localIndex) {\n"
1277             << "  int index = " << index << ";\n"
1278             << "  return "
1279                 << _GetPackedTypeAccessor(type, true) << "("
1280             << name << "[index]);\n}\n";
1281     }
1282     str << _GetUnpackedType(type, false) << " HdGet_" << name << "()"
1283         << " { return HdGet_" << name << "(0); }\n";
1284 }
1285 
_GetSwizzleString(TfToken const & type,std::string const & swizzle=std::string ())1286 static std::string _GetSwizzleString(TfToken const& type,
1287                                      std::string const& swizzle=std::string())
1288 {
1289     if (!swizzle.empty()) {
1290         return "." + swizzle;
1291     }
1292     if (type == _tokens->vec4 || type == _tokens->ivec4) {
1293         return "";
1294     }
1295     if (type == _tokens->vec3 || type == _tokens->ivec3) {
1296         return ".xyz";
1297     }
1298     if (type == _tokens->vec2 || type == _tokens->ivec2) {
1299         return ".xy";
1300     }
1301     if (type == _tokens->_float || type == _tokens->_int) {
1302         return ".x";
1303     }
1304     if (type == _tokens->packed_2_10_10_10) {
1305         return ".x";
1306     }
1307 
1308     return "";
1309 }
1310 
_GetNumComponents(TfToken const & type)1311 static int _GetNumComponents(TfToken const& type)
1312 {
1313     int numComponents = 1;
1314     if (type == _tokens->vec2 || type == _tokens->ivec2) {
1315         numComponents = 2;
1316     } else if (type == _tokens->vec3 || type == _tokens->ivec3) {
1317         numComponents = 3;
1318     } else if (type == _tokens->vec4 || type == _tokens->ivec4) {
1319         numComponents = 4;
1320     } else if (type == _tokens->mat3 || type == _tokens->dmat3) {
1321         numComponents = 9;
1322     } else if (type == _tokens->mat4 || type == _tokens->dmat4) {
1323         numComponents = 16;
1324     }
1325 
1326     return numComponents;
1327 }
1328 
_EmitComputeAccessor(std::stringstream & str,TfToken const & name,TfToken const & type,HdBinding const & binding,const char * index)1329 static void _EmitComputeAccessor(
1330                     std::stringstream &str,
1331                     TfToken const &name,
1332                     TfToken const &type,
1333                     HdBinding const &binding,
1334                     const char *index)
1335 {
1336     if (index) {
1337         str << _GetUnpackedType(type, false)
1338             << " HdGet_" << name << "(int localIndex) {\n";
1339         if (binding.GetType() == HdBinding::SSBO) {
1340             str << "  int index = " << index << ";\n";
1341             str << "  return " << _GetPackedTypeAccessor(type, false) << "("
1342                 << _GetPackedType(type, false) << "(";
1343             int numComponents = _GetNumComponents(type);
1344             for (int c = 0; c < numComponents; ++c) {
1345                 if (c > 0) {
1346                     str << ",\n              ";
1347                 }
1348                 str << name << "[index + " << c << "]";
1349             }
1350             str << "));\n}\n";
1351         } else if (binding.GetType() == HdBinding::BINDLESS_SSBO_RANGE) {
1352             str << "  return " << _GetPackedTypeAccessor(type, true) << "("
1353                 << name << "[localIndex]);\n}\n";
1354         } else {
1355             str << "  return " << _GetPackedTypeAccessor(type, true) << "("
1356                 << name << "[localIndex]);\n}\n";
1357         }
1358     } else {
1359         // non-indexed, only makes sense for uniform or vertex.
1360         if (binding.GetType() == HdBinding::UNIFORM ||
1361             binding.GetType() == HdBinding::VERTEX_ATTR) {
1362             str << _GetUnpackedType(type, false)
1363                 << " HdGet_" << name << "(int localIndex) { return ";
1364             str << _GetPackedTypeAccessor(type, true) << "(" << name << ");}\n";
1365         }
1366     }
1367     // GLSL spec doesn't allow default parameter. use function overload instead.
1368     // default to locaIndex=0
1369     str << _GetUnpackedType(type, false) << " HdGet_" << name << "()"
1370         << " { return HdGet_" << name << "(0); }\n";
1371 
1372 }
1373 
_EmitComputeMutator(std::stringstream & str,TfToken const & name,TfToken const & type,HdBinding const & binding,const char * index)1374 static void _EmitComputeMutator(
1375                     std::stringstream &str,
1376                     TfToken const &name,
1377                     TfToken const &type,
1378                     HdBinding const &binding,
1379                     const char *index)
1380 {
1381     if (index) {
1382         str << "void"
1383             << " HdSet_" << name << "(int localIndex, "
1384             << _GetUnpackedType(type, false) << " value) {\n";
1385         if (binding.GetType() == HdBinding::SSBO) {
1386             str << "  int index = " << index << ";\n";
1387             str << "  " << _GetPackedType(type, false) << " packedValue = "
1388                 << _GetPackedTypeMutator(type, false) << "(value);\n";
1389             int numComponents = _GetNumComponents(_GetPackedType(type, false));
1390             if (numComponents == 1) {
1391                 str << "  "
1392                     << name << "[index] = packedValue;\n";
1393             } else {
1394                 for (int c = 0; c < numComponents; ++c) {
1395                     str << "  "
1396                         << name << "[index + " << c << "] = "
1397                         << "packedValue[" << c << "];\n";
1398                 }
1399             }
1400         } else if (binding.GetType() == HdBinding::BINDLESS_SSBO_RANGE) {
1401             str << name << "[localIndex] = "
1402                 << _GetPackedTypeMutator(type, true) << "(value);\n";
1403         } else {
1404             TF_WARN("mutating non-SSBO not supported");
1405         }
1406         str << "}\n";
1407     } else {
1408         TF_WARN("mutating non-indexed data not supported");
1409     }
1410     // XXX Don't output a default mutator as we don't want accidental overwrites
1411     // of compute read-write data.
1412     // GLSL spec doesn't allow default parameter. use function overload instead.
1413     // default to locaIndex=0
1414     //str << "void HdSet_" << name << "(" << type << " value)"
1415     //    << " { HdSet_" << name << "(0, value); }\n";
1416 
1417 }
1418 
_EmitAccessor(std::stringstream & str,TfToken const & name,TfToken const & type,HdBinding const & binding,const char * index)1419 static void _EmitAccessor(std::stringstream &str,
1420                           TfToken const &name,
1421                           TfToken const &type,
1422                           HdBinding const &binding,
1423                           const char *index)
1424 {
1425     if (index) {
1426         str << _GetUnpackedType(type, false)
1427             << " HdGet_" << name << "(int localIndex) {\n"
1428             << "  int index = " << index << ";\n"
1429             << "  return " << _GetPackedTypeAccessor(type, true) << "("
1430             << name << "[index]);\n}\n";
1431     } else {
1432         // non-indexed, only makes sense for uniform or vertex.
1433         if (binding.GetType() == HdBinding::UNIFORM ||
1434             binding.GetType() == HdBinding::VERTEX_ATTR) {
1435             str << _GetUnpackedType(type, false)
1436                 << " HdGet_" << name << "(int localIndex) { return ";
1437             str << _GetPackedTypeAccessor(type, true) << "(" << name << ");}\n";
1438         }
1439     }
1440     // GLSL spec doesn't allow default parameter. use function overload instead.
1441     // default to locaIndex=0
1442     str << _GetUnpackedType(type, false) << " HdGet_" << name << "()"
1443         << " { return HdGet_" << name << "(0); }\n";
1444 
1445 }
1446 
_EmitTextureAccessors(std::stringstream & accessors,HdSt_ResourceBinder::MetaData::ShaderParameterAccessor const & acc,std::string const & swizzle,int const dim,bool const hasTextureTransform,bool const hasTextureScaleAndBias,bool const isBindless)1447 static void _EmitTextureAccessors(
1448     std::stringstream &accessors,
1449     HdSt_ResourceBinder::MetaData::ShaderParameterAccessor const &acc,
1450     std::string const &swizzle,
1451     int const dim,
1452     bool const hasTextureTransform,
1453     bool const hasTextureScaleAndBias,
1454     bool const isBindless)
1455 {
1456     GlfContextCaps const &caps = GlfContextCaps::GetInstance();
1457 
1458     TfToken const &name = acc.name;
1459 
1460     // Forward declare texture scale and bias
1461     if (hasTextureScaleAndBias) {
1462         accessors
1463             << "#ifdef HD_HAS_" << name << "_" << HdStTokens->scale << "\n"
1464             << "vec4 HdGet_" << name << "_" << HdStTokens->scale  << "();\n"
1465             << "#endif\n"
1466             << "#ifdef HD_HAS_" << name << "_" << HdStTokens->bias  << "\n"
1467             << "vec4 HdGet_" << name << "_" << HdStTokens->bias  << "();\n"
1468             << "#endif\n";
1469     }
1470 
1471     if (!isBindless) {
1472         // a function returning sampler requires bindless_texture
1473         if (caps.bindlessTextureEnabled) {
1474             accessors
1475                 << "sampler" << dim << "D\n"
1476                 << "HdGetSampler_" << name << "() {\n"
1477                 << "  return sampler" << dim << "d_" << name << ";"
1478                 << "}\n";
1479         } else {
1480             accessors
1481                 << "#define HdGetSampler_" << name << "()"
1482                 << " sampler" << dim << "d_" << name << "\n";
1483         }
1484     } else {
1485         if (caps.bindlessTextureEnabled) {
1486             accessors
1487                 << "sampler" << dim << "D\n"
1488                 << "HdGetSampler_" << name << "() {\n"
1489                 << "  int shaderCoord = GetDrawingCoord().shaderCoord; \n"
1490                 << "  return sampler" << dim << "D("
1491                 << "    shaderData[shaderCoord]." << name << ");\n"
1492                 << "}\n";
1493         }
1494     }
1495 
1496     TfToken const &dataType = acc.dataType;
1497 
1498     if (hasTextureTransform) {
1499         // Declare an eye to sampling transform and define function
1500         // to initialize it.
1501         const std::string eyeToSamplingTransform =
1502             "eyeTo" + name.GetString() + "SamplingTransform";
1503 
1504         // Computations in eye space are done with float precision, so the
1505         // eye to sampling transform is mat4.
1506         // Note that the multiplication that yiels this sampling transform
1507         // might be done using higher precision.
1508         accessors
1509             << "mat4 " << eyeToSamplingTransform << ";\n"
1510             << "\n"
1511             << "void Process_" << eyeToSamplingTransform
1512             << "(MAT4 instanceModelViewInverse) { \n"
1513             << "    int shaderCoord = GetDrawingCoord().shaderCoord; \n"
1514             << "    " << eyeToSamplingTransform << " = mat4(\n"
1515             << "        MAT4(shaderData[shaderCoord]."
1516             << name << HdSt_ResourceBindingSuffixTokens->samplingTransform
1517             << ") * instanceModelViewInverse);\n"
1518             << "}\n";
1519     }
1520 
1521     accessors
1522         << _GetUnpackedType(dataType, false)
1523         << " HdGet_" << name << "(vec" << dim << " coord) {\n"
1524         << "  int shaderCoord = GetDrawingCoord().shaderCoord; \n";
1525 
1526     if (hasTextureTransform) {
1527         const std::string eyeToSamplingTransform =
1528             "eyeTo" + name.GetString() + "SamplingTransform";
1529 
1530         accessors
1531             << "   vec4 c = " << eyeToSamplingTransform
1532             << " * vec4(coord, 1);\n"
1533             << "   vec3 sampleCoord = c.xyz / c.w;\n";
1534     } else {
1535         accessors
1536             << "  vec" << dim << " sampleCoord = coord;\n";
1537     }
1538 
1539     if (hasTextureScaleAndBias) {
1540         accessors
1541             << "  " << _GetUnpackedType(dataType, false)
1542             << " result = "
1543             << _GetPackedTypeAccessor(dataType, false)
1544             << "((texture(HdGetSampler_" << name << "(), sampleCoord)\n"
1545             << "#ifdef HD_HAS_" << name << "_" << HdStTokens->scale << "\n"
1546             << "    * HdGet_" << name << "_" << HdStTokens->scale << "()\n"
1547             << "#endif\n"
1548             << "#ifdef HD_HAS_" << name << "_" << HdStTokens->bias << "\n"
1549             << "    + HdGet_" << name << "_" << HdStTokens->bias  << "()\n"
1550             << "#endif\n"
1551             << ")" << swizzle << ");\n";
1552     } else {
1553         accessors
1554             << "  " << _GetUnpackedType(dataType, false)
1555             << " result = "
1556             << _GetPackedTypeAccessor(dataType, false)
1557             << "(texture(HdGetSampler_" << name << "(), sampleCoord)"
1558             << swizzle << ");\n";
1559     }
1560 
1561     if (acc.processTextureFallbackValue) {
1562         // Check whether texture is valid (using NAME_valid)
1563         //
1564         // Note that the OpenGL standard says that the
1565         // implicit derivatives (for accessing the right
1566         // mip-level) are undefined if the texture look-up
1567         // happens in a non-uniform control block, thus the
1568         // texture lookup is unconditionally assigned to
1569         // result outside of the if-block.
1570         //
1571         if (isBindless) {
1572             accessors
1573                 << "  if (shaderData[shaderCoord]." << name
1574                 << " != uvec2(0, 0)) {\n";
1575         } else {
1576             accessors
1577                 << "  if (shaderData[shaderCoord]." << name
1578                 << HdSt_ResourceBindingSuffixTokens->valid
1579                 << ") {\n";
1580         }
1581 
1582         if (hasTextureScaleAndBias) {
1583             accessors
1584                 << "    return result;\n"
1585                 << "  } else {\n"
1586                 << "    return ("
1587                 << _GetPackedTypeAccessor(dataType, false)
1588                 << "(shaderData[shaderCoord]."
1589                 << name
1590                 << HdSt_ResourceBindingSuffixTokens->fallback << ")\n"
1591                 << "#ifdef HD_HAS_" << name << "_" << HdStTokens->scale << "\n"
1592                 << "        * HdGet_" << name << "_" << HdStTokens->scale
1593                 << "()" << swizzle << "\n"
1594                 << "#endif\n"
1595                 << "#ifdef HD_HAS_" << name << "_" << HdStTokens->bias << "\n"
1596                 << "        + HdGet_" << name << "_" << HdStTokens->bias
1597                 << "()" << swizzle << "\n"
1598                 << "#endif\n"
1599                 << ");\n"
1600                 << "  }\n";
1601         } else {
1602             accessors
1603                 << "    return result;\n"
1604                 << "  } else {\n"
1605                 << "    return "
1606                 << _GetPackedTypeAccessor(dataType, false)
1607                 << "(shaderData[shaderCoord]."
1608                 << name
1609                 << HdSt_ResourceBindingSuffixTokens->fallback << ");\n"
1610                 << "  }\n";
1611         }
1612     } else {
1613         accessors
1614             << "  return result;\n";
1615     }
1616 
1617     accessors
1618         << "}\n";
1619 
1620     TfTokenVector const &inPrimvars = acc.inPrimvars;
1621 
1622     // Forward declare getter for inPrimvars in case it's a transform2d
1623     if (!inPrimvars.empty()) {
1624         accessors
1625             << "#if defined(HD_HAS_" << inPrimvars[0] << ")\n"
1626             << "vec" << dim << " HdGet_" << inPrimvars[0] << "(int localIndex);\n"
1627             << "#endif\n";
1628     }
1629 
1630     // Create accessor for texture coordinates based on texture param name
1631     // vec2 HdGetCoord_name(int localIndex)
1632     accessors
1633         << "vec" << dim << " HdGetCoord_" << name << "(int localIndex) {\n"
1634         << "  return \n";
1635     if (!inPrimvars.empty()) {
1636         accessors
1637             << "#if defined(HD_HAS_" << inPrimvars[0] <<")\n"
1638             << "  HdGet_" << inPrimvars[0] << "(localIndex).xy\n"
1639             << "#else\n"
1640             << "  vec" << dim << "(0.0)\n"
1641             << "#endif\n";
1642     } else {
1643         accessors
1644             << "  vec" << dim << "(0.0)\n";
1645     }
1646     accessors << ";}\n";
1647 
1648     // vec2 HdGetCoord_name()
1649     accessors
1650         << "vec" << dim << " HdGetCoord_" << name << "() {"
1651         << "  return HdGetCoord_" << name << "(0); }\n";
1652 
1653     // vec4 HdGet_name(int localIndex)
1654     accessors
1655         << _GetUnpackedType(dataType, false)
1656         << " HdGet_" << name
1657         << "(int localIndex) { return HdGet_" << name << "("
1658         << "HdGetCoord_" << name << "(localIndex)); }\n";
1659 
1660     // vec4 HdGet_name()
1661     accessors
1662         << _GetUnpackedType(dataType, false)
1663         << " HdGet_" << name
1664         << "() { return HdGet_" << name << "(0); }\n";
1665 
1666     // Emit pre-multiplication by alpha indicator
1667     if (acc.isPremultiplied) {
1668         accessors << "#define " << name << "_IS_PREMULTIPLIED 1\n";
1669     }
1670 }
1671 
1672 // Accessing face varying primvar data of a vertex in the GS requires special
1673 // case handling for refinement while providing a branchless solution.
1674 // When dealing with vertices on a refined face when the face-varying data has
1675 // not been refined, we use the patch coord to get its parametrization on the
1676 // sanitized (coarse) "ptex" face, and interpolate based on the face primitive
1677 // type (bilinear for quad faces, barycentric for tri faces).
1678 // When face varying data has been refined and the fvar patch type is quad or
1679 // tri, we still use bilinear or barycentric interpolation, respectively, but
1680 // we do it over the refined face and use refined face-varying values, accessed
1681 // using the refined face-varying indices.
1682 // When the fvar patch type is b-spline or box-spline, we solve over 16 or 12
1683 // refined values, respectively, also accessed via the refined indices, getting
1684 // the weights from OsdEvaluatePatchBasisNormalized().
_EmitFVarGSAccessor(std::stringstream & str,TfToken const & name,TfToken const & type,HdBinding const & binding,HdSt_GeometricShader::PrimitiveType const & primType,HdSt_GeometricShader::FvarPatchType const & fvarPatchType,int fvarChannel)1685 static void _EmitFVarGSAccessor(
1686                 std::stringstream &str,
1687                 TfToken const &name,
1688                 TfToken const &type,
1689                 HdBinding const &binding,
1690                 HdSt_GeometricShader::PrimitiveType const& primType,
1691                 HdSt_GeometricShader::FvarPatchType const& fvarPatchType,
1692                 int fvarChannel)
1693 {
1694     // emit an internal getter for accessing the coarse fvar data (corresponding
1695     // to the refined face, in the case of refinement)
1696     str << _GetUnpackedType(type, false)
1697         << " HdGet_" << name << "_Coarse(int localIndex) {\n";
1698     if ((fvarPatchType ==
1699             HdSt_GeometricShader::FvarPatchType::PATCH_COARSE_QUADS) ||
1700         (fvarPatchType ==
1701             HdSt_GeometricShader::FvarPatchType::PATCH_COARSE_TRIANGLES)) {
1702         str << "  int fvarIndex = GetFVarIndex(localIndex);\n";
1703     } else {
1704         str << "  int fvarIndex = GetDrawingCoord().fvarCoord + localIndex;\n";
1705     }
1706     str << "  return " << _GetPackedTypeAccessor(type, true) << "("
1707         <<       name << "[fvarIndex]);\n}\n";
1708 
1709     // emit the (public) accessor for the fvar data, accounting for refinement
1710     // interpolation
1711     str << _GetUnpackedType(type, false)
1712         << " HdGet_" << name << "(int localIndex, vec2 st) {\n";
1713 
1714     if (fvarPatchType ==
1715         HdSt_GeometricShader::FvarPatchType::PATCH_BSPLINE) {
1716         str << "  int patchType = OSD_PATCH_DESCRIPTOR_REGULAR;\n";
1717     } else if (fvarPatchType ==
1718         HdSt_GeometricShader::FvarPatchType::PATCH_BOXSPLINETRIANGLE) {
1719         str << "  int patchType = OSD_PATCH_DESCRIPTOR_LOOP;\n";
1720     }
1721 
1722     switch (fvarPatchType) {
1723         case HdSt_GeometricShader::FvarPatchType::PATCH_COARSE_QUADS:
1724         {
1725             // linear interpolation within a quad.
1726             str << "  return mix("
1727                 << "mix(" << "HdGet_" << name << "_Coarse(0),"
1728                 <<           "HdGet_" << name << "_Coarse(1), st.x),"
1729                 << "mix(" << "HdGet_" << name << "_Coarse(3),"
1730                 <<           "HdGet_" << name << "_Coarse(2), st.x), "
1731                 << "st.y);\n}\n";
1732             break;
1733         }
1734         case HdSt_GeometricShader::FvarPatchType::PATCH_COARSE_TRIANGLES:
1735         {
1736             // barycentric interpolation within a triangle.
1737             str << "  return ("
1738                 << "HdGet_" << name << "_Coarse(0) * (1-st.x-st.y)"
1739                 << " + HdGet_" << name << "_Coarse(1) * st.x"
1740                 << " + HdGet_" << name << "_Coarse(2) * st.y);\n}\n";
1741             break;
1742         }
1743         case HdSt_GeometricShader::FvarPatchType::PATCH_REFINED_QUADS:
1744         {
1745             // linear interpolation between 4 refined primvars
1746             str << "  ivec4 indices = HdGet_fvarIndices" << fvarChannel
1747                 << "();\n"
1748                 << "  return mix("
1749                 << "mix(" << "HdGet_" << name << "_Coarse(indices[0]),"
1750                 <<           "HdGet_" << name << "_Coarse(indices[1]), st.s),"
1751                 << "mix(" << "HdGet_" << name << "_Coarse(indices[3]),"
1752                 <<           "HdGet_" << name << "_Coarse(indices[2]), st.s), "
1753                 << "st.t);\n}\n";
1754             break;
1755         }
1756         case HdSt_GeometricShader::FvarPatchType::PATCH_REFINED_TRIANGLES:
1757         {
1758             // barycentric interpolation between 3 refined primvars
1759             str << "  ivec3 indices = HdGet_fvarIndices" << fvarChannel
1760                 << "();\n"
1761                 << "  return ("
1762                 << "HdGet_" << name << "_Coarse(indices[0]) * (1-st.s-st.t)"
1763                 << " + HdGet_" << name << "_Coarse(indices[1]) * st.s"
1764                 << " + HdGet_" << name << "_Coarse(indices[2]) * st.t);\n}\n";
1765             break;
1766         }
1767         case HdSt_GeometricShader::FvarPatchType::PATCH_BSPLINE:
1768         case HdSt_GeometricShader::FvarPatchType::PATCH_BOXSPLINETRIANGLE:
1769         {
1770             // evaluation of a bspline/box spline patch
1771             str << "  ivec2 fvarPatchParam = HdGet_fvarPatchParam"
1772                 << fvarChannel << "();\n"
1773                 << "  OsdPatchParam param = OsdPatchParamInit(fvarPatchParam.x,"
1774                 << " fvarPatchParam.y, 0);\n"
1775                 << "  float wP[20], wDu[20], wDv[20], wDuu[20], wDuv[20], "
1776                 << "wDvv[20];\n"
1777                 << "  OsdEvaluatePatchBasisNormalized(patchType, param,"
1778                 << " st.s, st.t, wP, wDu, wDv, wDuu, wDuv, wDvv);\n"
1779                 << "  " << _GetUnpackedType(type, false) << " result = "
1780                 << _GetUnpackedType(type, false) << "(0);\n"
1781                 << "  for (int i = 0; i < HD_NUM_PATCH_VERTS; ++i) {\n"
1782                 << "    int fvarIndex = HdGet_fvarIndices" << fvarChannel
1783                 << "(i);\n"
1784                 << "    " << _GetUnpackedType(type, false) << " cv = "
1785                 << _GetUnpackedType(type, false) << "(HdGet_" << name
1786                 << "_Coarse(fvarIndex));\n"
1787                 << "    result += wP[i] * cv;\n"
1788                 << "  }\n"
1789                 << " return result;\n}\n";
1790             break;
1791         }
1792         case HdSt_GeometricShader::FvarPatchType::PATCH_NONE:
1793         {
1794             str << "  return HdGet_" << name << "_Coarse(localIndex);\n}\n";
1795             break;
1796         }
1797         default:
1798         {
1799             // emit a default version for compilation sake
1800             str << "  return HdGet_" << name << "_Coarse(localIndex);\n}\n";
1801 
1802             TF_CODING_ERROR("Face varing bindings for unexpected for"
1803                             " HdSt_GeometricShader::PrimitiveType %d",
1804                             (int)primType);
1805         }
1806     }
1807 
1808     str << "vec4 GetPatchCoord(int index);\n"
1809         << _GetUnpackedType(type, false)
1810         << " HdGet_" << name << "(int localIndex) {\n";
1811 
1812     switch (fvarPatchType) {
1813         case HdSt_GeometricShader::FvarPatchType::PATCH_COARSE_QUADS:
1814         case HdSt_GeometricShader::FvarPatchType::PATCH_COARSE_TRIANGLES:
1815         {
1816             str << "  vec2 localST = GetPatchCoord(localIndex).xy;\n";
1817             break;
1818         }
1819         case HdSt_GeometricShader::FvarPatchType::PATCH_BSPLINE:
1820         {
1821             // Compute localST in normalized patch param space
1822             str << "  ivec2 fvarPatchParam = HdGet_fvarPatchParam"
1823                 << fvarChannel << "();\n"
1824                 << "  OsdPatchParam param = OsdPatchParamInit(fvarPatchParam.x,"
1825                 << " fvarPatchParam.y, 0);\n"
1826                 << "  vec2 unnormalized = GetPatchCoord(localIndex).xy;\n"
1827                 << "  float uv[2] = float[2](unnormalized.x, unnormalized.y);\n"
1828                 << "  OsdPatchParamNormalize(param, uv);\n"
1829                 << "  vec2 localST = vec2(uv[0], uv[1]);\n";
1830             break;
1831         }
1832         case HdSt_GeometricShader::FvarPatchType::PATCH_BOXSPLINETRIANGLE:
1833         {
1834             // Compute localST in normalized patch param space
1835             str << "  ivec2 fvarPatchParam = HdGet_fvarPatchParam"
1836                 << fvarChannel << "();\n"
1837                 << "  OsdPatchParam param = OsdPatchParamInit(fvarPatchParam.x,"
1838                 << " fvarPatchParam.y, 0);\n"
1839                 << "  vec2 unnormalized = GetPatchCoord(localIndex).xy;\n"
1840                 << "  float uv[2] = float[2](unnormalized.x, unnormalized.y);\n"
1841                 << "  OsdPatchParamNormalizeTriangle(param, uv);\n"
1842                 << "  vec2 localST = vec2(uv[0], uv[1]);\n";
1843             break;
1844         }
1845         case HdSt_GeometricShader::FvarPatchType::PATCH_REFINED_QUADS:
1846         {
1847             str << "  vec2 lut[4] = vec2[4](vec2(0,0), vec2(1,0), "
1848                 << "vec2(1,1), vec2(0,1));\n"
1849                 << "  vec2 localST = lut[localIndex];\n";
1850             break;
1851         }
1852         case HdSt_GeometricShader::FvarPatchType::PATCH_REFINED_TRIANGLES:
1853         {
1854             str << "  vec2 lut[3] = vec2[3](vec2(0,0), vec2(1,0), vec2(0,1));\n"
1855                 << "  vec2 localST = lut[localIndex];\n";
1856             break;
1857         }
1858         default:
1859         {
1860             str << "  vec2 localST = vec2(0);\n";
1861         }
1862     }
1863     str << "  return HdGet_" << name << "(localIndex, localST);\n}\n";
1864 
1865     // XXX: We shouldn't emit the default (argument free) accessor version,
1866     // since that doesn't make sense within a GS. Once we fix the XXX in
1867     // _GenerateShaderParameters, we should remove this.
1868     str << _GetUnpackedType(type, false) << " HdGet_" << name << "()"
1869         << " { return HdGet_" << name << "(0); }\n";
1870 }
1871 
1872 void
_GenerateDrawingCoord()1873 HdSt_CodeGen::_GenerateDrawingCoord()
1874 {
1875     TF_VERIFY(_metaData.drawingCoord0Binding.binding.IsValid());
1876     TF_VERIFY(_metaData.drawingCoord1Binding.binding.IsValid());
1877     TF_VERIFY(_metaData.drawingCoord2Binding.binding.IsValid());
1878 
1879     /*
1880        hd_drawingCoord is a struct of integer offsets to locate the primvars
1881        in buffer arrays at the current rendering location.
1882 
1883        struct hd_drawingCoord {
1884            int modelCoord;             // (reserved) model parameters
1885            int constantCoord;          // constant primvars (per object)
1886            int vertexCoord;            // vertex primvars   (per vertex)
1887            int elementCoord;           // element primvars  (per face/curve)
1888            int primitiveCoord;         // primitive ids     (per tri/quad/line)
1889            int fvarCoord;              // fvar primvars     (per face-vertex)
1890            int shaderCoord;            // shader parameters (per shader/object)
1891            int topologyVisibilityCoord // topological visibility data (per face/point)
1892            int varyingCoord;           // varying primvars  (per vertex)
1893            int instanceIndex[];        // (see below)
1894            int instanceCoords[];       // (see below)
1895        };
1896 
1897           instanceIndex[0]  : global instance ID (used for ID rendering)
1898                        [1]  : instance index for level = 0
1899                        [2]  : instance index for level = 1
1900                        ...
1901           instanceCoords[0] : instanceDC for level = 0
1902           instanceCoords[1] : instanceDC for level = 1
1903                        ...
1904 
1905        We also have a drawingcoord for vertex primvars. Currently it's not
1906        being passed into shader since the vertex shader takes pre-offsetted
1907        vertex arrays and no needs to apply offset in shader (except gregory
1908        patch drawing etc. In that case gl_BaseVertexARB can be used under
1909        GL_ARB_shader_draw_parameters extention)
1910 
1911        gl_InstanceID is available only in vertex shader, so codegen
1912        takes care of applying an offset for each instance for the later
1913        stage. On the other hand, gl_PrimitiveID is available in all stages
1914        except vertex shader, and since tess/geometry shaders may or may not
1915        exist, we don't apply an offset of primitiveID during interstage
1916        plumbing to avoid overlap. Instead, GetDrawingCoord() applies
1917        primitiveID if necessary.
1918 
1919        XXX:
1920        Ideally we should use an interface block like:
1921 
1922          in DrawingCoord {
1923              flat hd_drawingCoord drawingCoord;
1924          } inDrawingCoord;
1925          out DrawingCoord {
1926              flat hd_drawingCoord drawingCoord;
1927          } outDrawingCoord;
1928 
1929       then the fragment shader can take the same input regardless the
1930       existence of tess/geometry shaders. However it seems the current
1931       driver (331.79) doesn't handle multiple interface blocks
1932       appropriately, it fails matching and ends up undefined results at
1933       consuming shader.
1934 
1935       > OpenGL 4.4 Core profile
1936       > 7.4.1 Shader Interface Matching
1937       >
1938       > When multiple shader stages are active, the outputs of one stage form
1939       > an interface with the inputs of the next stage. At each such
1940       > interface, shader inputs are matched up against outputs from the
1941       > previous stage:
1942       >
1943       > An output block is considered to match an input block in the
1944       > subsequent shader if the two blocks have the same block name, and
1945       > the members of the block match exactly in name, type, qualification,
1946       > and declaration order.
1947       >
1948       > An output variable is considered to match an input variable in the
1949       > subsequent shader if:
1950       >  - the two variables match in name, type, and qualification; or
1951       >  - the two variables are declared with the same location and
1952       >     component layout qualifiers and match in type and qualification.
1953 
1954       We use non-block variable for drawingCoord as a workaround of this
1955       problem for now. There is a caveat we can't use the same name for input
1956       and output, the subsequent shader has to be aware which stage writes
1957       the drawingCoord.
1958 
1959       for example:
1960         drawingCoord--(VS)--vsDrawingCoord--(GS)--gsDrawingCoord--(FS)
1961         drawingCoord--(VS)------------------------vsDrawingCoord--(FS)
1962 
1963       Fortunately the compiler is smart enough to optimize out unused
1964       attributes. If the VS writes the same value into two attributes:
1965 
1966         drawingCoord--(VS)--vsDrawingCoord--(GS)--gsDrawingCoord--(FS)
1967                       (VS)--gsDrawingCoord--------gsDrawingCoord--(FS)
1968 
1969       The fragment shader can always take gsDrawingCoord. The following code
1970       does such a plumbing work.
1971 
1972      */
1973 
1974     // common
1975     //
1976     // note: instanceCoords should be [HD_INSTANCER_NUM_LEVELS], but since
1977     //       GLSL doesn't allow [0] declaration, we use +1 value (WIDTH)
1978     //       for the sake of simplicity.
1979     _genCommon << "struct hd_drawingCoord {                       \n"
1980                << "  int modelCoord;                              \n"
1981                << "  int constantCoord;                           \n"
1982                << "  int vertexCoord;                             \n"
1983                << "  int elementCoord;                            \n"
1984                << "  int primitiveCoord;                          \n"
1985                << "  int fvarCoord;                               \n"
1986                << "  int shaderCoord;                             \n"
1987                << "  int topologyVisibilityCoord;                 \n"
1988                << "  int varyingCoord;                            \n"
1989                << "  int instanceIndex[HD_INSTANCE_INDEX_WIDTH];  \n"
1990                << "  int instanceCoords[HD_INSTANCE_INDEX_WIDTH]; \n"
1991                << "};\n";
1992 
1993     _genCommon << "hd_drawingCoord GetDrawingCoord();\n"; // forward declaration
1994 
1995     // vertex shader
1996 
1997     // [immediate]
1998     //   layout (location=x) uniform ivec4 drawingCoord0;
1999     //   layout (location=y) uniform ivec4 drawingCoord1;
2000     //   layout (location=z) uniform int   drawingCoordI[N];
2001     // [indirect]
2002     //   layout (location=x) in ivec4 drawingCoord0
2003     //   layout (location=y) in ivec4 drawingCoord1
2004     //   layout (location=z) in ivec2 drawingCoord2
2005     //   layout (location=w) in int   drawingCoordI[N]
2006     _EmitDeclaration(_genVS, _metaData.drawingCoord0Binding);
2007     _EmitDeclaration(_genVS, _metaData.drawingCoord1Binding);
2008     _EmitDeclaration(_genVS, _metaData.drawingCoord2Binding);
2009     if (_metaData.drawingCoordIBinding.binding.IsValid()) {
2010         _EmitDeclaration(_genVS, _metaData.drawingCoordIBinding,
2011                          /*arraySize=*/std::max(1, _metaData.instancerNumLevels));
2012     }
2013 
2014     // instance index indirection
2015     _genCommon << "struct hd_instanceIndex { int indices[HD_INSTANCE_INDEX_WIDTH]; };\n";
2016 
2017     if (_metaData.instanceIndexArrayBinding.binding.IsValid()) {
2018         // << layout (location=x) uniform (int|ivec[234]) *instanceIndices;
2019         _EmitDeclaration(_genCommon, _metaData.instanceIndexArrayBinding);
2020 
2021         // << layout (location=x) uniform (int|ivec[234]) *culledInstanceIndices;
2022         _EmitDeclaration(_genCommon,  _metaData.culledInstanceIndexArrayBinding);
2023 
2024         /// if \p cullingPass is true, CodeGen generates GetInstanceIndex()
2025         /// such that it refers instanceIndices buffer (before culling).
2026         /// Otherwise, GetInstanceIndex() looks up culledInstanceIndices.
2027 
2028         _genVS << "int GetInstanceIndexCoord() {\n"
2029                << "  return drawingCoord1.y + gl_InstanceID * HD_INSTANCE_INDEX_WIDTH; \n"
2030                << "}\n";
2031 
2032         if (_geometricShader->IsFrustumCullingPass()) {
2033             // for frustum culling:  use instanceIndices.
2034             _genVS << "hd_instanceIndex GetInstanceIndex() {\n"
2035                    << "  int offset = GetInstanceIndexCoord();\n"
2036                    << "  hd_instanceIndex r;\n"
2037                    << "  for (int i = 0; i < HD_INSTANCE_INDEX_WIDTH; ++i)\n"
2038                    << "    r.indices[i] = instanceIndices[offset+i];\n"
2039                    << "  return r;\n"
2040                    << "}\n";
2041             _genVS << "void SetCulledInstanceIndex(uint instanceID) {\n"
2042                    << "  for (int i = 0; i < HD_INSTANCE_INDEX_WIDTH; ++i)\n"
2043                    << "    culledInstanceIndices[drawingCoord1.y + instanceID*HD_INSTANCE_INDEX_WIDTH+i]"
2044                    << "        = instanceIndices[drawingCoord1.y + gl_InstanceID*HD_INSTANCE_INDEX_WIDTH+i];\n"
2045                    << "}\n";
2046         } else {
2047             // for drawing:  use culledInstanceIndices.
2048             _EmitAccessor(_genVS, _metaData.culledInstanceIndexArrayBinding.name,
2049                           _metaData.culledInstanceIndexArrayBinding.dataType,
2050                           _metaData.culledInstanceIndexArrayBinding.binding,
2051                           "GetInstanceIndexCoord()+localIndex");
2052             _genVS << "hd_instanceIndex GetInstanceIndex() {\n"
2053                    << "  int offset = GetInstanceIndexCoord();\n"
2054                    << "  hd_instanceIndex r;\n"
2055                    << "  for (int i = 0; i < HD_INSTANCE_INDEX_WIDTH; ++i)\n"
2056                    << "    r.indices[i] = HdGet_culledInstanceIndices(/*localIndex=*/i);\n"
2057                    << "  return r;\n"
2058                    << "}\n";
2059         }
2060     } else {
2061         _genVS << "hd_instanceIndex GetInstanceIndex() {"
2062                << "  hd_instanceIndex r; r.indices[0] = 0; return r; }\n";
2063         if (_geometricShader->IsFrustumCullingPass()) {
2064             _genVS << "void SetCulledInstanceIndex(uint instance) "
2065                       "{ /*no-op*/ }\n";
2066         }
2067     }
2068 
2069     _genVS << "flat out hd_drawingCoord vsDrawingCoord;\n"
2070            // XXX: see the comment above why we need both vs and gs outputs.
2071            << "flat out hd_drawingCoord gsDrawingCoord;\n";
2072 
2073     _genVS << "hd_drawingCoord GetDrawingCoord() { hd_drawingCoord dc; \n"
2074            << "  dc.modelCoord              = drawingCoord0.x; \n"
2075            << "  dc.constantCoord           = drawingCoord0.y; \n"
2076            << "  dc.elementCoord            = drawingCoord0.z; \n"
2077            << "  dc.primitiveCoord          = drawingCoord0.w; \n"
2078            << "  dc.fvarCoord               = drawingCoord1.x; \n"
2079            << "  dc.shaderCoord             = drawingCoord1.z; \n"
2080            << "  dc.vertexCoord             = drawingCoord1.w; \n"
2081            << "  dc.topologyVisibilityCoord = drawingCoord2.x; \n"
2082            << "  dc.varyingCoord            = drawingCoord2.y; \n"
2083            << "  dc.instanceIndex           = GetInstanceIndex().indices;\n";
2084 
2085     if (_metaData.drawingCoordIBinding.binding.IsValid()) {
2086         _genVS << "  for (int i = 0; i < HD_INSTANCER_NUM_LEVELS; ++i) {\n"
2087                << "    dc.instanceCoords[i] = drawingCoordI[i] \n"
2088                << "      + dc.instanceIndex[i+1]; \n"
2089                << "  }\n";
2090     }
2091 
2092     _genVS << "  return dc;\n"
2093            << "}\n";
2094 
2095     // note: GL spec says tessellation input array size must be equal to
2096     //       gl_MaxPatchVertices, which is used for intrinsic declaration
2097     //       of built-in variables:
2098     //       in gl_PerVertex {} gl_in[gl_MaxPatchVertices];
2099 
2100     // tess control shader
2101     _genTCS << "flat in hd_drawingCoord vsDrawingCoord[gl_MaxPatchVertices];\n"
2102             << "flat out hd_drawingCoord tcsDrawingCoord[HD_NUM_PATCH_EVAL_VERTS];\n"
2103             << "hd_drawingCoord GetDrawingCoord() { \n"
2104             << "  hd_drawingCoord dc = vsDrawingCoord[0];\n"
2105             << "  dc.primitiveCoord += gl_PrimitiveID;\n"
2106             << "  return dc;\n"
2107             << "}\n";
2108     // tess eval shader
2109     _genTES << "flat in hd_drawingCoord tcsDrawingCoord[gl_MaxPatchVertices];\n"
2110             << "flat out hd_drawingCoord vsDrawingCoord;\n"
2111             << "flat out hd_drawingCoord gsDrawingCoord;\n"
2112             << "hd_drawingCoord GetDrawingCoord() { \n"
2113             << "  hd_drawingCoord dc = tcsDrawingCoord[0]; \n"
2114             << "  dc.primitiveCoord += gl_PrimitiveID; \n"
2115             << "  return dc;\n"
2116             << "}\n";
2117 
2118     // geometry shader ( VSdc + gl_PrimitiveIDIn )
2119     _genGS << "flat in hd_drawingCoord vsDrawingCoord[HD_NUM_PRIMITIVE_VERTS];\n"
2120            << "flat out hd_drawingCoord gsDrawingCoord;\n"
2121            << "hd_drawingCoord GetDrawingCoord() { \n"
2122            << "  hd_drawingCoord dc = vsDrawingCoord[0]; \n"
2123            << "  dc.primitiveCoord += gl_PrimitiveIDIn; \n"
2124            << "  return dc; \n"
2125            << "}\n";
2126 
2127     // fragment shader ( VSdc + gl_PrimitiveID )
2128     // note that gsDrawingCoord isn't offsetted by gl_PrimitiveIDIn
2129     _genFS << "flat in hd_drawingCoord gsDrawingCoord;\n"
2130            << "hd_drawingCoord GetDrawingCoord() { \n"
2131            << "  hd_drawingCoord dc = gsDrawingCoord; \n"
2132            << "  dc.primitiveCoord += gl_PrimitiveID; \n"
2133            << "  return dc; \n"
2134            << "}\n";
2135 
2136     // drawing coord plumbing.
2137     // Note that copying from [0] for multiple input source since the
2138     // drawingCoord is flat (no interpolation required).
2139     _procVS  << "  vsDrawingCoord = GetDrawingCoord();\n"
2140              << "  gsDrawingCoord = GetDrawingCoord();\n";
2141     _procTCS << "  tcsDrawingCoord[gl_InvocationID] = "
2142              << "  vsDrawingCoord[gl_InvocationID];\n";
2143     _procTES << "  vsDrawingCoord = tcsDrawingCoord[0];\n"
2144              << "  gsDrawingCoord = tcsDrawingCoord[0];\n";
2145     _procGS  << "  gsDrawingCoord = vsDrawingCoord[0];\n";
2146 
2147 }
2148 void
_GenerateConstantPrimvar()2149 HdSt_CodeGen::_GenerateConstantPrimvar()
2150 {
2151     /*
2152       // --------- constant data declaration ----------
2153       struct ConstantData0 {
2154           mat4 transform;
2155           mat4 transformInverse;
2156           mat4 instancerTransform[2];
2157           vec3 displayColor;
2158           vec4 primID;
2159       };
2160       // bindless
2161       layout (location=0) uniform ConstantData0 *constantData0;
2162       // not bindless
2163       layout (std430, binding=0) buffer {
2164           constantData0 constantData0[];
2165       };
2166 
2167       // --------- constant data accessors ----------
2168       mat4 HdGet_transform(int localIndex) {
2169           return constantData0[GetConstantCoord()].transform;
2170       }
2171       vec3 HdGet_displayColor(int localIndex) {
2172           return constantData0[GetConstantCoord()].displayColor;
2173       }
2174 
2175     */
2176 
2177     std::stringstream declarations;
2178     std::stringstream accessors;
2179     TF_FOR_ALL (it, _metaData.constantData) {
2180         // note: _constantData has been sorted by offset in HdSt_ResourceBinder.
2181         // XXX: not robust enough, should consider padding and layouting rules
2182         // to match with the logic in HdInterleavedMemoryManager if we
2183         // want to use a layouting policy other than default padding.
2184 
2185         HdBinding binding = it->first;
2186         TfToken typeName(TfStringPrintf("ConstantData%d", binding.GetValue()));
2187         TfToken varName = it->second.blockName;
2188 
2189         declarations << "struct " << typeName << " {\n";
2190 
2191         TF_FOR_ALL (dbIt, it->second.entries) {
2192             if (!TF_VERIFY(!dbIt->dataType.IsEmpty(),
2193                               "Unknown dataType for %s",
2194                               dbIt->name.GetText())) {
2195                 continue;
2196             }
2197 
2198             declarations << "  " << _GetPackedType(dbIt->dataType, false)
2199                          << " " << dbIt->name;
2200             if (dbIt->arraySize > 1) {
2201                 declarations << "[" << dbIt->arraySize << "]";
2202             }
2203 
2204             declarations << ";\n";
2205 
2206             _EmitStructAccessor(accessors, varName, dbIt->name, dbIt->dataType,
2207                                 dbIt->arraySize,
2208                                 "GetDrawingCoord().constantCoord");
2209         }
2210         declarations << "};\n";
2211 
2212         // XXX: passing arraySize=2 to cheat driver to not tell actual size.
2213         //      we should compute the actual size or maximum size if possible.
2214         _EmitDeclaration(declarations, varName, typeName, binding, /*arraySize=*/1);
2215     }
2216     _genCommon << declarations.str()
2217                << accessors.str();
2218 }
2219 
2220 void
_GenerateInstancePrimvar()2221 HdSt_CodeGen::_GenerateInstancePrimvar()
2222 {
2223     /*
2224       // --------- instance data declaration ----------
2225       // bindless
2226       layout (location=X) uniform vec4 *data;
2227       // not bindless
2228       layout (std430, binding=X) buffer buffer_X {
2229           vec4 data[];
2230       };
2231 
2232       // --------- instance data accessors ----------
2233       vec3 HdGet_translate(int localIndex=0) {
2234           return instanceData0[GetInstanceCoord()].translate;
2235       }
2236     */
2237 
2238     std::stringstream declarations;
2239     std::stringstream accessors;
2240 
2241     struct LevelEntries {
2242         TfToken dataType;
2243         std::vector<int> levels;
2244     };
2245     std::map<TfToken, LevelEntries> nameAndLevels;
2246 
2247     TF_FOR_ALL (it, _metaData.instanceData) {
2248         HdBinding binding = it->first;
2249         TfToken const &dataType = it->second.dataType;
2250         int level = it->second.level;
2251 
2252         nameAndLevels[it->second.name].dataType = dataType;
2253         nameAndLevels[it->second.name].levels.push_back(level);
2254 
2255         std::stringstream n;
2256         n << it->second.name << "_" << level;
2257         TfToken name(n.str());
2258         n.str("");
2259         n << "GetDrawingCoord().instanceCoords[" << level << "]";
2260 
2261         // << layout (location=x) uniform float *translate_0;
2262         _EmitDeclaration(declarations, name, dataType, binding);
2263         _EmitAccessor(accessors, name, dataType, binding, n.str().c_str());
2264 
2265     }
2266 
2267     /*
2268       accessor taking level as a parameter.
2269       note that instance primvar may or may not be defined for each level.
2270       we expect level is an unrollable constant to optimize out branching.
2271 
2272       vec3 HdGetInstance_translate(int level, vec3 defaultValue) {
2273           if (level == 0) return HdGet_translate_0();
2274           // level==1 is not defined. use default
2275           if (level == 2) return HdGet_translate_2();
2276           if (level == 3) return HdGet_translate_3();
2277           return defaultValue;
2278       }
2279     */
2280     TF_FOR_ALL (it, nameAndLevels) {
2281         accessors << _GetUnpackedType(it->second.dataType, false)
2282                   << " HdGetInstance_" << it->first << "(int level, "
2283                   << _GetUnpackedType(it->second.dataType, false)
2284                   << " defaultValue) {\n";
2285         TF_FOR_ALL (levelIt, it->second.levels) {
2286             accessors << "  if (level == " << *levelIt << ") "
2287                       << "return HdGet_" << it->first << "_" << *levelIt << "();\n";
2288         }
2289 
2290         accessors << "  return defaultValue;\n"
2291                   << "}\n";
2292     }
2293     /*
2294       common accessor, if the primvar is defined on the instancer but not
2295       the rprim.
2296 
2297       #if !defined(HD_HAS_translate)
2298       #define HD_HAS_translate 1
2299       vec3 HdGet_translate(int localIndex) {
2300           // 0 is the lowest level for which this is defined
2301           return HdGet_translate_0();
2302       }
2303       vec3 HdGet_translate() {
2304           return HdGet_translate(0);
2305       }
2306       #endif
2307     */
2308     TF_FOR_ALL (it, nameAndLevels) {
2309         accessors << "#if !defined(HD_HAS_" << it->first << ")\n"
2310                   << "#define HD_HAS_" << it->first << " 1\n"
2311                   << _GetUnpackedType(it->second.dataType, false)
2312                   << " HdGet_" << it->first << "(int localIndex) {\n"
2313                   << "  return HdGet_" << it->first << "_"
2314                                        << it->second.levels.front() << "();\n"
2315                   << "}\n"
2316                   << _GetUnpackedType(it->second.dataType, false)
2317                   << " HdGet_" << it->first << "() { return HdGet_"
2318                   << it->first << "(0); }\n"
2319                   << "#endif\n";
2320     }
2321 
2322 
2323     _genCommon << declarations.str()
2324                << accessors.str();
2325 }
2326 
2327 void
_GenerateElementPrimvar()2328 HdSt_CodeGen::_GenerateElementPrimvar()
2329 {
2330     /*
2331     Accessing uniform primvar data:
2332     ===============================
2333     Uniform primvar data is authored at the subprimitive (also called element or
2334     face below) granularity.
2335     To access uniform primvar data (say color), there are two indirections in
2336     the lookup because of aggregation in the buffer layout.
2337           ----------------------------------------------------
2338     color | prim0 colors | prim1 colors | .... | primN colors|
2339           ----------------------------------------------------
2340     For each prim, GetDrawingCoord().elementCoord holds the start index into
2341     this buffer.
2342 
2343     For an unrefined prim, the subprimitive ID is simply the gl_PrimitiveID.
2344     For a refined prim, gl_PrimitiveID corresponds to the refined element ID.
2345 
2346     To map a refined face to its coarse face, Storm builds a "primitive param"
2347     buffer (more details in the section below). This buffer is also aggregated,
2348     and for each subprimitive, GetDrawingCoord().primitiveCoord gives us the
2349     index into this buffer (meaning it has already added the gl_PrimitiveID)
2350 
2351     To have a single codepath for both cases, we build the primitive param
2352     buffer for unrefined prims as well, and effectively index the uniform
2353     primvar using:
2354     drawCoord.elementCoord + primitiveParam[ drawCoord.primitiveCoord ]
2355 
2356     The code generated looks something like:
2357 
2358       // --------- primitive param declaration ----------
2359       struct PrimitiveData { int elementID; }
2360       layout (std430, binding=?) buffer PrimitiveBuffer {
2361           PrimitiveData primitiveData[];
2362       };
2363 
2364       // --------- indirection accessors ---------
2365       // Gives us the "coarse" element ID
2366       int GetElementID() {
2367           return primitiveData[GetPrimitiveCoord()].elementID;
2368       }
2369 
2370       // Adds the offset to the start of the uniform primvar data for the prim
2371       int GetAggregatedElementID() {
2372           return GetElementID() + GetDrawingCoord().elementCoord;\n"
2373       }
2374 
2375       // --------- uniform primvar declaration ---------
2376       struct ElementData0 {
2377           vec3 displayColor;
2378       };
2379       layout (std430, binding=?) buffer buffer0 {
2380           ElementData0 elementData0[];
2381       };
2382 
2383       // ---------uniform primvar data accessor ---------
2384       vec3 HdGet_displayColor(int localIndex) {
2385           return elementData0[GetAggregatedElementID()].displayColor;
2386       }
2387 
2388     */
2389 
2390     // Primitive Param buffer layout:
2391     // ==============================
2392     // Depending on the prim, one of following is used:
2393     //
2394     // 1. basis curves
2395     //     1 int  : curve index
2396     //
2397     //     This lets us translate a basis curve segment to its curve id.
2398     //     A basis curve is made up for 'n' curves, each of which have a varying
2399     //     number of segments.
2400     //     (see hdSt/basisCurvesComputations.cpp)
2401     //
2402     // 2. mesh specific
2403     // a. tris
2404     //     1 int  : coarse face index + edge flag
2405     //     (see hd/meshUtil.h,cpp)
2406     //
2407     // b. quads coarse
2408     //     2 ints : coarse face index + edge flag
2409     //              ptex index
2410     //     (see hd/meshUtil.h,cpp)
2411     //
2412     // c. tris & quads uniformly refined
2413     //     3 ints : coarse face index + edge flag
2414     //              Far::PatchParam::field0 (includes ptex index)
2415     //              Far::PatchParam::field1
2416     //     (see hdSt/subdivision.cpp)
2417     //
2418     // d. patch adaptively refined
2419     //     4 ints : coarse face index + edge flag
2420     //              Far::PatchParam::field0 (includes ptex index)
2421     //              Far::PatchParam::field1
2422     //              sharpness (float)
2423     //     (see hdSt/subdivision.cpp)
2424     // -----------------------------------------------------------------------
2425     // note: decoding logic of primitiveParam has to match with
2426     // HdMeshTopology::DecodeFaceIndexFromPrimitiveParam()
2427     //
2428     // PatchParam is defined as ivec3 (see opensubdiv/far/patchParam.h)
2429     //  Field0     | Bits | Content
2430     //  -----------|:----:|---------------------------------------------------
2431     //  faceId     | 28   | the faceId of the patch (Storm uses ptexIndex)
2432     //  transition | 4    | transition edge mask encoding
2433     //
2434     //  Field1     | Bits | Content
2435     //  -----------|:----:|---------------------------------------------------
2436     //  level      | 4    | the subdivision level of the patch
2437     //  nonquad    | 1    | whether patch is refined from a non-quad face
2438     //  regular    | 1    | whether patch is regular
2439     //  unused     | 1    | unused
2440     //  boundary   | 5    | boundary mask encoding
2441     //  v          | 10   | log2 value of u parameter at first patch corner
2442     //  u          | 10   | log2 value of v parameter at first patch corner
2443     //
2444     //  Field2     (float)  sharpness
2445     //
2446     // whereas adaptive patches have PatchParams computed by OpenSubdiv,
2447     // we need to construct PatchParams for coarse tris and quads.
2448     // Currently it's enough to fill just faceId for coarse quads for
2449     // ptex shading.
2450 
2451     std::stringstream declarations;
2452     std::stringstream accessors;
2453 
2454     if (_metaData.primitiveParamBinding.binding.IsValid()) {
2455 
2456         HdBinding binding = _metaData.primitiveParamBinding.binding;
2457         _EmitDeclaration(declarations, _metaData.primitiveParamBinding);
2458         _EmitAccessor(accessors, _metaData.primitiveParamBinding.name,
2459                         _metaData.primitiveParamBinding.dataType, binding,
2460                         "GetDrawingCoord().primitiveCoord");
2461 
2462         if (_geometricShader->IsPrimTypePoints()) {
2463             // do nothing.
2464             // e.g. if a prim's geomstyle is points and it has a valid
2465             // primitiveParamBinding, we don't generate any of the
2466             // accessor methods.
2467             ;
2468         }
2469         else if (_geometricShader->IsPrimTypeBasisCurves()) {
2470             // straight-forward indexing to get the segment's curve id
2471             accessors
2472                 << "int GetElementID() {\n"
2473                 << "  return (hd_int_get(HdGet_primitiveParam()));\n"
2474                 << "}\n";
2475             accessors
2476                 << "int GetAggregatedElementID() {\n"
2477                 << "  return GetElementID()\n"
2478                 << "  + GetDrawingCoord().elementCoord;\n"
2479                 << "}\n";
2480         }
2481         else if (_geometricShader->IsPrimTypeMesh()) {
2482             // GetPatchParam, GetEdgeFlag
2483             switch (_geometricShader->GetPrimitiveType()) {
2484                 case HdSt_GeometricShader::PrimitiveType::PRIM_MESH_REFINED_QUADS:
2485                 case HdSt_GeometricShader::PrimitiveType::PRIM_MESH_REFINED_TRIANGLES:
2486                 {
2487                     // refined quads (catmulClark uniform subdiv) or
2488                     // refined tris (loop uniform subdiv)
2489                     accessors
2490                         << "ivec3 GetPatchParam() {\n"
2491                         << "  return ivec3(HdGet_primitiveParam().y, \n"
2492                         << "               HdGet_primitiveParam().z, 0);\n"
2493                         << "}\n";
2494                     accessors
2495                         << "int GetEdgeFlag() {\n"
2496                         << "  return (HdGet_primitiveParam().x & 3);\n"
2497                         << "}\n";
2498                     break;
2499                 }
2500 
2501                 case HdSt_GeometricShader::PrimitiveType::PRIM_MESH_BSPLINE:
2502                 case HdSt_GeometricShader::PrimitiveType::PRIM_MESH_BOXSPLINETRIANGLE:
2503                 {
2504                     // "adaptive" subdivision generates refined patches
2505                     // (tessellated triangles)
2506                     accessors
2507                         << "ivec3 GetPatchParam() {\n"
2508                         << "  return ivec3(HdGet_primitiveParam().y, \n"
2509                         << "               HdGet_primitiveParam().z, \n"
2510                         << "               HdGet_primitiveParam().w);\n"
2511                         << "}\n";
2512                     accessors
2513                         << "int GetEdgeFlag() {\n"
2514                         << "  return (HdGet_primitiveParam().x & 3);\n"
2515                         << "}\n";
2516                     break;
2517                 }
2518 
2519                 case HdSt_GeometricShader::PrimitiveType::PRIM_MESH_COARSE_QUADS:
2520                 case HdSt_GeometricShader::PrimitiveType::PRIM_MESH_COARSE_TRIANGLES:
2521                 {
2522                     // coarse quads or coarse triangles
2523                     // ptexId matches the primitiveID for quadrangulated or
2524                     // triangulated meshes, the other fields can be left as 0.
2525                     // When there are geom subsets, we can no longer use the
2526                     // primitiveId and instead use a buffer source generated
2527                     // per subset draw item containing the coarse face indices.
2528                     accessors
2529                         << "#if defined(HD_HAS_coarseFaceIndex)\n"
2530                         << "int HdGet_coarseFaceIndex();\n"
2531                         << "#endif\n"
2532                         << "ivec3 GetPatchParam() {\n"
2533                         << "#if defined(HD_HAS_coarseFaceIndex)\n "
2534                         << "  return ivec3(HdGet_coarseFaceIndex().x, 0, 0);\n"
2535                         << "#else\n "
2536                         << "  return ivec3(gl_PrimitiveID, 0, 0);\n"
2537                         << "#endif\n"
2538                         << "}\n";
2539                     // edge flag encodes edges which have been
2540                     // introduced by quadrangulation or triangulation
2541                     accessors
2542                         << "int GetEdgeFlag() {\n"
2543                         << "  return (HdGet_primitiveParam() & 3);\n"
2544                         << "}\n";
2545                     break;
2546                 }
2547 
2548                 default:
2549                 {
2550                     TF_CODING_ERROR("HdSt_GeometricShader::PrimitiveType %d is "
2551                       "unexpected in _GenerateElementPrimvar().",
2552                       (int)_geometricShader->GetPrimitiveType());
2553                 }
2554             }
2555 
2556             // GetFVarIndex
2557             if (_geometricShader->GetFvarPatchType() ==
2558                 HdSt_GeometricShader::FvarPatchType::PATCH_COARSE_TRIANGLES)
2559             {
2560                 // note that triangulated meshes don't have ptexIndex.
2561                 // Here we're passing primitiveID as ptexIndex PatchParam
2562                 // since Hd_TriangulateFaceVaryingComputation unrolls facevaring
2563                 // primvars for each triangles.
2564                 accessors
2565                     << "int GetFVarIndex(int localIndex) {\n"
2566                     << "  int fvarCoord = GetDrawingCoord().fvarCoord;\n"
2567                     << "  int ptexIndex = GetPatchParam().x & 0xfffffff;\n"
2568                     << "  return fvarCoord + ptexIndex * 3 + localIndex;\n"
2569                     << "}\n";
2570             } else if (_geometricShader->GetFvarPatchType() ==
2571                 HdSt_GeometricShader::FvarPatchType::PATCH_COARSE_QUADS) {
2572                 accessors
2573                     << "int GetFVarIndex(int localIndex) {\n"
2574                     << "  int fvarCoord = GetDrawingCoord().fvarCoord;\n"
2575                     << "  int ptexIndex = GetPatchParam().x & 0xfffffff;\n"
2576                     << "  return fvarCoord + ptexIndex * 4 + localIndex;\n"
2577                     << "}\n";
2578             }
2579 
2580             // ElementID getters
2581             accessors
2582                 << "int GetElementID() {\n"
2583                 << "  return (hd_int_get(HdGet_primitiveParam()) >> 2);\n"
2584                 << "}\n";
2585 
2586             accessors
2587                 << "int GetAggregatedElementID() {\n"
2588                 << "  return GetElementID()\n"
2589                 << "  + GetDrawingCoord().elementCoord;\n"
2590                 << "}\n";
2591         }
2592         else {
2593             TF_CODING_ERROR("HdSt_GeometricShader::PrimitiveType %d is "
2594                   "unexpected in _GenerateElementPrimvar().",
2595                   (int)_geometricShader->GetPrimitiveType());
2596         }
2597     } else {
2598         // no primitiveParamBinding
2599 
2600         // XXX: this is here only to keep the compiler happy, we don't expect
2601         // users to call them -- we really should restructure whatever is
2602         // necessary to avoid having to do this and thus guarantee that users
2603         // can never call bogus versions of these functions.
2604 
2605         // Use a fallback of -1, so that points aren't selection highlighted
2606         // when face 0 is selected. This would be the case if we returned 0,
2607         // since the selection highlighting code is repr-agnostic.
2608         // It is safe to do this for points, since  we don't generate accessors
2609         // for element primvars, and thus don't use it as an index into
2610         // elementCoord.
2611         if (_geometricShader->IsPrimTypePoints()) {
2612             accessors
2613               << "int GetElementID() {\n"
2614               << "  return -1;\n"
2615               << "}\n";
2616         } else {
2617             accessors
2618                 << "int GetElementID() {\n"
2619                 << "  return 0;\n"
2620                 << "}\n";
2621         }
2622         accessors
2623             << "int GetAggregatedElementID() {\n"
2624             << "  return GetElementID();\n"
2625             << "}\n";
2626         accessors
2627             << "int GetEdgeFlag() {\n"
2628             << "  return 0;\n"
2629             << "}\n";
2630         accessors
2631             << "ivec3 GetPatchParam() {\n"
2632             << "  return ivec3(0, 0, 0);\n"
2633             << "}\n";
2634         accessors
2635             << "int GetFVarIndex(int localIndex) {\n"
2636             << "  return 0;\n"
2637             << "}\n";
2638     }
2639     declarations
2640         << "int GetElementID();\n"
2641         << "int GetAggregatedElementID();\n";
2642 
2643 
2644     if (_metaData.edgeIndexBinding.binding.IsValid()) {
2645 
2646         HdBinding binding = _metaData.edgeIndexBinding.binding;
2647 
2648         _EmitDeclaration(declarations, _metaData.edgeIndexBinding);
2649         _EmitAccessor(accessors, _metaData.edgeIndexBinding.name,
2650                     _metaData.edgeIndexBinding.dataType, binding,
2651                     "GetDrawingCoord().primitiveCoord");
2652     }
2653 
2654     if (_metaData.coarseFaceIndexBinding.binding.IsValid()) {
2655         _genCommon << "#define HD_HAS_"
2656             << _metaData.coarseFaceIndexBinding.name << " 1\n";
2657 
2658         const HdBinding &binding = _metaData.coarseFaceIndexBinding.binding;
2659 
2660         _EmitDeclaration(declarations, _metaData.coarseFaceIndexBinding);
2661         _EmitAccessor(accessors, _metaData.coarseFaceIndexBinding.name,
2662                     _metaData.coarseFaceIndexBinding.dataType, binding,
2663                     "GetDrawingCoord().primitiveCoord  + localIndex");
2664     }
2665 
2666     switch (_geometricShader->GetPrimitiveType()) {
2667         case HdSt_GeometricShader::PrimitiveType::PRIM_MESH_REFINED_QUADS:
2668         case HdSt_GeometricShader::PrimitiveType::PRIM_MESH_REFINED_TRIANGLES:
2669         case HdSt_GeometricShader::PrimitiveType::PRIM_MESH_BSPLINE:
2670         case HdSt_GeometricShader::PrimitiveType::PRIM_MESH_BOXSPLINETRIANGLE:
2671         case HdSt_GeometricShader::PrimitiveType::PRIM_MESH_COARSE_QUADS:
2672         case HdSt_GeometricShader::PrimitiveType::PRIM_MESH_COARSE_TRIANGLES:
2673             // This is no longer used by Storm but is generated for backward
2674             // compatibility with production shaders.
2675             accessors
2676                 << "int GetAuthoredEdgeId(int primitiveEdgeId) {\n"
2677                 << "  return primitiveEdgeId;\n"
2678                 << "}\n";
2679             break;
2680         default:
2681             // The functions below are used in picking (id render) and/or
2682             // selection highlighting, and are expected to be defined.
2683             // Generate fallback versions when we aren't rendering meshes.
2684             accessors
2685                 << "int GetAuthoredEdgeId(int primitiveEdgeId) {\n"
2686                 << "  return -1;\n"
2687                 << "}\n";
2688             accessors
2689                 << "int GetPrimitiveEdgeId() {\n"
2690                 << "  return -1;\n"
2691                 << "}\n";
2692             accessors
2693                 << "float GetSelectedEdgeOpacity() {\n"
2694                 << "  return 0.0;\n"
2695                 << "}\n";
2696             break;
2697     }
2698 
2699     declarations
2700         << "int GetPrimitiveEdgeId();\n"
2701         << "float GetSelectedEdgeOpacity();\n";
2702 
2703     // Uniform primvar data declarations & accessors
2704     if (!_geometricShader->IsPrimTypePoints()) {
2705         TF_FOR_ALL (it, _metaData.elementData) {
2706             HdBinding binding = it->first;
2707             TfToken const &name = it->second.name;
2708             TfToken const &dataType = it->second.dataType;
2709 
2710             _EmitDeclaration(declarations, name, dataType, binding);
2711             // AggregatedElementID gives us the buffer index post batching, which
2712             // is what we need for accessing element (uniform) primvar data.
2713             _EmitAccessor(accessors, name, dataType, binding,"GetAggregatedElementID()");
2714         }
2715     }
2716 
2717     for (size_t i = 0; i < _metaData.fvarIndicesBindings.size(); ++i) {
2718         if (!_metaData.fvarIndicesBindings[i].binding.IsValid()) {
2719             continue;
2720         }
2721 
2722         HdBinding binding = _metaData.fvarIndicesBindings[i].binding;
2723         TfToken name = _metaData.fvarIndicesBindings[i].name;
2724         _EmitDeclaration(declarations, name,
2725             _metaData.fvarIndicesBindings[i].dataType,
2726             _metaData.fvarIndicesBindings[i].binding, 0);
2727 
2728         if (_geometricShader->GetFvarPatchType() ==
2729             HdSt_GeometricShader::FvarPatchType::PATCH_BSPLINE ||
2730             _geometricShader->GetFvarPatchType() ==
2731             HdSt_GeometricShader::FvarPatchType::PATCH_BOXSPLINETRIANGLE) {
2732             _EmitAccessor(accessors, name,
2733                 _metaData.fvarIndicesBindings[i].dataType, binding,
2734                 "GetDrawingCoord().primitiveCoord * HD_NUM_PATCH_VERTS + "
2735                 "localIndex");
2736         } else {
2737             _EmitAccessor(accessors,name,
2738                 _metaData.fvarIndicesBindings[i].dataType, binding,
2739                 "GetDrawingCoord().primitiveCoord + localIndex");
2740         }
2741     }
2742 
2743     for (size_t i = 0; i < _metaData.fvarPatchParamBindings.size(); ++i) {
2744         if (!_metaData.fvarPatchParamBindings[i].binding.IsValid()) {
2745             continue;
2746         }
2747 
2748         HdBinding binding = _metaData.fvarPatchParamBindings[i].binding;
2749         TfToken name = _metaData.fvarPatchParamBindings[i].name;
2750         _EmitDeclaration(declarations, name,
2751             _metaData.fvarPatchParamBindings[i].dataType,
2752             _metaData.fvarPatchParamBindings[i].binding, 0);
2753 
2754         // Only need fvar patch param for bspline or box spline patches
2755         if (_geometricShader->GetFvarPatchType() ==
2756             HdSt_GeometricShader::FvarPatchType::PATCH_BSPLINE ||
2757             _geometricShader->GetFvarPatchType() ==
2758             HdSt_GeometricShader::FvarPatchType::PATCH_BOXSPLINETRIANGLE) {
2759             _EmitAccessor(accessors, name,
2760                 _metaData.fvarPatchParamBindings[i].dataType, binding,
2761                 "GetDrawingCoord().primitiveCoord + localIndex");
2762         }
2763     }
2764 
2765     // Emit primvar declarations and accessors.
2766     _genTCS << declarations.str()
2767             << accessors.str();
2768     _genTES << declarations.str()
2769             << accessors.str();
2770     _genGS << declarations.str()
2771            << accessors.str();
2772     _genFS << declarations.str()
2773            << accessors.str();
2774 }
2775 
2776 void
_GenerateVertexAndFaceVaryingPrimvar(bool hasGS)2777 HdSt_CodeGen::_GenerateVertexAndFaceVaryingPrimvar(bool hasGS)
2778 {
2779     // VS specific accessor for the "vertex drawing coordinate"
2780     // Even though we currently always plumb vertexCoord as part of the drawing
2781     // coordinate, we expect clients to use this accessor when querying the base
2782     // vertex offset for a draw call.
2783     GlfContextCaps const &caps = GlfContextCaps::GetInstance();
2784     _genVS << "int GetBaseVertexOffset() {\n";
2785     if (caps.shaderDrawParametersEnabled) {
2786         if (caps.glslVersion < 460) { // use ARB extension
2787             _genVS << "  return gl_BaseVertexARB;\n";
2788         } else {
2789             _genVS << "  return gl_BaseVertex;\n";
2790         }
2791     } else {
2792         _genVS << "  return GetDrawingCoord().vertexCoord;\n";
2793     }
2794     _genVS << "}\n";
2795 
2796     // Vertex, Varying, and FVar primvar flow into the fragment shader as
2797     // per-fragment attribute data that has been interpolated by the rasterizer,
2798     // and hence have similarities for code gen.
2799     // While vertex primvar are authored per vertex and require plumbing
2800     // through all shader stages, fVar is emitted only in the GS stage.
2801     // Varying primvar are bound in the VS via buffer array but are processed as
2802     // vertex data for the rest of the stages.
2803     /*
2804       // --------- vertex data declaration (VS) ----------
2805       layout (location = 0) in vec3 normals;
2806       layout (location = 1) in vec3 points;
2807 
2808       out Primvars {
2809           vec3 normals;
2810           vec3 points;
2811       } outPrimvars;
2812 
2813       void ProcessPrimvars() {
2814           outPrimvars.normals = normals;
2815           outPrimvars.points = points;
2816       }
2817 
2818       // --------- geometry stage plumbing -------
2819       in Primvars {
2820           vec3 normals;
2821           vec3 points;
2822       } inPrimvars[];
2823       out Primvars {
2824           vec3 normals;
2825           vec3 points;
2826       } outPrimvars;
2827 
2828       void ProcessPrimvars(int index) {
2829           outPrimvars = inPrimvars[index];
2830       }
2831 
2832       // --------- vertex/varying data accessors (used in GS/FS) ---
2833       in Primvars {
2834           vec3 normals;
2835           vec3 points;
2836       } inPrimvars;
2837       vec3 HdGet_normals(int localIndex=0) {
2838           return inPrimvars.normals;
2839       }
2840     */
2841 
2842     std::stringstream vertexInputs;
2843     std::stringstream interstageVertexData;
2844     std::stringstream accessorsVS, accessorsTCS, accessorsTES,
2845         accessorsGS, accessorsFS;
2846 
2847     // vertex
2848     TF_FOR_ALL (it, _metaData.vertexData) {
2849         HdBinding binding = it->first;
2850         TfToken const &name = it->second.name;
2851         TfToken const &dataType = it->second.dataType;
2852 
2853         // future work:
2854         // with ARB_enhanced_layouts extention, it's possible
2855         // to use "component" qualifier to declare offsetted primvars
2856         // in interleaved buffer.
2857         _EmitDeclaration(vertexInputs, name, dataType, binding);
2858 
2859         interstageVertexData << "  " << _GetPackedType(dataType, false)
2860                              << " " << name << ";\n";
2861 
2862         // primvar accessors
2863         _EmitAccessor(accessorsVS, name, dataType, binding);
2864 
2865         _EmitStructAccessor(accessorsTCS, _tokens->inPrimvars,
2866                             name, dataType, /*arraySize=*/1, "gl_InvocationID");
2867         _EmitStructAccessor(accessorsTES, _tokens->inPrimvars,
2868                             name, dataType, /*arraySize=*/1, "localIndex");
2869         _EmitStructAccessor(accessorsGS,  _tokens->inPrimvars,
2870                             name, dataType, /*arraySize=*/1, "localIndex");
2871         _EmitStructAccessor(accessorsFS,  _tokens->inPrimvars,
2872                             name, dataType, /*arraySize=*/1);
2873 
2874         // interstage plumbing
2875         _procVS << "  outPrimvars." << name
2876                 << " = " << name << ";\n";
2877         _procTCS << "  outPrimvars[gl_InvocationID]." << name
2878                  << " = inPrimvars[gl_InvocationID]." << name << ";\n";
2879         _procTES << "  outPrimvars." << name
2880                  << " = basis[0] * inPrimvars[i0]." << name
2881                  << " + basis[1] * inPrimvars[i1]." << name
2882                  << " + basis[2] * inPrimvars[i2]." << name
2883                  << " + basis[3] * inPrimvars[i3]." << name << ";\n";
2884         _procGS  << "  outPrimvars." << name
2885                  << " = inPrimvars[index]." << name << ";\n";
2886     }
2887 
2888     /*
2889       // --------- varying data declaration (VS) ----------------
2890       layout (std430, binding=?) buffer buffer0 {
2891           vec3 displayColor[];
2892       };
2893 
2894       vec3 HdGet_displayColor(int localIndex) {
2895         int index =  GetDrawingCoord().varyingCoord + gl_VertexID -
2896             GetBaseVertexOffset();
2897         return vec3(displayColor[index]);
2898       }
2899       vec3 HdGet_displayColor() { return HdGet_displayColor(0); }
2900 
2901       out Primvars {
2902           vec3 displayColor;
2903       } outPrimvars;
2904 
2905       void ProcessPrimvars() {
2906           outPrimvars.displayColor = HdGet_displayColor();
2907       }
2908 
2909       // --------- fragment stage plumbing -------
2910       in Primvars {
2911           vec3 displayColor;
2912       } inPrimvars;
2913     */
2914 
2915     std::stringstream varyingDeclarations;
2916 
2917     TF_FOR_ALL (it, _metaData.varyingData) {
2918         HdBinding binding = it->first;
2919         TfToken const &name = it->second.name;
2920         TfToken const &dataType = it->second.dataType;
2921 
2922         _EmitDeclaration(varyingDeclarations, name, dataType, binding);
2923 
2924         interstageVertexData << "  " << _GetPackedType(dataType, false)
2925                              << " " << name << ";\n";
2926 
2927         // primvar accessors
2928         _EmitBufferAccessor(accessorsVS, name, dataType,
2929             "GetDrawingCoord().varyingCoord + gl_VertexID - GetBaseVertexOffset()");
2930         _EmitStructAccessor(accessorsTCS, _tokens->inPrimvars,
2931                             name, dataType, /*arraySize=*/1, "gl_InvocationID");
2932         _EmitStructAccessor(accessorsTES, _tokens->inPrimvars,
2933                             name, dataType, /*arraySize=*/1, "localIndex");
2934         _EmitStructAccessor(accessorsGS,  _tokens->inPrimvars,
2935                             name, dataType, /*arraySize=*/1, "localIndex");
2936         _EmitStructAccessor(accessorsFS,  _tokens->inPrimvars,
2937                             name, dataType, /*arraySize=*/1);
2938 
2939         // interstage plumbing
2940         _procVS << "  outPrimvars." << name
2941                 << " = " << "HdGet_" << name << "();\n";
2942         _procTCS << "  outPrimvars[gl_InvocationID]." << name
2943                  << " = inPrimvars[gl_InvocationID]." << name << ";\n";
2944         _procTES << "  outPrimvars." << name  << " = ProcessPrimvar("
2945                  << "inPrimvars[i0]." << name
2946                  << ", inPrimvars[i1]." << name
2947                  << ", inPrimvars[i2]." << name
2948                  << ", inPrimvars[i3]." << name
2949                  << ", basis, uv);\n";
2950         _procGS  << "  outPrimvars." << name
2951                  << " = inPrimvars[index]." << name << ";\n";
2952     }
2953 
2954     /*
2955       // --------- facevarying data declaration ----------------
2956       layout (std430, binding=?) buffer buffer0 {
2957           vec2 map1[];
2958       };
2959       layout (std430, binding=?) buffer buffer1 {
2960           float map2_u[];
2961       };
2962 
2963       // --------- geometry stage plumbing -------
2964       out Primvars {
2965           ...
2966           vec2 map1;
2967           float map2_u;
2968       } outPrimvars;
2969 
2970       void ProcessPrimvars(int index) {
2971           outPrimvars.map1 = HdGet_map1(index, localST);
2972           outPrimvars.map2_u = HdGet_map2_u(index, localST);
2973       }
2974 
2975       // --------- fragment stage plumbing -------
2976       in Primvars {
2977           ...
2978           vec2 map1;
2979           float map2_u;
2980       } inPrimvars;
2981 
2982       // --------- facevarying data accessors ----------
2983       // in geometry shader
2984       // unrefined internal accessor
2985       vec2 HdGet_map1_Coarse(int localIndex) {
2986           int fvarIndex = GetFVarIndex(localIndex);
2987           return vec2(map1[fvarIndex]);
2988       }
2989       // unrefined public accessors
2990       vec2 HdGet_map1(int localIndex, vec2 st) {
2991           int fvarIndex = GetFVarIndex(localIndex);
2992           return (HdGet_map1_Coarse(0) * ...);
2993       }
2994       vec2 HdGet_map1(int localIndex) {
2995           vec2 localST = GetPatchCoord(localIndex).xy;
2996           return HdGet_map1(localIndex, localST);
2997       }
2998 
2999       // refined internal accessor
3000       vec2 HdGet_map1_Coarse(int localIndex) {
3001           int fvarIndex = GetDrawingCoord().fvarCoord + localIndex;
3002           return vec2(map1[fvarIndex]);
3003       }
3004       // refined public accessors
3005       vec2 HdGet_map1(int localIndex, vec2 st) {
3006           ivec4 indices = HdGet_fvarIndices0();
3007           return mix(mix(HdGet_map1_Coarse(indices[0])...);
3008       }
3009       // refined quads:
3010       vec2 HdGet_map1(int localIndex) {
3011           vec2 lut[4] = vec2[4](vec2(0,0), vec2(1,0), vec2(1,1), vec2(0,1));
3012           vec2 localST = lut[localIndex];\n";
3013           return HdGet_map1(localIndex, localST);
3014       }
3015       // refined triangles:
3016       vec2 HdGet_map1(int localIndex) {
3017           vec2 lut[3] = vec2[3](vec2(0,0), vec2(1,0), vec2(0,1));
3018           vec2 localST = lut[localIndex];\n";
3019           return HdGet_map1(localIndex, localST);
3020       }
3021 
3022       // refined public accessor for b-spline/box-spline patches
3023       vec2 HdGet_map1(int localIndex, vec2 st) {
3024           int patchType = OSD_PATCH_DESCRIPTOR_REGULAR; // b-spline patches
3025           // OR int patchType = OSD_PATCH_DESCRIPTOR_LOOP; for box-spline
3026           ivec2 fvarPatchParam = HdGet_fvarPatchParam0();
3027           OsdPatchParam param = OsdPatchParamInit(fvarPatchParam.x,
3028                                                   fvarPatchParam.y, 0);
3029           float wP[20], wDu[20], wDv[20], wDuu[20], wDuv[20], wDvv[20];
3030           OsdEvaluatePatchBasisNormalized(patchType, param, st.s,
3031             st.t, wP, wDu, wDv, wDuu, wDuv, wDvv);
3032           vec2 result = vec2(0);
3033           for (int i = 0; i < HD_NUM_PATCH_VERTS; ++i) {
3034               int fvarIndex = HdGet_fvarIndices0(i);
3035                vec2 cv = vec2(HdGet_map1_Coarse(fvarIndex));
3036                result += wP[i] * cv;
3037           }
3038           return result;
3039       }
3040 
3041       // in fragment shader
3042       vec2 HdGet_map1() {
3043           return inPrimvars.map1;
3044       }
3045     */
3046 
3047     // face varying
3048     std::stringstream fvarDeclarations;
3049     std::stringstream interstageFVarData;
3050 
3051      if (hasGS) {
3052         // FVar primvars are emitted only by the GS.
3053         // If the GS isn't active, we can skip processing them.
3054         TF_FOR_ALL (it, _metaData.fvarData) {
3055             HdBinding binding = it->first;
3056             TfToken const &name = it->second.name;
3057             TfToken const &dataType = it->second.dataType;
3058             const int channel = it->second.channel;
3059 
3060             _EmitDeclaration(fvarDeclarations, name, dataType, binding);
3061 
3062             interstageFVarData << "  " << _GetPackedType(dataType, false)
3063                                << " " << name << ";\n";
3064 
3065             // primvar accessors (only in GS and FS)
3066             _EmitFVarGSAccessor(accessorsGS, name, dataType, binding,
3067                                 _geometricShader->GetPrimitiveType(),
3068                                 _geometricShader->GetFvarPatchType(),
3069                                 channel);
3070 
3071             _EmitStructAccessor(accessorsFS, _tokens->inPrimvars, name, dataType,
3072                                 /*arraySize=*/1, NULL);
3073 
3074             if (_geometricShader->GetFvarPatchType() ==
3075                 HdSt_GeometricShader::FvarPatchType::PATCH_BSPLINE ||
3076                 _geometricShader->GetFvarPatchType() ==
3077                 HdSt_GeometricShader::FvarPatchType::PATCH_BOXSPLINETRIANGLE) {
3078                     _procGS << "  outPrimvars." << name
3079                     <<" = HdGet_" << name << "(index, localST);\n";
3080             } else {
3081                 _procGS << "  outPrimvars." << name
3082                     <<" = HdGet_" << name << "(index);\n";
3083             }
3084 
3085         }
3086     }
3087 
3088     if (!interstageVertexData.str().empty()) {
3089         _genVS  << vertexInputs.str()
3090                 << varyingDeclarations.str()
3091                 << "out Primvars {\n"
3092                 << interstageVertexData.str()
3093                 << "} outPrimvars;\n"
3094                 << accessorsVS.str();
3095 
3096         _genTCS << "in Primvars {\n"
3097                 << interstageVertexData.str()
3098                 << "} inPrimvars[gl_MaxPatchVertices];\n"
3099                 << "out Primvars {\n"
3100                 << interstageVertexData.str()
3101                 << "} outPrimvars[HD_NUM_PATCH_EVAL_VERTS];\n"
3102                 << accessorsTCS.str();
3103 
3104         _genTES << "in Primvars {\n"
3105                 << interstageVertexData.str()
3106                 << "} inPrimvars[gl_MaxPatchVertices];\n"
3107                 << "out Primvars {\n"
3108                 << interstageVertexData.str()
3109                 << "} outPrimvars;\n"
3110                 << accessorsTES.str();
3111 
3112         _genGS  << fvarDeclarations.str()
3113                 << "in Primvars {\n"
3114                 << interstageVertexData.str()
3115                 << "} inPrimvars[HD_NUM_PRIMITIVE_VERTS];\n"
3116                 << "out Primvars {\n"
3117                 << interstageVertexData.str()
3118                 << interstageFVarData.str()
3119                 << "} outPrimvars;\n"
3120                 << accessorsGS.str();
3121 
3122         _genFS  << "in Primvars {\n"
3123                 << interstageVertexData.str()
3124                 << interstageFVarData.str()
3125                 << "} inPrimvars;\n"
3126                 << accessorsFS.str();
3127     }
3128 
3129     // ---------
3130     _genFS << "vec4 GetPatchCoord(int index);\n";
3131     _genFS << "vec4 GetPatchCoord() { return GetPatchCoord(0); }\n";
3132 
3133     _genGS << "vec4 GetPatchCoord(int localIndex);\n";
3134 }
3135 
3136 void
_GenerateShaderParameters()3137 HdSt_CodeGen::_GenerateShaderParameters()
3138 {
3139     /*
3140       ------------- Declarations -------------
3141 
3142       // shader parameter buffer
3143       struct ShaderData {
3144           <type>          <name>;
3145           vec4            diffuseColor;     // fallback uniform
3146           sampler2D       kdTexture;        // uv texture    (bindless texture)
3147           sampler2DArray  ptexTexels;       // ptex texels   (bindless texture)
3148           usamplerBuffer  ptexLayouts;      // ptex layouts  (bindless texture)
3149       };
3150 
3151       // bindless buffer
3152       layout (location=0) uniform ShaderData *shaderData;
3153       // not bindless buffer
3154       layout (std430, binding=0) buffer {
3155           ShaderData shaderData[];
3156       };
3157 
3158       // non bindless textures
3159       uniform sampler2D      samplers_2d[N];
3160       uniform sampler2DArray samplers_2darray[N];
3161       uniform isamplerBuffer isamplerBuffers[N];
3162 
3163       ------------- Accessors -------------
3164 
3165       * fallback value
3166       <type> HdGet_<name>(int localIndex=0) {
3167           return shaderData[GetDrawingCoord().shaderCoord].<name>
3168       }
3169 
3170       * primvar redirect
3171       <type> HdGet_<name>(int localIndex=0) {
3172           return HdGet_<inPrimvars>().xxx;
3173       }
3174 
3175       * bindless 2D texture
3176       <type> HdGet_<name>(int localIndex=0) {
3177           return texture(sampler2D(shaderData[GetDrawingCoord().shaderCoord].<name>), <inPrimvars>).xxx;
3178       }
3179 
3180       * non-bindless 2D texture
3181       <type> HdGet_<name>(int localIndex=0) {
3182           return texture(samplers_2d[<offset> + drawIndex * <stride>], <inPrimvars>).xxx;
3183       }
3184 
3185       * bindless Ptex texture
3186       <type> HdGet_<name>(int localIndex=0) {
3187           return GlopPtexTextureLookup(<name>_Data, <name>_Packing, GetPatchCoord()).xxx;
3188       }
3189 
3190       * non-bindless Ptex texture
3191       <type> HdGet_<name>(int localIndex=0) {
3192           return GlopPtexTextureLookup(
3193               samplers_2darray[<offset_ptex_texels> + drawIndex * <stride>],
3194               usamplerBuffers[<offset_ptex_layouts> + drawIndex * <stride>],
3195               GetPatchCoord()).xxx;
3196       }
3197 
3198       * bindless Ptex texture with patchcoord
3199       <type> HdGet_<name>(vec4 patchCoord) {
3200           return GlopPtexTextureLookup(<name>_Data, <name>_Packing, patchCoord).xxx;
3201       }
3202 
3203       * non-bindless Ptex texture
3204       <type> HdGet_<name>(vec4 patchCoord) {
3205           return GlopPtexTextureLookup(
3206               samplers_2darray[<offset_ptex_texels> + drawIndex * <stride>],
3207               usamplerBuffers[<offset_ptex_layouts> + drawIndex * <stride>],
3208               patchCoord).xxx;
3209       }
3210 
3211       * transform2d
3212       vec2 HdGet_<name>(int localIndex=0) {
3213           float angleRad = HdGet_<name>_rotation() * 3.1415926f / 180.f;
3214           mat2 rotMat = mat2(cos(angleRad), sin(angleRad),
3215                              -sin(angleRad), cos(angleRad));
3216       #if defined(HD_HAS_<primvarName>)
3217           return vec2(HdGet_<name>_translation() + rotMat *
3218             (HdGet_<name>_scale() * HdGet_<primvarName>(localIndex)));
3219       #else
3220           int shaderCoord = GetDrawingCoord().shaderCoord;
3221           return vec2(HdGet_<name>_translation() + rotMat *
3222            (HdGet_<name>_scale() * shaderData[shaderCoord].<name>_fallback.xy));
3223       #endif
3224       }
3225 
3226     */
3227 
3228     std::stringstream declarations;
3229     std::stringstream accessors;
3230 
3231     GlfContextCaps const &caps = GlfContextCaps::GetInstance();
3232 
3233     TfToken typeName("ShaderData");
3234     TfToken varName("shaderData");
3235 
3236     // for shader parameters, we create declarations and accessors separetely.
3237     TF_FOR_ALL (it, _metaData.shaderData) {
3238         HdBinding binding = it->first;
3239 
3240         declarations << "struct " << typeName << " {\n";
3241 
3242         TF_FOR_ALL (dbIt, it->second.entries) {
3243             declarations << "  " << _GetPackedType(dbIt->dataType, false)
3244                          << " " << dbIt->name
3245                          << ";\n";
3246 
3247         }
3248         declarations << "};\n";
3249 
3250         // for array delaration, SSBO and bindless uniform can use [].
3251         // UBO requires the size [N].
3252         // XXX: [1] is a hack to cheat driver not telling the actual size.
3253         //      may not work some GPUs.
3254         // XXX: we only have 1 shaderData entry (interleaved).
3255         int arraySize = (binding.GetType() == HdBinding::UBO) ? 1 : 0;
3256         _EmitDeclaration(declarations, varName, typeName, binding, arraySize);
3257 
3258         break;
3259     }
3260 
3261     // Non-field redirect accessors.
3262     TF_FOR_ALL (it, _metaData.shaderParameterBinding) {
3263 
3264         // adjust datatype
3265         std::string swizzle = _GetSwizzleString(it->second.dataType,
3266                                                 it->second.swizzle);
3267 
3268         HdBinding::Type bindingType = it->first.GetType();
3269         if (bindingType == HdBinding::FALLBACK) {
3270             // vec4 HdGet_name(int localIndex)
3271             accessors
3272                 << _GetUnpackedType(it->second.dataType, false)
3273                 << " HdGet_" << it->second.name << "(int localIndex) {\n"
3274                 << "  int shaderCoord = GetDrawingCoord().shaderCoord; \n"
3275                 << "  return "
3276                 << _GetPackedTypeAccessor(it->second.dataType, false)
3277                 << "(shaderData[shaderCoord]."
3278                 << it->second.name << HdSt_ResourceBindingSuffixTokens->fallback
3279                 << swizzle
3280                 << ");\n"
3281                 << "}\n";
3282 
3283             // vec4 HdGet_name()
3284             accessors
3285                 << _GetUnpackedType(it->second.dataType, false)
3286                 << " HdGet_" << it->second.name
3287                 << "() { return HdGet_" << it->second.name << "(0); }\n";
3288 
3289         } else if (bindingType == HdBinding::BINDLESS_TEXTURE_2D) {
3290             // a function returning sampler requires bindless_texture
3291 
3292             _EmitTextureAccessors(
3293                 accessors, it->second, swizzle,
3294                 /* dim = */ 2,
3295                 /* hasTextureTransform = */ false,
3296                 /* hasTextureScaleAndBias = */ true,
3297                 /* isBindless = */ true);
3298 
3299         } else if (bindingType == HdBinding::TEXTURE_2D) {
3300 
3301             declarations
3302                 << LayoutQualifier(it->first)
3303                 << "uniform sampler2D sampler2d_" << it->second.name << ";\n";
3304 
3305             _EmitTextureAccessors(
3306                 accessors, it->second, swizzle,
3307                 /* dim = */ 2,
3308                 /* hasTextureTransform = */ false,
3309                 /* hasTextureScaleAndBias = */ true,
3310                 /* isBindless = */ false);
3311 
3312         } else if (bindingType == HdBinding::BINDLESS_TEXTURE_FIELD) {
3313 
3314             _EmitTextureAccessors(
3315                 accessors, it->second, swizzle,
3316                 /* dim = */ 3,
3317                 /* hasTextureTransform = */ true,
3318                 /* hasTextureScaleAndBias = */ false,
3319                 /* isBindless = */ true);
3320 
3321         } else if (bindingType == HdBinding::TEXTURE_FIELD) {
3322 
3323             declarations
3324                 << LayoutQualifier(it->first)
3325                 << "uniform sampler3D sampler3d_" << it->second.name << ";\n";
3326 
3327             _EmitTextureAccessors(
3328                 accessors, it->second, swizzle,
3329                 /* dim = */ 3,
3330                 /* hasTextureTransform = */ true,
3331                 /* hasTextureScaleAndBias = */ false,
3332                 /* isBindless = */ false);
3333 
3334         } else if (bindingType == HdBinding::BINDLESS_TEXTURE_UDIM_ARRAY) {
3335             accessors
3336                 << "#ifdef HD_HAS_" << it->second.name << "_"
3337                 << HdStTokens->scale << "\n"
3338                 << "vec4 HdGet_" << it->second.name << "_"
3339                 << HdStTokens->scale << "();\n"
3340                 << "#endif\n"
3341                 << "#ifdef HD_HAS_" << it->second.name << "_"
3342                 << HdStTokens->bias << "\n"
3343                 << "vec4 HdGet_" << it->second.name << "_"
3344                 << HdStTokens->bias << "();\n"
3345                 << "#endif\n";
3346 
3347             // a function returning sampler requires bindless_texture
3348             if (caps.bindlessTextureEnabled) {
3349                 accessors
3350                     << "sampler2DArray\n"
3351                     << "HdGetSampler_" << it->second.name << "() {\n"
3352                     << "  int shaderCoord = GetDrawingCoord().shaderCoord; \n"
3353                     << "  return sampler2DArray(shaderData[shaderCoord]."
3354                     << it->second.name << ");\n"
3355                     << "}\n";
3356             }
3357             accessors
3358                 << it->second.dataType
3359                 << " HdGet_" << it->second.name << "()" << " {\n"
3360                 << "  int shaderCoord = GetDrawingCoord().shaderCoord;\n";
3361             if (!it->second.inPrimvars.empty()) {
3362                 accessors
3363                     << "  vec3 c = vec3(0.0, 0.0, 0.0);\n"
3364                     << "#if defined(HD_HAS_"
3365                     << it->second.inPrimvars[0] << ")\n"
3366                     << "  uvec2 handle = shaderData[shaderCoord]."
3367                     << it->second.name
3368                     << HdSt_ResourceBindingSuffixTokens->layout << ";\n"
3369                     << "  if (handle != uvec2(0)) {\n"
3370                     << "    c = hd_sample_udim(HdGet_"
3371                     << it->second.inPrimvars[0] << "().xy);\n"
3372                     << "    c.z = "
3373                     << "texelFetch(sampler1D(handle), int(c.z), 0).x - 1;\n"
3374                     << "  }\n"
3375                     << "#endif\n";
3376             } else {
3377                 accessors
3378                     << "  vec3 c = vec3(0.0, 0.0, 0.0);\n";
3379             }
3380             accessors
3381                 << "  vec4 ret = vec4(0, 0, 0, 0);\n"
3382                 << "  if (c.z >= -0.5) {\n"
3383                 << "    uvec2 handleTexels = shaderData[shaderCoord]."
3384                 << it->second.name << ";\n"
3385                 << "    if (handleTexels != uvec2(0)) {\n"
3386                 << "      ret = texture(sampler2DArray(handleTexels), c);\n"
3387                 << "    }\n  }\n"
3388                 << "  return (ret\n"
3389                 << "#ifdef HD_HAS_" << it->second.name << "_"
3390                 << HdStTokens->scale << "\n"
3391                 << "    * HdGet_" << it->second.name << "_"
3392                 << HdStTokens->scale << "()\n"
3393                 << "#endif\n"
3394                 << "#ifdef HD_HAS_" << it->second.name << "_"
3395                 << HdStTokens->bias << "\n"
3396                 << "    + HdGet_" << it->second.name << "_"
3397                 << HdStTokens->bias  << "()\n"
3398                 << "#endif\n"
3399                 << "  )" << swizzle << ";\n}\n";
3400 
3401             // Create accessor for texture coordinates based on param name
3402             // vec2 HdGetCoord_name()
3403             accessors
3404                 << "vec2 HdGetCoord_" << it->second.name << "() {\n"
3405                 << "  return \n";
3406             if (!it->second.inPrimvars.empty()) {
3407                 accessors
3408                     << "#if defined(HD_HAS_" << it->second.inPrimvars[0] <<")\n"
3409                     << "  HdGet_" << it->second.inPrimvars[0] << "().xy;\n"
3410                     << "#else\n"
3411                     << "  vec2(0.0, 0.0)\n"
3412                     << "#endif\n";
3413             } else {
3414                 accessors
3415                     << "  vec2(0.0, 0.0)\n";
3416             }
3417             accessors << "; }\n";
3418 
3419             // Emit pre-multiplication by alpha indicator
3420             if (it->second.isPremultiplied) {
3421                 accessors
3422                     << "#define " << it->second.name << "_IS_PREMULTIPLIED 1\n";
3423             }
3424         } else if (bindingType == HdBinding::TEXTURE_UDIM_ARRAY) {
3425             accessors
3426                 << "#ifdef HD_HAS_" << it->second.name << "_"
3427                 << HdStTokens->scale << "\n"
3428                 << "vec4 HdGet_" << it->second.name << "_"
3429                 << HdStTokens->scale << "();\n"
3430                 << "#endif\n"
3431                 << "#ifdef HD_HAS_" << it->second.name << "_"
3432                 << HdStTokens->bias << "\n"
3433                 << "vec4 HdGet_" << it->second.name << "_"
3434                 << HdStTokens->bias << "();\n"
3435                 << "#endif\n";
3436 
3437             declarations
3438                 << LayoutQualifier(it->first)
3439                 << "uniform sampler2DArray sampler2dArray_"
3440                 << it->second.name << ";\n";
3441 
3442             // a function returning sampler requires bindless_texture
3443             if (caps.bindlessTextureEnabled) {
3444                 accessors
3445                     << "sampler2DArray\n"
3446                     << "HdGetSampler_" << it->second.name << "() {\n"
3447                     << "  return sampler2dArray_" << it->second.name << ";"
3448                     << "}\n";
3449             } else {
3450                 accessors
3451                     << "#define HdGetSampler_" << it->second.name << "()"
3452                     << " sampler2dArray_" << it->second.name << "\n";
3453             }
3454             // vec4 HdGet_name(vec2 coord) { vec3 c = hd_sample_udim(coord);
3455             // c.z = texelFetch(sampler1d_name_layout, int(c.z), 0).x - 1;
3456             // vec4 ret = vec4(0, 0, 0, 0);
3457             // if (c.z >= -0.5) { ret = texture(sampler2dArray_name, c); }
3458             // return (ret
3459             // #ifdef HD_HAS_name_scale
3460             //   * HdGet_name_scale()
3461             // #endif
3462             // #ifdef HD_HAS_name_bias
3463             //   + HdGet_name_bias()
3464             // #endif
3465             // ).xyz; }
3466             accessors
3467                 << it->second.dataType
3468                 << " HdGet_" << it->second.name
3469                 << "(vec2 coord) { vec3 c = hd_sample_udim(coord);\n"
3470                 << "  c.z = texelFetch(sampler1d_"
3471                 << it->second.name << HdSt_ResourceBindingSuffixTokens->layout
3472                 << ", int(c.z), 0).x - 1;\n"
3473                 << "  vec4 ret = vec4(0, 0, 0, 0);\n"
3474                 << "  if (c.z >= -0.5) { ret = texture(sampler2dArray_"
3475                 << it->second.name << ", c); }\n  return (ret\n"
3476                 << "#ifdef HD_HAS_" << it->second.name << "_"
3477                 << HdStTokens->scale << "\n"
3478                 << "    * HdGet_" << it->second.name << "_"
3479                 << HdStTokens->scale << "()\n"
3480                 << "#endif\n"
3481                 << "#ifdef HD_HAS_" << it->second.name << "_"
3482                 << HdStTokens->bias << "\n"
3483                 << "    + HdGet_" << it->second.name << "_"
3484                 << HdStTokens->bias  << "()\n"
3485                 << "#endif\n"
3486                 << "  )" << swizzle << ";\n}\n";
3487 
3488             // Create accessor for texture coordinates based on param name
3489             // vec2 HdGetCoord_name()
3490             accessors
3491                 << "vec2 HdGetCoord_" << it->second.name << "() {\n"
3492                 << "  return \n";
3493             if (!it->second.inPrimvars.empty()) {
3494                 accessors
3495                     << "#if defined(HD_HAS_" << it->second.inPrimvars[0] <<")\n"
3496                     << "  HdGet_" << it->second.inPrimvars[0] << "().xy\n"
3497                     << "#else\n"
3498                     << "  vec2(0.0, 0.0)\n"
3499                     << "#endif\n";
3500             } else {
3501                 accessors
3502                     << "  vec2(0.0, 0.0)\n";
3503             }
3504             accessors << "; }\n";
3505 
3506             // vec4 HdGet_name() { return HdGet_name(HdGetCoord_name()); }
3507             accessors
3508                 << it->second.dataType
3509                 << " HdGet_" << it->second.name
3510                 << "() { return HdGet_" << it->second.name << "("
3511                 << "HdGetCoord_" << it->second.name << "()); }\n";
3512 
3513             // Emit pre-multiplication by alpha indicator
3514             if (it->second.isPremultiplied) {
3515                 accessors
3516                     << "#define " << it->second.name << "_IS_PREMULTIPLIED 1\n";
3517             }
3518         } else if (bindingType == HdBinding::TEXTURE_UDIM_LAYOUT) {
3519             declarations
3520                 << LayoutQualifier(it->first)
3521                 << "uniform sampler1D sampler1d_" << it->second.name << ";\n";
3522         } else if (bindingType == HdBinding::BINDLESS_TEXTURE_PTEX_TEXEL) {
3523             accessors
3524                 << _GetUnpackedType(it->second.dataType, false)
3525                 << " HdGet_" << it->second.name << "(int localIndex) {\n"
3526                 << "  int shaderCoord = GetDrawingCoord().shaderCoord; \n"
3527                 << "  return " << _GetPackedTypeAccessor(it->second.dataType, false)
3528                 << "(PtexTextureLookup("
3529                 << "sampler2DArray(shaderData[shaderCoord]."
3530                 << it->second.name << "),"
3531                 << "usampler1DArray(shaderData[shaderCoord]."
3532                 << it->second.name << HdSt_ResourceBindingSuffixTokens->layout
3533                 <<"), "
3534                 << "GetPatchCoord(localIndex))" << swizzle << ");\n"
3535                 << "}\n"
3536                 << _GetUnpackedType(it->second.dataType, false)
3537                 << " HdGet_" << it->second.name << "()"
3538                 << "{ return HdGet_" << it->second.name << "(0); }\n"
3539                 << _GetUnpackedType(it->second.dataType, false)
3540                 << " HdGet_" << it->second.name << "(vec4 patchCoord) {\n"
3541                 << "  int shaderCoord = GetDrawingCoord().shaderCoord; \n"
3542                 << "  return " << _GetPackedTypeAccessor(it->second.dataType, false)
3543                 << "(PtexTextureLookup("
3544                 << "sampler2DArray(shaderData[shaderCoord]."
3545                 << it->second.name << "),"
3546                 << "usampler1DArray(shaderData[shaderCoord]."
3547                 << it->second.name << HdSt_ResourceBindingSuffixTokens->layout
3548                 << "), "
3549                 << "patchCoord)" << swizzle << ");\n"
3550                 << "}\n";
3551 
3552             // Emit pre-multiplication by alpha indicator
3553             if (it->second.isPremultiplied) {
3554                 accessors
3555                     << "#define " << it->second.name << "_IS_PREMULTIPLIED 1\n";
3556             }
3557         } else if (bindingType == HdBinding::TEXTURE_PTEX_TEXEL) {
3558             declarations
3559                 << LayoutQualifier(it->first)
3560                 << "uniform sampler2DArray sampler2darray_"
3561                 << it->second.name << ";\n";
3562             accessors
3563                 << _GetUnpackedType(it->second.dataType, false)
3564                 << " HdGet_" << it->second.name << "(int localIndex) {\n"
3565                 << "  return " << _GetPackedTypeAccessor(it->second.dataType, false)
3566                 << "(PtexTextureLookup("
3567                 << "sampler2darray_" << it->second.name << ", "
3568                 << "usampler1darray_"
3569                 << it->second.name << HdSt_ResourceBindingSuffixTokens->layout
3570                 << ", "
3571                 << "GetPatchCoord(localIndex))" << swizzle << ");\n"
3572                 << "}\n"
3573                 << _GetUnpackedType(it->second.dataType, false)
3574                 << " HdGet_" << it->second.name << "()"
3575                 << "{ return HdGet_" << it->second.name << "(0); }\n"
3576                 << _GetUnpackedType(it->second.dataType, false)
3577                 << " HdGet_" << it->second.name << "(vec4 patchCoord) {\n"
3578                 << "  return " << _GetPackedTypeAccessor(it->second.dataType, false)
3579                 << "(PtexTextureLookup("
3580                 << "sampler2darray_" << it->second.name << ", "
3581                 << "usampler1darray_"
3582                 << it->second.name << HdSt_ResourceBindingSuffixTokens->layout
3583                 << ", "
3584                 << "patchCoord)" << swizzle << ");\n"
3585                 << "}\n";
3586 
3587             // Emit pre-multiplication by alpha indicator
3588             if (it->second.isPremultiplied) {
3589                 accessors
3590                     << "#define " << it->second.name << "_IS_PREMULTIPLIED 1\n";
3591             }
3592         } else if (bindingType == HdBinding::BINDLESS_TEXTURE_PTEX_LAYOUT) {
3593             //accessors << _GetUnpackedType(it->second.dataType) << "(0)";
3594         } else if (bindingType == HdBinding::TEXTURE_PTEX_LAYOUT) {
3595             declarations
3596                 << LayoutQualifier(HdBinding(it->first.GetType(),
3597                                              it->first.GetLocation(),
3598                                              it->first.GetTextureUnit()))
3599                 << "uniform usampler1DArray usampler1darray_"
3600                 << it->second.name << ";\n";
3601         } else if (bindingType == HdBinding::PRIMVAR_REDIRECT) {
3602             // Create an HdGet_INPUTNAME for the shader to access a primvar
3603             // for which a HdGet_PRIMVARNAME was already generated earlier.
3604 
3605             // XXX: shader and primvar name collisions are a problem!
3606             // (see, e.g., HYD-1800).
3607             if (it->second.name == it->second.inPrimvars[0]) {
3608                 // Avoid the following:
3609                 // If INPUTNAME and PRIMVARNAME are the same and the
3610                 // primvar exists, we would generate two functions
3611                 // both called HdGet_PRIMVAR, one to read the primvar
3612                 // (based on _metaData.constantData) and one for the
3613                 // primvar redirect here.
3614                 accessors
3615                     << "#if !defined(HD_HAS_" << it->second.name << ")\n";
3616             }
3617 
3618             accessors
3619                 << _GetUnpackedType(it->second.dataType, false)
3620                 << " HdGet_" << it->second.name << "() {\n"
3621                 // If primvar exists, use it
3622                 << "#if defined(HD_HAS_" << it->second.inPrimvars[0] << ")\n"
3623                 << "  return HdGet_" << it->second.inPrimvars[0] << "();\n"
3624                 << "#else\n"
3625                 // Otherwise use default value.
3626                 << "  int shaderCoord = GetDrawingCoord().shaderCoord;\n"
3627                 << "  return "
3628                 << _GetPackedTypeAccessor(it->second.dataType, false)
3629                 << "(shaderData[shaderCoord]."
3630                 << it->second.name << HdSt_ResourceBindingSuffixTokens->fallback
3631                 << swizzle <<  ");\n"
3632                 << "#endif\n"
3633                 << "\n}\n"
3634                 << "#define HD_HAS_" << it->second.name << " 1\n";
3635 
3636             if (it->second.name == it->second.inPrimvars[0]) {
3637                 accessors
3638                     << "#endif\n";
3639             }
3640         } else if (bindingType == HdBinding::TRANSFORM_2D) {
3641             // Forward declare rotation, scale, and translation
3642             accessors
3643                 << "float HdGet_" << it->second.name << "_"
3644                 << HdStTokens->rotation  << "();\n"
3645                 << "vec2 HdGet_" << it->second.name << "_"
3646                 << HdStTokens->scale  << "();\n"
3647                 << "vec2 HdGet_" << it->second.name << "_"
3648                 << HdStTokens->translation  << "();\n";
3649 
3650             // vec2 HdGet_name(int localIndex)
3651             accessors
3652                 << _GetUnpackedType(it->second.dataType, false)
3653                 << " HdGet_" << it->second.name << "(int localIndex) {\n"
3654                 << "  float angleRad = HdGet_" << it->second.name << "_"
3655                 << HdStTokens->rotation  << "()"
3656                 << " * 3.1415926f / 180.f;\n"
3657                 << "  mat2 rotMat = mat2(cos(angleRad), sin(angleRad), "
3658                 << "-sin(angleRad), cos(angleRad)); \n";
3659             // If primvar exists, use it
3660             if (!it->second.inPrimvars.empty()) {
3661                 accessors
3662                     << "#if defined(HD_HAS_" << it->second.inPrimvars[0] << ")\n"
3663                     << "  return vec2(HdGet_" << it->second.name << "_"
3664                     << HdStTokens->translation << "() + rotMat * (HdGet_"
3665                     << it->second.name << "_" << HdStTokens->scale << "() * "
3666                     << "HdGet_" << it->second.inPrimvars[0] << "(localIndex)));\n"
3667                     << "#else\n";
3668             }
3669             // Otherwise use default value.
3670             accessors
3671                 << "  int shaderCoord = GetDrawingCoord().shaderCoord;\n"
3672                 << "  return vec2(HdGet_" << it->second.name << "_"
3673                 << HdStTokens->translation << "() + rotMat * (HdGet_"
3674                 << it->second.name << "_" << HdStTokens->scale << "() * "
3675                 << "shaderData[shaderCoord]." << it->second.name
3676                 << HdSt_ResourceBindingSuffixTokens->fallback << swizzle
3677                 << "));\n";
3678             if (!it->second.inPrimvars.empty()) {
3679                 accessors << "#endif\n";
3680             }
3681             accessors << "}\n";
3682 
3683             // vec2 HdGet_name()
3684             accessors
3685                 << _GetUnpackedType(it->second.dataType, false)
3686                 << " HdGet_" << it->second.name << "() {\n"
3687                 << "  return HdGet_" << it->second.name << "(0);\n"
3688                 << "}\n";
3689         }
3690     }
3691 
3692 
3693     accessors
3694         << "void ProcessSamplingTransforms("
3695         << "MAT4 instanceModelViewInverse) {\n";
3696 
3697     TF_FOR_ALL (it, _metaData.shaderParameterBinding) {
3698         const HdBinding::Type bindingType = it->first.GetType();
3699 
3700         if ( bindingType == HdBinding::TEXTURE_FIELD ||
3701              bindingType == HdBinding::BINDLESS_TEXTURE_FIELD) {
3702 
3703             const std::string eyeToSamplingTransform =
3704                 "eyeTo" + it->second.name.GetString() + "SamplingTransform";
3705 
3706             accessors
3707                 << "    Process_" << eyeToSamplingTransform
3708                 << "(instanceModelViewInverse);\n";
3709         }
3710     }
3711 
3712     accessors
3713         << "}\n";
3714 
3715     // Field redirect accessors, need to access above field textures.
3716     TF_FOR_ALL (it, _metaData.shaderParameterBinding) {
3717         HdBinding::Type bindingType = it->first.GetType();
3718 
3719         if (bindingType == HdBinding::FIELD_REDIRECT) {
3720 
3721             // adjust datatype
3722             std::string swizzle = _GetSwizzleString(it->second.dataType);
3723 
3724             const TfToken fieldName =
3725                 it->second.inPrimvars.empty()
3726                 ? TfToken("FIELDNAME_WAS_NOT_SPECIFIED")
3727                 : it->second.inPrimvars[0];
3728 
3729             // Create an HdGet_INPUTNAME(vec3) for the shader to access a
3730             // field texture HdGet_FIELDNAMETexture(vec3).
3731             accessors
3732                 << _GetUnpackedType(it->second.dataType, false)
3733                 << " HdGet_" << it->second.name << "(vec3 coord) {\n"
3734                 // If field exists, use it
3735                 << "#if defined(HD_HAS_"
3736                 << fieldName << HdSt_ResourceBindingSuffixTokens->texture
3737                 << ")\n"
3738                 << "  return HdGet_"
3739                 << fieldName << HdSt_ResourceBindingSuffixTokens->texture
3740                 << "(coord)"
3741                 << swizzle << ";\n"
3742                 << "#else\n"
3743                 // Otherwise use default value.
3744                 << "  int shaderCoord = GetDrawingCoord().shaderCoord;\n"
3745                 << "  return "
3746                 << _GetPackedTypeAccessor(it->second.dataType, false)
3747                 << "(shaderData[shaderCoord]."
3748                 << it->second.name << HdSt_ResourceBindingSuffixTokens->fallback
3749                 <<  ");\n"
3750                 << "#endif\n"
3751                 << "\n}\n";
3752         }
3753     }
3754 
3755     _genFS << declarations.str()
3756            << accessors.str();
3757 
3758     _genGS << declarations.str()
3759            << accessors.str();
3760 }
3761 
3762 void
_GenerateTopologyVisibilityParameters()3763 HdSt_CodeGen::_GenerateTopologyVisibilityParameters()
3764 {
3765     std::stringstream declarations;
3766     std::stringstream accessors;
3767     TF_FOR_ALL (it, _metaData.topologyVisibilityData) {
3768         // See note in _GenerateConstantPrimvar re: padding.
3769         HdBinding binding = it->first;
3770         TfToken typeName(TfStringPrintf("TopologyVisibilityData%d",
3771                                         binding.GetValue()));
3772         TfToken varName = it->second.blockName;
3773 
3774         declarations << "struct " << typeName << " {\n";
3775 
3776         TF_FOR_ALL (dbIt, it->second.entries) {
3777             if (!TF_VERIFY(!dbIt->dataType.IsEmpty(),
3778                               "Unknown dataType for %s",
3779                               dbIt->name.GetText())) {
3780                 continue;
3781             }
3782 
3783             declarations << "  " << _GetPackedType(dbIt->dataType, false)
3784                          << " " << dbIt->name;
3785             if (dbIt->arraySize > 1) {
3786                 declarations << "[" << dbIt->arraySize << "]";
3787             }
3788 
3789             declarations << ";\n";
3790 
3791             _EmitStructAccessor(accessors, varName, dbIt->name, dbIt->dataType,
3792                                 dbIt->arraySize,
3793                                 "GetDrawingCoord().topologyVisibilityCoord");
3794         }
3795         declarations << "};\n";
3796 
3797         _EmitDeclaration(declarations, varName, typeName, binding,
3798                          /*arraySize=*/1);
3799     }
3800     _genCommon << declarations.str()
3801                << accessors.str();
3802 }
3803 
3804 PXR_NAMESPACE_CLOSE_SCOPE
3805 
3806