diff --git a/lib/mayaUsd/render/vp2RenderDelegate/basisCurves.cpp b/lib/mayaUsd/render/vp2RenderDelegate/basisCurves.cpp index b680aa9b68..d716a3b962 100644 --- a/lib/mayaUsd/render/vp2RenderDelegate/basisCurves.cpp +++ b/lib/mayaUsd/render/vp2RenderDelegate/basisCurves.cpp @@ -450,8 +450,10 @@ void HdVP2BasisCurves::Sync( const HdVP2Material* material = static_cast( renderIndex.GetSprim(HdPrimTypeTokens->material, GetMaterialId())); - const TfTokenVector& requiredPrimvars = (material && material->GetSurfaceShader()) - ? material->GetRequiredPrimvars() + TfToken materialNetworkToken = _GetMaterialNetworkToken(reprToken); + const TfTokenVector& requiredPrimvars + = (material && material->GetSurfaceShader(materialNetworkToken)) + ? material->GetRequiredPrimvars(materialNetworkToken) : sFallbackShaderPrimvars; _UpdatePrimvarSources(delegate, *dirtyBits, requiredPrimvars); @@ -525,6 +527,7 @@ void HdVP2BasisCurves::Sync( void HdVP2BasisCurves::_UpdateDrawItem( HdSceneDelegate* sceneDelegate, HdVP2DrawItem* drawItem, + const TfToken& reprToken, HdBasisCurvesReprDesc const& desc) { MHWRender::MRenderItem* renderItem = drawItem->GetRenderItem(); @@ -686,12 +689,9 @@ void HdVP2BasisCurves::_UpdateDrawItem( unsigned int numWidths = widths.size(); if (widthsBuffer && numWidths > 0) { - void* bufferData = widthsBuffer->acquire(numWidths, true); - stateToCommit._primvarBufferDataMap[HdTokens->widths] = bufferData; - - if (bufferData != nullptr) { - memcpy(bufferData, widths.cdata(), numWidths * sizeof(float)); - } + auto& bufferData = stateToCommit._primvarBufferDataMap[HdTokens->widths]; + bufferData.resize(numWidths * sizeof(float)); + memcpy(&bufferData[0], widths.cdata(), numWidths * sizeof(float)); } } @@ -701,7 +701,8 @@ void HdVP2BasisCurves::_UpdateDrawItem( renderIndex.GetSprim(HdPrimTypeTokens->material, GetMaterialId())); if (material) { - MHWRender::MShaderInstance* shader = material->GetSurfaceShader(); + MHWRender::MShaderInstance* shader + = material->GetSurfaceShader(_GetMaterialNetworkToken(reprToken)); drawItemData._shaderIsFallback = (shader == nullptr); if (shader != nullptr && shader != drawItemData._shader) { drawItemData._shader = shader; @@ -1112,14 +1113,15 @@ void HdVP2BasisCurves::_UpdateDrawItem( // If available, something changed for (const auto& entry : stateToCommit._primvarBufferDataMap) { - const TfToken& primvarName = entry.first; - void* primvarBufferData = entry.second; - if (primvarBufferData) { - const auto it = primvarBuffers->find(primvarName); + auto& primvarBufferData = entry.second; + if (!primvarBufferData.empty()) { + const auto it = primvarBuffers->find(entry.first); if (it != primvarBuffers->end()) { - MHWRender::MVertexBuffer* primvarBuffer = it->second.get(); - if (primvarBuffer) { - primvarBuffer->commit(primvarBufferData); + if (auto primvarBuffer = it->second.get()) { + const auto& desc = primvarBuffer->descriptor(); + unsigned int numElems + = primvarBufferData.size() / (desc.dataTypeSize() * desc.dimension()); + primvarBuffer->update(&primvarBufferData[0], 0, numElems, true); } } } @@ -1311,7 +1313,7 @@ void HdVP2BasisCurves::_InitRepr(TfToken const& reprToken, HdDirtyBits* dirtyBit switch (desc.geomStyle) { case HdBasisCurvesGeomStylePatch: - renderItem = _CreatePatchRenderItem(renderItemName); + renderItem = _CreatePatchRenderItem(renderItemName, reprToken); drawItem->AddUsage(HdVP2DrawItem::kSelectionHighlight); #ifdef HAS_DEFAULT_MATERIAL_SUPPORT_API renderItem->setDefaultMaterialHandling(MRenderItem::SkipWhenDefaultMaterialActive); @@ -1349,7 +1351,8 @@ void HdVP2BasisCurves::_InitRepr(TfToken const& reprToken, HdDirtyBits* dirtyBit kOpaqueGray, MSelectionMask::kSelectNurbsCurves, MHWRender::MFrameContext::kExcludeNurbsCurves); - renderItem->setDrawMode(MHWRender::MGeometry::kAll); + renderItem->setDrawMode(static_cast( + MHWRender::MGeometry::kShaded | MHWRender::MGeometry::kTextured)); drawItem->AddUsage(HdVP2DrawItem::kSelectionHighlight); renderItem->setDefaultMaterialHandling( MRenderItem::DrawOnlyWhenDefaultMaterialActive); @@ -1400,7 +1403,7 @@ void HdVP2BasisCurves::_UpdateRepr(HdSceneDelegate* sceneDelegate, TfToken const HdVP2DrawItem* drawItem = static_cast(repr->GetDrawItem(drawItemIndex++)); if (drawItem) { - _UpdateDrawItem(sceneDelegate, drawItem, desc); + _UpdateDrawItem(sceneDelegate, drawItem, reprToken, desc); } } } @@ -1451,13 +1454,21 @@ void HdVP2BasisCurves::_UpdatePrimvarSources( /*! \brief Create render item for smoothHull repr. */ -MHWRender::MRenderItem* HdVP2BasisCurves::_CreatePatchRenderItem(const MString& name) const +MHWRender::MRenderItem* +HdVP2BasisCurves::_CreatePatchRenderItem(const MString& name, const TfToken& reprToken) const { MHWRender::MRenderItem* const renderItem = MHWRender::MRenderItem::Create( name, MHWRender::MRenderItem::MaterialSceneItem, MHWRender::MGeometry::kLines); - renderItem->setDrawMode(static_cast( - MHWRender::MGeometry::kShaded | MHWRender::MGeometry::kTextured)); + MHWRender::MGeometry::DrawMode drawMode = static_cast( + MHWRender::MGeometry::kShaded | MHWRender::MGeometry::kTextured); + if (reprToken == HdReprTokens->smoothHull) { + drawMode = MHWRender::MGeometry::kTextured; + } else if (reprToken == HdVP2ReprTokens->smoothHullUntextured) { + drawMode = MHWRender::MGeometry::kShaded; + } + + renderItem->setDrawMode(drawMode); renderItem->castsShadows(false); renderItem->receivesShadows(false); renderItem->setShader(_delegate->Get3dSolidShader(kOpaqueGray)); diff --git a/lib/mayaUsd/render/vp2RenderDelegate/basisCurves.h b/lib/mayaUsd/render/vp2RenderDelegate/basisCurves.h index c9153f7cbb..eab55a6cec 100644 --- a/lib/mayaUsd/render/vp2RenderDelegate/basisCurves.h +++ b/lib/mayaUsd/render/vp2RenderDelegate/basisCurves.h @@ -139,6 +139,7 @@ class HdVP2BasisCurves final void _UpdateDrawItem( HdSceneDelegate* sceneDelegate, HdVP2DrawItem* drawItem, + const TfToken& reprToken, HdBasisCurvesReprDesc const& desc); void _UpdatePrimvarSources( @@ -146,7 +147,8 @@ class HdVP2BasisCurves final HdDirtyBits dirtyBits, TfTokenVector const& requiredPrimvars); - MHWRender::MRenderItem* _CreatePatchRenderItem(const MString& name) const; + MHWRender::MRenderItem* + _CreatePatchRenderItem(const MString& name, const TfToken& reprToken) const; enum DirtyBits : HdDirtyBits { diff --git a/lib/mayaUsd/render/vp2RenderDelegate/material.cpp b/lib/mayaUsd/render/vp2RenderDelegate/material.cpp index b04ade9188..e4756ff3b1 100644 --- a/lib/mayaUsd/render/vp2RenderDelegate/material.cpp +++ b/lib/mayaUsd/render/vp2RenderDelegate/material.cpp @@ -1788,6 +1788,7 @@ void HdVP2TextureDeleter::operator()(MHWRender::MTexture* texture) HdVP2Material::HdVP2Material(HdVP2RenderDelegate* renderDelegate, const SdfPath& id) : HdMaterial(id) , _renderDelegate(renderDelegate) + , _compiledNetworks { this, this } { } @@ -1835,202 +1836,204 @@ void HdVP2Material::Sync( VtValue vtMatResource = sceneDelegate->GetMaterialResource(id); if (vtMatResource.IsHolding()) { - auto* const param = static_cast(_renderDelegate->GetRenderParam()); - const bool inUntexturedMode - = (param->GetDrawScene().GetDisplayStyle() & MHWRender::MFrameContext::kTextured) - == 0; + const HdMaterialNetworkMap& fullNetworkMap + = vtMatResource.UncheckedGet(); - HdMaterialNetworkMap untexturedNetworkMap; - const HdMaterialNetworkMap& networkMap = inUntexturedMode - ? untexturedNetworkMap - : vtMatResource.UncheckedGet(); + // untextured network is always synced + HdMaterialNetworkMap untexturedNetworkMap = fullNetworkMap; + ConvertNetworkMapToUntextured(untexturedNetworkMap); + _compiledNetworks[kUntextured].Sync(sceneDelegate, untexturedNetworkMap); - if (inUntexturedMode) { - untexturedNetworkMap = vtMatResource.UncheckedGet(); - ConvertNetworkMapToUntextured(untexturedNetworkMap); + // full network is synced only if required by display style + auto* const param = static_cast(_renderDelegate->GetRenderParam()); + if (param->GetDrawScene().NeedTexturedMaterials()) { + _compiledNetworks[kFull].Sync(sceneDelegate, fullNetworkMap); } + } else { + TF_WARN( + "Expected material resource for <%s> to hold HdMaterialNetworkMap," + "but found %s instead.", + id.GetText(), + vtMatResource.GetTypeName().c_str()); + } + } + + *dirtyBits = HdMaterial::Clean; +} - HdMaterialNetwork bxdfNet, dispNet, vp2BxdfNet; +void HdVP2Material::CompiledNetwork::Sync( + HdSceneDelegate* sceneDelegate, + const HdMaterialNetworkMap& networkMap) +{ + const SdfPath& id = _owner->GetId(); + HdMaterialNetwork bxdfNet, dispNet, vp2BxdfNet; - TfMapLookup(networkMap.map, HdMaterialTerminalTokens->surface, &bxdfNet); - TfMapLookup(networkMap.map, HdMaterialTerminalTokens->displacement, &dispNet); + TfMapLookup(networkMap.map, HdMaterialTerminalTokens->surface, &bxdfNet); + TfMapLookup(networkMap.map, HdMaterialTerminalTokens->displacement, &dispNet); #ifdef WANT_MATERIALX_BUILD - if (!bxdfNet.nodes.empty()) { - if (_IsMaterialX(bxdfNet.nodes.back())) { + if (!bxdfNet.nodes.empty()) { + if (_IsMaterialX(bxdfNet.nodes.back())) { - bool isVolume = false; + bool isVolume = false; #if PXR_VERSION > 2203 - const HdMaterialNetwork2 surfaceNetwork - = HdConvertToHdMaterialNetwork2(networkMap, &isVolume); + const HdMaterialNetwork2 surfaceNetwork + = HdConvertToHdMaterialNetwork2(networkMap, &isVolume); #else - HdMaterialNetwork2 surfaceNetwork; - HdMaterialNetwork2ConvertFromHdMaterialNetworkMap( - networkMap, &surfaceNetwork, &isVolume); + HdMaterialNetwork2 surfaceNetwork; + HdMaterialNetwork2ConvertFromHdMaterialNetworkMap( + networkMap, &surfaceNetwork, &isVolume); #endif - if (isVolume) { - // Not supported. - return; - } + if (isVolume) { + // Not supported. + return; + } - size_t topoHash = _GenerateNetwork2TopoHash(surfaceNetwork); + size_t topoHash = _GenerateNetwork2TopoHash(surfaceNetwork); - if (!_surfaceShader || topoHash != _topoHash) { - _surfaceShader.reset( - _CreateMaterialXShaderInstance(GetId(), surfaceNetwork)); - _pointShader.reset(nullptr); - _topoHash = topoHash; - // TopoChanged: We have a brand new surface material, tell the mesh to use - // it. - _MaterialChanged(sceneDelegate); - } + if (!_surfaceShader || topoHash != _topoHash) { + _surfaceShader.reset(_CreateMaterialXShaderInstance(id, surfaceNetwork)); + _pointShader.reset(nullptr); + _topoHash = topoHash; + // TopoChanged: We have a brand new surface material, tell the mesh to use + // it. + _owner->_MaterialChanged(sceneDelegate); + } - if (_surfaceShader) { - _UpdateShaderInstance(sceneDelegate, bxdfNet); + if (_surfaceShader) { + _UpdateShaderInstance(sceneDelegate, bxdfNet); // Consolidation workaround requires dirtying the mesh even on a ValueChanged #ifdef HDVP2_MATERIAL_CONSOLIDATION_UPDATE_WORKAROUND - _MaterialChanged(sceneDelegate); + _owner->_MaterialChanged(sceneDelegate); #endif - *dirtyBits = HdMaterial::Clean; - } - return; - } } + return; + } + } #endif - _ApplyVP2Fixes(vp2BxdfNet, bxdfNet); + _ApplyVP2Fixes(vp2BxdfNet, bxdfNet); - if (!vp2BxdfNet.nodes.empty()) { - // Generate a XML string from the material network and convert it to a token for - // faster hashing and comparison. - const TfToken token(_GenerateXMLString(vp2BxdfNet, false)); + if (!vp2BxdfNet.nodes.empty()) { + // Generate a XML string from the material network and convert it to a token for + // faster hashing and comparison. + const TfToken token(_GenerateXMLString(vp2BxdfNet, false)); - // Skip creating a new shader instance if the token is unchanged. There is no plan - // to implement fine-grain dirty bit in Hydra for the same purpose: - // https://groups.google.com/g/usd-interest/c/xytT2azlJec/m/22Tnw4yXAAAJ - if (_surfaceNetworkToken != token) { - MProfilingScope subProfilingScope( - HdVP2RenderDelegate::sProfilerCategory, - MProfiler::kColorD_L2, - "CreateShaderInstance"); + // Skip creating a new shader instance if the token is unchanged. There is no plan + // to implement fine-grain dirty bit in Hydra for the same purpose: + // https://groups.google.com/g/usd-interest/c/xytT2azlJec/m/22Tnw4yXAAAJ + if (_surfaceNetworkToken != token) { + MProfilingScope subProfilingScope( + HdVP2RenderDelegate::sProfilerCategory, + MProfiler::kColorD_L2, + "CreateShaderInstance"); - // Remember the path of the surface shader for special handling: unlike other - // fragments, the parameters of the surface shader fragment can't be renamed. - _surfaceShaderId = vp2BxdfNet.nodes.back().path; + // Remember the path of the surface shader for special handling: unlike other + // fragments, the parameters of the surface shader fragment can't be renamed. + _surfaceShaderId = vp2BxdfNet.nodes.back().path; - MHWRender::MShaderInstance* shader; + MHWRender::MShaderInstance* shader; #ifndef HDVP2_DISABLE_SHADER_CACHE - // Acquire a shader instance from the shader cache. If a shader instance has - // been cached with the same token, a clone of the shader instance will be - // returned. Multiple clones of a shader instance will share the same shader - // effect, thus reduce compilation overhead and enable material consolidation. - shader = _renderDelegate->GetShaderFromCache(token); - - // If the shader instance is not found in the cache, create one from the - // material network and add a clone to the cache for reuse. - if (!shader) { - shader = _CreateShaderInstance(vp2BxdfNet); - - if (shader) { - _renderDelegate->AddShaderToCache(token, *shader); - } - } + // Acquire a shader instance from the shader cache. If a shader instance has + // been cached with the same token, a clone of the shader instance will be + // returned. Multiple clones of a shader instance will share the same shader + // effect, thus reduce compilation overhead and enable material consolidation. + shader = _owner->_renderDelegate->GetShaderFromCache(token); + + // If the shader instance is not found in the cache, create one from the + // material network and add a clone to the cache for reuse. + if (!shader) { + shader = _CreateShaderInstance(vp2BxdfNet); + + if (shader) { + _owner->_renderDelegate->AddShaderToCache(token, *shader); + } + } #else - shader = _CreateShaderInstance(vp2BxdfNet); + shader = _CreateShaderInstance(vp2BxdfNet); #endif - // The shader instance is owned by the material solely. - _surfaceShader.reset(shader); - _pointShader.reset(nullptr); - // TopoChanged: We have a brand new surface material, tell the mesh to use it. - _MaterialChanged(sceneDelegate); - - if (TfDebug::IsEnabled(HDVP2_DEBUG_MATERIAL)) { - std::cout << "BXDF material network for " << id << ":\n" - << _GenerateXMLString(bxdfNet) << "\n" - << "BXDF (with VP2 fixes) material network for " << id << ":\n" - << _GenerateXMLString(vp2BxdfNet) << "\n" - << "Displacement material network for " << id << ":\n" - << _GenerateXMLString(dispNet) << "\n"; - - if (_surfaceShader) { - auto tmpDir = ghc::filesystem::temp_directory_path(); - tmpDir /= "HdVP2Material_"; - tmpDir += id.GetName(); - tmpDir += ".txt"; - _surfaceShader->writeEffectSourceToFile(tmpDir.c_str()); - - std::cout << "BXDF generated shader code for " << id << ":\n"; - std::cout << " " << tmpDir << "\n"; - } - } + // The shader instance is owned by the material solely. + _surfaceShader.reset(shader); + _pointShader.reset(nullptr); + // TopoChanged: We have a brand new surface material, tell the mesh to use it. + _owner->_MaterialChanged(sceneDelegate); - // Store primvar requirements. - _requiredPrimvars = std::move(vp2BxdfNet.primvars); - - // Verify that _requiredPrivars contains all the requiredVertexBuffers() the - // shader instance needs. - if (shader) { - MVertexBufferDescriptorList requiredVertexBuffers; - MStatus status = shader->requiredVertexBuffers(requiredVertexBuffers); - if (status) { - for (int reqIndex = 0; reqIndex < requiredVertexBuffers.length(); - reqIndex++) { - MVertexBufferDescriptor desc; - requiredVertexBuffers.getDescriptor(reqIndex, desc); - TfToken requiredPrimvar = MayaDescriptorToToken(desc); - // now make sure something matching requiredPrimvar is in - // _requiredPrimvars - if (requiredPrimvar != _tokens->Unknown - && requiredPrimvar != _tokens->Computed) { - bool found = false; - for (TfToken const& primvar : _requiredPrimvars) { - if (primvar == requiredPrimvar) { - found = true; - break; - } - } - if (!found) { - _requiredPrimvars.push_back(requiredPrimvar); - } + if (TfDebug::IsEnabled(HDVP2_DEBUG_MATERIAL)) { + std::cout << "BXDF material network for " << id << ":\n" + << _GenerateXMLString(bxdfNet) << "\n" + << "BXDF (with VP2 fixes) material network for " << id << ":\n" + << _GenerateXMLString(vp2BxdfNet) << "\n" + << "Displacement material network for " << id << ":\n" + << _GenerateXMLString(dispNet) << "\n"; + + if (_surfaceShader) { + auto tmpDir = ghc::filesystem::temp_directory_path(); + tmpDir /= "HdVP2Material_"; + tmpDir += id.GetName(); + tmpDir += ".txt"; + _surfaceShader->writeEffectSourceToFile(tmpDir.c_str()); + + std::cout << "BXDF generated shader code for " << id << ":\n"; + std::cout << " " << tmpDir << "\n"; + } + } + + // Store primvar requirements. + _requiredPrimvars = std::move(vp2BxdfNet.primvars); + + // Verify that _requiredPrivars contains all the requiredVertexBuffers() the + // shader instance needs. + if (shader) { + MVertexBufferDescriptorList requiredVertexBuffers; + MStatus status = shader->requiredVertexBuffers(requiredVertexBuffers); + if (status) { + for (int reqIndex = 0; reqIndex < requiredVertexBuffers.length(); reqIndex++) { + MVertexBufferDescriptor desc; + requiredVertexBuffers.getDescriptor(reqIndex, desc); + TfToken requiredPrimvar = MayaDescriptorToToken(desc); + // now make sure something matching requiredPrimvar is in + // _requiredPrimvars + if (requiredPrimvar != _tokens->Unknown + && requiredPrimvar != _tokens->Computed) { + bool found = false; + for (TfToken const& primvar : _requiredPrimvars) { + if (primvar == requiredPrimvar) { + found = true; + break; } } + if (!found) { + _requiredPrimvars.push_back(requiredPrimvar); + } } } - - // The token is saved and will be used to determine whether a new shader - // instance is needed during the next sync. - _surfaceNetworkToken = token; - - // If the surface shader has its opacity attribute connected to a node which - // isn't a primvar reader, it is set as transparent. If the opacity attr is - // connected to a primvar reader, the Rprim side will determine the transparency - // state according to the primvars:displayOpacity data. If the opacity attr - // isn't connected, the transparency state will be set in - // _UpdateShaderInstance() according to the opacity value. - if (shader) { - shader->setIsTransparent(_IsTransparent(bxdfNet)); - } } + } - _UpdateShaderInstance(sceneDelegate, bxdfNet); + // The token is saved and will be used to determine whether a new shader + // instance is needed during the next sync. + _surfaceNetworkToken = token; + + // If the surface shader has its opacity attribute connected to a node which + // isn't a primvar reader, it is set as transparent. If the opacity attr is + // connected to a primvar reader, the Rprim side will determine the transparency + // state according to the primvars:displayOpacity data. If the opacity attr + // isn't connected, the transparency state will be set in + // _UpdateShaderInstance() according to the opacity value. + if (shader) { + shader->setIsTransparent(_IsTransparent(bxdfNet)); + } + } + + _UpdateShaderInstance(sceneDelegate, bxdfNet); // Consolidation workaround requires dirtying the mesh even on a ValueChanged #ifdef HDVP2_MATERIAL_CONSOLIDATION_UPDATE_WORKAROUND - _MaterialChanged(sceneDelegate); + _owner->_MaterialChanged(sceneDelegate); #endif - } - } else { - TF_WARN( - "Expected material resource for <%s> to hold HdMaterialNetworkMap," - "but found %s instead.", - id.GetText(), - vtMatResource.GetTypeName().c_str()); - } } - - *dirtyBits = HdMaterial::Clean; } /*! \brief Returns the minimal set of dirty bits to place in the @@ -2040,7 +2043,9 @@ HdDirtyBits HdVP2Material::GetInitialDirtyBitsMask() const { return HdMaterial:: /*! \brief Applies VP2-specific fixes to the material network. */ -void HdVP2Material::_ApplyVP2Fixes(HdMaterialNetwork& outNet, const HdMaterialNetwork& inNet) +void HdVP2Material::CompiledNetwork::_ApplyVP2Fixes( + HdMaterialNetwork& outNet, + const HdMaterialNetwork& inNet) { // To avoid relocation, reserve enough space for possible maximal size. The // output network is temporary C++ object that will be released after use. @@ -2381,7 +2386,9 @@ TfToken _RequiresColorManagement( } } -void HdVP2Material::_ApplyMtlxVP2Fixes(HdMaterialNetwork2& outNet, const HdMaterialNetwork2& inNet) +void HdVP2Material::CompiledNetwork::_ApplyMtlxVP2Fixes( + HdMaterialNetwork2& outNet, + const HdMaterialNetwork2& inNet) { // The goal here is to strip all local names in the network paths in order to reduce the shader @@ -2487,10 +2494,11 @@ void HdVP2Material::_ApplyMtlxVP2Fixes(HdMaterialNetwork2& outNet, const HdMater /*! \brief Detects MaterialX networks and rehydrates them. */ -MHWRender::MShaderInstance* HdVP2Material::_CreateMaterialXShaderInstance( +MHWRender::MShaderInstance* HdVP2Material::CompiledNetwork::_CreateMaterialXShaderInstance( SdfPath const& materialId, HdMaterialNetwork2 const& surfaceNetwork) { + auto renderDelegate = _owner->_renderDelegate; MHWRender::MShaderInstance* shaderInstance = nullptr; auto const& terminalConnIt = surfaceNetwork.terminals.find(HdMaterialTerminalTokens->surface); @@ -2510,10 +2518,10 @@ MHWRender::MShaderInstance* HdVP2Material::_CreateMaterialXShaderInstance( // the same token, a clone of the shader instance will be returned. Multiple clones of a shader // instance will share the same shader effect, thus reduce compilation overhead and enable // material consolidation. - shaderInstance = _renderDelegate->GetShaderFromCache(shaderCacheID); + shaderInstance = renderDelegate->GetShaderFromCache(shaderCacheID); if (shaderInstance) { _surfaceShaderId = terminalPath; - const TfTokenVector* cachedPrimvars = _renderDelegate->GetPrimvarsFromCache(shaderCacheID); + const TfTokenVector* cachedPrimvars = renderDelegate->GetPrimvarsFromCache(shaderCacheID); if (cachedPrimvars) { _requiredPrimvars = *cachedPrimvars; } @@ -2701,8 +2709,8 @@ MHWRender::MShaderInstance* HdVP2Material::_CreateMaterialXShaderInstance( } if (shaderInstance) { - _renderDelegate->AddShaderToCache(shaderCacheID, *shaderInstance); - _renderDelegate->AddPrimvarsToCache(shaderCacheID, _requiredPrimvars); + renderDelegate->AddShaderToCache(shaderCacheID, *shaderInstance); + renderDelegate->AddPrimvarsToCache(shaderCacheID, _requiredPrimvars); } return shaderInstance; @@ -2712,7 +2720,8 @@ MHWRender::MShaderInstance* HdVP2Material::_CreateMaterialXShaderInstance( /*! \brief Creates a shader instance for the surface shader. */ -MHWRender::MShaderInstance* HdVP2Material::_CreateShaderInstance(const HdMaterialNetwork& mat) +MHWRender::MShaderInstance* +HdVP2Material::CompiledNetwork::_CreateShaderInstance(const HdMaterialNetwork& mat) { MHWRender::MRenderer* const renderer = MHWRender::MRenderer::theRenderer(); if (!TF_VERIFY(renderer)) { @@ -2900,7 +2909,7 @@ MHWRender::MShaderInstance* HdVP2Material::_CreateShaderInstance(const HdMateria /*! \brief Updates parameters for the surface shader. */ -void HdVP2Material::_UpdateShaderInstance( +void HdVP2Material::CompiledNetwork::_UpdateShaderInstance( HdSceneDelegate* sceneDelegate, const HdMaterialNetwork& mat) { @@ -2950,7 +2959,8 @@ void HdVP2Material::_UpdateShaderInstance( if (_IsUsdUVTexture(node)) { const MHWRender::MSamplerStateDesc desc = _GetSamplerStateDesc(node); - const MHWRender::MSamplerState* sampler = _renderDelegate->GetSamplerState(desc); + const MHWRender::MSamplerState* sampler + = _owner->_renderDelegate->GetSamplerState(desc); if (sampler) { #ifdef WANT_MATERIALX_BUILD if (isMaterialXNode) { @@ -3012,7 +3022,7 @@ void HdVP2Material::_UpdateShaderInstance( const std::string& resolvedPath = val.GetResolvedPath(); const std::string& assetPath = val.GetAssetPath(); if (_IsUsdUVTexture(node) && token == _tokens->file) { - const HdVP2TextureInfo& info = _AcquireTexture( + const HdVP2TextureInfo& info = _owner->_AcquireTexture( sceneDelegate, !resolvedPath.empty() ? resolvedPath : assetPath, node); MHWRender::MTextureAssignment assignment; @@ -3284,7 +3294,7 @@ void HdVP2Material::_ScheduleRefresh() } } -MHWRender::MShaderInstance* HdVP2Material::GetPointShader() const +MHWRender::MShaderInstance* HdVP2Material::CompiledNetwork::GetPointShader() const { if (!_pointShader && _surfaceShader) { _pointShader.reset(_surfaceShader->clone()); @@ -3294,6 +3304,26 @@ MHWRender::MShaderInstance* HdVP2Material::GetPointShader() const return _pointShader.get(); } +HdVP2Material::NetworkConfig HdVP2Material::_GetCompiledConfig(const TfToken& reprToken) const +{ + return (reprToken == HdReprTokens->smoothHull) ? kFull : kUntextured; +} + +MHWRender::MShaderInstance* HdVP2Material::GetSurfaceShader(const TfToken& reprToken) const +{ + return _compiledNetworks[_GetCompiledConfig(reprToken)].GetSurfaceShader(); +} + +MHWRender::MShaderInstance* HdVP2Material::GetPointShader(const TfToken& reprToken) const +{ + return _compiledNetworks[_GetCompiledConfig(reprToken)].GetPointShader(); +} + +const TfTokenVector& HdVP2Material::GetRequiredPrimvars(const TfToken& reprToken) const +{ + return _compiledNetworks[_GetCompiledConfig(reprToken)].GetRequiredPrimvars(); +} + void HdVP2Material::SubscribeForMaterialUpdates(const SdfPath& rprimId) { std::lock_guard lock(_materialSubscriptionsMutex); diff --git a/lib/mayaUsd/render/vp2RenderDelegate/material.h b/lib/mayaUsd/render/vp2RenderDelegate/material.h index 15de42f81b..d812923822 100644 --- a/lib/mayaUsd/render/vp2RenderDelegate/material.h +++ b/lib/mayaUsd/render/vp2RenderDelegate/material.h @@ -100,11 +100,11 @@ class HdVP2Material final : public HdMaterial #endif //! Get the surface shader instance. - MHWRender::MShaderInstance* GetSurfaceShader() const { return _surfaceShader.get(); } - MHWRender::MShaderInstance* GetPointShader() const; + MHWRender::MShaderInstance* GetSurfaceShader(const TfToken& reprToken) const; + MHWRender::MShaderInstance* GetPointShader(const TfToken& reprToken) const; //! Get primvar tokens required by this material. - const TfTokenVector& GetRequiredPrimvars() const { return _requiredPrimvars; } + const TfTokenVector& GetRequiredPrimvars(const TfToken& reprToken) const; void EnqueueLoadTextures(); void ClearPendingTasks(); @@ -121,15 +121,52 @@ class HdVP2Material final : public HdMaterial static void OnMayaExit(); private: - void _ApplyVP2Fixes(HdMaterialNetwork& outNet, const HdMaterialNetwork& inNet); + class CompiledNetwork + { + public: + CompiledNetwork(HdVP2Material* m) + : _owner(m) + { + } + + void Sync(HdSceneDelegate*, const HdMaterialNetworkMap&); + + MHWRender::MShaderInstance* GetSurfaceShader() const { return _surfaceShader.get(); } + MHWRender::MShaderInstance* GetPointShader() const; + const TfTokenVector& GetRequiredPrimvars() const { return _requiredPrimvars; } + + private: + HdVP2Material* _owner; + TfToken _surfaceNetworkToken; //!< Generated token to uniquely identify a material network + SdfPath _surfaceShaderId; //!< Path of the surface shader + HdVP2ShaderUniquePtr _surfaceShader; //!< VP2 surface shader instance + mutable HdVP2ShaderUniquePtr _pointShader; //!< VP2 point shader instance, if needed + TfTokenVector _requiredPrimvars; //!< primvars required by this network + std::unordered_map + _nodePathMap; //!< Mapping from authored node paths to VP2-specific simplified pathes #ifdef WANT_MATERIALX_BUILD - void _ApplyMtlxVP2Fixes(HdMaterialNetwork2& outNet, const HdMaterialNetwork2& inNet); - MHWRender::MShaderInstance* _CreateMaterialXShaderInstance( - SdfPath const& materialId, - HdMaterialNetwork2 const& hdNetworkMap); + // MaterialX-only at the moment, but will be used for UsdPreviewSurface when the upgrade to + // HdMaterialNetwork2 is complete. + size_t _topoHash = 0; + + void _ApplyMtlxVP2Fixes(HdMaterialNetwork2& outNet, const HdMaterialNetwork2& inNet); + MHWRender::MShaderInstance* _CreateMaterialXShaderInstance( + SdfPath const& materialId, + HdMaterialNetwork2 const& hdNetworkMap); #endif - MHWRender::MShaderInstance* _CreateShaderInstance(const HdMaterialNetwork& mat); - void _UpdateShaderInstance(HdSceneDelegate* sceneDelegate, const HdMaterialNetwork& mat); + void _ApplyVP2Fixes(HdMaterialNetwork& outNet, const HdMaterialNetwork& inNet); + MHWRender::MShaderInstance* _CreateShaderInstance(const HdMaterialNetwork& mat); + void _UpdateShaderInstance(HdSceneDelegate* sceneDelegate, const HdMaterialNetwork& mat); + }; + + enum NetworkConfig + { + kFull = 0, + kUntextured, + + kNumNetworkConfigs + }; + const HdVP2TextureInfo& _AcquireTexture( HdSceneDelegate* sceneDelegate, const std::string& path, @@ -146,6 +183,8 @@ class HdVP2Material final : public HdMaterial static void _ScheduleRefresh(); + NetworkConfig _GetCompiledConfig(const TfToken& reprToken) const; + static std::mutex _refreshMutex; static std::chrono::steady_clock::time_point _startTime; static std::atomic_size_t _runningTasksCounter; @@ -153,17 +192,9 @@ class HdVP2Material final : public HdMaterial HdVP2RenderDelegate* const _renderDelegate; //!< VP2 render delegate for which this material was created - std::unordered_map - _nodePathMap; //!< Mapping from authored node paths to VP2-specific simplified pathes - - TfToken _surfaceNetworkToken; //!< Generated token to uniquely identify a material network - - HdVP2ShaderUniquePtr _surfaceShader; //!< VP2 surface shader instance - mutable HdVP2ShaderUniquePtr _pointShader; //!< VP2 point shader instance, if needed - SdfPath _surfaceShaderId; //!< Path of the surface shader + CompiledNetwork _compiledNetworks[kNumNetworkConfigs]; static HdVP2GlobalTextureMap _globalTextureMap; //!< Texture in use by all materials in MayaUSD HdVP2LocalTextureMap _localTextureMap; //!< Textures used by this material - TfTokenVector _requiredPrimvars; //!< primvars required by this material std::unordered_map _textureLoadingTasks; @@ -172,12 +203,6 @@ class HdVP2Material final : public HdMaterial //! The set of Rprims listening to changes on this material std::set _materialSubscriptions; - -#ifdef WANT_MATERIALX_BUILD - // MaterialX-only at the moment, but will be used for UsdPreviewSurface when the upgrade to - // HdMaterialNetwork2 is complete. - size_t _topoHash = 0; -#endif }; PXR_NAMESPACE_CLOSE_SCOPE diff --git a/lib/mayaUsd/render/vp2RenderDelegate/mayaPrimCommon.cpp b/lib/mayaUsd/render/vp2RenderDelegate/mayaPrimCommon.cpp index 7c1e4e4f05..72af145bae 100644 --- a/lib/mayaUsd/render/vp2RenderDelegate/mayaPrimCommon.cpp +++ b/lib/mayaUsd/render/vp2RenderDelegate/mayaPrimCommon.cpp @@ -320,6 +320,11 @@ TfToken MayaUsdRPrim::_GetOverrideToken(TfToken const& reprToken) const return TfToken(); } +TfToken MayaUsdRPrim::_GetMaterialNetworkToken(const TfToken& reprToken) const +{ + return _displayLayerModes._texturing ? reprToken : TfToken(); +} + HdReprSharedPtr MayaUsdRPrim::_InitReprCommon( HdRprim& refThis, TfToken const& reprToken, @@ -724,9 +729,11 @@ void MayaUsdRPrim::_SyncDisplayLayerModes(const HdRprim& MPlug layerDisplayType = displayLayerNodeFn.findPlug("displayType"); MPlug levelOfDetail = displayLayerNodeFn.findPlug("levelOfDetail"); MPlug shading = displayLayerNodeFn.findPlug("shading"); + MPlug texturing = displayLayerNodeFn.findPlug("texturing"); _displayLayerModes._visibility &= layerEnabled.asBool() ? layerVisible.asBool() : true; _displayLayerModes._hideOnPlayback |= layerHidesOnPlayback.asBool(); + _displayLayerModes._texturing = texturing.asBool(); if (levelOfDetail.asShort() != 0) { _displayLayerModes._reprOverride = kBBox; } else if (shading.asShort() == 0 && _displayLayerModes._reprOverride != kBBox) { diff --git a/lib/mayaUsd/render/vp2RenderDelegate/mayaPrimCommon.h b/lib/mayaUsd/render/vp2RenderDelegate/mayaPrimCommon.h index 2d863d421e..9c0984e4c5 100644 --- a/lib/mayaUsd/render/vp2RenderDelegate/mayaPrimCommon.h +++ b/lib/mayaUsd/render/vp2RenderDelegate/mayaPrimCommon.h @@ -69,7 +69,7 @@ class MayaUsdCustomData #endif //! A primvar vertex buffer data map indexed by primvar name. -using PrimvarBufferDataMap = std::unordered_map; +using PrimvarBufferDataMap = std::unordered_map, TfToken::HashFunctor>; //! \brief Helper struct used to package all the changes into single commit task //! (such commit task will be executed on main-thread) @@ -199,6 +199,9 @@ class MayaUsdRPrim //! Requested display type of the Rprim DisplayType _displayType { kNormal }; + + //! Requested texturing status + bool _texturing { true }; }; void _CommitMVertexBuffer(MHWRender::MVertexBuffer* const, void*) const; @@ -217,6 +220,8 @@ class MayaUsdRPrim TfToken _GetOverrideToken(TfToken const& reprToken) const; + TfToken _GetMaterialNetworkToken(const TfToken& reprToken) const; + HdReprSharedPtr _InitReprCommon( HdRprim& refThis, TfToken const& reprToken, diff --git a/lib/mayaUsd/render/vp2RenderDelegate/mesh.cpp b/lib/mayaUsd/render/vp2RenderDelegate/mesh.cpp index 0244c5f1ca..0a8541ee75 100644 --- a/lib/mayaUsd/render/vp2RenderDelegate/mesh.cpp +++ b/lib/mayaUsd/render/vp2RenderDelegate/mesh.cpp @@ -884,8 +884,10 @@ void HdVP2Mesh::Sync( auto addRequiredPrimvars = [&](const SdfPath& materialId) { const HdVP2Material* material = static_cast( renderIndex.GetSprim(HdPrimTypeTokens->material, materialId)); - const TfTokenVector& requiredPrimvars = material && material->GetSurfaceShader() - ? material->GetRequiredPrimvars() + TfToken materialNetworkToken = _GetMaterialNetworkToken(reprToken); + const TfTokenVector& requiredPrimvars + = material && material->GetSurfaceShader(materialNetworkToken) + ? material->GetRequiredPrimvars(materialNetworkToken) : sFallbackShaderPrimvars; for (const auto& requiredPrimvar : requiredPrimvars) { @@ -1182,9 +1184,9 @@ void HdVP2Mesh::_InitRepr(const TfToken& reprToken, HdDirtyBits* dirtyBits) MHWRender::MRenderItem* defaultMaterialItem = _CreateSmoothHullRenderItem( #if HD_API_VERSION < 35 - renderItemName, *drawItem, *subSceneContainer, nullptr) + renderItemName, *drawItem, reprToken, *subSceneContainer, nullptr) #else - renderItemName, *drawItem.get(), *subSceneContainer, nullptr) + renderItemName, *drawItem.get(), reprToken, *subSceneContainer, nullptr) #endif ._renderItem; defaultMaterialItem->setDefaultMaterialHandling( @@ -1194,9 +1196,9 @@ void HdVP2Mesh::_InitRepr(const TfToken& reprToken, HdDirtyBits* dirtyBits) if (!GetInstancerId().IsEmpty()) { defaultMaterialItem = _CreateShadedSelectedInstancesItem( #if HD_API_VERSION < 35 - renderItemName, *drawItem, *subSceneContainer, nullptr); + renderItemName, *drawItem, reprToken, *subSceneContainer, nullptr); #else - renderItemName, *drawItem.get(), *subSceneContainer, nullptr); + renderItemName, *drawItem.get(), reprToken, *subSceneContainer, nullptr); #endif defaultMaterialItem->setDefaultMaterialHandling( MRenderItem::DrawOnlyWhenDefaultMaterialActive); @@ -1207,19 +1209,13 @@ void HdVP2Mesh::_InitRepr(const TfToken& reprToken, HdDirtyBits* dirtyBits) #endif break; case HdMeshGeomStyleHullEdgeOnly: - // The smoothHull repr uses the wireframe item for selection highlight only. -#ifdef HAS_DEFAULT_MATERIAL_SUPPORT_API + // The hull reprs use the wireframe item for selection highlight only. if (reprToken == HdReprTokens->smoothHull + || reprToken == HdVP2ReprTokens->smoothHullUntextured || reprToken == HdVP2ReprTokens->defaultMaterial) { - // Share selection highlight render item between smoothHull and defaultMaterial: - bool foundShared = false; - _ReprVector::const_iterator it = std::find_if( - _reprs.begin(), - _reprs.end(), - _ReprComparator( - reprToken == HdReprTokens->smoothHull ? HdVP2ReprTokens->defaultMaterial - : HdReprTokens->smoothHull)); - if (it != _reprs.end()) { + // Share selection highlight render item between hull reprs + bool foundShared = false; + for (auto it = _reprs.begin(); (it != _reprs.end()) && !foundShared; ++it) { const HdReprSharedPtr& repr = it->second; const auto& items = repr->GetDrawItems(); #if HD_API_VERSION < 35 @@ -1242,13 +1238,6 @@ void HdVP2Mesh::_InitRepr(const TfToken& reprToken, HdDirtyBits* dirtyBits) } drawItem->SetUsage(HdVP2DrawItem::kSelectionHighlight); } -#else - // The smoothHull repr uses the wireframe item for selection highlight only. - if (reprToken == HdReprTokens->smoothHull) { - renderItem = _CreateSelectionHighlightRenderItem(renderItemName); - drawItem->SetUsage(HdVP2DrawItem::kSelectionHighlight); - } -#endif // The item is used for wireframe display and selection highlight. else if (reprToken == HdReprTokens->wire) { renderItem = _CreateWireframeRenderItem( @@ -1307,6 +1296,7 @@ void HdVP2Mesh::_InitRepr(const TfToken& reprToken, HdDirtyBits* dirtyBits) void HdVP2Mesh::_CreateSmoothHullRenderItems( HdVP2DrawItem& drawItem, + const TfToken& reprToken, MSubSceneContainer& subSceneContainer) { // 2021-01-29: Changing topology is not tested @@ -1343,12 +1333,13 @@ void HdVP2Mesh::_CreateSmoothHullRenderItems( MString renderItemName = drawItem.GetDrawItemName(); renderItemName += std::string(1, VP2_RENDER_DELEGATE_SEPARATOR).c_str(); renderItemName += geomSubset.id.GetString().c_str(); - _CreateSmoothHullRenderItem(renderItemName, drawItem, subSceneContainer, &geomSubset); + _CreateSmoothHullRenderItem( + renderItemName, drawItem, reprToken, subSceneContainer, &geomSubset); #ifdef MAYA_NEW_POINT_SNAPPING_SUPPORT if (!GetInstancerId().IsEmpty()) { _CreateShadedSelectedInstancesItem( - renderItemName, drawItem, subSceneContainer, &geomSubset); + renderItemName, drawItem, reprToken, subSceneContainer, &geomSubset); } #endif @@ -1375,12 +1366,12 @@ void HdVP2Mesh::_CreateSmoothHullRenderItems( if (numFacesWithoutRenderItem > 0) { // create an item for the remaining faces _CreateSmoothHullRenderItem( - drawItem.GetDrawItemName(), drawItem, subSceneContainer, nullptr); + drawItem.GetDrawItemName(), drawItem, reprToken, subSceneContainer, nullptr); #ifdef MAYA_NEW_POINT_SNAPPING_SUPPORT if (!GetInstancerId().IsEmpty()) { _CreateShadedSelectedInstancesItem( - drawItem.GetDrawItemName(), drawItem, subSceneContainer, nullptr); + drawItem.GetDrawItemName(), drawItem, reprToken, subSceneContainer, nullptr); } #endif @@ -1433,7 +1424,7 @@ void HdVP2Mesh::_UpdateRepr(HdSceneDelegate* sceneDelegate, const TfToken& reprT // it is possible we haven't created MRenderItems for this HdDrawItem yet. // if there are no MRenderItems, create them. if (drawItem->GetRenderItems().size() == 0) { - _CreateSmoothHullRenderItems(*drawItem, *subSceneContainer); + _CreateSmoothHullRenderItems(*drawItem, reprToken, *subSceneContainer); } } @@ -1648,7 +1639,8 @@ void HdVP2Mesh::_UpdateDrawItem( renderIndex.GetSprim(HdPrimTypeTokens->material, materialId)); if (material) { - MHWRender::MShaderInstance* shader = material->GetSurfaceShader(); + MHWRender::MShaderInstance* shader + = material->GetSurfaceShader(_GetMaterialNetworkToken(reprToken)); if (shader != nullptr && (shader != drawItemData._shader || shader != stateToCommit._shader)) { drawItemData._shader = shader; @@ -2508,6 +2500,7 @@ void HdVP2Mesh::_UpdatePrimvarSources( MHWRender::MRenderItem* HdVP2Mesh::_CreateShadedSelectedInstancesItem( const MString& name, HdVP2DrawItem& drawItem, + const TfToken& reprToken, MSubSceneContainer& subSceneContainer, const HdGeomSubset* geomSubset) const { @@ -2515,7 +2508,7 @@ MHWRender::MRenderItem* HdVP2Mesh::_CreateShadedSelectedInstancesItem( ssiName += std::string(1, VP2_RENDER_DELEGATE_SEPARATOR).c_str(); ssiName += "shadedSelectedInstances"; HdVP2DrawItem::RenderItemData& renderItemData - = _CreateSmoothHullRenderItem(ssiName, drawItem, subSceneContainer, geomSubset); + = _CreateSmoothHullRenderItem(ssiName, drawItem, reprToken, subSceneContainer, geomSubset); renderItemData._shadedSelectedInstances = true; return renderItemData._renderItem; @@ -2527,6 +2520,7 @@ MHWRender::MRenderItem* HdVP2Mesh::_CreateShadedSelectedInstancesItem( HdVP2DrawItem::RenderItemData& HdVP2Mesh::_CreateSmoothHullRenderItem( const MString& name, HdVP2DrawItem& drawItem, + const TfToken& reprToken, MSubSceneContainer& subSceneContainer, const HdGeomSubset* geomSubset) const { @@ -2539,8 +2533,14 @@ HdVP2DrawItem::RenderItemData& HdVP2Mesh::_CreateSmoothHullRenderItem( MHWRender::MRenderItem* const renderItem = MHWRender::MRenderItem::Create( itemName, MHWRender::MRenderItem::MaterialSceneItem, MHWRender::MGeometry::kTriangles); - constexpr MHWRender::MGeometry::DrawMode drawMode = static_cast( + MHWRender::MGeometry::DrawMode drawMode = static_cast( MHWRender::MGeometry::kShaded | MHWRender::MGeometry::kTextured); + if (reprToken == HdReprTokens->smoothHull) { + drawMode = MHWRender::MGeometry::kTextured; + } else if (reprToken == HdVP2ReprTokens->smoothHullUntextured) { + drawMode = MHWRender::MGeometry::kShaded; + } + renderItem->setDrawMode(drawMode); renderItem->setExcludedFromPostEffects(false); renderItem->castsShadows(true); diff --git a/lib/mayaUsd/render/vp2RenderDelegate/mesh.h b/lib/mayaUsd/render/vp2RenderDelegate/mesh.h index 75618d4712..9deeeb8aca 100644 --- a/lib/mayaUsd/render/vp2RenderDelegate/mesh.h +++ b/lib/mayaUsd/render/vp2RenderDelegate/mesh.h @@ -161,19 +161,23 @@ class HdVP2Mesh final const HdDirtyBits& rprimDirtyBits, const TfToken& reprToken); - void - _CreateSmoothHullRenderItems(HdVP2DrawItem& drawItem, MSubSceneContainer& subSceneContainer); + void _CreateSmoothHullRenderItems( + HdVP2DrawItem& drawItem, + const TfToken& reprToken, + MSubSceneContainer& subSceneContainer); #ifdef MAYA_NEW_POINT_SNAPPING_SUPPORT MHWRender::MRenderItem* _CreateShadedSelectedInstancesItem( const MString& name, HdVP2DrawItem& drawItem, + const TfToken& reprToken, MSubSceneContainer& subSceneContainer, const HdGeomSubset* geomSubset) const; #endif HdVP2DrawItem::RenderItemData& _CreateSmoothHullRenderItem( const MString& name, HdVP2DrawItem& drawItem, + const TfToken& reprToken, MSubSceneContainer& subSceneContainer, const HdGeomSubset* geomSubset) const; MHWRender::MRenderItem* _CreateSelectionHighlightRenderItem(const MString& name) const; diff --git a/lib/mayaUsd/render/vp2RenderDelegate/points.cpp b/lib/mayaUsd/render/vp2RenderDelegate/points.cpp index d05f65b65e..538b69353f 100644 --- a/lib/mayaUsd/render/vp2RenderDelegate/points.cpp +++ b/lib/mayaUsd/render/vp2RenderDelegate/points.cpp @@ -148,8 +148,9 @@ void HdVP2Points::Sync( TfTokenVector materialPrimvars; const TfTokenVector* requiredPrimvars = &sFallbackShaderPrimvars; - if (material && material->GetSurfaceShader()) { - materialPrimvars = material->GetRequiredPrimvars(); + TfToken materialNetworkToken = _GetMaterialNetworkToken(reprToken); + if (material && material->GetSurfaceShader(materialNetworkToken)) { + materialPrimvars = material->GetRequiredPrimvars(materialNetworkToken); materialPrimvars.push_back(HdTokens->widths); requiredPrimvars = &materialPrimvars; } @@ -243,12 +244,9 @@ void PreparePrimvarBuffer( unsigned int numElems = primvarArray.size(); if (primvarBuffer && numElems > 0) { - void* bufferData = primvarBuffer->acquire(numElems, true); - stateToCommit._primvarBufferDataMap[bufferToken] = bufferData; - - if (bufferData != nullptr) { - memcpy(bufferData, primvarArray.cdata(), numElems * sizeof(BaseType)); - } + auto& bufferData = stateToCommit._primvarBufferDataMap[bufferToken]; + bufferData.resize(numElems * sizeof(BaseType)); + memcpy(&bufferData[0], primvarArray.cdata(), numElems * sizeof(BaseType)); } } @@ -260,6 +258,7 @@ void PreparePrimvarBuffer( void HdVP2Points::_UpdateDrawItem( HdSceneDelegate* sceneDelegate, HdVP2DrawItem* drawItem, + const TfToken& reprToken, HdPointsReprDesc const& desc) { if (drawItem->GetRenderItems().empty()) { @@ -393,7 +392,8 @@ void HdVP2Points::_UpdateDrawItem( renderIndex.GetSprim(HdPrimTypeTokens->material, GetMaterialId())); if (material) { - MHWRender::MShaderInstance* shader = material->GetPointShader(); + MHWRender::MShaderInstance* shader + = material->GetPointShader(_GetMaterialNetworkToken(reprToken)); drawItemData._shaderIsFallback = (shader == nullptr); if (shader != nullptr && shader != drawItemData._shader) { drawItemData._shader = shader; @@ -788,14 +788,15 @@ void HdVP2Points::_UpdateDrawItem( // If available, something changed for (const auto& entry : stateToCommit._primvarBufferDataMap) { - const TfToken& primvarName = entry.first; - void* primvarBufferData = entry.second; - if (primvarBufferData) { - const auto it = primvarBuffers->find(primvarName); + auto& primvarBufferData = entry.second; + if (!primvarBufferData.empty()) { + const auto it = primvarBuffers->find(entry.first); if (it != primvarBuffers->end()) { - MHWRender::MVertexBuffer* primvarBuffer = it->second.get(); - if (primvarBuffer) { - primvarBuffer->commit(primvarBufferData); + if (auto primvarBuffer = it->second.get()) { + const auto& desc = primvarBuffer->descriptor(); + unsigned int numElems + = primvarBufferData.size() / (desc.dataTypeSize() * desc.dimension()); + primvarBuffer->update(&primvarBufferData[0], 0, numElems, true); } } } @@ -921,6 +922,10 @@ void HdVP2Points::_UpdateDrawItem( */ HdDirtyBits HdVP2Points::_PropagateDirtyBits(HdDirtyBits bits) const { + if (bits & HdChangeTracker::DirtyMaterialId) { + bits |= HdChangeTracker::DirtyPrimvar; + } + _PropagateDirtyBitsCommon(bits, _reprs); return bits; } @@ -974,8 +979,9 @@ void HdVP2Points::_InitRepr(TfToken const& reprToken, HdDirtyBits* dirtyBits) switch (desc.geomStyle) { case HdPointsGeomStylePoints: - if (reprToken == HdReprTokens->smoothHull) { - renderItem = _CreateFatPointsRenderItem(renderItemName); + if (reprToken == HdReprTokens->smoothHull + || reprToken == HdVP2ReprTokens->smoothHullUntextured) { + renderItem = _CreateFatPointsRenderItem(renderItemName, reprToken); drawItem->AddUsage(HdVP2DrawItem::kSelectionHighlight); #ifdef HAS_DEFAULT_MATERIAL_SUPPORT_API renderItem->setDefaultMaterialHandling(MRenderItem::SkipWhenDefaultMaterialActive); @@ -1018,7 +1024,7 @@ void HdVP2Points::_UpdateRepr(HdSceneDelegate* sceneDelegate, TfToken const& rep HdVP2DrawItem* drawItem = static_cast(repr->GetDrawItem(drawItemIndex++)); if (drawItem) { - _UpdateDrawItem(sceneDelegate, drawItem, desc); + _UpdateDrawItem(sceneDelegate, drawItem, reprToken, desc); } } } @@ -1067,13 +1073,21 @@ void HdVP2Points::_UpdatePrimvarSources( /*! \brief Create render item for smoothHull repr. */ -MHWRender::MRenderItem* HdVP2Points::_CreateFatPointsRenderItem(const MString& name) const +MHWRender::MRenderItem* +HdVP2Points::_CreateFatPointsRenderItem(const MString& name, const TfToken& reprToken) const { MHWRender::MRenderItem* const renderItem = MHWRender::MRenderItem::Create( name, MHWRender::MRenderItem::MaterialSceneItem, MHWRender::MGeometry::kPoints); - renderItem->setDrawMode(static_cast( - MHWRender::MGeometry::kShaded | MHWRender::MGeometry::kTextured)); + MHWRender::MGeometry::DrawMode drawMode = static_cast( + MHWRender::MGeometry::kShaded | MHWRender::MGeometry::kTextured); + if (reprToken == HdReprTokens->smoothHull) { + drawMode = MHWRender::MGeometry::kTextured; + } else if (reprToken == HdVP2ReprTokens->smoothHullUntextured) { + drawMode = MHWRender::MGeometry::kShaded; + } + + renderItem->setDrawMode(drawMode); renderItem->castsShadows(false); renderItem->receivesShadows(false); renderItem->setShader(_delegate->GetPointsFallbackShader(MColor())); diff --git a/lib/mayaUsd/render/vp2RenderDelegate/points.h b/lib/mayaUsd/render/vp2RenderDelegate/points.h index f3a91fd926..00fb9e992e 100644 --- a/lib/mayaUsd/render/vp2RenderDelegate/points.h +++ b/lib/mayaUsd/render/vp2RenderDelegate/points.h @@ -123,6 +123,7 @@ class HdVP2Points final void _UpdateDrawItem( HdSceneDelegate* sceneDelegate, HdVP2DrawItem* drawItem, + const TfToken& reprToken, HdPointsReprDesc const& desc); void _UpdatePrimvarSources( @@ -130,7 +131,8 @@ class HdVP2Points final HdDirtyBits dirtyBits, TfTokenVector const& requiredPrimvars); - MHWRender::MRenderItem* _CreateFatPointsRenderItem(const MString& name) const; + MHWRender::MRenderItem* + _CreateFatPointsRenderItem(const MString& name, const TfToken& reprToken) const; enum DirtyBits : HdDirtyBits { diff --git a/lib/mayaUsd/render/vp2RenderDelegate/proxyRenderDelegate.cpp b/lib/mayaUsd/render/vp2RenderDelegate/proxyRenderDelegate.cpp index f27a07a5de..00adcfc443 100644 --- a/lib/mayaUsd/render/vp2RenderDelegate/proxyRenderDelegate.cpp +++ b/lib/mayaUsd/render/vp2RenderDelegate/proxyRenderDelegate.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -96,19 +97,6 @@ PXR_NAMESPACE_OPEN_SCOPE namespace { -//! Representation selector for shaded and textured viewport mode -const HdReprSelector kSmoothHullReprSelector(HdReprTokens->smoothHull); - -#ifdef HAS_DEFAULT_MATERIAL_SUPPORT_API -//! Representation selector for default material viewport mode -const HdReprSelector kDefaultMaterialReprSelector(HdVP2ReprTokens->defaultMaterial); -#endif - -//! Representation selector for wireframe viewport mode -const HdReprSelector kWireReprSelector(TfToken(), HdReprTokens->wire); - -//! Representation selector for bounding box viewport mode -const HdReprSelector kBBoxReprSelector(TfToken(), HdVP2ReprTokens->bbox); //! Representation selector for point snapping const HdReprSelector kPointsReprSelector(TfToken(), TfToken(), HdReprTokens->points); @@ -292,6 +280,7 @@ void _ConfigureReprs() // Hull desc for shaded display, edge desc for selection highlight. HdMesh::ConfigureRepr(HdReprTokens->smoothHull, reprDescHull, reprDescEdge); + HdMesh::ConfigureRepr(HdVP2ReprTokens->smoothHullUntextured, reprDescHull, reprDescEdge); #ifdef HAS_DEFAULT_MATERIAL_SUPPORT_API // Hull desc for default material display, edge desc for selection highlight. @@ -302,6 +291,10 @@ void _ConfigureReprs() // Edge desc for bbox display. HdMesh::ConfigureRepr(HdVP2ReprTokens->bbox, reprDescEdge); + // smooth hull for untextured display + HdBasisCurves::ConfigureRepr( + HdVP2ReprTokens->smoothHullUntextured, HdBasisCurvesGeomStylePatch); + // Wireframe desc for bbox display. HdBasisCurves::ConfigureRepr(HdVP2ReprTokens->bbox, HdBasisCurvesGeomStyleWire); @@ -309,6 +302,8 @@ void _ConfigureReprs() // Wire for default material: HdBasisCurves::ConfigureRepr(HdVP2ReprTokens->defaultMaterial, HdBasisCurvesGeomStyleWire); #endif + + HdPoints::ConfigureRepr(HdVP2ReprTokens->smoothHullUntextured, HdPointsGeomStylePoints); } #if defined(WANT_UFE_BUILD) @@ -820,7 +815,8 @@ void ProxyRenderDelegate::_DirtyUsdSubtree(const UsdPrim& prim) HdChangeTracker& changeTracker = _renderIndex->GetChangeTracker(); constexpr HdDirtyBits dirtyBits = HdChangeTracker::DirtyVisibility | HdChangeTracker::DirtyRepr - | HdChangeTracker::DirtyDisplayStyle | MayaUsdRPrim::DirtySelectionHighlight; + | HdChangeTracker::DirtyDisplayStyle | MayaUsdRPrim::DirtySelectionHighlight + | HdChangeTracker::DirtyMaterialId; if (prim.IsA()) { auto indexPath = _sceneDelegate->ConvertCachePathToIndexPath(prim.GetPath()); @@ -867,6 +863,53 @@ void ProxyRenderDelegate::_DirtyUfeSubtree(const MString& rootStr) } #endif +void ProxyRenderDelegate::ComputeCombinedDisplayStyles(const unsigned int newDisplayStyle) +{ + // Add new display styles to the map + if (newDisplayStyle & MHWRender::MFrameContext::kBoundingBox) { + _combinedDisplayStyles[HdVP2ReprTokens->bbox] = _frameCounter; + } else { + if (newDisplayStyle & MHWRender::MFrameContext::kWireFrame) { + _combinedDisplayStyles[HdReprTokens->wire] = _frameCounter; + } + + if (newDisplayStyle & MHWRender::MFrameContext::kGouraudShaded) { +#ifdef HAS_DEFAULT_MATERIAL_SUPPORT_API + if (newDisplayStyle & MHWRender::MFrameContext::kDefaultMaterial) { + _combinedDisplayStyles[HdVP2ReprTokens->defaultMaterial] = _frameCounter; + } else +#endif + if (newDisplayStyle & MHWRender::MFrameContext::kTextured) { + _combinedDisplayStyles[HdReprTokens->smoothHull] = _frameCounter; + } else { + _combinedDisplayStyles[HdVP2ReprTokens->smoothHullUntextured] = _frameCounter; + } + } + } + + // Erase aged styles + for (auto it = _combinedDisplayStyles.begin(); it != _combinedDisplayStyles.end();) { + auto curIt = it++; + constexpr int numFramesToAge = 8; + if (curIt->second + numFramesToAge < _frameCounter) { + _combinedDisplayStyles.erase(curIt); + } + } + + // Erase excessive styles + while (_combinedDisplayStyles.size() > HdReprSelector::MAX_TOPOLOGY_REPRS) { + auto oldestIt = _combinedDisplayStyles.begin(); + auto curIt = _combinedDisplayStyles.begin(); + for (++curIt; curIt != _combinedDisplayStyles.end(); ++curIt) { + if (oldestIt->second > curIt->second) { + oldestIt = curIt; + } + } + + _combinedDisplayStyles.erase(oldestIt); + } +} + //! \brief Execute Hydra engine to perform minimal VP2 draw data update based on change tracker. void ProxyRenderDelegate::_Execute(const MHWRender::MFrameContext& frameContext) { @@ -884,8 +927,6 @@ void ProxyRenderDelegate::_Execute(const MHWRender::MFrameContext& frameContext) // won't be prepared until point snapping is activated; otherwise the draw // data have to be prepared early for possible activation of point snapping. #if defined(MAYA_ENABLE_UPDATE_FOR_SELECTION) - HdReprSelector reprSelector; - const bool inSelectionPass = (frameContext.getSelectionInfo() != nullptr); #if !defined(MAYA_NEW_POINT_SNAPPING_SUPPORT) || defined(WANT_UFE_BUILD) const bool inPointSnapping = pointSnappingActive(); @@ -905,22 +946,14 @@ void ProxyRenderDelegate::_Execute(const MHWRender::MFrameContext& frameContext) #endif // defined(WANT_UFE_BUILD) #else // !defined(MAYA_ENABLE_UPDATE_FOR_SELECTION) - HdReprSelector reprSelector = kPointsReprSelector; + _combinedDisplayStyles[HdReprTokens->points] = _frameCounter; - constexpr bool inSelectionPass = false; + constexpr bool inSelectionPass = false; #if !defined(MAYA_NEW_POINT_SNAPPING_SUPPORT) - constexpr bool inPointSnapping = false; + constexpr bool inPointSnapping = false; #endif #endif // defined(MAYA_ENABLE_UPDATE_FOR_SELECTION) -#ifdef MAYA_HAS_DISPLAY_STYLE_ALL_VIEWPORTS - const unsigned int displayStyle = frameContext.getDisplayStyleOfAllViewports(); -#else - const unsigned int displayStyle = frameContext.getDisplayStyle(); -#endif - const unsigned int oldDisplayStyle = _currentDisplayStyle; - _currentDisplayStyle = frameContext.getDisplayStyle(); - // Work around USD issue #1516. There is a significant performance overhead caused by populating // selection, so only force the populate selection to occur when we detect a change which // impacts the instance indexing. @@ -942,6 +975,7 @@ void ProxyRenderDelegate::_Execute(const MHWRender::MFrameContext& frameContext) } #endif + HdReprSelector reprSelector; if (inSelectionPass) { // The new Maya point snapping support doesn't require point snapping items any more. #if !defined(MAYA_NEW_POINT_SNAPPING_SUPPORT) @@ -950,33 +984,18 @@ void ProxyRenderDelegate::_Execute(const MHWRender::MFrameContext& frameContext) } #endif } else { - // Update repr selector based on display style of the current viewport - if (displayStyle & MHWRender::MFrameContext::kBoundingBox) { - if (!reprSelector.Contains(HdVP2ReprTokens->bbox)) { - reprSelector = reprSelector.CompositeOver(kBBoxReprSelector); - } - } else { - // To support Wireframe on Shaded mode, the two displayStyle checks - // should not be mutually excluded. - if (displayStyle & MHWRender::MFrameContext::kGouraudShaded) { -#ifdef HAS_DEFAULT_MATERIAL_SUPPORT_API - if (displayStyle & MHWRender::MFrameContext::kDefaultMaterial) { - if (!reprSelector.Contains(HdVP2ReprTokens->defaultMaterial)) { - reprSelector = reprSelector.CompositeOver(kDefaultMaterialReprSelector); - } - } else -#endif - if (!reprSelector.Contains(HdReprTokens->smoothHull)) { - reprSelector = reprSelector.CompositeOver(kSmoothHullReprSelector); - } - } - - if (displayStyle & MHWRender::MFrameContext::kWireFrame) { - if (!reprSelector.Contains(HdReprTokens->wire)) { - reprSelector = reprSelector.CompositeOver(kWireReprSelector); - } - } + ComputeCombinedDisplayStyles(frameContext.getDisplayStyle()); + + // Update repr selector based on combined display styles + TfToken reprNames[HdReprSelector::MAX_TOPOLOGY_REPRS]; + auto it = _combinedDisplayStyles.begin(); + for (size_t j = 0; + (it != _combinedDisplayStyles.end()) && (j < HdReprSelector::MAX_TOPOLOGY_REPRS); + ++it, ++j) { + reprNames[j] = it->first; } + + reprSelector = HdReprSelector(reprNames[0], reprNames[1], reprNames[2]); } // if there are no repr's to update then don't even call sync. @@ -1000,8 +1019,11 @@ void ProxyRenderDelegate::_Execute(const MHWRender::MFrameContext& frameContext) } #endif - // if textured/untextured mode has changed, we need to update materials - if (((_currentDisplayStyle ^ oldDisplayStyle) & MHWRender::MFrameContext::kTextured) != 0) { + // if switching to textured mode, we need to update materials + const bool neededTexturedMaterials = _needTexturedMaterials; + _needTexturedMaterials + = _combinedDisplayStyles.find(HdReprTokens->smoothHull) != _combinedDisplayStyles.end(); + if (_needTexturedMaterials && !neededTexturedMaterials) { auto materials = _renderIndex->GetSprimSubtree( HdPrimTypeTokens->material, SdfPath::AbsoluteRootPath()); for (auto material : materials) { diff --git a/lib/mayaUsd/render/vp2RenderDelegate/proxyRenderDelegate.h b/lib/mayaUsd/render/vp2RenderDelegate/proxyRenderDelegate.h index 9783b82ec6..5737956f27 100644 --- a/lib/mayaUsd/render/vp2RenderDelegate/proxyRenderDelegate.h +++ b/lib/mayaUsd/render/vp2RenderDelegate/proxyRenderDelegate.h @@ -211,7 +211,7 @@ class ProxyRenderDelegate uint64_t GetFrameCounter() const { return _frameCounter; } MAYAUSD_CORE_PUBLIC - unsigned int GetDisplayStyle() const { return _currentDisplayStyle; } + bool NeedTexturedMaterials() const { return _needTexturedMaterials; } MAYAUSD_CORE_PUBLIC const HdSelection::PrimSelectionState* GetLeadSelectionState(const SdfPath& path) const; @@ -272,6 +272,8 @@ class ProxyRenderDelegate SdfPathVector _GetFilteredRprims(HdRprimCollection const& collection, TfTokenVector const& renderTags); + void ComputeCombinedDisplayStyles(const unsigned int newDisplayStyle); + /*! \brief Hold all data related to the proxy shape. In addition to holding data read from the proxy shape, ProxyShapeData tracks when data read @@ -331,7 +333,8 @@ class ProxyRenderDelegate //!< synchronization running without it) std::unique_ptr _sceneDelegate; //!< USD scene delegate const MHWRender::MFrameContext* _currentFrameContext = nullptr; - unsigned int _currentDisplayStyle = 0; + std::map _combinedDisplayStyles; + bool _needTexturedMaterials = false; bool _isPopulated { false diff --git a/lib/mayaUsd/render/vp2RenderDelegate/tokens.h b/lib/mayaUsd/render/vp2RenderDelegate/tokens.h index e5ad3a4247..d19b94f3c9 100644 --- a/lib/mayaUsd/render/vp2RenderDelegate/tokens.h +++ b/lib/mayaUsd/render/vp2RenderDelegate/tokens.h @@ -24,7 +24,8 @@ PXR_NAMESPACE_OPEN_SCOPE // clang-format off #define HDVP2_REPR_TOKENS \ (bbox) \ - (defaultMaterial) + (defaultMaterial) \ + (smoothHullUntextured) #define HDVP2_TOKENS \ (displayColorAndOpacity) \