Skip to content

Commit 157ec4c

Browse files
committed
Add texture support for geometric shader
1 parent 60a8d58 commit 157ec4c

15 files changed

+662
-57
lines changed

pxr/imaging/hdSt/CMakeLists.txt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,19 @@ pxr_build_test(testHdStSubResourceRegistry
588588
CPPFILES
589589
testenv/testHdStSubResourceRegistry.cpp
590590
)
591+
592+
pxr_build_test(testHdStGeometricShader
593+
LIBRARIES
594+
gf
595+
hdSt
596+
hd
597+
hgi
598+
tf
599+
vt
600+
CPPFILES
601+
testenv/testHdStGeometricShader.cpp
602+
)
603+
591604
endif()
592605

593606
if (X11_FOUND)
@@ -3123,6 +3136,14 @@ pxr_register_test(testHdStSubResourceRegistry
31233136
TF_DEBUG=HD_SAFE_MODE
31243137
)
31253138

3139+
pxr_register_test(testHdStGeometricShader
3140+
COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testHdStGeometricShader --offscreen"
3141+
EXPECTED_RETURN_CODE 0
3142+
TESTENV testHdStGeometricShader
3143+
ENV
3144+
TF_DEBUG=HD_SAFE_MODE
3145+
)
3146+
31263147
# Certain tests use plugins that require shared libraries.
31273148
if (TARGET shared_libs)
31283149

pxr/imaging/hdSt/basisCurves.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ HdStBasisCurves::_UpdateDrawItemGeometricShader(
381381
GetId().GetText(), HdSt_PrimTypeToString(shaderKey.primType));
382382

383383
HdSt_GeometricShaderSharedPtr geomShader =
384-
HdSt_GeometricShader::Create(shaderKey, resourceRegistry);
384+
HdSt_GeometricShader::Create(shaderKey, {}, {}, resourceRegistry);
385385

386386
TF_VERIFY(geomShader);
387387

pxr/imaging/hdSt/commandBuffer.cpp

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,21 @@ struct _SortByTexture {
7979
HdStDrawItem const *a = aInstance->GetDrawItem();
8080
HdStDrawItem const *b = bInstance->GetDrawItem();
8181

82-
size_t const textureA =
83-
a->GetMaterialNetworkShader()->ComputeTextureSourceHash();
84-
size_t const textureB =
85-
b->GetMaterialNetworkShader()->ComputeTextureSourceHash();
86-
return textureA < textureB;
82+
size_t const geometricTextureHashA =
83+
a->GetGeometricShader()->ComputeTextureSourceHash();
84+
size_t const geometricTextureHashB =
85+
b->GetGeometricShader()->ComputeTextureSourceHash();
86+
if (geometricTextureHashA != geometricTextureHashB) {
87+
return geometricTextureHashA < geometricTextureHashB;
88+
}
89+
else
90+
{
91+
size_t const materialTextureHashA =
92+
a->GetMaterialNetworkShader()->ComputeTextureSourceHash();
93+
size_t const materialTextureHashB =
94+
b->GetMaterialNetworkShader()->ComputeTextureSourceHash();
95+
return materialTextureHashA < materialTextureHashB;
96+
}
8797
}
8898
};
8999

@@ -170,9 +180,11 @@ _InsertDrawItemInstance(
170180
// batch, we'll also combine the texture source hash into the key.
171181
// (Note the texture source hash will be 0 for bindless textures).
172182
if (!allowTextureResourceRebinding) {
173-
size_t const textureHash =
183+
size_t const geometricTextureHash =
184+
drawItem->GetGeometricShader()->ComputeTextureSourceHash();
185+
size_t const materialTextureHash =
174186
drawItem->GetMaterialNetworkShader()->ComputeTextureSourceHash();
175-
key = TfHash::Combine(key, textureHash);
187+
key = TfHash::Combine(key, geometricTextureHash, materialTextureHash);
176188
}
177189

178190
// Keep track of newly created draw batches.

pxr/imaging/hdSt/drawBatch.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -212,8 +212,10 @@ HdSt_DrawBatch::_CanAggregateTextures(HdStDrawItem const *drawItem0,
212212
HdStDrawItem const *drawItem1)
213213
{
214214
return _allowTextureResourceRebinding ||
215-
(drawItem0->GetMaterialNetworkShader()->ComputeTextureSourceHash() ==
216-
drawItem1->GetMaterialNetworkShader()->ComputeTextureSourceHash());
215+
((drawItem0->GetMaterialNetworkShader()->ComputeTextureSourceHash() ==
216+
drawItem1->GetMaterialNetworkShader()->ComputeTextureSourceHash()) &&
217+
(drawItem0->GetGeometricShader()->ComputeTextureSourceHash() ==
218+
drawItem1->GetGeometricShader()->ComputeTextureSourceHash()));
217219
}
218220

219221
bool
@@ -444,8 +446,10 @@ HdSt_DrawBatch::_DrawingProgram::CompileShader(
444446

445447
// also (surface, renderPass) shaders use their bindings
446448
HdStShaderCodeSharedPtrVector shaders = GetComposedShaders();
449+
HdStShaderCodeSharedPtrVector shadersForParameterBinding = shaders;
450+
shadersForParameterBinding.push_back(_geometricShader);
447451

448-
TF_FOR_ALL(it, shaders) {
452+
TF_FOR_ALL(it, shadersForParameterBinding) {
449453
(*it)->AddBindings(&customBindings);
450454
}
451455

@@ -455,7 +459,7 @@ HdSt_DrawBatch::_DrawingProgram::CompileShader(
455459
// let resourcebinder resolve bindings and populate metadata
456460
// which is owned by codegen.
457461
_resourceBinder.ResolveBindings(drawItem,
458-
shaders,
462+
shadersForParameterBinding,
459463
metaData.get(),
460464
_drawingCoordBufferBinding,
461465
instanceDraw,

pxr/imaging/hdSt/geometricShader.cpp

Lines changed: 149 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,13 @@
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(
151148
HdStShaderCode::ID
152149
HdSt_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 */
158178
std::string
159179
HdSt_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*/
164199
void
165200
HdSt_GeometricShader::BindResources(const int program,
166201
HdSt_ResourceBinder const &binder)
167202
{
168-
// no-op
203+
HdSt_TextureBinder::BindResources(binder, _namedTextureHandles);
169204
}
170205

206+
/*virtual*/
171207
void
172208
HdSt_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

Comments
 (0)