diff --git a/pxr/imaging/hdSt/CMakeLists.txt b/pxr/imaging/hdSt/CMakeLists.txt index 7f05abfbbc6..88c41958240 100644 --- a/pxr/imaging/hdSt/CMakeLists.txt +++ b/pxr/imaging/hdSt/CMakeLists.txt @@ -588,6 +588,19 @@ pxr_build_test(testHdStSubResourceRegistry CPPFILES testenv/testHdStSubResourceRegistry.cpp ) + +pxr_build_test(testHdStGeometricShader + LIBRARIES + gf + hdSt + hd + hgi + tf + vt + CPPFILES + testenv/testHdStGeometricShader.cpp +) + endif() if (X11_FOUND) @@ -3123,6 +3136,14 @@ pxr_register_test(testHdStSubResourceRegistry TF_DEBUG=HD_SAFE_MODE ) +pxr_register_test(testHdStGeometricShader + COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testHdStGeometricShader --offscreen" + EXPECTED_RETURN_CODE 0 + TESTENV testHdStGeometricShader + ENV + TF_DEBUG=HD_SAFE_MODE +) + # Certain tests use plugins that require shared libraries. if (TARGET shared_libs) diff --git a/pxr/imaging/hdSt/basisCurves.cpp b/pxr/imaging/hdSt/basisCurves.cpp index b37c0800f5d..089bdff1633 100644 --- a/pxr/imaging/hdSt/basisCurves.cpp +++ b/pxr/imaging/hdSt/basisCurves.cpp @@ -381,7 +381,7 @@ HdStBasisCurves::_UpdateDrawItemGeometricShader( GetId().GetText(), HdSt_PrimTypeToString(shaderKey.primType)); HdSt_GeometricShaderSharedPtr geomShader = - HdSt_GeometricShader::Create(shaderKey, resourceRegistry); + HdSt_GeometricShader::Create(shaderKey, {}, {}, resourceRegistry); TF_VERIFY(geomShader); diff --git a/pxr/imaging/hdSt/commandBuffer.cpp b/pxr/imaging/hdSt/commandBuffer.cpp index 3469792b21b..81c903fe98b 100644 --- a/pxr/imaging/hdSt/commandBuffer.cpp +++ b/pxr/imaging/hdSt/commandBuffer.cpp @@ -79,11 +79,21 @@ struct _SortByTexture { HdStDrawItem const *a = aInstance->GetDrawItem(); HdStDrawItem const *b = bInstance->GetDrawItem(); - size_t const textureA = - a->GetMaterialNetworkShader()->ComputeTextureSourceHash(); - size_t const textureB = - b->GetMaterialNetworkShader()->ComputeTextureSourceHash(); - return textureA < textureB; + size_t const geometricTextureHashA = + a->GetGeometricShader()->ComputeTextureSourceHash(); + size_t const geometricTextureHashB = + b->GetGeometricShader()->ComputeTextureSourceHash(); + if (geometricTextureHashA != geometricTextureHashB) { + return geometricTextureHashA < geometricTextureHashB; + } + else + { + size_t const materialTextureHashA = + a->GetMaterialNetworkShader()->ComputeTextureSourceHash(); + size_t const materialTextureHashB = + b->GetMaterialNetworkShader()->ComputeTextureSourceHash(); + return materialTextureHashA < materialTextureHashB; + } } }; @@ -170,9 +180,11 @@ _InsertDrawItemInstance( // batch, we'll also combine the texture source hash into the key. // (Note the texture source hash will be 0 for bindless textures). if (!allowTextureResourceRebinding) { - size_t const textureHash = + size_t const geometricTextureHash = + drawItem->GetGeometricShader()->ComputeTextureSourceHash(); + size_t const materialTextureHash = drawItem->GetMaterialNetworkShader()->ComputeTextureSourceHash(); - key = TfHash::Combine(key, textureHash); + key = TfHash::Combine(key, geometricTextureHash, materialTextureHash); } // Keep track of newly created draw batches. diff --git a/pxr/imaging/hdSt/drawBatch.cpp b/pxr/imaging/hdSt/drawBatch.cpp index 7d66320ada6..788817a8a82 100644 --- a/pxr/imaging/hdSt/drawBatch.cpp +++ b/pxr/imaging/hdSt/drawBatch.cpp @@ -212,8 +212,10 @@ HdSt_DrawBatch::_CanAggregateTextures(HdStDrawItem const *drawItem0, HdStDrawItem const *drawItem1) { return _allowTextureResourceRebinding || - (drawItem0->GetMaterialNetworkShader()->ComputeTextureSourceHash() == - drawItem1->GetMaterialNetworkShader()->ComputeTextureSourceHash()); + ((drawItem0->GetMaterialNetworkShader()->ComputeTextureSourceHash() == + drawItem1->GetMaterialNetworkShader()->ComputeTextureSourceHash()) && + (drawItem0->GetGeometricShader()->ComputeTextureSourceHash() == + drawItem1->GetGeometricShader()->ComputeTextureSourceHash())); } bool @@ -444,8 +446,10 @@ HdSt_DrawBatch::_DrawingProgram::CompileShader( // also (surface, renderPass) shaders use their bindings HdStShaderCodeSharedPtrVector shaders = GetComposedShaders(); + HdStShaderCodeSharedPtrVector shadersForParameterBinding = shaders; + shadersForParameterBinding.push_back(_geometricShader); - TF_FOR_ALL(it, shaders) { + TF_FOR_ALL(it, shadersForParameterBinding) { (*it)->AddBindings(&customBindings); } @@ -455,7 +459,7 @@ HdSt_DrawBatch::_DrawingProgram::CompileShader( // let resourcebinder resolve bindings and populate metadata // which is owned by codegen. _resourceBinder.ResolveBindings(drawItem, - shaders, + shadersForParameterBinding, metaData.get(), _drawingCoordBufferBinding, instanceDraw, diff --git a/pxr/imaging/hdSt/geometricShader.cpp b/pxr/imaging/hdSt/geometricShader.cpp index 32c78091940..7374ebbec06 100644 --- a/pxr/imaging/hdSt/geometricShader.cpp +++ b/pxr/imaging/hdSt/geometricShader.cpp @@ -10,9 +10,13 @@ #include "pxr/imaging/hdSt/binding.h" #include "pxr/imaging/hdSt/debugCodes.h" #include "pxr/imaging/hdSt/shaderKey.h" +#include "pxr/imaging/hdSt/textureBinder.h" +#include "pxr/imaging/hdSt/textureHandle.h" #include "pxr/imaging/hd/tokens.h" +#include "pxr/imaging/hgi/capabilities.h" + #include "pxr/imaging/hio/glslfx.h" #include "pxr/base/tf/hash.h" @@ -47,6 +51,8 @@ HdSt_GeometricShader::HdSt_GeometricShader(std::string const &glslfxString, , _frustumCullingPass(cullingPass) , _fvarPatchType(fvarPatchType) , _hash(0) + , _isValidComputedTextureSourceHash(false) + , _isValidComputedHash(false) { HD_TRACE_FUNCTION(); HF_MALLOC_TAG_FUNCTION(); @@ -63,15 +69,6 @@ HdSt_GeometricShader::HdSt_GeometricShader(std::string const &glslfxString, std::stringstream ss(glslfxString); _glslfx.reset(new HioGlslfx(ss)); - _hash = TfHash::Combine( - _hash, - _glslfx->GetHash(), - cullingPass, - primType, - cullStyle, - useMetalTessellation, - fvarPatchType - ); // // note: Don't include polygonMode into the hash. // It is independent from the GLSL program. @@ -151,9 +148,32 @@ HdSt_GeometricShader::ResolveCullMode( HdStShaderCode::ID HdSt_GeometricShader::ComputeHash() const { + // All mutator methods that might affect the hash must reset this (fragile). + if (!_isValidComputedHash) { + _hash = _ComputeHash(); + _isValidComputedHash = true; + } return _hash; } +HdStShaderCode::ID +HdSt_GeometricShader::_ComputeHash() const +{ + size_t hash = HdSt_MaterialParam::ComputeHash(_params); + + hash = TfHash::Combine( + hash, + _glslfx->GetHash(), + _frustumCullingPass, + _primType, + _cullStyle, + _useMetalTessellation, + _fvarPatchType + ); + + return hash; +} + /* virtual */ std::string HdSt_GeometricShader::GetSource(TfToken const &shaderStageKey) const @@ -161,18 +181,34 @@ HdSt_GeometricShader::GetSource(TfToken const &shaderStageKey) const return _glslfx->GetSource(shaderStageKey); } +/*virtual*/ +HdSt_MaterialParamVector const& +HdSt_GeometricShader::GetParams() const +{ + return _params; +} + +/*virtual*/ +HdStShaderCode::NamedTextureHandleVector const& +HdSt_GeometricShader::GetNamedTextureHandles() const +{ + return _namedTextureHandles; +} + +/*virtual*/ void HdSt_GeometricShader::BindResources(const int program, HdSt_ResourceBinder const &binder) { - // no-op + HdSt_TextureBinder::BindResources(binder, _namedTextureHandles); } +/*virtual*/ void HdSt_GeometricShader::UnbindResources(const int program, HdSt_ResourceBinder const &binder) { - // no-op + HdSt_TextureBinder::UnbindResources(binder, _namedTextureHandles); } /*virtual*/ @@ -336,15 +372,112 @@ HdSt_GeometricShader::GetHgiPrimitiveType() const return primitiveType; } +/*virtual*/ +HdStShaderCode::ID +HdSt_GeometricShader::ComputeTextureSourceHash() const +{ + if (!_isValidComputedTextureSourceHash) { + _computedTextureSourceHash = _ComputeTextureSourceHash(); + _isValidComputedTextureSourceHash = true; + } + return _computedTextureSourceHash; +} + +HdStShaderCode::ID +HdSt_GeometricShader::_ComputeTextureSourceHash() const +{ + TRACE_FUNCTION(); + + // To avoid excessive plumbing and checking of HgiCapabilities in order to + // determine if bindless textures are enabled, we make things a little + // easier for ourselves by having this function check and return 0 if + // using bindless textures. + const bool useBindlessHandles = _namedTextureHandles.empty() ? false : + _namedTextureHandles[0].handles[0]->UseBindlessHandles(); + + if (useBindlessHandles) { + return 0; + } + + size_t hash = 0; + + for (const HdStShaderCode::NamedTextureHandle& namedHandle : + _namedTextureHandles) { + + // Use name, texture object and sampling parameters. + hash = TfHash::Combine(hash, namedHandle.name, namedHandle.hash); + } + + return hash; +} + +void +HdSt_GeometricShader::_SetNamedTextureHandles( + const NamedTextureHandleVector& namedTextureHandles) +{ + _namedTextureHandles = namedTextureHandles; + _isValidComputedTextureSourceHash = false; +} + +void +HdSt_GeometricShader::_SetParams(const HdSt_MaterialParamVector& params) +{ + _params = params; + _isValidComputedHash = false; +} + +/*virtual*/ +void +HdSt_GeometricShader::AddResourcesFromTextures(ResourceContext& ctx) const +{ + const bool doublesSupported = ctx.GetResourceRegistry()->GetHgi()-> + GetCapabilities()->IsSet( + HgiDeviceCapabilitiesBitsShaderDoublePrecision); + + // Add buffer sources for bindless texture handles (and + // other texture metadata such as the sampling transform for + // a field texture). + HdBufferSourceSharedPtrVector result; + HdSt_TextureBinder::ComputeBufferSources( + GetNamedTextureHandles(), &result, doublesSupported); + + if (!result.empty()) { + ctx.AddSources(GetShaderData(), std::move(result)); + } +} + +namespace { + size_t + _GetGeometricShaderHash( + HdSt_ShaderKey const& shaderKey, + HdStShaderCode::NamedTextureHandleVector const& namedTextureHandles, + HdSt_MaterialParamVector const& params) + { + size_t hash = shaderKey.ComputeHash(); + for (const HdStShaderCode::NamedTextureHandle& namedHandle : + namedTextureHandles) { + + // Use name, texture object and sampling parameters. + hash = TfHash::Combine(hash, namedHandle.name, namedHandle.hash); + } + if (!params.empty()) + hash = TfHash::Combine(hash, HdSt_MaterialParam::ComputeHash(params)); + + return hash; + } +} /*static*/ HdSt_GeometricShaderSharedPtr HdSt_GeometricShader::Create( HdSt_ShaderKey const &shaderKey, + NamedTextureHandleVector const& namedTextureHandles, + HdSt_MaterialParamVector const& params, HdStResourceRegistrySharedPtr const &resourceRegistry) { // Use the shaderKey hash to deduplicate geometric shaders. HdInstance geometricShaderInstance = - resourceRegistry->RegisterGeometricShader(shaderKey.ComputeHash()); + resourceRegistry->RegisterGeometricShader( + _GetGeometricShaderHash(shaderKey, namedTextureHandles, params)); if (geometricShaderInstance.IsFirstInstance()) { geometricShaderInstance.SetValue( @@ -361,6 +494,10 @@ HdSt_GeometricShader::GetHgiPrimitiveType() const shaderKey.GetFvarPatchType(), /*debugId=*/SdfPath(), shaderKey.GetLineWidth())); + if(!namedTextureHandles.empty()) + geometricShaderInstance.GetValue()->_SetNamedTextureHandles(namedTextureHandles); + if (!params.empty()) + geometricShaderInstance.GetValue()->_SetParams(params); } return geometricShaderInstance.GetValue(); } diff --git a/pxr/imaging/hdSt/geometricShader.h b/pxr/imaging/hdSt/geometricShader.h index e5157b495dd..0091a7e7005 100644 --- a/pxr/imaging/hdSt/geometricShader.h +++ b/pxr/imaging/hdSt/geometricShader.h @@ -9,6 +9,7 @@ #include "pxr/pxr.h" #include "pxr/imaging/hdSt/api.h" +#include "pxr/imaging/hdSt/materialParam.h" #include "pxr/imaging/hdSt/shaderCode.h" #include "pxr/imaging/hd/version.h" #include "pxr/imaging/hd/enums.h" @@ -245,13 +246,45 @@ class HdSt_GeometricShader : public HdStShaderCode { HDST_API HgiCullMode ResolveCullMode(HdCullStyle const renderStateCullStyle) const; + /// Called after textures have been committed. + /// + /// Shader can return buffer sources for different BARs (most + /// likely, the shader bar) that require texture metadata such as + /// the bindless texture handle which is only available after the + /// commit. + /// + HDST_API + void AddResourcesFromTextures(ResourceContext& ctx) const override; + + HDST_API + NamedTextureHandleVector const& GetNamedTextureHandles() const override; + + HDST_API + HdSt_MaterialParamVector const& GetParams() const override; + + HDST_API + ID ComputeTextureSourceHash() const override; + // Factory for convenience. HDST_API static HdSt_GeometricShaderSharedPtr Create( HdSt_ShaderKey const &shaderKey, + NamedTextureHandleVector const& namedTextureHandles, + HdSt_MaterialParamVector const& params, HdStResourceRegistrySharedPtr const &resourceRegistry); +protected: + void _SetNamedTextureHandles(const NamedTextureHandleVector&); + + void _SetParams(const HdSt_MaterialParamVector& params); + private: + HDST_API + ID _ComputeTextureSourceHash() const; + + HDST_API + ID _ComputeHash() const; + PrimitiveType _primType; HdCullStyle _cullStyle; bool _useHardwareFaceCulling; @@ -264,7 +297,16 @@ class HdSt_GeometricShader : public HdStShaderCode { std::unique_ptr _glslfx; bool _frustumCullingPass; FvarPatchType _fvarPatchType; - ID _hash; + mutable ID _hash; + + HdSt_MaterialParamVector _params; + + mutable bool _isValidComputedHash; + + mutable size_t _computedTextureSourceHash; + mutable bool _isValidComputedTextureSourceHash; + + NamedTextureHandleVector _namedTextureHandles; // No copying HdSt_GeometricShader(const HdSt_GeometricShader &) = delete; diff --git a/pxr/imaging/hdSt/imageShaderRenderPass.cpp b/pxr/imaging/hdSt/imageShaderRenderPass.cpp index 022cff08c13..7718e42714f 100644 --- a/pxr/imaging/hdSt/imageShaderRenderPass.cpp +++ b/pxr/imaging/hdSt/imageShaderRenderPass.cpp @@ -119,7 +119,7 @@ HdSt_ImageShaderRenderPass::SetupFullscreenTriangleDrawItem() HdSt_ImageShaderShaderKey shaderKey; HdSt_GeometricShaderSharedPtr geometricShader = - HdSt_GeometricShader::Create(shaderKey, resourceRegistry); + HdSt_GeometricShader::Create(shaderKey, {}, {}, resourceRegistry); _drawItem.SetGeometricShader(geometricShader); } diff --git a/pxr/imaging/hdSt/indirectDrawBatch.cpp b/pxr/imaging/hdSt/indirectDrawBatch.cpp index 4d1e181cf70..5ef4df36961 100644 --- a/pxr/imaging/hdSt/indirectDrawBatch.cpp +++ b/pxr/imaging/hdSt/indirectDrawBatch.cpp @@ -457,14 +457,13 @@ _GetShaderBar(HdSt_MaterialNetworkShaderSharedPtr const & shader) return shader ? shader->GetShaderData() : nullptr; } -using TextureResourceID = HdSt_MaterialNetworkShader::ID; +using TextureResourceID = HdStShaderCode::ID; TextureResourceID -_GetTextureResourceID(HdStDrawItem const * drawItem) +_GetTextureResourceID(HdStShaderCodeSharedPtr const& shader) { - if (HdSt_MaterialNetworkShaderSharedPtr const &materialNetworkShader = - drawItem->GetMaterialNetworkShader()) { - return materialNetworkShader->ComputeTextureSourceHash(); + if (shader) { + return shader->ComputeTextureSourceHash(); } return 0; } @@ -552,10 +551,12 @@ HdSt_IndirectDrawBatch::_CompileBatch( if (_drawItemInstances.empty()) return; + HdStDrawItem const* drawItem = _drawItemInstances[0]->GetDrawItem(); + size_t const numDrawItemInstances = _drawItemInstances.size(); size_t const instancerNumLevels = - _drawItemInstances[0]->GetDrawItem()->GetInstancePrimvarNumLevels(); + drawItem->GetInstancePrimvarNumLevels(); // Get the layout of the command buffer we are building. _DrawCommandTraits const traits = @@ -580,8 +581,10 @@ HdSt_IndirectDrawBatch::_CompileBatch( // We'll need to rebind textures while drawing if we have // a draw item instance with a different texture resource id // than the first draw item. - TextureResourceID const firstTextureResourceID = - _GetTextureResourceID(_drawItemInstances[0]->GetDrawItem()); + TextureResourceID const firstGeometricTextureID = + _GetTextureResourceID(drawItem->GetGeometricShader()); + TextureResourceID const firstMaterialTextureID = + _GetTextureResourceID(drawItem->GetMaterialNetworkShader()); _needsTextureResourceRebinding = false; TF_DEBUG(HDST_DRAW).Msg(" - Processing Items:\n"); @@ -597,9 +600,12 @@ HdSt_IndirectDrawBatch::_CompileBatch( _DrawItemState const dc(drawItem); if (_allowTextureResourceRebinding && !_needsTextureResourceRebinding) { - TextureResourceID const textureResourceID = - _GetTextureResourceID(drawItem); - if (firstTextureResourceID != textureResourceID) { + TextureResourceID const geometricTextureID = + _GetTextureResourceID(drawItem->GetGeometricShader()); + TextureResourceID const materialTextureID = + _GetTextureResourceID(drawItem->GetMaterialNetworkShader()); + if (firstGeometricTextureID != geometricTextureID || + firstMaterialTextureID != materialTextureID) { _needsTextureResourceRebinding = true; } } @@ -1053,6 +1059,17 @@ _BindingState::BindResourcesForDrawing( shader->BindResources( glslProgram->GetProgram()->GetRawResource(), binder); } + + // Bind resources for geometric shader. + HdStBufferArrayRangeSharedPtr shaderBar = + std::static_pointer_cast( + geometricShader->GetShaderData()); + if (shaderBar) { + binder.BindBuffer(HdTokens->materialParams, + shaderBar->GetResource()); + } + geometricShader->BindResources( + glslProgram->GetProgram()->GetRawResource(), binder); renderPassState->Bind(hgiCapabilities); renderPassState->ApplyStateFromGeometricShader(binder, geometricShader); @@ -1082,6 +1099,16 @@ _BindingState::UnbindResourcesForDrawing( } shader->UnbindResources(0, binder); } + + // Unbind resources for geometric shader. + HdStBufferArrayRangeSharedPtr shaderBar = + std::static_pointer_cast( + geometricShader->GetShaderData()); + if (shaderBar) { + binder.UnbindBuffer(HdTokens->materialParams, + shaderBar->GetResource()); + } + geometricShader->UnbindResources(0, binder); renderPassState->Unbind(hgiCapabilities); } @@ -1091,13 +1118,27 @@ _BindTextureResources( HdStDrawItem const * drawItem, HdSt_ResourceBinder const & binder, HdStGLSLProgramSharedPtr const & glslProgram, - TextureResourceID * currentTextureResourceID) + TextureResourceID * currentGeometricTextureID, + TextureResourceID * currentMaterialTextureID) { - // Bind texture resources via the drawItem's materialNetworkShader - // when the currentTextureResourceID changes between draw items. - TextureResourceID textureResourceID = _GetTextureResourceID(drawItem); - if (*currentTextureResourceID != textureResourceID) { - *currentTextureResourceID = textureResourceID; + // Bind texture resources via the drawItem's geometricShader + // and materialNetworkShader when the currentTextureResourceID + // changes between draw items. + TextureResourceID geometricTextureID = _GetTextureResourceID(drawItem->GetGeometricShader()); + if (*currentGeometricTextureID != geometricTextureID) + { + *currentGeometricTextureID = geometricTextureID; + if (HdSt_GeometricShaderSharedPtr const &geometricShader = + drawItem->GetGeometricShader()) { + geometricShader->BindResources( + glslProgram->GetProgram()->GetRawResource(), + binder); + } + } + TextureResourceID materialTextureID = _GetTextureResourceID(drawItem->GetMaterialNetworkShader()); + if (*currentMaterialTextureID != materialTextureID) + { + *currentMaterialTextureID = materialTextureID; if (HdSt_MaterialNetworkShaderSharedPtr const &materialNetworkShader = drawItem->GetMaterialNetworkShader()) { materialNetworkShader->BindResources( @@ -1266,15 +1307,20 @@ HdSt_IndirectDrawBatch::_ExecuteDrawImmediate( uint32_t const drawCount = dispatchBuffer->GetCount(); // We'll rebind texture resources while drawing only if the drawing - // program's material network shader uses texture resources. + // program's geometric shader or material network shader uses texture + // resources. bool const programUsesTextureResources = - program.GetMaterialNetworkShader()->ComputeTextureSourceHash() != 0; + (program.GetGeometricShader()->ComputeTextureSourceHash() != 0) || + (program.GetMaterialNetworkShader()->ComputeTextureSourceHash() != 0); bool const rebindTextureResources = _needsTextureResourceRebinding && programUsesTextureResources; - TextureResourceID currentTextureResourceID = - _GetTextureResourceID(_drawItemInstances[0]->GetDrawItem()); + HdStDrawItem const* drawItem = _drawItemInstances[0]->GetDrawItem(); + TextureResourceID currentGeometricID = + _GetTextureResourceID(drawItem->GetGeometricShader()); + TextureResourceID currentMaterialNetworkID = + _GetTextureResourceID(drawItem->GetMaterialNetworkShader()); if (!_useDrawIndexed) { TF_DEBUG(HDST_DRAW).Msg("Drawing Arrays:\n" @@ -1295,7 +1341,8 @@ HdSt_IndirectDrawBatch::_ExecuteDrawImmediate( _drawItemInstances[i]->GetDrawItem(), program.GetBinder(), program.GetGLSLProgram(), - ¤tTextureResourceID); + ¤tGeometricID, + ¤tMaterialNetworkID); } glDrawArraysInstancedBaseInstance( @@ -1325,7 +1372,8 @@ HdSt_IndirectDrawBatch::_ExecuteDrawImmediate( _drawItemInstances[i]->GetDrawItem(), program.GetBinder(), program.GetGLSLProgram(), - ¤tTextureResourceID); + ¤tGeometricID, + ¤tMaterialNetworkID); } uint32_t const indexBufferByteOffset = @@ -1668,7 +1716,7 @@ HdSt_IndirectDrawBatch::_GetCullingProgram( // sharing the culling geometric shader for the same configuration. HdSt_GeometricShaderSharedPtr cullShader = - HdSt_GeometricShader::Create(shaderKey, resourceRegistry); + HdSt_GeometricShader::Create(shaderKey, {}, {}, resourceRegistry); _cullingProgram.SetGeometricShader(cullShader); _cullingProgram.CompileShader(_drawItemInstances.front()->GetDrawItem(), diff --git a/pxr/imaging/hdSt/mesh.cpp b/pxr/imaging/hdSt/mesh.cpp index 8c6a3ab03b9..c48a57f758b 100644 --- a/pxr/imaging/hdSt/mesh.cpp +++ b/pxr/imaging/hdSt/mesh.cpp @@ -2660,7 +2660,7 @@ HdStMesh::_UpdateDrawItemGeometricShader(HdSceneDelegate *sceneDelegate, nativeRoundPoints); HdSt_GeometricShaderSharedPtr geomShader = - HdSt_GeometricShader::Create(shaderKey, resourceRegistry); + HdSt_GeometricShader::Create(shaderKey, {}, {}, resourceRegistry); TF_VERIFY(geomShader); diff --git a/pxr/imaging/hdSt/pipelineDrawBatch.cpp b/pxr/imaging/hdSt/pipelineDrawBatch.cpp index b416dd69157..8bb7b3b4ef3 100644 --- a/pxr/imaging/hdSt/pipelineDrawBatch.cpp +++ b/pxr/imaging/hdSt/pipelineDrawBatch.cpp @@ -1118,6 +1118,20 @@ _BindingState::GetBindingsForDrawing( HdSt_TextureBinder::GetBindingDescs( binder, bindingsDesc, shader->GetNamedTextureHandles()); } + HdStBufferArrayRangeSharedPtr shaderBar = + std::static_pointer_cast( + geometricShader->GetShaderData()); + + binder.GetInterleavedBufferArrayBindingDesc( + bindingsDesc, shaderBar, HdTokens->materialParams); + + HdStBindingRequestVector bindingRequests; + geometricShader->AddBindings(&bindingRequests); + for (auto const& req : bindingRequests) { + binder.GetBindingRequestBindingDesc(bindingsDesc, req); + } + HdSt_TextureBinder::GetBindingDescs( + binder, bindingsDesc, geometricShader->GetNamedTextureHandles()); } HgiVertexBufferDescVector @@ -1968,7 +1982,7 @@ HdSt_PipelineDrawBatch::_CreateCullingProgram( // sharing the culling geometric shader for the same configuration. HdSt_GeometricShaderSharedPtr cullShader = - HdSt_GeometricShader::Create(shaderKey, resourceRegistry); + HdSt_GeometricShader::Create(shaderKey, {}, {}, resourceRegistry); _cullingProgram.SetDrawingCoordBufferBinding(drawingCoordBufferBinding); _cullingProgram.SetGeometricShader(cullShader); diff --git a/pxr/imaging/hdSt/points.cpp b/pxr/imaging/hdSt/points.cpp index 83bf6c76fd0..e90007f1f38 100644 --- a/pxr/imaging/hdSt/points.cpp +++ b/pxr/imaging/hdSt/points.cpp @@ -178,7 +178,7 @@ HdStPoints::_UpdateDrawItem(HdSceneDelegate *sceneDelegate, HdSt_PointsShaderKey shaderKey{nativeRoundPoints}; drawItem->SetGeometricShader( - HdSt_GeometricShader::Create(shaderKey, resourceRegistry)); + HdSt_GeometricShader::Create(shaderKey, {}, {}, resourceRegistry)); /* PRIMVAR */ if (HdChangeTracker::IsAnyPrimvarDirty(*dirtyBits, id)) { diff --git a/pxr/imaging/hdSt/testenv/testHdStCodeGen.cpp b/pxr/imaging/hdSt/testenv/testHdStCodeGen.cpp index 00d91351783..ebb576e4adb 100644 --- a/pxr/imaging/hdSt/testenv/testHdStCodeGen.cpp +++ b/pxr/imaging/hdSt/testenv/testHdStCodeGen.cpp @@ -91,7 +91,7 @@ CodeGenTest(HdStResourceRegistrySharedPtr const ®istry, HdDrawingCoord *drawingCoord = drawItem.GetDrawingCoord(); HdSt_GeometricShaderSharedPtr geometricShader = - HdSt_GeometricShader::Create(key, registry); + HdSt_GeometricShader::Create(key, {}, {}, registry); // topology { diff --git a/pxr/imaging/hdSt/testenv/testHdStDrawBatching.cpp b/pxr/imaging/hdSt/testenv/testHdStDrawBatching.cpp index 307a2d9f28c..1bf1594162a 100644 --- a/pxr/imaging/hdSt/testenv/testHdStDrawBatching.cpp +++ b/pxr/imaging/hdSt/testenv/testHdStDrawBatching.cpp @@ -223,7 +223,7 @@ _RegisterDrawItem( // need to register to get batching works HdSt_GeometricShaderSharedPtr const geomShader = - HdSt_GeometricShader::Create(shaderKey, registry); + HdSt_GeometricShader::Create(shaderKey, {}, {}, registry); TF_VERIFY(geomShader); drawItem.SetGeometricShader(geomShader); drawItem.SetMaterialNetworkShader(_GetFallbackShader()); @@ -723,7 +723,7 @@ EmptyDrawBatchTest(HdStResourceRegistrySharedPtr const ®istry) // need to register to get batching works HdSt_GeometricShaderSharedPtr const geomShader = - HdSt_GeometricShader::Create(shaderKey, registry); + HdSt_GeometricShader::Create(shaderKey, {}, {}, registry); TF_VERIFY(geomShader); drawItem.SetGeometricShader(geomShader); drawItem.SetMaterialNetworkShader(_GetFallbackShader()); diff --git a/pxr/imaging/hdSt/testenv/testHdStGeometricShader.cpp b/pxr/imaging/hdSt/testenv/testHdStGeometricShader.cpp new file mode 100644 index 00000000000..2645e32f30e --- /dev/null +++ b/pxr/imaging/hdSt/testenv/testHdStGeometricShader.cpp @@ -0,0 +1,327 @@ +// +// Copyright 2022 Pixar +// +// Licensed under the terms set forth in the LICENSE.txt file available at +// https://openusd.org/license. +// + +// This test harness is mostly a clone of testHdStBasicDrawing.cpp with fewer +// options and a custom test scene. +// + +#include "pxr/imaging/hd/tokens.h" +#include "pxr/imaging/hdSt/geometricShader.h" +#include "pxr/imaging/hdSt/materialParam.h" +#include "pxr/imaging/hdSt/shaderKey.h" +#include "pxr/imaging/hdSt/textureIdentifier.h" +#include "pxr/imaging/hdSt/unitTestGLDrawing.h" +#include "pxr/imaging/hdSt/unitTestHelper.h" +#include "pxr/imaging/hgi/texture.h" + +#include "pxr/base/tf/errorMark.h" + +#include + +PXR_NAMESPACE_USING_DIRECTIVE + +class My_ShaderKey : public HdSt_ShaderKey { +public: + TfToken const& GetGlslfxFilename() const override + { + static TfToken glslfxFilename("testGlslfxFile.glslfx"); + return glslfxFilename; + } + + std::string GetGlslfxString() const override + { + return "glslfxString1"; // Dummy glslfx string for testing + } + HdSt_GeometricShader::PrimitiveType GetPrimitiveType() const override + { + return HdSt_GeometricShader::PrimitiveType::PRIM_POINTS; + } + HdCullStyle GetCullStyle() const override + { + return HdCullStyleDontCare; + } + bool UseHardwareFaceCulling() const override + { + return false; + } + bool HasMirroredTransform() const override + { + return false; + } + bool IsDoubleSided() const override + { + return false; + } + bool UseMetalTessellation() const override + { + return false; + } + HdPolygonMode GetPolygonMode() const override + { + return HdPolygonModeFill; + } + bool IsFrustumCullingPass() const override + { + return false; + } + HdSt_GeometricShader::FvarPatchType GetFvarPatchType() const override + { + return HdSt_GeometricShader::FvarPatchType::PATCH_COARSE_TRIANGLES; + } + float GetLineWidth() const override + { + return 1.0f; + } +}; + +class My_TestGLDrawing : public HdSt_UnitTestGLDrawing { +public: + My_TestGLDrawing() { + } + + // HdSt_UnitTestGLDrawing overrides + void InitTest() override; + void DrawTest() override + { + BasicTest(); + } + void OffscreenTest() override + { + BasicTest(); + } + +private: + void BasicTest(); + + HdSt_TestDriverUniquePtr _driver; +}; + +void +My_TestGLDrawing::InitTest() +{ + _driver = std::make_unique(); +} + +void +My_TestGLDrawing::BasicTest() +{ + HdSt_GeometricShaderSharedPtr geometricShader1 = + std::make_shared( + "glslfxString1", //glslfxString + HdSt_GeometricShader::PrimitiveType::PRIM_POINTS, // primType + HdCullStyleDontCare, // cullStyle + false, // useHardwareFaceCulling + false, // hasMirroredTransform + false, // doubleSided + false, // useMetalTessellation + HdPolygonModeFill, // polygonMode + false, // cullingPass + HdSt_GeometricShader::FvarPatchType::PATCH_COARSE_TRIANGLES, // fvarPatchType + SdfPath(), + 1.0f); + + HdSt_GeometricShaderSharedPtr geometricShader2 = + std::make_shared( + "glslfxString1", //glslfxString + HdSt_GeometricShader::PrimitiveType::PRIM_POINTS, // primType + HdCullStyleDontCare, // cullStyle + true, // useHardwareFaceCulling + true, // hasMirroredTransform + true, // doubleSided + false, // useMetalTessellation + HdPolygonModeLine, // polygonMode + false, // cullingPass + HdSt_GeometricShader::FvarPatchType::PATCH_COARSE_TRIANGLES, // fvarPatchType + SdfPath(), + 3.0f); + + // glslfxString, primType, cullStyle, useMetalTessellation, cullingPass and fvarPatchType + // will impact the hash. + TF_AXIOM(geometricShader1->ComputeHash() == geometricShader2->ComputeHash()); + + HdSt_GeometricShaderSharedPtr geometricShader3 = + std::make_shared( + "glslfxString2", //glslfxString + HdSt_GeometricShader::PrimitiveType::PRIM_POINTS, // primType + HdCullStyleDontCare, // cullStyle + true, // useHardwareFaceCulling + true, // hasMirroredTransform + true, // doubleSided + false, // useMetalTessellation + HdPolygonModeLine, // polygonMode + false, // cullingPass + HdSt_GeometricShader::FvarPatchType::PATCH_COARSE_TRIANGLES, // fvarPatchType + SdfPath(), + 3.0f); + // glslfxString will impact the hash value. + TF_AXIOM(geometricShader1->ComputeHash() != geometricShader3->ComputeHash()); + + HdSt_GeometricShaderSharedPtr geometricShader4 = + std::make_shared( + "glslfxString1", //glslfxString + HdSt_GeometricShader::PrimitiveType::PRIM_BASIS_CURVES_LINEAR_PATCHES, // primType + HdCullStyleDontCare, // cullStyle + true, // useHardwareFaceCulling + true, // hasMirroredTransform + true, // doubleSided + false, // useMetalTessellation + HdPolygonModeLine, // polygonMode + false, // cullingPass + HdSt_GeometricShader::FvarPatchType::PATCH_COARSE_TRIANGLES, // fvarPatchType + SdfPath(), + 3.0f); + // primType will impact the hash value. + TF_AXIOM(geometricShader2->ComputeHash() != geometricShader4->ComputeHash()); + + HdSt_GeometricShaderSharedPtr geometricShader5 = + std::make_shared( + "glslfxString1", //glslfxString + HdSt_GeometricShader::PrimitiveType::PRIM_POINTS, // primType + HdCullStyleBack, // cullStyle + false, // useHardwareFaceCulling + false, // hasMirroredTransform + false, // doubleSided + false, // useMetalTessellation + HdPolygonModeFill, // polygonMode + false, // cullingPass + HdSt_GeometricShader::FvarPatchType::PATCH_COARSE_TRIANGLES, // fvarPatchType + SdfPath(), + 1.0f); + // cullStyle will impact the hash value. + TF_AXIOM(geometricShader1->ComputeHash() != geometricShader5->ComputeHash()); + + HdSt_GeometricShaderSharedPtr geometricShader6 = + std::make_shared( + "glslfxString1", //glslfxString + HdSt_GeometricShader::PrimitiveType::PRIM_POINTS, // primType + HdCullStyleDontCare, // cullStyle + false, // useHardwareFaceCulling + false, // hasMirroredTransform + false, // doubleSided + true, // useMetalTessellation + HdPolygonModeFill, // polygonMode + false, // cullingPass + HdSt_GeometricShader::FvarPatchType::PATCH_COARSE_TRIANGLES, // fvarPatchType + SdfPath(), + 1.0f); + // useMetalTessellation will impact the hash value. + TF_AXIOM(geometricShader1->ComputeHash() != geometricShader6->ComputeHash()); + + HdSt_GeometricShaderSharedPtr geometricShader7 = + std::make_shared( + "glslfxString1", //glslfxString + HdSt_GeometricShader::PrimitiveType::PRIM_POINTS, // primType + HdCullStyleDontCare, // cullStyle + false, // useHardwareFaceCulling + false, // hasMirroredTransform + false, // doubleSided + false, // useMetalTessellation + HdPolygonModeFill, // polygonMode + true, // cullingPass + HdSt_GeometricShader::FvarPatchType::PATCH_COARSE_TRIANGLES, // fvarPatchType + SdfPath(), + 1.0f); + // cullingPass will impact the hash value. + TF_AXIOM(geometricShader1->ComputeHash() != geometricShader7->ComputeHash()); + + HdSt_GeometricShaderSharedPtr geometricShader8 = + std::make_shared( + "glslfxString1", //glslfxString + HdSt_GeometricShader::PrimitiveType::PRIM_POINTS, // primType + HdCullStyleDontCare, // cullStyle + false, // useHardwareFaceCulling + false, // hasMirroredTransform + false, // doubleSided + false, // useMetalTessellation + HdPolygonModeFill, // polygonMode + false, // cullingPass + HdSt_GeometricShader::FvarPatchType::PATCH_COARSE_QUADS, // fvarPatchType + SdfPath(), + 1.0f); + // fvarPatchType will impact the hash value. + TF_AXIOM(geometricShader1->ComputeHash() != geometricShader8->ComputeHash()); + + HdStResourceRegistrySharedPtr const& resourceRegistry = + std::static_pointer_cast( + _driver->GetDelegate().GetRenderIndex().GetResourceRegistry()); + My_ShaderKey key; + HdSt_GeometricShaderSharedPtr geometricShader9 = + HdSt_GeometricShader::Create(key, {}, {}, resourceRegistry); + TF_AXIOM(geometricShader1->ComputeHash() == geometricShader9->ComputeHash()); + + HdSt_MaterialParam param1(HdSt_MaterialParam::ParamTypeFallback, TfToken("Param1"), VtValue()); + HdSt_GeometricShaderSharedPtr geometricShader10 = + HdSt_GeometricShader::Create(key, {}, { param1 }, resourceRegistry); + TF_AXIOM(geometricShader9 != geometricShader10); + + int width = 10; + int height = 10; + HgiTextureDesc texDesc; + texDesc.debugName = "textureHandle"; + texDesc.usage = HgiTextureUsageBitsColorTarget; + texDesc.type = HgiTextureType2D; + texDesc.dimensions = GfVec3i(width, height, 1); + texDesc.layerCount = 1; + texDesc.format = HgiFormatFloat32Vec4; + texDesc.mipLevels = 1; + texDesc.pixelsByteSize = + HgiGetDataSize(texDesc.format, texDesc.dimensions); + + // Fill output texture with dark gray + std::vector initialData; + initialData.resize(width* height * 4); + for (int i = 0; i < height; i++) { + for (int j = 0; j < width; j++) { + initialData[width * 4 * i + 4 * j + 0] = 0.1; + initialData[width * 4 * i + 4 * j + 1] = 0.1; + initialData[width * 4 * i + 4 * j + 2] = 0.1; + initialData[width * 4 * i + 4 * j + 3] = 1.f; + } + } + texDesc.initialData = initialData.data(); + + HgiTextureHandle dstTexture = _driver->GetHgi()->CreateTexture(texDesc); + + HdStTextureHandleSharedPtr textureHandle = resourceRegistry->AllocateTextureHandle( + HdStTextureIdentifier(TfToken()), + HdStTextureType::Uv, + HdSamplerParameters( + HdWrapRepeat, + HdWrapRepeat, + HdWrapClamp, + HdMinFilterNearest, + HdMagFilterNearest), + /* memoryRequest = */ 2000, + HdStShaderCodePtr()); + + HdStShaderCode::NamedTextureHandleVector textures; + textures.push_back( + { TfToken(), + HdStTextureType::Uv, + { textureHandle }, 100 }); + + HdSt_GeometricShaderSharedPtr geometricShader11 = + HdSt_GeometricShader::Create(key, textures, { param1 }, resourceRegistry); + TF_AXIOM(geometricShader10 != geometricShader11); +} + +int main(int argc, char *argv[]) +{ + TfErrorMark mark; + + My_TestGLDrawing driver; + driver.RunTest(argc, argv); + + if (mark.IsClean()) { + std::cout << "OK" << std::endl; + return EXIT_SUCCESS; + } else { + std::cout << "FAILED" << std::endl; + return EXIT_FAILURE; + } +} + diff --git a/pxr/imaging/hdSt/volume.cpp b/pxr/imaging/hdSt/volume.cpp index f3ac3bd433d..325a159a3b7 100644 --- a/pxr/imaging/hdSt/volume.cpp +++ b/pxr/imaging/hdSt/volume.cpp @@ -623,7 +623,7 @@ HdStVolume::_UpdateDrawItem(HdSceneDelegate *sceneDelegate, const HdSt_VolumeShaderKey shaderKey; drawItem->SetGeometricShader( - HdSt_GeometricShader::Create(shaderKey, resourceRegistry)); + HdSt_GeometricShader::Create(shaderKey, {}, {}, resourceRegistry)); /* TRIANGLE INDICES */ {