1010#include " pxr/imaging/hdSt/binding.h"
1111#include " pxr/imaging/hdSt/debugCodes.h"
1212#include " pxr/imaging/hdSt/shaderKey.h"
13+ #include " pxr/imaging/hdSt/textureBinder.h"
14+ #include " pxr/imaging/hdSt/textureHandle.h"
1315
1416#include " pxr/imaging/hd/tokens.h"
1517
18+ #include " pxr/imaging/hgi/capabilities.h"
19+
1620#include " pxr/imaging/hio/glslfx.h"
1721
1822#include " pxr/base/tf/hash.h"
@@ -47,6 +51,8 @@ HdSt_GeometricShader::HdSt_GeometricShader(std::string const &glslfxString,
4751 , _frustumCullingPass(cullingPass)
4852 , _fvarPatchType(fvarPatchType)
4953 , _hash(0 )
54+ , _isValidComputedTextureSourceHash(false )
55+ , _isValidComputedHash(false )
5056{
5157 HD_TRACE_FUNCTION ();
5258 HF_MALLOC_TAG_FUNCTION ();
@@ -63,15 +69,6 @@ HdSt_GeometricShader::HdSt_GeometricShader(std::string const &glslfxString,
6369
6470 std::stringstream ss (glslfxString);
6571 _glslfx.reset (new HioGlslfx (ss));
66- _hash = TfHash::Combine (
67- _hash,
68- _glslfx->GetHash (),
69- cullingPass,
70- primType,
71- cullStyle,
72- useMetalTessellation,
73- fvarPatchType
74- );
7572 //
7673 // note: Don't include polygonMode into the hash.
7774 // It is independent from the GLSL program.
@@ -151,28 +148,67 @@ HdSt_GeometricShader::ResolveCullMode(
151148HdStShaderCode::ID
152149HdSt_GeometricShader::ComputeHash () const
153150{
151+ // All mutator methods that might affect the hash must reset this (fragile).
152+ if (!_isValidComputedHash) {
153+ _hash = _ComputeHash ();
154+ _isValidComputedHash = true ;
155+ }
154156 return _hash;
155157}
156158
159+ HdStShaderCode::ID
160+ HdSt_GeometricShader::_ComputeHash () const
161+ {
162+ size_t hash = HdSt_MaterialParam::ComputeHash (_params);
163+
164+ hash = TfHash::Combine (
165+ hash,
166+ _glslfx->GetHash (),
167+ _frustumCullingPass,
168+ _primType,
169+ _cullStyle,
170+ _useMetalTessellation,
171+ _fvarPatchType
172+ );
173+
174+ return hash;
175+ }
176+
157177/* virtual */
158178std::string
159179HdSt_GeometricShader::GetSource (TfToken const &shaderStageKey) const
160180{
161181 return _glslfx->GetSource (shaderStageKey);
162182}
163183
184+ /* virtual*/
185+ HdSt_MaterialParamVector const &
186+ HdSt_GeometricShader::GetParams () const
187+ {
188+ return _params;
189+ }
190+
191+ /* virtual*/
192+ HdStShaderCode::NamedTextureHandleVector const &
193+ HdSt_GeometricShader::GetNamedTextureHandles () const
194+ {
195+ return _namedTextureHandles;
196+ }
197+
198+ /* virtual*/
164199void
165200HdSt_GeometricShader::BindResources (const int program,
166201 HdSt_ResourceBinder const &binder)
167202{
168- // no-op
203+ HdSt_TextureBinder::BindResources (binder, _namedTextureHandles);
169204}
170205
206+ /* virtual*/
171207void
172208HdSt_GeometricShader::UnbindResources (const int program,
173209 HdSt_ResourceBinder const &binder)
174210{
175- // no-op
211+ HdSt_TextureBinder::UnbindResources (binder, _namedTextureHandles);
176212}
177213
178214/* virtual*/
@@ -336,15 +372,112 @@ HdSt_GeometricShader::GetHgiPrimitiveType() const
336372 return primitiveType;
337373}
338374
375+ /* virtual*/
376+ HdStShaderCode::ID
377+ HdSt_GeometricShader::ComputeTextureSourceHash () const
378+ {
379+ if (!_isValidComputedTextureSourceHash) {
380+ _computedTextureSourceHash = _ComputeTextureSourceHash ();
381+ _isValidComputedTextureSourceHash = true ;
382+ }
383+ return _computedTextureSourceHash;
384+ }
385+
386+ HdStShaderCode::ID
387+ HdSt_GeometricShader::_ComputeTextureSourceHash () const
388+ {
389+ TRACE_FUNCTION ();
390+
391+ // To avoid excessive plumbing and checking of HgiCapabilities in order to
392+ // determine if bindless textures are enabled, we make things a little
393+ // easier for ourselves by having this function check and return 0 if
394+ // using bindless textures.
395+ const bool useBindlessHandles = _namedTextureHandles.empty () ? false :
396+ _namedTextureHandles[0 ].handles [0 ]->UseBindlessHandles ();
397+
398+ if (useBindlessHandles) {
399+ return 0 ;
400+ }
401+
402+ size_t hash = 0 ;
403+
404+ for (const HdStShaderCode::NamedTextureHandle& namedHandle :
405+ _namedTextureHandles) {
406+
407+ // Use name, texture object and sampling parameters.
408+ hash = TfHash::Combine (hash, namedHandle.name , namedHandle.hash );
409+ }
410+
411+ return hash;
412+ }
413+
414+ void
415+ HdSt_GeometricShader::_SetNamedTextureHandles (
416+ const NamedTextureHandleVector& namedTextureHandles)
417+ {
418+ _namedTextureHandles = namedTextureHandles;
419+ _isValidComputedTextureSourceHash = false ;
420+ }
421+
422+ void
423+ HdSt_GeometricShader::_SetParams (const HdSt_MaterialParamVector& params)
424+ {
425+ _params = params;
426+ _isValidComputedHash = false ;
427+ }
428+
429+ /* virtual*/
430+ void
431+ HdSt_GeometricShader::AddResourcesFromTextures (ResourceContext& ctx) const
432+ {
433+ const bool doublesSupported = ctx.GetResourceRegistry ()->GetHgi ()->
434+ GetCapabilities ()->IsSet (
435+ HgiDeviceCapabilitiesBitsShaderDoublePrecision);
436+
437+ // Add buffer sources for bindless texture handles (and
438+ // other texture metadata such as the sampling transform for
439+ // a field texture).
440+ HdBufferSourceSharedPtrVector result;
441+ HdSt_TextureBinder::ComputeBufferSources (
442+ GetNamedTextureHandles (), &result, doublesSupported);
443+
444+ if (!result.empty ()) {
445+ ctx.AddSources (GetShaderData (), std::move (result));
446+ }
447+ }
448+
449+ namespace {
450+ size_t
451+ _GetGeometricShaderHash (
452+ HdSt_ShaderKey const & shaderKey,
453+ HdStShaderCode::NamedTextureHandleVector const & namedTextureHandles,
454+ HdSt_MaterialParamVector const & params)
455+ {
456+ size_t hash = shaderKey.ComputeHash ();
457+ for (const HdStShaderCode::NamedTextureHandle& namedHandle :
458+ namedTextureHandles) {
459+
460+ // Use name, texture object and sampling parameters.
461+ hash = TfHash::Combine (hash, namedHandle.name , namedHandle.hash );
462+ }
463+ if (!params.empty ())
464+ hash = TfHash::Combine (hash, HdSt_MaterialParam::ComputeHash (params));
465+
466+ return hash;
467+ }
468+ }
339469/* static*/
340470 HdSt_GeometricShaderSharedPtr
341471 HdSt_GeometricShader::Create (
342472 HdSt_ShaderKey const &shaderKey,
473+ NamedTextureHandleVector const & namedTextureHandles,
474+ HdSt_MaterialParamVector const & params,
343475 HdStResourceRegistrySharedPtr const &resourceRegistry)
344476{
345477 // Use the shaderKey hash to deduplicate geometric shaders.
346478 HdInstance<HdSt_GeometricShaderSharedPtr> geometricShaderInstance =
347- resourceRegistry->RegisterGeometricShader (shaderKey.ComputeHash ());
479+ resourceRegistry->RegisterGeometricShader (
480+ _GetGeometricShaderHash (shaderKey, namedTextureHandles, params));
348481
349482 if (geometricShaderInstance.IsFirstInstance ()) {
350483 geometricShaderInstance.SetValue (
@@ -361,6 +494,10 @@ HdSt_GeometricShader::GetHgiPrimitiveType() const
361494 shaderKey.GetFvarPatchType (),
362495 /* debugId=*/ SdfPath (),
363496 shaderKey.GetLineWidth ()));
497+ if (!namedTextureHandles.empty ())
498+ geometricShaderInstance.GetValue ()->_SetNamedTextureHandles (namedTextureHandles);
499+ if (!params.empty ())
500+ geometricShaderInstance.GetValue ()->_SetParams (params);
364501 }
365502 return geometricShaderInstance.GetValue ();
366503}
0 commit comments