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/garch/glApi.h"
25
26 #include "pxr/imaging/glf/contextCaps.h"
27
28 #include "pxr/imaging/hdSt/resourceBinder.h"
29 #include "pxr/imaging/hdSt/glConversions.h"
30 #include "pxr/imaging/hdSt/bufferArrayRange.h"
31 #include "pxr/imaging/hdSt/bufferResource.h"
32 #include "pxr/imaging/hdSt/shaderCode.h"
33 #include "pxr/imaging/hdSt/drawItem.h"
34 #include "pxr/imaging/hdSt/materialNetworkShader.h"
35 #include "pxr/imaging/hdSt/materialParam.h"
36 #include "pxr/imaging/hdSt/textureBinder.h"
37 #include "pxr/imaging/hdSt/tokens.h"
38 #include "pxr/imaging/hd/bufferSpec.h"
39 #include "pxr/imaging/hd/enums.h"
40 #include "pxr/imaging/hd/instancer.h"
41 #include "pxr/imaging/hd/tokens.h"
42
43 #include "pxr/imaging/hgiGL/buffer.h"
44 #include "pxr/imaging/hgiGL/texture.h"
45 #include "pxr/imaging/hgiGL/sampler.h"
46 #include "pxr/imaging/hgiGL/shaderProgram.h"
47
48 #include "pxr/base/tf/staticTokens.h"
49
50 #include <boost/functional/hash.hpp>
51
52 PXR_NAMESPACE_OPEN_SCOPE
53
54 TF_DEFINE_PUBLIC_TOKENS(HdSt_ResourceBindingSuffixTokens,
55 HDST_RESOURCE_BINDING_SUFFIX_TOKENS);
56
57 TF_DEFINE_PRIVATE_TOKENS(
58 _tokens,
59 ((_double, "double"))
60 ((_float, "float"))
61 ((_int, "int"))
62 (vec2)
63 (vec3)
64 (vec4)
65 (dvec2)
66 (dvec3)
67 (dvec4)
68 (ivec2)
69 (ivec3)
70 (ivec4)
71 (constantPrimvars)
72 (primitiveParam)
73 (topologyVisibility)
74 );
75
76 namespace {
77 struct BindingLocator {
BindingLocator__anonb3ee4bde0111::BindingLocator78 BindingLocator() :
79 uniformLocation(0), uboLocation(0),
80 ssboLocation(0), attribLocation(0),
81 textureUnit(0) {}
82
GetBinding__anonb3ee4bde0111::BindingLocator83 HdBinding GetBinding(HdBinding::Type type, TfToken const &debugName) {
84 switch(type) {
85 case HdBinding::UNIFORM:
86 return HdBinding(HdBinding::UNIFORM, uniformLocation++);
87 break;
88 case HdBinding::UBO:
89 return HdBinding(HdBinding::UBO, uboLocation++);
90 break;
91 case HdBinding::SSBO:
92 return HdBinding(HdBinding::SSBO, ssboLocation++);
93 break;
94 case HdBinding::BINDLESS_SSBO_RANGE:
95 return HdBinding(HdBinding::BINDLESS_SSBO_RANGE, uniformLocation++);
96 case HdBinding::BINDLESS_UNIFORM:
97 return HdBinding(HdBinding::BINDLESS_UNIFORM, uniformLocation++);
98 break;
99 case HdBinding::VERTEX_ATTR:
100 return HdBinding(HdBinding::VERTEX_ATTR, attribLocation++);
101 break;
102 case HdBinding::DRAW_INDEX:
103 return HdBinding(HdBinding::DRAW_INDEX, attribLocation++);
104 break;
105 case HdBinding::DRAW_INDEX_INSTANCE:
106 return HdBinding(HdBinding::DRAW_INDEX_INSTANCE, attribLocation++);
107 break;
108 default:
109 TF_CODING_ERROR("Unknown binding type %d for %s",
110 type, debugName.GetText());
111 return HdBinding();
112 break;
113 }
114 }
115
116 int uniformLocation;
117 int uboLocation;
118 int ssboLocation;
119 int attribLocation;
120 int textureUnit;
121 };
122
_ShouldBeNormalized(HdType type)123 static inline GLboolean _ShouldBeNormalized(HdType type) {
124 return type == HdTypeInt32_2_10_10_10_REV;
125 }
126
127 // GL has special handling for the "number of components" for
128 // packed vectors. Handle that here.
_GetNumComponents(HdType type)129 static inline int _GetNumComponents(HdType type) {
130 if (type == HdTypeInt32_2_10_10_10_REV) {
131 return 4;
132 } else {
133 return HdGetComponentCount(type);
134 }
135 }
136
137 // Modify datatype if swizzle is specified
_AdjustHdType(HdType type,std::string const & swizzle)138 static HdType _AdjustHdType(HdType type, std::string const &swizzle) {
139 size_t numChannels = swizzle.size();
140 if (numChannels == 4) {
141 return HdTypeFloatVec4;
142 } else if (numChannels == 3) {
143 return HdTypeFloatVec3;
144 } else if (numChannels == 2) {
145 return HdTypeFloatVec2;
146 } else if (numChannels == 1) {
147 return HdTypeFloat;
148 }
149
150 return type;
151 }
152 }
153
HdSt_ResourceBinder()154 HdSt_ResourceBinder::HdSt_ResourceBinder()
155 : _numReservedUniformBlockLocations(0)
156 , _numReservedTextureUnits(0)
157 {
158 }
159
160 static
161 TfToken
_ConcatLayout(const TfToken & token)162 _ConcatLayout(const TfToken &token)
163 {
164 return TfToken(
165 token.GetString()
166 + HdSt_ResourceBindingSuffixTokens->layout.GetString());
167 }
168
169 static
170 TfTokenVector
_GetInstancerFilterNames(HdStDrawItem const * drawItem)171 _GetInstancerFilterNames(HdStDrawItem const * drawItem)
172 {
173 TfTokenVector filterNames = HdInstancer::GetBuiltinPrimvarNames();;
174
175 HdSt_MaterialNetworkShaderSharedPtr materialNetworkShader =
176 drawItem->GetMaterialNetworkShader();
177 if (materialNetworkShader) {
178 TfTokenVector const & names = materialNetworkShader->GetPrimvarNames();
179 filterNames.insert(filterNames.end(), names.begin(), names.end());
180 }
181
182 return filterNames;
183 }
184
185 static
186 bool
_TokenContainsString(const TfToken & token,const std::string & string)187 _TokenContainsString(const TfToken &token, const std::string &string)
188 {
189 return (token.GetString().find(string) != std::string::npos);
190 }
191
192 void
ResolveBindings(HdStDrawItem const * drawItem,HdStShaderCodeSharedPtrVector const & shaders,HdSt_ResourceBinder::MetaData * metaDataOut,bool indirect,bool instanceDraw,HdBindingRequestVector const & customBindings)193 HdSt_ResourceBinder::ResolveBindings(HdStDrawItem const *drawItem,
194 HdStShaderCodeSharedPtrVector const &shaders,
195 HdSt_ResourceBinder::MetaData *metaDataOut,
196 bool indirect,
197 bool instanceDraw,
198 HdBindingRequestVector const &customBindings)
199 {
200 HD_TRACE_FUNCTION();
201 HF_MALLOC_TAG_FUNCTION();
202
203 if (!TF_VERIFY(metaDataOut)) return;
204
205 // GL context caps
206 const bool ssboEnabled
207 = GlfContextCaps::GetInstance().shaderStorageBufferEnabled;
208 const bool bindlessUniformEnabled
209 = GlfContextCaps::GetInstance().bindlessBufferEnabled;
210 const bool bindlessTextureEnabled
211 = GlfContextCaps::GetInstance().bindlessTextureEnabled;
212
213 HdBinding::Type arrayBufferBindingType = HdBinding::SSBO;
214 if (bindlessUniformEnabled) {
215 arrayBufferBindingType = HdBinding::BINDLESS_UNIFORM; // EXT
216 }
217
218 HdBinding::Type structBufferBindingType = HdBinding::UBO; // 3.1
219 if (bindlessUniformEnabled) {
220 structBufferBindingType = HdBinding::BINDLESS_UNIFORM; // EXT
221 } else if (ssboEnabled) {
222 structBufferBindingType = HdBinding::SSBO; // 4.3
223 }
224
225 HdBinding::Type drawingCoordBindingType = HdBinding::UNIFORM;
226 if (indirect) {
227 if (instanceDraw) {
228 drawingCoordBindingType = HdBinding::DRAW_INDEX_INSTANCE;
229 } else {
230 drawingCoordBindingType = HdBinding::DRAW_INDEX;
231 }
232 }
233
234 // binding assignments
235 BindingLocator locator;
236
237 int bindlessTextureLocation = 0;
238 // Note that these locations are used for hash keys only and
239 // are never used for actual resource binding.
240 int shaderFallbackLocation = 0;
241 int shaderPrimvarRedirectLocation = 0;
242 int shaderFieldRedirectLocation = 0;
243 int shaderTransform2dLocation = 0;
244
245 // clear all
246 _bindingMap.clear();
247
248 // constant primvar (per-object)
249 HdBinding constantPrimvarBinding =
250 locator.GetBinding(structBufferBindingType,
251 _tokens->constantPrimvars);
252
253 if (HdBufferArrayRangeSharedPtr constantBar_ =
254 drawItem->GetConstantPrimvarRange()) {
255
256 HdStBufferArrayRangeSharedPtr constantBar =
257 std::static_pointer_cast<HdStBufferArrayRange>(constantBar_);
258
259 MetaData::StructBlock sblock(_tokens->constantPrimvars);
260 TF_FOR_ALL (it, constantBar->GetResources()) {
261 HdTupleType valueType = it->second->GetTupleType();
262 TfToken glType = HdStGLConversions::GetGLSLTypename(valueType.type);
263 TfToken glName = HdStGLConversions::GetGLSLIdentifier(it->first);
264 sblock.entries.emplace_back(
265 /*name=*/glName,
266 /*type=*/glType,
267 /*offset=*/it->second->GetOffset(),
268 /*arraySize=*/valueType.count);
269 }
270 // sort by offset
271 // XXX: not robust enough, should consider padding and layouting rules
272 // to match with the logic in HdInterleavedMemoryManager if we
273 // want to use a layouting policy other than default padding.
274 std::sort(sblock.entries.begin(), sblock.entries.end());
275
276 metaDataOut->constantData.insert(
277 std::make_pair(constantPrimvarBinding, sblock));
278 }
279
280 // constant primvars are interleaved into single struct.
281 _bindingMap[_tokens->constantPrimvars] = constantPrimvarBinding;
282
283 TfTokenVector filterNames = _GetInstancerFilterNames(drawItem);
284
285 // instance primvar (per-instance)
286 int instancerNumLevels = drawItem->GetInstancePrimvarNumLevels();
287 metaDataOut->instancerNumLevels = instancerNumLevels;
288 for (int i = 0; i < instancerNumLevels; ++i) {
289 if (HdBufferArrayRangeSharedPtr instanceBar_ =
290 drawItem->GetInstancePrimvarRange(i)) {
291
292 HdStBufferArrayRangeSharedPtr instanceBar =
293 std::static_pointer_cast<HdStBufferArrayRange>(instanceBar_);
294
295 TF_FOR_ALL (it, instanceBar->GetResources()) {
296 TfToken const& name = it->first;
297 // skip instance primvars that are not used in this batch.
298 if (std::find(filterNames.begin(), filterNames.end(), name)
299 == filterNames.end()) {
300 continue;
301 }
302
303 TfToken glName = HdStGLConversions::GetGLSLIdentifier(name);
304 // non-interleaved, always create new binding.
305 HdBinding instancePrimvarBinding =
306 locator.GetBinding(arrayBufferBindingType, name);
307 _bindingMap[NameAndLevel(name, i)] = instancePrimvarBinding;
308
309 HdTupleType valueType = it->second->GetTupleType();
310 TfToken glType =
311 HdStGLConversions::GetGLSLTypename(valueType.type);
312 metaDataOut->instanceData[instancePrimvarBinding] =
313 MetaData::NestedPrimvar(
314 /*name=*/glName,
315 /*type=*/glType,
316 /*level=*/i);
317 }
318 }
319 }
320
321 // vertex primvar (per-vertex)
322 // always assigned to VertexAttribute.
323 if (HdBufferArrayRangeSharedPtr vertexBar_ =
324 drawItem->GetVertexPrimvarRange()) {
325
326 HdStBufferArrayRangeSharedPtr vertexBar =
327 std::static_pointer_cast<HdStBufferArrayRange>(vertexBar_);
328
329 TF_FOR_ALL (it, vertexBar->GetResources()) {
330 TfToken const& name = it->first;
331 TfToken glName = HdStGLConversions::GetGLSLIdentifier(name);
332 HdBinding vertexPrimvarBinding =
333 locator.GetBinding(HdBinding::VERTEX_ATTR, name);
334 _bindingMap[name] = vertexPrimvarBinding;
335
336 HdTupleType valueType = it->second->GetTupleType();
337 // Special case: VBOs have intrinsic support for packed types,
338 // so expand them out to their target type for the shader binding.
339 if (valueType.type == HdTypeInt32_2_10_10_10_REV) {
340 valueType.type = HdTypeFloatVec4;
341 } else if (valueType.type == HdTypeHalfFloatVec2) {
342 valueType.type = HdTypeFloatVec2;
343 } else if (valueType.type == HdTypeHalfFloatVec4) {
344 valueType.type = HdTypeFloatVec4;
345 }
346 TfToken glType = HdStGLConversions::GetGLSLTypename(valueType.type);
347 metaDataOut->vertexData[vertexPrimvarBinding] =
348 MetaData::Primvar(/*name=*/glName,
349 /*type=*/glType);
350 }
351 }
352
353 // varying primvar
354 if (HdBufferArrayRangeSharedPtr varyingBar_ =
355 drawItem->GetVaryingPrimvarRange()) {
356
357 HdStBufferArrayRangeSharedPtr varyingBar =
358 std::static_pointer_cast<HdStBufferArrayRange>(varyingBar_);
359
360 for (const auto &resource : varyingBar->GetResources()) {
361 TfToken const& name = resource.first;
362 TfToken glName = HdStGLConversions::GetGLSLIdentifier(name);
363 HdBinding varyingPrimvarBinding =
364 locator.GetBinding(arrayBufferBindingType, name);
365 _bindingMap[name] = varyingPrimvarBinding;
366
367 HdTupleType valueType = resource.second->GetTupleType();
368 TfToken glType = HdStGLConversions::GetGLSLTypename(valueType.type);
369 metaDataOut->varyingData[varyingPrimvarBinding] =
370 MetaData::Primvar(/*name=*/glName,
371 /*type=*/glType);
372 }
373 }
374
375 // index buffer
376 if (HdBufferArrayRangeSharedPtr topologyBar_ =
377 drawItem->GetTopologyRange()) {
378
379 HdStBufferArrayRangeSharedPtr topologyBar =
380 std::static_pointer_cast<HdStBufferArrayRange>(topologyBar_);
381
382 TF_FOR_ALL (it, topologyBar->GetResources()) {
383 // Don't need to sanitize the name, since topology resources are
384 // created internally.
385 TfToken const& name = it->first;
386 HdStBufferResourceSharedPtr const& resource = it->second;
387
388 if (name == HdTokens->indices) {
389 // IBO. no need for codegen
390 _bindingMap[name] = HdBinding(HdBinding::INDEX_ATTR, 0);
391 } else {
392 // We expect the following additional topology based info:
393 // - primitive parameter (for all tris, quads and patches)
394 // - edge indices (for all tris, quads and patches)
395 // - fvar indices (for refined tris, quads, and patches with
396 // face-varying primvars)
397 // - fvar patch params (for refined tris, quads, and patches
398 // with face-varying primvars)
399
400 HdBinding binding =
401 locator.GetBinding(arrayBufferBindingType, name);
402 _bindingMap[name] = binding;
403
404 HdTupleType valueType = resource->GetTupleType();
405 TfToken glType =
406 HdStGLConversions::GetGLSLTypename(valueType.type);
407
408 auto bindingDecl = MetaData::BindingDeclaration(
409 /*name=*/name,
410 /*type=*/glType,
411 /*binding=*/binding);
412
413 if (name == HdTokens->primitiveParam) {
414 metaDataOut->primitiveParamBinding = bindingDecl;
415 } else if (name == HdTokens->edgeIndices) {
416 metaDataOut->edgeIndexBinding = bindingDecl;
417 } else if (name == HdStTokens->coarseFaceIndex) {
418 metaDataOut->coarseFaceIndexBinding = bindingDecl;
419 } else if (_TokenContainsString(name,
420 HdStTokens->fvarIndices.GetString())) {
421 metaDataOut->fvarIndicesBindings.push_back(bindingDecl);
422 } else if (_TokenContainsString(name,
423 HdStTokens->fvarPatchParam.GetString())) {
424 metaDataOut->fvarPatchParamBindings.push_back(bindingDecl);
425 } else {
426 TF_WARN("Unexpected topological resource '%s'\n",
427 name.GetText());
428 }
429 }
430 }
431 }
432
433 // topology visibility
434 HdBinding topologyVisibilityBinding =
435 locator.GetBinding(structBufferBindingType,
436 /*debugName*/_tokens->topologyVisibility);
437
438 if (HdBufferArrayRangeSharedPtr topVisBar_ =
439 drawItem->GetTopologyVisibilityRange()) {
440
441 HdStBufferArrayRangeSharedPtr topVisBar =
442 std::static_pointer_cast<HdStBufferArrayRange>(topVisBar_);
443
444 MetaData::StructBlock sblock(_tokens->topologyVisibility);
445 TF_FOR_ALL (it, topVisBar->GetResources()) {
446 HdTupleType valueType = it->second->GetTupleType();
447 TfToken glType = HdStGLConversions::GetGLSLTypename(valueType.type);
448 sblock.entries.emplace_back(
449 /*name=*/it->first,
450 /*type=*/glType,
451 /*offset=*/it->second->GetOffset(),
452 /*arraySize=*/valueType.count);
453 }
454
455 std::sort(sblock.entries.begin(), sblock.entries.end());
456
457 metaDataOut->topologyVisibilityData.insert(
458 std::make_pair(topologyVisibilityBinding, sblock));
459 }
460
461 // topology visibility is interleaved into single struct.
462 _bindingMap[_tokens->topologyVisibility] = topologyVisibilityBinding;
463
464 // element primvar (per-face, per-line)
465 if (HdBufferArrayRangeSharedPtr elementBar_ =
466 drawItem->GetElementPrimvarRange()) {
467
468 HdStBufferArrayRangeSharedPtr elementBar =
469 std::static_pointer_cast<HdStBufferArrayRange>(elementBar_);
470
471 TF_FOR_ALL (it, elementBar->GetResources()) {
472 TfToken const& name = it->first;
473 TfToken glName = HdStGLConversions::GetGLSLIdentifier(name);
474 HdBinding elementPrimvarBinding =
475 locator.GetBinding(arrayBufferBindingType, name);
476 _bindingMap[name] = elementPrimvarBinding;
477 HdTupleType valueType = it->second->GetTupleType();
478 TfToken glType =
479 HdStGLConversions::GetGLSLTypename(valueType.type);
480 metaDataOut->elementData[elementPrimvarBinding] =
481 MetaData::Primvar(/*name=*/glName,
482 /*type=*/glType);
483 }
484 }
485
486 // facevarying primvar (per-face-vertex)
487 if (HdBufferArrayRangeSharedPtr fvarBar_ =
488 drawItem->GetFaceVaryingPrimvarRange()) {
489
490 HdStBufferArrayRangeSharedPtr fvarBar =
491 std::static_pointer_cast<HdStBufferArrayRange>(fvarBar_);
492
493 TopologyToPrimvarVector const & fvarTopoToPvMap =
494 drawItem->GetFvarTopologyToPrimvarVector();
495
496 TF_FOR_ALL (it, fvarBar->GetResources()) {
497 TfToken const& name = it->first;
498 TfToken glName = HdStGLConversions::GetGLSLIdentifier(name);
499
500 HdBinding fvarPrimvarBinding =
501 locator.GetBinding(arrayBufferBindingType, name);
502 _bindingMap[name] = fvarPrimvarBinding;
503 HdTupleType valueType = it->second->GetTupleType();
504 TfToken glType = HdStGLConversions::GetGLSLTypename(valueType.type);
505
506 // Fine if no channel is found, might be unrefined primvar
507 int fvarChannel = 0;
508 for (size_t i = 0; i < fvarTopoToPvMap.size(); ++i) {
509 if (std::find(fvarTopoToPvMap[i].second.begin(),
510 fvarTopoToPvMap[i].second.end(),
511 name) != fvarTopoToPvMap[i].second.end()) {
512 fvarChannel = i;
513 }
514 }
515
516 metaDataOut->fvarData[fvarPrimvarBinding] =
517 MetaData::FvarPrimvar(/*name=*/glName,
518 /*type=*/glType,
519 /*channel=*/fvarChannel);
520 }
521 }
522
523 // draw parameter
524 // assigned to draw index (vertex attributeI w/divisor) (indiect)
525 // assigned to uniform (immediate)
526 //
527 // note that instanceDraw may be true even for non-instance drawing,
528 // because there's only instanced version of glMultiDrawElementsIndirect.
529 HdBinding drawingCoord0Binding = locator.GetBinding(
530 drawingCoordBindingType, HdTokens->drawingCoord0);
531 _bindingMap[HdTokens->drawingCoord0] = drawingCoord0Binding;
532 metaDataOut->drawingCoord0Binding =
533 MetaData::BindingDeclaration(/*name=*/HdTokens->drawingCoord0,
534 /*type=*/_tokens->ivec4,
535 /*binding=*/drawingCoord0Binding);
536
537 HdBinding drawingCoord1Binding = locator.GetBinding(
538 drawingCoordBindingType, HdTokens->drawingCoord1);
539 _bindingMap[HdTokens->drawingCoord1] = drawingCoord1Binding;
540 metaDataOut->drawingCoord1Binding =
541 MetaData::BindingDeclaration(/*name=*/HdTokens->drawingCoord1,
542 /*type=*/_tokens->ivec4,
543 /*binding=*/drawingCoord1Binding);
544
545 HdBinding drawingCoord2Binding = locator.GetBinding(
546 drawingCoordBindingType, HdTokens->drawingCoord2);
547 _bindingMap[HdTokens->drawingCoord2] = drawingCoord2Binding;
548 metaDataOut->drawingCoord2Binding =
549 MetaData::BindingDeclaration(/*name=*/HdTokens->drawingCoord2,
550 /*type=*/_tokens->ivec2,
551 /*binding=*/drawingCoord2Binding);
552
553 if (instancerNumLevels > 0) {
554 HdBinding drawingCoordIBinding = indirect
555 ? HdBinding(HdBinding::DRAW_INDEX_INSTANCE_ARRAY, locator.attribLocation)
556 : HdBinding(HdBinding::UNIFORM_ARRAY, locator.uniformLocation);
557 if (indirect) {
558 // each vertex attribute takes 1 location
559 locator.attribLocation += instancerNumLevels;
560 } else {
561 // int[N] may consume more than 1 location
562 locator.uniformLocation += instancerNumLevels;
563 }
564 _bindingMap[HdTokens->drawingCoordI] = drawingCoordIBinding;
565 metaDataOut->drawingCoordIBinding =
566 MetaData::BindingDeclaration(/*name=*/HdTokens->drawingCoordI,
567 /*type=*/_tokens->_int,
568 /*binding=*/drawingCoordIBinding);
569 }
570
571 // instance index indirection buffer
572 if (HdBufferArrayRangeSharedPtr instanceIndexBar_ =
573 drawItem->GetInstanceIndexRange()) {
574
575 HdStBufferArrayRangeSharedPtr instanceIndexBar =
576 std::static_pointer_cast<HdStBufferArrayRange>(
577 instanceIndexBar_);
578
579 HdStBufferResourceSharedPtr instanceIndices
580 = instanceIndexBar->GetResource(
581 HdInstancerTokens->instanceIndices);
582 HdStBufferResourceSharedPtr culledInstanceIndices
583 = instanceIndexBar->GetResource(
584 HdInstancerTokens->culledInstanceIndices);
585
586 if (instanceIndices) {
587 HdBinding instanceIndexArrayBinding =
588 locator.GetBinding(arrayBufferBindingType,
589 HdInstancerTokens->instanceIndices);
590 _bindingMap[HdInstancerTokens->instanceIndices] =
591 instanceIndexArrayBinding;
592 HdTupleType valueType = instanceIndices->GetTupleType();
593 TfToken glType =
594 HdStGLConversions::GetGLSLTypename(valueType.type);
595 metaDataOut->instanceIndexArrayBinding =
596 MetaData::BindingDeclaration(
597 /*name=*/HdInstancerTokens->instanceIndices,
598 /*type=*/glType,
599 /*binding=*/instanceIndexArrayBinding);
600 }
601 if (culledInstanceIndices) {
602 HdBinding culledInstanceIndexArrayBinding =
603 locator.GetBinding(arrayBufferBindingType,
604 HdInstancerTokens->culledInstanceIndices);
605 _bindingMap[HdInstancerTokens->culledInstanceIndices] =
606 culledInstanceIndexArrayBinding;
607 HdTupleType valueType = instanceIndices->GetTupleType();
608 TfToken glType =
609 HdStGLConversions::GetGLSLTypename(valueType.type);
610 metaDataOut->culledInstanceIndexArrayBinding =
611 MetaData::BindingDeclaration(
612 /*name=*/HdInstancerTokens->culledInstanceIndices,
613 /*type=*/glType,
614 /*binding=*/culledInstanceIndexArrayBinding);
615 }
616 }
617
618 // indirect dispatch
619 if (indirect) {
620 HdBinding dispatchBinding(HdBinding::DISPATCH, /*location=(not used)*/0);
621 _bindingMap[HdTokens->drawDispatch] = dispatchBinding;
622 }
623
624 // shader parameter bindings
625 TF_FOR_ALL(shader, shaders) {
626
627 // uniform block
628 HdBufferArrayRangeSharedPtr const &shaderBar_ =
629 (*shader)->GetShaderData();
630 HdStBufferArrayRangeSharedPtr shaderBar =
631 std::static_pointer_cast<HdStBufferArrayRange> (shaderBar_);
632 if (shaderBar) {
633 HdBinding shaderParamBinding =
634 locator.GetBinding(structBufferBindingType,
635 HdTokens->materialParams);
636
637 // for fallback values and bindless textures
638 // XXX: name of sblock must be unique for each shaders.
639 MetaData::StructBlock sblock(HdTokens->materialParams);
640 TF_FOR_ALL(it, shaderBar->GetResources()) {
641 TfToken const& name = it->first;
642 TfToken glName = HdStGLConversions::GetGLSLIdentifier(name);
643 HdTupleType valueType = it->second->GetTupleType();
644 TfToken glType =
645 HdStGLConversions::GetGLSLTypename(valueType.type);
646 sblock.entries.emplace_back(
647 /*name=*/glName,
648 /*type=*/glType,
649 /*offset=*/it->second->GetOffset(),
650 /*arraySize=*/valueType.count);
651 }
652 // sort by offset
653 std::sort(sblock.entries.begin(), sblock.entries.end());
654 metaDataOut->shaderData.insert(
655 std::make_pair(shaderParamBinding, sblock));
656
657 //XXX:hack we want to generalize materialParams to other shaders.
658 if ((*shader) == drawItem->GetMaterialNetworkShader()) {
659 // shader parameters are interleaved into single struct.
660 _bindingMap[HdTokens->materialParams] = shaderParamBinding;
661 }
662 }
663
664 HdSt_MaterialParamVector params = (*shader)->GetParams();
665 // for primvar and texture accessors
666 for (HdSt_MaterialParam const& param : params) {
667 const bool isMaterialShader =
668 ((*shader) == drawItem->GetMaterialNetworkShader());
669
670 // renderpass texture should be bindfull (for now)
671 const bool bindless = bindlessTextureEnabled && isMaterialShader;
672 std::string const& glSwizzle = param.swizzle;
673 HdTupleType valueType = param.GetTupleType();
674 TfToken glType =
675 HdStGLConversions::GetGLSLTypename(_AdjustHdType(valueType.type,
676 glSwizzle));
677 TfToken const& name = param.name;
678 TfToken glName = HdStGLConversions::GetGLSLIdentifier(name);
679
680 if (param.IsFallback()) {
681 metaDataOut->shaderParameterBinding[
682 HdBinding(HdBinding::FALLBACK,
683 shaderFallbackLocation++)]
684 = MetaData::ShaderParameterAccessor(glName,
685 /*type=*/glType);
686 }
687 else if (param.IsTexture()) {
688 if (param.textureType == HdTextureType::Ptex) {
689 // ptex texture
690 HdBinding texelBinding = bindless
691 ? HdBinding(HdBinding::BINDLESS_TEXTURE_PTEX_TEXEL,
692 bindlessTextureLocation++)
693 : HdBinding(HdBinding::TEXTURE_PTEX_TEXEL,
694 locator.uniformLocation++,
695 locator.textureUnit++);
696
697 metaDataOut->shaderParameterBinding[texelBinding] =
698 MetaData::ShaderParameterAccessor(
699 /*name=*/glName,
700 /*type=*/glType,
701 /*swizzle=*/glSwizzle,
702 /*inPrimvars=*/param.samplerCoords,
703 /*isPremultiplied=*/param.isPremultiplied);
704 _bindingMap[name] = texelBinding; // used for non-bindless
705
706 HdBinding layoutBinding = bindless
707 ? HdBinding(HdBinding::BINDLESS_TEXTURE_PTEX_LAYOUT,
708 bindlessTextureLocation++)
709 : HdBinding(HdBinding::TEXTURE_PTEX_LAYOUT,
710 locator.uniformLocation++,
711 locator.textureUnit++);
712
713 const TfToken glLayoutName(_ConcatLayout(glName));
714 metaDataOut->shaderParameterBinding[layoutBinding] =
715 MetaData::ShaderParameterAccessor(
716 /*name=*/glLayoutName,
717 /*type=*/HdStGLConversions::GetGLSLTypename(
718 HdType::HdTypeInt32));
719
720 // Layout for Ptex
721 const TfToken layoutName(_ConcatLayout(name));
722 // used for non-bindless
723 _bindingMap[layoutName] = layoutBinding;
724 } else if (param.textureType == HdTextureType::Udim) {
725 // Texture Array for UDIM
726 HdBinding textureBinding = bindless
727 ? HdBinding(HdBinding::BINDLESS_TEXTURE_UDIM_ARRAY,
728 bindlessTextureLocation++)
729 : HdBinding(HdBinding::TEXTURE_UDIM_ARRAY,
730 locator.uniformLocation++,
731 locator.textureUnit++);
732
733 metaDataOut->shaderParameterBinding[textureBinding] =
734 MetaData::ShaderParameterAccessor(
735 /*name=*/param.name,
736 /*type=*/glType,
737 /*swizzle=*/glSwizzle,
738 /*inPrimvars=*/param.samplerCoords,
739 /*isPremultiplied=*/param.isPremultiplied);
740 // used for non-bindless
741 _bindingMap[param.name] = textureBinding;
742
743 // Layout for UDIM
744 const TfToken layoutName(_ConcatLayout(param.name));
745
746 HdBinding layoutBinding = bindless
747 ? HdBinding(HdBinding::BINDLESS_TEXTURE_UDIM_LAYOUT,
748 bindlessTextureLocation++)
749 : HdBinding(HdBinding::TEXTURE_UDIM_LAYOUT,
750 locator.uniformLocation++,
751 locator.textureUnit++);
752
753 metaDataOut->shaderParameterBinding[layoutBinding] =
754 MetaData::ShaderParameterAccessor(
755 /*name=*/layoutName,
756 /*type=*/HdStGLConversions::GetGLSLTypename(
757 HdType::HdTypeFloat));
758
759 // used for non-bindless
760 _bindingMap[layoutName] = layoutBinding;
761 } else if (param.textureType == HdTextureType::Uv) {
762 // 2d texture
763 HdBinding textureBinding = bindless
764 ? HdBinding(HdBinding::BINDLESS_TEXTURE_2D,
765 bindlessTextureLocation++)
766 : HdBinding(HdBinding::TEXTURE_2D,
767 locator.uniformLocation++,
768 locator.textureUnit++);
769
770 metaDataOut->shaderParameterBinding[textureBinding] =
771 MetaData::ShaderParameterAccessor(
772 /*name=*/glName,
773 /*type=*/glType,
774 /*swizzle=*/glSwizzle,
775 /*inPrimvars=*/param.samplerCoords,
776 /*isPremultiplied=*/param.isPremultiplied,
777 /*processTextureFallbackValue=*/isMaterialShader);
778 _bindingMap[name] = textureBinding; // used for non-bindless
779 } else if (param.textureType == HdTextureType::Field) {
780 // 3d texture
781 HdBinding textureBinding = bindless
782 ? HdBinding(HdBinding::BINDLESS_TEXTURE_FIELD,
783 bindlessTextureLocation++)
784 : HdBinding(HdBinding::TEXTURE_FIELD,
785 locator.uniformLocation++,
786 locator.textureUnit++);
787
788 metaDataOut->shaderParameterBinding[textureBinding] =
789 MetaData::ShaderParameterAccessor(
790 /*name=*/glName,
791 /*type=*/glType,
792 /*swizzle=*/glSwizzle,
793 /*inPrimvars=*/param.samplerCoords,
794 /*isPremultiplied=*/param.isPremultiplied,
795 /*processTextureFallbackValue=*/isMaterialShader);
796 _bindingMap[name] = textureBinding; // used for non-bindless
797 }
798 } else if (param.IsPrimvarRedirect() || param.IsFieldRedirect()) {
799 TfTokenVector const& samplePrimvars = param.samplerCoords;
800 TfTokenVector glNames;
801 glNames.reserve(samplePrimvars.size());
802 for (auto const& pv : samplePrimvars) {
803 glNames.push_back(HdStGLConversions::GetGLSLIdentifier(pv));
804 }
805
806 HdBinding binding = param.IsPrimvarRedirect()
807 ? HdBinding(HdBinding::PRIMVAR_REDIRECT,
808 shaderPrimvarRedirectLocation++)
809 : HdBinding(HdBinding::FIELD_REDIRECT,
810 shaderFieldRedirectLocation++);
811
812 metaDataOut->shaderParameterBinding[binding]
813 = MetaData::ShaderParameterAccessor(
814 /*name=*/glName,
815 /*type=*/glType,
816 /*swizzle=*/glSwizzle,
817 /*inPrimvars=*/glNames);
818 } else if (param.IsTransform2d()) {
819 HdBinding binding = HdBinding(HdBinding::TRANSFORM_2D,
820 shaderTransform2dLocation++);
821 metaDataOut->shaderParameterBinding[binding] =
822 MetaData::ShaderParameterAccessor(
823 /*name=*/glName,
824 /*type=*/glType,
825 /*swizzle=*/glSwizzle,
826 /*inPrimvars=*/param.samplerCoords);
827 } else if (param.IsAdditionalPrimvar()) {
828 // Additional primvars is used so certain primvars survive
829 // primvar filtering. We can ignore them here, because primvars
830 // found on the drawItem are already processed further above.
831 } else {
832 TF_CODING_ERROR("Can't resolve %s", param.name.GetText());
833 }
834 }
835 }
836
837 // Add custom bindings.
838 // Don't need to sanitize the name used, since these are internally
839 // generated.
840 TF_FOR_ALL (it, customBindings) {
841 if (it->IsInterleavedBufferArray()) {
842 // Interleaved resource, only need a single binding point
843 HdBinding binding = locator.GetBinding(it->GetBindingType(),
844 it->GetName());
845 MetaData::StructBlock sblock(it->GetName());
846
847 HdBufferArrayRangeSharedPtr bar_ = it->GetBar();
848 HdStBufferArrayRangeSharedPtr bar =
849 std::static_pointer_cast<HdStBufferArrayRange> (bar_);
850
851 for (auto const& nameRes : bar->GetResources()) {
852 HdTupleType valueType = nameRes.second->GetTupleType();
853 TfToken glType =
854 HdStGLConversions::GetGLSLTypename(valueType.type);
855 sblock.entries.emplace_back(nameRes.first,
856 glType,
857 nameRes.second->GetOffset(),
858 valueType.count);
859 }
860 metaDataOut->customInterleavedBindings.insert(
861 std::make_pair(binding, sblock));
862 _bindingMap[it->GetName()] = binding;
863 } else {
864 // Non interleaved resource
865 typedef MetaData::BindingDeclaration BindingDeclaration;
866 if (it->IsBufferArray()) {
867 // The BAR was provided, so we will record the name, dataType,
868 // binding type and binding location.
869
870 HdBufferArrayRangeSharedPtr bar_ = it->GetBar();
871 HdStBufferArrayRangeSharedPtr bar =
872 std::static_pointer_cast<HdStBufferArrayRange> (bar_);
873
874 for (auto const& nameRes : bar->GetResources()) {
875 HdBinding binding = locator.GetBinding(it->GetBindingType(), nameRes.first);
876 BindingDeclaration b(nameRes.first,
877 HdStGLConversions::GetGLSLTypename(
878 nameRes.second->GetTupleType().type),
879 binding);
880 metaDataOut->customBindings.push_back(b);
881 _bindingMap[nameRes.first] = binding;
882 }
883 } else {
884 HdBinding binding = locator.GetBinding(it->GetBindingType(), it->GetName());
885 BindingDeclaration b(it->GetName(),
886 HdStGLConversions::GetGLSLTypename(
887 it->GetDataType()),
888 binding);
889
890 // note that GetDataType() may return HdTypeInvalid,
891 // in case it's a typeless binding. CodeGen generates
892 // declarations and accessors only for BindingDeclaration
893 // with a valid type.
894 metaDataOut->customBindings.push_back(b);
895 _bindingMap[it->GetName()] = binding;
896 }
897 }
898 }
899 _numReservedUniformBlockLocations = locator.uboLocation;
900 _numReservedTextureUnits = locator.textureUnit;
901 }
902
903 void
ResolveComputeBindings(HdBufferSpecVector const & readWriteBufferSpecs,HdBufferSpecVector const & readOnlyBufferSpecs,HdStShaderCodeSharedPtrVector const & shaders,MetaData * metaDataOut)904 HdSt_ResourceBinder::ResolveComputeBindings(
905 HdBufferSpecVector const &readWriteBufferSpecs,
906 HdBufferSpecVector const &readOnlyBufferSpecs,
907 HdStShaderCodeSharedPtrVector const &shaders,
908 MetaData *metaDataOut)
909 {
910 HD_TRACE_FUNCTION();
911 HF_MALLOC_TAG_FUNCTION();
912
913 if (!TF_VERIFY(metaDataOut)) {
914 return;
915 }
916
917 // GL context caps
918 HdBinding::Type bindingType =
919 (GlfContextCaps::GetInstance().bindlessBufferEnabled
920 ? HdBinding::BINDLESS_SSBO_RANGE : HdBinding::SSBO);
921
922 // binding assignments
923 BindingLocator locator;
924
925 // clear all
926 _bindingMap.clear();
927
928 // read-write per prim data
929 for (HdBufferSpec const& spec: readWriteBufferSpecs) {
930 HdBinding binding = locator.GetBinding(bindingType, spec.name);
931 _bindingMap[spec.name] = binding;
932 metaDataOut->computeReadWriteData[binding] =
933 MetaData::Primvar(spec.name,
934 HdStGLConversions::GetGLSLTypename(
935 spec.tupleType.type));
936 }
937
938 // read-only per prim data
939 for (HdBufferSpec const& spec: readOnlyBufferSpecs) {
940 HdBinding binding = locator.GetBinding(bindingType, spec.name);
941 _bindingMap[spec.name] = binding;
942 metaDataOut->computeReadOnlyData[binding] =
943 MetaData::Primvar(spec.name,
944 HdStGLConversions::GetGLSLTypename(
945 spec.tupleType.type));
946 }
947 }
948
949 void
BindBuffer(TfToken const & name,HdStBufferResourceSharedPtr const & buffer) const950 HdSt_ResourceBinder::BindBuffer(TfToken const &name,
951 HdStBufferResourceSharedPtr const &buffer) const
952 {
953 BindBuffer(name, buffer, buffer->GetOffset(), /*level=*/-1);
954 }
955
956 void
BindBuffer(TfToken const & name,HdStBufferResourceSharedPtr const & buffer,int offset,int level) const957 HdSt_ResourceBinder::BindBuffer(TfToken const &name,
958 HdStBufferResourceSharedPtr const &buffer,
959 int offset,
960 int level) const
961 {
962 HD_TRACE_FUNCTION();
963
964 // it is possible that the buffer has not been initialized when
965 // the instanceIndex is empty (e.g. FX points. see bug 120354)
966 if (!buffer->GetHandle()) return;
967
968 HdBinding binding = GetBinding(name, level);
969 HdBinding::Type type = binding.GetType();
970 int loc = binding.GetLocation();
971
972 HdTupleType tupleType = buffer->GetTupleType();
973
974 void const* offsetPtr =
975 reinterpret_cast<const void*>(
976 static_cast<intptr_t>(offset));
977 switch(type) {
978 case HdBinding::VERTEX_ATTR:
979 glBindBuffer(GL_ARRAY_BUFFER, buffer->GetHandle()->GetRawResource());
980 glVertexAttribPointer(loc,
981 _GetNumComponents(tupleType.type),
982 HdStGLConversions::GetGLAttribType(tupleType.type),
983 _ShouldBeNormalized(tupleType.type),
984 buffer->GetStride(),
985 offsetPtr);
986 glBindBuffer(GL_ARRAY_BUFFER, 0);
987
988 glEnableVertexAttribArray(loc);
989 break;
990 case HdBinding::DRAW_INDEX:
991 glBindBuffer(GL_ARRAY_BUFFER, buffer->GetHandle()->GetRawResource());
992 glVertexAttribIPointer(loc,
993 HdGetComponentCount(tupleType.type),
994 GL_INT,
995 buffer->GetStride(),
996 offsetPtr);
997 glBindBuffer(GL_ARRAY_BUFFER, 0);
998 glEnableVertexAttribArray(loc);
999 break;
1000 case HdBinding::DRAW_INDEX_INSTANCE:
1001 glBindBuffer(GL_ARRAY_BUFFER, buffer->GetHandle()->GetRawResource());
1002 glVertexAttribIPointer(loc,
1003 HdGetComponentCount(tupleType.type),
1004 GL_INT,
1005 buffer->GetStride(),
1006 offsetPtr);
1007 glBindBuffer(GL_ARRAY_BUFFER, 0);
1008
1009 // set the divisor to uint-max so that the same base value is used
1010 // for all instances.
1011 glVertexAttribDivisor(loc,
1012 std::numeric_limits<GLint>::max());
1013 glEnableVertexAttribArray(loc);
1014 break;
1015 case HdBinding::DRAW_INDEX_INSTANCE_ARRAY:
1016 glBindBuffer(GL_ARRAY_BUFFER, buffer->GetHandle()->GetRawResource());
1017 // instancerNumLevels is represented by the tuple size.
1018 // We unroll this to an array of int[1] attributes.
1019 for (size_t i = 0; i < buffer->GetTupleType().count; ++i) {
1020 offsetPtr = reinterpret_cast<const void*>(offset + i*sizeof(int));
1021 glVertexAttribIPointer(loc, 1, GL_INT, buffer->GetStride(),
1022 offsetPtr);
1023 // set the divisor to uint-max so that the same base value is used
1024 // for all instances.
1025 glVertexAttribDivisor(loc, std::numeric_limits<GLint>::max());
1026 glEnableVertexAttribArray(loc);
1027 ++loc;
1028 }
1029 glBindBuffer(GL_ARRAY_BUFFER, 0);
1030 break;
1031 case HdBinding::INDEX_ATTR:
1032 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
1033 buffer->GetHandle()->GetRawResource());
1034 break;
1035 case HdBinding::BINDLESS_UNIFORM:
1036 // at least in nvidia driver 346.59, this query call doesn't show
1037 // any pipeline stall.
1038 if (!glIsNamedBufferResidentNV(buffer->GetHandle()->GetRawResource())) {
1039 glMakeNamedBufferResidentNV(
1040 buffer->GetHandle()->GetRawResource(), GL_READ_WRITE);
1041 }
1042 {
1043 HgiGLBuffer * bufferGL =
1044 static_cast<HgiGLBuffer*>(buffer->GetHandle().Get());
1045 glUniformui64NV(loc, bufferGL->GetBindlessGPUAddress());
1046 }
1047 break;
1048 case HdBinding::SSBO:
1049 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, loc,
1050 buffer->GetHandle()->GetRawResource());
1051 break;
1052 case HdBinding::BINDLESS_SSBO_RANGE:
1053 // at least in nvidia driver 346.59, this query call doesn't show
1054 // any pipeline stall.
1055 if (!glIsNamedBufferResidentNV(buffer->GetHandle()->GetRawResource())) {
1056 glMakeNamedBufferResidentNV(
1057 buffer->GetHandle()->GetRawResource(), GL_READ_WRITE);
1058 }
1059 {
1060 HgiGLBuffer * bufferGL =
1061 static_cast<HgiGLBuffer*>(buffer->GetHandle().Get());
1062 glUniformui64NV(loc, bufferGL->GetBindlessGPUAddress()+offset);
1063 }
1064 break;
1065 case HdBinding::DISPATCH:
1066 glBindBuffer(GL_DRAW_INDIRECT_BUFFER,
1067 buffer->GetHandle()->GetRawResource());
1068 break;
1069 case HdBinding::UBO:
1070 case HdBinding::UNIFORM:
1071 glBindBufferRange(GL_UNIFORM_BUFFER, loc,
1072 buffer->GetHandle()->GetRawResource(),
1073 offset,
1074 buffer->GetStride());
1075 break;
1076 case HdBinding::TEXTURE_2D:
1077 case HdBinding::TEXTURE_FIELD:
1078 // nothing
1079 break;
1080 default:
1081 TF_CODING_ERROR("binding type %d not found for %s",
1082 type, name.GetText());
1083 break;
1084 }
1085 }
1086
1087 void
UnbindBuffer(TfToken const & name,HdStBufferResourceSharedPtr const & buffer,int level) const1088 HdSt_ResourceBinder::UnbindBuffer(TfToken const &name,
1089 HdStBufferResourceSharedPtr const &buffer,
1090 int level) const
1091 {
1092 HD_TRACE_FUNCTION();
1093
1094 // it is possible that the buffer has not been initialized when
1095 // the instanceIndex is empty (e.g. FX points)
1096 if (!buffer->GetHandle()) return;
1097
1098 HdBinding binding = GetBinding(name, level);
1099 HdBinding::Type type = binding.GetType();
1100 int loc = binding.GetLocation();
1101
1102 switch(type) {
1103 case HdBinding::VERTEX_ATTR:
1104 glDisableVertexAttribArray(loc);
1105 break;
1106 case HdBinding::DRAW_INDEX:
1107 glDisableVertexAttribArray(loc);
1108 break;
1109 case HdBinding::DRAW_INDEX_INSTANCE:
1110 glDisableVertexAttribArray(loc);
1111 glVertexAttribDivisor(loc, 0);
1112 break;
1113 case HdBinding::DRAW_INDEX_INSTANCE_ARRAY:
1114 // instancerNumLevels is represented by the tuple size.
1115 for (size_t i = 0; i < buffer->GetTupleType().count; ++i) {
1116 glDisableVertexAttribArray(loc);
1117 glVertexAttribDivisor(loc, 0);
1118 ++loc;
1119 }
1120 break;
1121 case HdBinding::INDEX_ATTR:
1122 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1123 break;
1124 case HdBinding::BINDLESS_UNIFORM:
1125 if (glIsNamedBufferResidentNV(buffer->GetHandle()->GetRawResource())) {
1126 glMakeNamedBufferNonResidentNV(
1127 buffer->GetHandle()->GetRawResource());
1128 }
1129 break;
1130 case HdBinding::SSBO:
1131 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, loc, 0);
1132 break;
1133 case HdBinding::BINDLESS_SSBO_RANGE:
1134 if (glIsNamedBufferResidentNV(buffer->GetHandle()->GetRawResource())) {
1135 glMakeNamedBufferNonResidentNV(
1136 buffer->GetHandle()->GetRawResource());
1137 }
1138 break;
1139 case HdBinding::DISPATCH:
1140 glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0);
1141 break;
1142 case HdBinding::UBO:
1143 case HdBinding::UNIFORM:
1144 glBindBufferBase(GL_UNIFORM_BUFFER, loc, 0);
1145 break;
1146 case HdBinding::TEXTURE_2D:
1147 case HdBinding::TEXTURE_FIELD:
1148 // nothing
1149 break;
1150 default:
1151 TF_CODING_ERROR("binding type %d not found for %s",
1152 type, name.GetText());
1153 break;
1154 }
1155 }
1156
1157 void
BindConstantBuffer(HdStBufferArrayRangeSharedPtr const & constantBar) const1158 HdSt_ResourceBinder::BindConstantBuffer(
1159 HdStBufferArrayRangeSharedPtr const &constantBar) const
1160 {
1161 if (!constantBar) return;
1162
1163 // constant buffer is interleaved. we just need to bind a buffer.
1164 BindBuffer(_tokens->constantPrimvars, constantBar->GetResource());
1165 }
1166
1167 void
UnbindConstantBuffer(HdStBufferArrayRangeSharedPtr const & constantBar) const1168 HdSt_ResourceBinder::UnbindConstantBuffer(
1169 HdStBufferArrayRangeSharedPtr const &constantBar) const
1170 {
1171 if (!constantBar) return;
1172
1173 UnbindBuffer(_tokens->constantPrimvars, constantBar->GetResource());
1174 }
1175
1176 void
BindInterleavedBuffer(HdStBufferArrayRangeSharedPtr const & interleavedBar,TfToken const & name) const1177 HdSt_ResourceBinder::BindInterleavedBuffer(
1178 HdStBufferArrayRangeSharedPtr const &interleavedBar,
1179 TfToken const &name) const
1180 {
1181 if (!interleavedBar) return;
1182
1183 BindBuffer(name, interleavedBar->GetResource());
1184 }
1185
1186 void
UnbindInterleavedBuffer(HdStBufferArrayRangeSharedPtr const & interleavedBar,TfToken const & name) const1187 HdSt_ResourceBinder::UnbindInterleavedBuffer(
1188 HdStBufferArrayRangeSharedPtr const &interleavedBar,
1189 TfToken const &name) const
1190 {
1191 if (!interleavedBar) return;
1192
1193 UnbindBuffer(name, interleavedBar->GetResource());
1194 }
1195
1196 void
BindInstanceBufferArray(HdStBufferArrayRangeSharedPtr const & bar,int level) const1197 HdSt_ResourceBinder::BindInstanceBufferArray(
1198 HdStBufferArrayRangeSharedPtr const &bar, int level) const
1199 {
1200 if (!bar) return;
1201
1202 TF_FOR_ALL(it, bar->GetResources()) {
1203 if (HasBinding(it->first, level)) {
1204 BindBuffer(it->first, it->second, it->second->GetOffset(), level);
1205 }
1206 }
1207 }
1208
1209 void
UnbindInstanceBufferArray(HdStBufferArrayRangeSharedPtr const & bar,int level) const1210 HdSt_ResourceBinder::UnbindInstanceBufferArray(
1211 HdStBufferArrayRangeSharedPtr const &bar, int level) const
1212 {
1213 if (!bar) return;
1214
1215 TF_FOR_ALL(it, bar->GetResources()) {
1216 if (HasBinding(it->first, level)) {
1217 UnbindBuffer(it->first, it->second, level);
1218 }
1219 }
1220 }
1221
1222 void
BindShaderResources(HdStShaderCode const * shader) const1223 HdSt_ResourceBinder::BindShaderResources(HdStShaderCode const *shader) const
1224 {
1225 }
1226
1227 void
UnbindShaderResources(HdStShaderCode const * shader) const1228 HdSt_ResourceBinder::UnbindShaderResources(HdStShaderCode const *shader) const
1229 {
1230 }
1231
1232 void
BindBufferArray(HdStBufferArrayRangeSharedPtr const & bar) const1233 HdSt_ResourceBinder::BindBufferArray(HdStBufferArrayRangeSharedPtr const &bar) const
1234 {
1235 if (!bar) return;
1236
1237 TF_FOR_ALL(it, bar->GetResources()) {
1238 BindBuffer(it->first, it->second);
1239 }
1240 }
1241
1242 void
Bind(HdBindingRequest const & req) const1243 HdSt_ResourceBinder::Bind(HdBindingRequest const& req) const
1244 {
1245 if (req.IsTypeless()) {
1246 return;
1247 } else if (req.IsResource()) {
1248 HdBufferResourceSharedPtr res_ = req.GetResource();
1249 HdStBufferResourceSharedPtr res =
1250 std::static_pointer_cast<HdStBufferResource> (res_);
1251
1252 BindBuffer(req.GetName(), res, req.GetByteOffset());
1253 } else if (req.IsInterleavedBufferArray()) {
1254 // note: interleaved buffer needs only 1 binding
1255 HdBufferArrayRangeSharedPtr bar_ = req.GetBar();
1256 HdStBufferArrayRangeSharedPtr bar =
1257 std::static_pointer_cast<HdStBufferArrayRange> (bar_);
1258 BindBuffer(req.GetName(), bar->GetResource(), req.GetByteOffset());
1259 } else if (req.IsBufferArray()) {
1260 HdBufferArrayRangeSharedPtr bar_ = req.GetBar();
1261 HdStBufferArrayRangeSharedPtr bar =
1262 std::static_pointer_cast<HdStBufferArrayRange> (bar_);
1263 BindBufferArray(bar);
1264 }
1265 }
1266
1267 void
Unbind(HdBindingRequest const & req) const1268 HdSt_ResourceBinder::Unbind(HdBindingRequest const& req) const
1269 {
1270 if (req.IsTypeless()) {
1271 return;
1272 } else if (req.IsResource()) {
1273 HdBufferResourceSharedPtr res_ = req.GetResource();
1274 HdStBufferResourceSharedPtr res =
1275 std::static_pointer_cast<HdStBufferResource> (res_);
1276
1277 UnbindBuffer(req.GetName(), res);
1278 } else if (req.IsInterleavedBufferArray()) {
1279 // note: interleaved buffer needs only 1 binding
1280 HdBufferArrayRangeSharedPtr bar_ = req.GetBar();
1281 HdStBufferArrayRangeSharedPtr bar =
1282 std::static_pointer_cast<HdStBufferArrayRange> (bar_);
1283
1284 UnbindBuffer(req.GetName(), bar->GetResource());
1285 } else if (req.IsBufferArray()) {
1286 HdBufferArrayRangeSharedPtr bar_ = req.GetBar();
1287 HdStBufferArrayRangeSharedPtr bar =
1288 std::static_pointer_cast<HdStBufferArrayRange> (bar_);
1289
1290 UnbindBufferArray(bar);
1291 }
1292 }
1293
1294 void
UnbindBufferArray(HdStBufferArrayRangeSharedPtr const & bar) const1295 HdSt_ResourceBinder::UnbindBufferArray(
1296 HdStBufferArrayRangeSharedPtr const &bar) const
1297 {
1298 if (!bar) return;
1299
1300 TF_FOR_ALL(it, bar->GetResources()) {
1301 UnbindBuffer(it->first, it->second);
1302 }
1303 }
1304
1305 void
BindUniformi(TfToken const & name,int count,const int * value) const1306 HdSt_ResourceBinder::BindUniformi(TfToken const &name,
1307 int count, const int *value) const
1308 {
1309 HdBinding uniformLocation = GetBinding(name);
1310 if (uniformLocation.GetLocation() == HdBinding::NOT_EXIST) return;
1311
1312 TF_VERIFY(uniformLocation.IsValid());
1313 TF_VERIFY(uniformLocation.GetType() == HdBinding::UNIFORM);
1314
1315 if (count == 1) {
1316 glUniform1iv(uniformLocation.GetLocation(), 1, value);
1317 } else if (count == 2) {
1318 glUniform2iv(uniformLocation.GetLocation(), 1, value);
1319 } else if (count == 3) {
1320 glUniform3iv(uniformLocation.GetLocation(), 1, value);
1321 } else if (count == 4) {
1322 glUniform4iv(uniformLocation.GetLocation(), 1, value);
1323 } else {
1324 TF_CODING_ERROR("Invalid count %d.\n", count);
1325 }
1326 }
1327
1328 void
BindUniformArrayi(TfToken const & name,int count,const int * value) const1329 HdSt_ResourceBinder::BindUniformArrayi(TfToken const &name,
1330 int count, const int *value) const
1331 {
1332 HdBinding uniformLocation = GetBinding(name);
1333 if (uniformLocation.GetLocation() == HdBinding::NOT_EXIST) return;
1334
1335 TF_VERIFY(uniformLocation.IsValid());
1336 TF_VERIFY(uniformLocation.GetType() == HdBinding::UNIFORM_ARRAY);
1337
1338 glUniform1iv(uniformLocation.GetLocation(), count, value);
1339 }
1340
1341 void
BindUniformui(TfToken const & name,int count,const unsigned int * value) const1342 HdSt_ResourceBinder::BindUniformui(TfToken const &name,
1343 int count, const unsigned int *value) const
1344 {
1345 HdBinding uniformLocation = GetBinding(name);
1346 if (uniformLocation.GetLocation() == HdBinding::NOT_EXIST) return;
1347
1348 TF_VERIFY(uniformLocation.IsValid());
1349 TF_VERIFY(uniformLocation.GetType() == HdBinding::UNIFORM);
1350
1351 if (count == 1) {
1352 glUniform1uiv(uniformLocation.GetLocation(), 1, value);
1353 } else if (count == 2) {
1354 glUniform2uiv(uniformLocation.GetLocation(), 1, value);
1355 } else if (count == 3) {
1356 glUniform3uiv(uniformLocation.GetLocation(), 1, value);
1357 } else if (count == 4) {
1358 glUniform4uiv(uniformLocation.GetLocation(), 1, value);
1359 } else {
1360 TF_CODING_ERROR("Invalid count %d.", count);
1361 }
1362 }
1363
1364 void
BindUniformf(TfToken const & name,int count,const float * value) const1365 HdSt_ResourceBinder::BindUniformf(TfToken const &name,
1366 int count, const float *value) const
1367 {
1368 HdBinding uniformLocation = GetBinding(name);
1369 if (uniformLocation.GetLocation() == HdBinding::NOT_EXIST) return;
1370
1371 if (!TF_VERIFY(uniformLocation.IsValid())) return;
1372 if (!TF_VERIFY(uniformLocation.GetType() == HdBinding::UNIFORM)) return;
1373 GLint location = uniformLocation.GetLocation();
1374
1375 if (count == 1) {
1376 glUniform1fv(location, 1, value);
1377 } else if (count == 2) {
1378 glUniform2fv(location, 1, value);
1379 } else if (count == 3) {
1380 glUniform3fv(location, 1, value);
1381 } else if (count == 4) {
1382 glUniform4fv(location, 1, value);
1383 } else if (count == 16) {
1384 glUniformMatrix4fv(location, 1, /*transpose=*/false, value);
1385 } else {
1386 TF_CODING_ERROR("Invalid count %d.", count);
1387 }
1388 }
1389
1390 void
IntrospectBindings(HgiShaderProgramHandle const & hgiProgram)1391 HdSt_ResourceBinder::IntrospectBindings(HgiShaderProgramHandle const & hgiProgram)
1392 {
1393 GlfContextCaps const &caps = GlfContextCaps::GetInstance();
1394
1395 GLuint program = hgiProgram->GetRawResource();
1396
1397 if (ARCH_UNLIKELY(!caps.shadingLanguage420pack)) {
1398 GLint numUBO = 0;
1399 glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCKS, &numUBO);
1400
1401 const int MAX_NAME = 256;
1402 int length = 0;
1403 char name[MAX_NAME+1];
1404 for (int i = 0; i < numUBO; ++i) {
1405 glGetActiveUniformBlockName(program, i, MAX_NAME, &length, name);
1406 // note: ubo_ prefix is added in HdCodeGen::_EmitDeclaration()
1407 if (strstr(name, "ubo_") == name) {
1408 HdBinding binding;
1409 if (TfMapLookup(_bindingMap, NameAndLevel(TfToken(name+4)), &binding)) {
1410 // set uniform block binding.
1411 glUniformBlockBinding(program, i, binding.GetLocation());
1412 }
1413 }
1414 }
1415 }
1416
1417 if (ARCH_UNLIKELY(!caps.explicitUniformLocation)) {
1418 for (auto & it: _bindingMap) {
1419 HdBinding binding = it.second;
1420 HdBinding::Type type = binding.GetType();
1421 std::string name = it.first.name;
1422 int level = it.first.level;
1423 if (level >=0) {
1424 // follow nested instancing naming convention.
1425 std::stringstream n;
1426 n << name << "_" << level;
1427 name = n.str();
1428 }
1429 if (type == HdBinding::UNIFORM ||
1430 type == HdBinding::UNIFORM_ARRAY) {
1431 GLint loc = glGetUniformLocation(program, name.c_str());
1432 // update location in resource binder.
1433 // some uniforms may be optimized out.
1434 if (loc < 0) loc = HdBinding::NOT_EXIST;
1435 it.second.Set(type, loc, binding.GetTextureUnit());
1436 }
1437 }
1438 }
1439
1440 if (ARCH_UNLIKELY(!caps.shadingLanguage420pack)) {
1441 for (auto & it: _bindingMap) {
1442 HdBinding binding = it.second;
1443 HdBinding::Type type = binding.GetType();
1444 std::string name = it.first.name;
1445 std::string textureName;
1446
1447 // note: sampler prefix is added in
1448 // HdCodeGen::_GenerateShaderParameters
1449 if (type == HdBinding::TEXTURE_2D) {
1450 textureName = "sampler2d_" + name;
1451 } else if (type == HdBinding::TEXTURE_FIELD) {
1452 textureName = "sampler3d_" + name;
1453 } else if (type == HdBinding::TEXTURE_PTEX_TEXEL) {
1454 textureName = "sampler2darray_" + name;
1455 } else if (type == HdBinding::TEXTURE_PTEX_LAYOUT) {
1456 textureName = "isampler1darray_" + name;
1457 } else if (type == HdBinding::TEXTURE_UDIM_ARRAY) {
1458 textureName = "sampler2dArray_" + name;
1459 } else if (type == HdBinding::TEXTURE_UDIM_LAYOUT) {
1460 textureName = "sampler1d_" + name;
1461 }
1462
1463 if (!textureName.empty()) {
1464 GLint loc = glGetUniformLocation(program, textureName.c_str());
1465 glProgramUniform1i(program, loc, binding.GetTextureUnit());
1466 if (loc < 0) loc = HdBinding::NOT_EXIST;
1467 it.second.Set(type, loc, binding.GetTextureUnit());
1468 }
1469 }
1470 }
1471 }
1472
1473 HdSt_ResourceBinder::MetaData::ID
ComputeHash() const1474 HdSt_ResourceBinder::MetaData::ComputeHash() const
1475 {
1476 ID hash = 0;
1477
1478 boost::hash_combine(hash, drawingCoord0Binding.binding.GetValue());
1479 boost::hash_combine(hash, drawingCoord0Binding.dataType);
1480 boost::hash_combine(hash, drawingCoord1Binding.binding.GetValue());
1481 boost::hash_combine(hash, drawingCoord1Binding.dataType);
1482 boost::hash_combine(hash, drawingCoord2Binding.binding.GetValue());
1483 boost::hash_combine(hash, drawingCoord2Binding.dataType);
1484 boost::hash_combine(hash, drawingCoordIBinding.binding.GetValue());
1485 boost::hash_combine(hash, drawingCoordIBinding.dataType);
1486 boost::hash_combine(hash, instanceIndexArrayBinding.binding.GetValue());
1487 boost::hash_combine(hash, instanceIndexArrayBinding.dataType);
1488 boost::hash_combine(hash, instanceIndexBaseBinding.binding.GetValue());
1489 boost::hash_combine(hash, instanceIndexBaseBinding.dataType);
1490 boost::hash_combine(hash, primitiveParamBinding.binding.GetValue());
1491 boost::hash_combine(hash, primitiveParamBinding.dataType);
1492 boost::hash_combine(hash, edgeIndexBinding.binding.GetValue());
1493 boost::hash_combine(hash, edgeIndexBinding.dataType);
1494 boost::hash_combine(hash, coarseFaceIndexBinding.binding.GetValue());
1495 boost::hash_combine(hash, coarseFaceIndexBinding.dataType);
1496
1497 TF_FOR_ALL(binDecl, fvarIndicesBindings) {
1498 boost::hash_combine(hash, binDecl->binding.GetValue());
1499 boost::hash_combine(hash, binDecl->dataType);
1500 }
1501 TF_FOR_ALL(binDecl, fvarPatchParamBindings) {
1502 boost::hash_combine(hash, binDecl->binding.GetValue());
1503 boost::hash_combine(hash, binDecl->dataType);
1504 }
1505
1506 // separators are inserted to distinguish primvars have a same layout
1507 // but different interpolation.
1508 boost::hash_combine(hash, 0); // separator
1509 TF_FOR_ALL(binDecl, customBindings) {
1510 boost::hash_combine(hash, binDecl->name.Hash());
1511 boost::hash_combine(hash, binDecl->dataType);
1512 boost::hash_combine(hash, binDecl->binding.GetType());
1513 boost::hash_combine(hash, binDecl->binding.GetLocation());
1514 }
1515
1516 boost::hash_combine(hash, 0); // separator
1517 TF_FOR_ALL(blockIt, customInterleavedBindings) {
1518 boost::hash_combine(hash, (int)blockIt->first.GetType()); // binding
1519 TF_FOR_ALL (it, blockIt->second.entries) {
1520 StructEntry const &entry = *it;
1521 boost::hash_combine(hash, entry.name.Hash());
1522 boost::hash_combine(hash, entry.dataType);
1523 boost::hash_combine(hash, entry.offset);
1524 boost::hash_combine(hash, entry.arraySize);
1525 }
1526 }
1527
1528 boost::hash_combine(hash, 0); // separator
1529 TF_FOR_ALL (blockIt, constantData) {
1530 boost::hash_combine(hash, (int)blockIt->first.GetType()); // binding
1531 TF_FOR_ALL (it, blockIt->second.entries) {
1532 StructEntry const &entry = *it;
1533 boost::hash_combine(hash, entry.name.Hash());
1534 boost::hash_combine(hash, entry.dataType);
1535 boost::hash_combine(hash, entry.offset);
1536 boost::hash_combine(hash, entry.arraySize);
1537 }
1538 }
1539
1540 boost::hash_combine(hash, 0); // separator
1541 TF_FOR_ALL (blockIt, topologyVisibilityData) {
1542 boost::hash_combine(hash, (int)blockIt->first.GetType()); // binding
1543 TF_FOR_ALL (it, blockIt->second.entries) {
1544 StructEntry const &entry = *it;
1545 boost::hash_combine(hash, entry.name.Hash());
1546 boost::hash_combine(hash, entry.dataType);
1547 boost::hash_combine(hash, entry.offset);
1548 boost::hash_combine(hash, entry.arraySize);
1549 }
1550 }
1551
1552 boost::hash_combine(hash, 0); // separator
1553 TF_FOR_ALL (it, instanceData) {
1554 boost::hash_combine(hash, (int)it->first.GetType()); // binding
1555 NestedPrimvar const &primvar = it->second;
1556 boost::hash_combine(hash, primvar.name.Hash());
1557 boost::hash_combine(hash, primvar.dataType);
1558 boost::hash_combine(hash, primvar.level);
1559 }
1560 boost::hash_combine(hash, 0); // separator
1561 TF_FOR_ALL (it, vertexData) {
1562 boost::hash_combine(hash, (int)it->first.GetType()); // binding
1563 Primvar const &primvar = it->second;
1564 boost::hash_combine(hash, primvar.name.Hash());
1565 boost::hash_combine(hash, primvar.dataType);
1566 }
1567 boost::hash_combine(hash, 0); // separator
1568 TF_FOR_ALL (it, varyingData) {
1569 boost::hash_combine(hash, (int)it->first.GetType()); // binding
1570 Primvar const &primvar = it->second;
1571 boost::hash_combine(hash, primvar.name.Hash());
1572 boost::hash_combine(hash, primvar.dataType);
1573 }
1574 boost::hash_combine(hash, 0); // separator
1575 TF_FOR_ALL (it, elementData) {
1576 boost::hash_combine(hash, (int)it->first.GetType()); // binding
1577 Primvar const &primvar = it->second;
1578 boost::hash_combine(hash, primvar.name.Hash());
1579 boost::hash_combine(hash, primvar.dataType);
1580 }
1581 boost::hash_combine(hash, 0); // separator
1582 TF_FOR_ALL (it, fvarData) {
1583 boost::hash_combine(hash, (int)it->first.GetType()); // binding
1584 FvarPrimvar const &primvar = it->second;
1585 boost::hash_combine(hash, primvar.name.Hash());
1586 boost::hash_combine(hash, primvar.dataType);
1587 boost::hash_combine(hash, primvar.channel);
1588 }
1589 boost::hash_combine(hash, 0); // separator
1590 TF_FOR_ALL (blockIt, shaderData) {
1591 boost::hash_combine(hash, (int)blockIt->first.GetType()); // binding
1592 TF_FOR_ALL (it, blockIt->second.entries) {
1593 StructEntry const &entry = *it;
1594 boost::hash_combine(hash, entry.name.Hash());
1595 boost::hash_combine(hash, entry.dataType);
1596 boost::hash_combine(hash, entry.offset);
1597 boost::hash_combine(hash, entry.arraySize);
1598 }
1599 }
1600 boost::hash_combine(hash, 0); // separator
1601 TF_FOR_ALL (it, shaderParameterBinding) {
1602 boost::hash_combine(hash, (int)it->first.GetType()); // binding
1603 ShaderParameterAccessor const &entry = it->second;
1604 boost::hash_combine(hash, entry.name.Hash());
1605 boost::hash_combine(hash, entry.dataType);
1606 boost::hash_combine(hash, entry.swizzle);
1607 }
1608
1609 return hash;
1610 }
1611
1612 /* static */
1613 bool
UseBindlessHandles()1614 HdSt_ResourceBinder::UseBindlessHandles()
1615 {
1616 return GlfContextCaps::GetInstance().bindlessTextureEnabled;
1617 }
1618
1619 /* static */
1620 uint64_t
GetSamplerBindlessHandle(HgiSamplerHandle const & samplerHandle,HgiTextureHandle const & textureHandle)1621 HdSt_ResourceBinder::GetSamplerBindlessHandle(
1622 HgiSamplerHandle const &samplerHandle,
1623 HgiTextureHandle const &textureHandle)
1624 {
1625 HgiGLSampler * const glSampler =
1626 const_cast<HgiGLSampler*>(
1627 dynamic_cast<const HgiGLSampler*>(samplerHandle.Get()));
1628
1629 HgiGLTexture * const glTexture =
1630 const_cast<HgiGLTexture*>(
1631 dynamic_cast<const HgiGLTexture*>(textureHandle.Get()));
1632
1633 if (!glSampler || !glTexture) {
1634 return 0;
1635 }
1636
1637 return glSampler->GetBindlessHandle(textureHandle);
1638 }
1639
1640 /* static */
1641 uint64_t
GetTextureBindlessHandle(HgiTextureHandle const & textureHandle)1642 HdSt_ResourceBinder::GetTextureBindlessHandle(
1643 HgiTextureHandle const &textureHandle)
1644 {
1645 HgiGLTexture * const glTexture =
1646 const_cast<HgiGLTexture*>(
1647 dynamic_cast<const HgiGLTexture*>(textureHandle.Get()));
1648
1649 if (!glTexture) {
1650 return 0;
1651 }
1652
1653 return glTexture->GetBindlessHandle();
1654 }
1655
1656 static
1657 bool
_IsBindless(HdBinding const & binding)1658 _IsBindless(HdBinding const & binding)
1659 {
1660 switch (binding.GetType()) {
1661 case HdBinding::BINDLESS_TEXTURE_2D:
1662 case HdBinding::BINDLESS_TEXTURE_FIELD:
1663 case HdBinding::BINDLESS_TEXTURE_UDIM_ARRAY:
1664 case HdBinding::BINDLESS_TEXTURE_UDIM_LAYOUT:
1665 case HdBinding::BINDLESS_TEXTURE_PTEX_TEXEL:
1666 case HdBinding::BINDLESS_TEXTURE_PTEX_LAYOUT:
1667 return true;
1668 default:
1669 return false;;
1670 }
1671 }
1672
1673 static
1674 GLenum
_GetTextureTarget(HdBinding const & binding)1675 _GetTextureTarget(HdBinding const & binding)
1676 {
1677 switch (binding.GetType()) {
1678 case HdBinding::TEXTURE_2D:
1679 return GL_TEXTURE_2D;
1680 case HdBinding::TEXTURE_FIELD:
1681 return GL_TEXTURE_3D;
1682 case HdBinding::TEXTURE_UDIM_ARRAY:
1683 case HdBinding::TEXTURE_PTEX_TEXEL:
1684 return GL_TEXTURE_2D_ARRAY;
1685 case HdBinding::TEXTURE_UDIM_LAYOUT:
1686 return GL_TEXTURE_1D;
1687 case HdBinding::TEXTURE_PTEX_LAYOUT:
1688 return GL_TEXTURE_1D_ARRAY;
1689 default:
1690 TF_CODING_ERROR("Unknown texture binding type");
1691 return GL_NONE;
1692 }
1693 }
1694
1695 void
BindTexture(const TfToken & name,HgiSamplerHandle const & samplerHandle,HgiTextureHandle const & textureHandle,const bool bind) const1696 HdSt_ResourceBinder::BindTexture(
1697 const TfToken &name,
1698 HgiSamplerHandle const &samplerHandle,
1699 HgiTextureHandle const &textureHandle,
1700 const bool bind) const
1701 {
1702 const HdBinding binding = GetBinding(name);
1703 if (_IsBindless(binding)) {
1704 return;
1705 }
1706
1707 const int samplerUnit = binding.GetTextureUnit();
1708
1709 glActiveTexture(GL_TEXTURE0 + samplerUnit);
1710
1711 const HgiTexture * const tex = textureHandle.Get();
1712 const HgiGLTexture * const glTex =
1713 dynamic_cast<const HgiGLTexture*>(tex);
1714
1715 if (tex && !glTex) {
1716 TF_CODING_ERROR("Resource binder only supports OpenGL");
1717 }
1718
1719 const GLuint texName =
1720 (bind && glTex) ? glTex->GetTextureId() : 0;
1721 glBindTexture(_GetTextureTarget(binding), texName);
1722
1723 const HgiSampler * const sampler = samplerHandle.Get();
1724 const HgiGLSampler * const glSampler =
1725 dynamic_cast<const HgiGLSampler*>(sampler);
1726
1727 if (sampler && !glSampler) {
1728 TF_CODING_ERROR("Resource binder only supports OpenGL");
1729 }
1730
1731 const GLuint samplerName =
1732 (bind && glSampler) ? glSampler->GetSamplerId() : 0;
1733 glBindSampler(samplerUnit, samplerName);
1734
1735 glActiveTexture(GL_TEXTURE0);
1736 }
1737
1738 void
BindTextureWithLayout(TfToken const & name,HgiSamplerHandle const & texelSampler,HgiTextureHandle const & texelTexture,HgiTextureHandle const & layoutTexture,const bool bind) const1739 HdSt_ResourceBinder::BindTextureWithLayout(
1740 TfToken const &name,
1741 HgiSamplerHandle const &texelSampler,
1742 HgiTextureHandle const &texelTexture,
1743 HgiTextureHandle const &layoutTexture,
1744 const bool bind) const
1745 {
1746 const HdBinding texelBinding = GetBinding(name);
1747 if (_IsBindless(texelBinding)) {
1748 return;
1749 }
1750
1751 const int texelSamplerUnit = texelBinding.GetTextureUnit();
1752
1753 glActiveTexture(GL_TEXTURE0 + texelSamplerUnit);
1754 glBindTexture(_GetTextureTarget(texelBinding),
1755 (bind && texelTexture) ? texelTexture->GetRawResource() : 0);
1756
1757 const HgiGLSampler * const glSampler =
1758 bind ? dynamic_cast<HgiGLSampler*>(texelSampler.Get()) : nullptr;
1759
1760 if (glSampler) {
1761 glBindSampler(texelSamplerUnit, (GLuint)glSampler->GetSamplerId());
1762 } else {
1763 glBindSampler(texelSamplerUnit, 0);
1764 }
1765
1766 const HdBinding layoutBinding = GetBinding(_ConcatLayout(name));
1767 const int layoutSamplerUnit = layoutBinding.GetTextureUnit();
1768
1769 glActiveTexture(GL_TEXTURE0 + layoutSamplerUnit);
1770 glBindTexture(_GetTextureTarget(layoutBinding),
1771 (bind && layoutTexture) ? layoutTexture->GetRawResource() : 0);
1772 glActiveTexture(GL_TEXTURE0);
1773 }
1774
1775
1776 PXR_NAMESPACE_CLOSE_SCOPE
1777