Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 16 additions & 8 deletions pxr/imaging/hd/sceneIndexAdapterSceneDelegate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1308,29 +1308,37 @@ _ToMaterialNetworkMap(
}

VtValue
HdSceneIndexAdapterSceneDelegate::GetMaterialResource(SdfPath const & id)
HdSceneIndexAdapterSceneDelegate::GetMaterialResourceFromSceneIndexPrim(
HdSceneIndexPrim& prim, const TfTokenVector& renderContexts)
{
TRACE_FUNCTION();
HF_MALLOC_TAG_FUNCTION();
HdSceneIndexPrim prim = _GetInputPrim(id);

HdMaterialSchema matSchema = HdMaterialSchema::GetFromParent(
prim.dataSource);
if (!matSchema.IsDefined()) {
return VtValue();
}

// Query for a material network to match the requested render contexts
const TfTokenVector renderContexts =
GetRenderIndex().GetRenderDelegate()->GetMaterialRenderContexts();
HdMaterialNetworkSchema netSchema = matSchema.GetMaterialNetwork(renderContexts);
HdMaterialNetworkSchema netSchema =
matSchema.GetMaterialNetwork(renderContexts);
if (!netSchema.IsDefined()) {
return VtValue();
}

return VtValue(_ToMaterialNetworkMap(netSchema, renderContexts));
}
Comment on lines 1325 to 1344
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extracted this static function for code reuse between the old synchronous code path and the new scene index which gets scene index prims without any conversions.


VtValue
HdSceneIndexAdapterSceneDelegate::GetMaterialResource(SdfPath const & id)
{
TRACE_FUNCTION();
HF_MALLOC_TAG_FUNCTION();

HdSceneIndexPrim prim = _GetInputPrim(id);
return GetMaterialResourceFromSceneIndexPrim(
prim,
GetRenderIndex().GetRenderDelegate()->GetMaterialRenderContexts());
}

static
TfTokenVector
_ToTokenVector(const std::vector<std::string> &strings)
Expand Down
3 changes: 3 additions & 0 deletions pxr/imaging/hd/sceneIndexAdapterSceneDelegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,9 @@ class HdSceneIndexAdapterSceneDelegate
// ------------------------------------------------------------------------
// Material API

static HD_API VtValue GetMaterialResourceFromSceneIndexPrim(
HdSceneIndexPrim& prim, const TfTokenVector& renderContexts);

SdfPath GetMaterialId(SdfPath const &id) override;
VtValue GetMaterialResource(SdfPath const &id) override;
HdIdVectorSharedPtr GetCoordSysBindings(SdfPath const &id) override;
Expand Down
1 change: 1 addition & 0 deletions pxr/imaging/hdSt/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ if (${PXR_ENABLE_MATERIALX_SUPPORT})
list(APPEND optionalPrivateClasses
materialXFilter
materialXShaderGen
materialXSyncSceneIndex
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new scene index implementation, which replaces materialXSyncDispatcher in the original PR.

)
endif()
if (PXR_ENABLE_PTEX_SUPPORT)
Expand Down
39 changes: 29 additions & 10 deletions pxr/imaging/hdSt/material.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@
#include "pxr/imaging/hdSt/tokens.h"
#include "pxr/imaging/hdSt/materialParam.h"

#ifdef PXR_MATERIALX_SUPPORT_ENABLED
#include "pxr/imaging/hdSt/materialXSyncSceneIndex.h"
#include "pxr/imaging/hdSt/renderDelegate.h"
#endif

#include "pxr/imaging/hd/changeTracker.h"
#include "pxr/imaging/hd/tokens.h"

Expand Down Expand Up @@ -172,8 +177,8 @@ HdStMaterial::_ProcessTextureDescriptors(
/* virtual */
void
HdStMaterial::Sync(HdSceneDelegate *sceneDelegate,
HdRenderParam *renderParam,
HdDirtyBits *dirtyBits)
HdRenderParam *renderParam,
HdDirtyBits *dirtyBits)
{
HD_TRACE_FUNCTION();
HF_MALLOC_TAG_FUNCTION();
Expand All @@ -191,6 +196,19 @@ HdStMaterial::Sync(HdSceneDelegate *sceneDelegate,

bool markBatchesDirty = false;

#ifdef PXR_MATERIALX_SUPPORT_ENABLED
{
HdStRenderDelegate* stormDelegate = static_cast<HdStRenderDelegate*>(
sceneDelegate->GetRenderIndex().GetRenderDelegate());

if (HdSt_MaterialXSyncSceneIndex* sceneIndex =
stormDelegate->GetMaterialXSyncSceneIndex()) {

sceneIndex->Wait();
}
}
#endif
Comment on lines 199 to 228

This comment was marked as outdated.


std::string fragmentSource;
std::string displacementSource;
std::string volumeSource;
Expand All @@ -201,18 +219,19 @@ HdStMaterial::Sync(HdSceneDelegate *sceneDelegate,

VtValue vtMat = sceneDelegate->GetMaterialResource(GetId());
if (vtMat.IsHolding<HdMaterialNetworkMap>()) {

HdMaterialNetworkMap const& hdNetworkMap =
vtMat.UncheckedGet<HdMaterialNetworkMap>();
if (!hdNetworkMap.terminals.empty() && !hdNetworkMap.map.empty()) {
_networkProcessor.ProcessMaterialNetwork(GetId(), hdNetworkMap,
_hdStMaterialNetwork.ProcessMaterialNetwork(GetId(), hdNetworkMap,
resourceRegistry.get());
fragmentSource = _networkProcessor.GetFragmentCode();
volumeSource = _networkProcessor.GetVolumeCode();
displacementSource = _networkProcessor.GetDisplacementCode();
materialMetadata = _networkProcessor.GetMetadata();
materialTag = _networkProcessor.GetMaterialTag();
params = _networkProcessor.GetMaterialParams();
textureDescriptors = _networkProcessor.GetTextureDescriptors();
fragmentSource = _hdStMaterialNetwork.GetFragmentCode();
volumeSource = _hdStMaterialNetwork.GetVolumeCode();
displacementSource = _hdStMaterialNetwork.GetDisplacementCode();
materialMetadata = _hdStMaterialNetwork.GetMetadata();
materialTag = _hdStMaterialNetwork.GetMaterialTag();
params = _hdStMaterialNetwork.GetMaterialParams();
textureDescriptors = _hdStMaterialNetwork.GetTextureDescriptors();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I propose to rename _networkProcessor to _hdStMaterialNetwork. IMHO "Processor" sounds confusing here because the object _hdStMaterialNetwork is simply initialized with those Process methods from hdNetworkMap, it doesn't process some external objects.

}
}

Expand Down
4 changes: 3 additions & 1 deletion pxr/imaging/hdSt/material.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@
#define PXR_IMAGING_HD_ST_MATERIAL_H

#include "pxr/pxr.h"

#include "pxr/imaging/hdSt/api.h"
#include "pxr/imaging/hdSt/materialNetwork.h"
#include "pxr/imaging/hdSt/shaderCode.h"

#include "pxr/imaging/hd/material.h"
#include "pxr/imaging/hf/perfLog.h"

Expand Down Expand Up @@ -123,7 +125,7 @@ class HdStMaterial final: public HdMaterial
TfToken _materialTag;
size_t _textureHash;

HdStMaterialNetwork _networkProcessor;
HdStMaterialNetwork _hdStMaterialNetwork;
};

inline bool HdStMaterial::HasPtex() const
Expand Down
112 changes: 70 additions & 42 deletions pxr/imaging/hdSt/materialNetwork.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,8 @@ _GetGlslfxForTerminal(
}
}

static HdMaterialNode2 const*
_GetTerminalNode(
HdMaterialNode2 const*
HdSt_GetTerminalNode(
Comment on lines +162 to +163
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now need to call it from outside this source file.

HdMaterialNetwork2 const& network,
TfToken const& terminalName,
SdfPath * terminalNodePath)
Expand Down Expand Up @@ -1100,57 +1100,85 @@ HdStMaterialNetwork::ProcessMaterialNetwork(
{
HD_TRACE_FUNCTION();

_fragmentSource.clear();
_displacementSource.clear();
_materialMetadata.clear();
_materialParams.clear();
_textureDescriptors.clear();
_materialTag = HdStMaterialTagTokens->defaultMaterialTag;
bool isVolume = false;

auto filterTask = std::make_shared<HdSt_MaterialFilterTask>();
filterTask->hdNetwork =
HdConvertToHdMaterialNetwork2(hdNetworkMap, &isVolume);
Comment on lines +1105 to +1107
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The state necessary for the codegen process is now encapsulated in the HdSt_MaterialFilterTask class, because it needs to be created earlier than the material sprim and to persist until the parallel codegen task is finished.

HdStMaterialNetwork::ProcessMaterialNetwork is called in the old, synchronous code path, but we create a HdSt_MaterialFilterTask here in order to share code between the two code paths.


// The fragment source comes from the 'surface' network or the
// 'volume' network.
bool isVolume = false;
HdMaterialNetwork2 surfaceNetwork =
HdConvertToHdMaterialNetwork2(hdNetworkMap, &isVolume);
const TfToken &terminalName = (isVolume) ? HdMaterialTerminalTokens->volume
: HdMaterialTerminalTokens->surface;

SdfPath surfTerminalPath;
if (HdMaterialNode2 const* surfTerminal =
_GetTerminalNode(surfaceNetwork, terminalName, &surfTerminalPath)) {
filterTask->terminalNode =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here & material.*, instead of bringing the "filterTask" API into a bunch of files in Storm, you could modularize things better by either:
(1) having the scene index produce a "glsl" material network that can be read by the non-materialx code; or
(2) having the scene index produce a digested material network as code snippets for each stage & params, and pass them through as datasources. If material.cpp finds that, it uses it, and otherwise it falls back to network processing.

This splits the code up a little better, which is nice since the MaterialX code is an external dependency with an evolving API and hidden behind a build flag, so having a big API interface between the two makes me a bit worried.

HdSt_GetTerminalNode(
filterTask->hdNetwork,
terminalName,
&filterTask->terminalNodePath);

if (!filterTask->terminalNode) {
return;
}

ProcessFilterTask(materialId, filterTask, isVolume, resourceRegistry);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ProcessMaterialNetwork is now implemented via ProcessFilterTask for code reuse.

}

void
HdStMaterialNetwork::ProcessFilterTask(
SdfPath const& materialId,
HdSt_MaterialFilterTaskSharedPtr filterTask,
bool isVolume,
HdStResourceRegistry *resourceRegistry)
{
HD_TRACE_FUNCTION();

_fragmentSource.clear();
_displacementSource.clear();
_materialMetadata.clear();
_materialParams.clear();
_textureDescriptors.clear();

_materialTag = HdStMaterialTagTokens->defaultMaterialTag;

if (!filterTask || !filterTask->terminalNode) {
return;
}

#ifdef PXR_MATERIALX_SUPPORT_ENABLED
if (!isVolume) {
_materialXGfx = HdSt_ApplyMaterialXFilter(&surfaceNetwork, materialId,
*surfTerminal, surfTerminalPath,
&_materialParams, resourceRegistry);
}
if (!isVolume) {
_materialXGfx = HdSt_ApplyMaterialXFilter(filterTask, materialId,
&_materialParams, resourceRegistry);
}
#endif
// Extract the glslfx and metadata for surface/volume.
_GetGlslfxForTerminal(_surfaceGfx, &_surfaceGfxHash,
surfTerminal->nodeTypeId, resourceRegistry);
if (_surfaceGfx) {

// If the glslfx file is not valid we skip parsing the network.
// This produces no fragmentSource which means Storm's material
// will use the fallback shader.
if (_surfaceGfx->IsValid()) {

_fragmentSource = _surfaceGfx->GetSurfaceSource();
_volumeSource = _surfaceGfx->GetVolumeSource();

_materialMetadata = _surfaceGfx->GetMetadata();
_materialTag = _GetMaterialTag(_materialMetadata, *surfTerminal);
_GatherMaterialParams(surfaceNetwork, *surfTerminal,
&_materialParams, &_textureDescriptors,
_materialTag);

// OSL networks have a displacement network in hdNetworkMap
// under terminal: HdMaterialTerminalTokens->displacement.
// For Storm however we expect the displacement shader to be
// provided via the surface glslfx / terminal.
_displacementSource = _surfaceGfx->GetDisplacementSource();
}
// Extract the glslfx and metadata for surface/volume.
_GetGlslfxForTerminal(_surfaceGfx, &_surfaceGfxHash,
filterTask->terminalNode->nodeTypeId, resourceRegistry);
if (_surfaceGfx) {

// If the glslfx file is not valid we skip parsing the network.
// This produces no fragmentSource which means Storm's material
// will use the fallback shader.
if (_surfaceGfx->IsValid()) {
_fragmentSource = _surfaceGfx->GetSurfaceSource();
_volumeSource = _surfaceGfx->GetVolumeSource();

_materialMetadata = _surfaceGfx->GetMetadata();

_materialTag = _GetMaterialTag(
_surfaceGfx->GetMetadata(), *filterTask->terminalNode);
_GatherMaterialParams(
filterTask->hdNetwork, *filterTask->terminalNode,
&_materialParams, &_textureDescriptors,
_materialTag);

// OSL networks have a displacement network in hdNetworkMap
// under terminal: HdMaterialTerminalTokens->displacement.
// For Storm however we expect the displacement shader to be
// provided via the surface glslfx / terminal.
_displacementSource = _surfaceGfx->GetDisplacementSource();
}
}
}
Expand Down
58 changes: 57 additions & 1 deletion pxr/imaging/hdSt/materialNetwork.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,57 @@

PXR_NAMESPACE_OPEN_SCOPE

class SdrRegistry;
class HdStResourceRegistry;
using HioGlslfxSharedPtr = std::shared_ptr<class HioGlslfx>;
using HdSt_MaterialParamVector = std::vector<class HdSt_MaterialParam>;
struct HdSt_MaterialFilterTask;
using HdSt_MaterialFilterTaskSharedPtr =
std::shared_ptr<HdSt_MaterialFilterTask>;

extern HdMaterialNode2 const*
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't think this needs an extern, but if you want it to be publicly visible (which maybe we don't care?) you could throw an HDST_API on it...

HdSt_GetTerminalNode(
HdMaterialNetwork2 const& network,
TfToken const& terminalName,
SdfPath * terminalNodePath);

/// Encapsulates the input data for MaterialX codegen as well as metadata
/// necessary for completing `HdStMaterial::Sync` based on the result of the
/// codegen.
/// This object can either live on the stack, if MaterialX codegen happens
/// synchronously, or on the heap, owned by the respective Sprim, if the
/// codegen happens in parallel tasks.
///
struct ARCH_EXPORT_TYPE HdSt_MaterialFilterTask final
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels like an implementation detail of the MaterialX code, and I don't think this belongs in hdSt/materialNetwork.h. Also curious why we need ARCH_EXPORT_TYPE here.

{
HdMaterialNetwork2 hdNetwork;
HdMaterialNode2 const* terminalNode = nullptr; // pointer to a node
// in the above network
SdfPath terminalNodePath; // path to the above node

#ifdef PXR_MATERIALX_SUPPORT_ENABLED
// Stores the mappings between the node paths in the original
// HdMaterialNetwork to the corresponding anonymized node paths
using OrigToAnonSdfPathMap =
std::unordered_map<SdfPath, SdfPath, SdfPath::Hash>;
OrigToAnonSdfPathMap origToAnonSdfPathMap;

/// Build the `anonNetwork`, equivalent to the given hdNetwork but anonymized
/// and stripped of non-topological parameters to better re-use the generated
/// shader.
/// Returns the hash of the anonymized network.
size_t BuildAnonymizedMaterialNetwork(
HdMaterialNetwork2* anonNetwork);

void AddFallbackDomeLightTextureNode();

void AddMaterialXParams(
MaterialX::Shader const& mxShader,
HdSt_MaterialParamVector* materialParams);

bool IsMaterialX(SdrRegistry* sdrRegistry) const;
#endif
};

/// \class HdStMaterialNetwork
///
Expand All @@ -37,6 +85,14 @@ class HdStMaterialNetwork final
HDST_API
~HdStMaterialNetwork();

/// Process the necessary network information cached in the filter task.
HDST_API
void ProcessFilterTask(
SdfPath const& materialId,
HdSt_MaterialFilterTaskSharedPtr filterTask,
bool isVolume,
HdStResourceRegistry *resourceRegistry);

/// Process a material network topology and extract all the information we
/// need from it.
HDST_API
Expand Down Expand Up @@ -67,7 +123,7 @@ class HdStMaterialNetwork final
struct TextureDescriptor
{
// Name by which the texture will be accessed, i.e., the name
// of the accesor for thexture will be HdGet_name(...).
// of the accessor for the texture will be HdGet_name(...).
// It is generated from the input name the corresponding texture
// node is connected to.
TfToken name;
Expand Down
Loading