Skip to content

Commit

Permalink
HnMesh: look up primvars by role if match by name is not found
Browse files Browse the repository at this point in the history
  • Loading branch information
TheMostDiligent committed Oct 22, 2024
1 parent ddb0c7c commit a333ad9
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 43 deletions.
6 changes: 4 additions & 2 deletions Hydrogent/interface/HnMesh.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,10 @@ class HnMesh final : public pxr::HdMesh
// The total number of supported primvars
Uint32 Count = 0;

// Dirty primvars
pxr::HdPrimvarDescriptorVector Dirty;
// Dirty primvars arranged by name.
// Typically, the name is the same as the primvar descriptor name,
// but it may be different if the primvar is found using the role.
std::unordered_map<pxr::TfToken, pxr::HdPrimvarDescriptor, pxr::TfToken::HashFunctor> Dirty;

// Computation primvars
pxr::HdExtComputationPrimvarDescriptorVector ExtComp;
Expand Down
5 changes: 3 additions & 2 deletions Hydrogent/interface/HnRenderPass.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,9 @@ class HnRenderPass final : public pxr::HdRenderPass
return m_Params.Name;
}

using SupportedVertexInputsSetType = std::unordered_set<pxr::TfToken, pxr::TfToken::HashFunctor>;
static SupportedVertexInputsSetType GetSupportedVertexInputs(const HnMaterial* Material);
// A mapping from the primvar name to its role (e.g. "points" -> "point", "normals" -> "normal", "st0" -> "textureCoordinate", etc.)
using SupportedVertexInputsMapType = std::unordered_map<pxr::TfToken, pxr::TfToken, pxr::TfToken::HashFunctor>;
static SupportedVertexInputsMapType GetSupportedVertexInputs(const HnMaterial* Material);
static PBR_Renderer::PSO_FLAGS GetMaterialPSOFlags(const HnMaterial& Material);

enum DRAW_LIST_ITEM_DIRTY_FLAGS : Uint32
Expand Down
46 changes: 23 additions & 23 deletions Hydrogent/src/HnMaterial.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ TF_DEFINE_PRIVATE_TOKENS(
(whiteRgba8)
(blackRgba8)
(whiteR8)
(st0)
);
// clang-format on

Expand Down Expand Up @@ -548,37 +549,36 @@ void HnMaterial::AllocateTextures(const HnMaterialNetwork& Network, HnTextureReg
m_Textures[TexDescriptor.Name] = std::move(pTex);

// Find texture coordinate
size_t TexCoordIdx = ~size_t{0};
if (const HnMaterialParameter* Param = Network.GetParameter(HnMaterialParameter::ParamType::Texture, TexDescriptor.Name))
{
if (!Param->SamplerCoords.empty())
const pxr::TfToken& TexCoordName = !Param->SamplerCoords.empty() ? Param->SamplerCoords[0] : HnMaterialPrivateTokens->st0;
if (Param->SamplerCoords.empty())
{
if (Param->SamplerCoords.size() > 1)
LOG_WARNING_MESSAGE("Texture '", TexDescriptor.Name, "' has ", Param->SamplerCoords.size(), " texture coordinates. Only the first set will be used");
const pxr::TfToken& TexCoordName = Param->SamplerCoords[0];

// Check if the texture coordinate set primvar (e.g. "st0") has already been allocated
auto it_inserted = TexCoordPrimvarMapping.emplace(TexCoordName, m_TexCoords.size());
TexCoordIdx = it_inserted.first->second;
if (it_inserted.second)
{
// Add new texture coordinate set
VERIFY_EXPR(TexCoordIdx == m_TexCoords.size());
m_TexCoords.resize(TexCoordIdx + 1);
m_TexCoords[TexCoordIdx] = {TexCoordName};
}

TexNameToCoordSetMap[TexDescriptor.Name] = TexCoordIdx;
LOG_WARNING_MESSAGE("Texture '", TexDescriptor.Name, "' in material '", GetId(), "' has no texture coordinates. Using ", TexCoordName, " as fallback.");
}
else
else if (Param->SamplerCoords.size() > 1)
{
LOG_ERROR_MESSAGE("Texture '", TexDescriptor.Name, "' in material '", GetId(), "' has no texture coordinates");
LOG_WARNING_MESSAGE("Texture '", TexDescriptor.Name, "' has ", Param->SamplerCoords.size(), " texture coordinates. Using the first one (", TexCoordName, ").");
}
}

if (TexCoordIdx == ~size_t{0})
// Check if the texture coordinate set primvar (e.g. "st0") has already been allocated
auto it_inserted = TexCoordPrimvarMapping.emplace(TexCoordName, m_TexCoords.size());
size_t TexCoordIdx = it_inserted.first->second;
if (it_inserted.second)
{
// Add new texture coordinate set
VERIFY_EXPR(TexCoordIdx == m_TexCoords.size());
m_TexCoords.resize(TexCoordIdx + 1);
m_TexCoords[TexCoordIdx] = {TexCoordName};
}

TexNameToCoordSetMap[TexDescriptor.Name] = TexCoordIdx;
}
else
{
LOG_ERROR_MESSAGE("Failed to find texture coordinates for texture '", TexDescriptor.Name, "' in material '", GetId(), "'");
UNEXPECTED("Texture parameter '", TexDescriptor.Name,
"' is not found in the material network. This looks like a bug since we obtained the texture descriptor from the network, "
"and all textures in the network should have a corresponding parameter.");
}
}
}
Expand Down
64 changes: 51 additions & 13 deletions Hydrogent/src/HnMesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
#include "pxr/imaging/hd/vtBufferSource.h"
#include "pxr/imaging/hd/vertexAdjacency.h"
#include "pxr/imaging/hd/smoothNormals.h"
#include "pxr/imaging/hd/primvarSchema.h"

namespace Diligent
{
Expand Down Expand Up @@ -570,19 +571,19 @@ bool HnMesh::AddStagingBufferSourceForPrimvar(StagingVertexData& StagingVerts,
return true;
}

static HnRenderPass::SupportedVertexInputsSetType GetSupportedPrimvars(
static HnRenderPass::SupportedVertexInputsMapType GetSupportedPrimvars(
const pxr::HdRenderIndex& RenderIndex,
const pxr::SdfPath& MaterialId,
const pxr::HdMeshTopology& Topology)
{
HnRenderPass::SupportedVertexInputsSetType SupportedPrimvars =
HnRenderPass::SupportedVertexInputsMapType SupportedPrimvars =
HnRenderPass::GetSupportedVertexInputs(static_cast<const HnMaterial*>(RenderIndex.GetSprim(pxr::HdPrimTypeTokens->material, MaterialId)));

{
const pxr::HdGeomSubsets GeomSubsets = Topology.GetGeomSubsets();
for (const pxr::HdGeomSubset& Subset : GeomSubsets)
{
HnRenderPass::SupportedVertexInputsSetType SubsetPrimvars =
HnRenderPass::SupportedVertexInputsMapType SubsetPrimvars =
HnRenderPass::GetSupportedVertexInputs(static_cast<const HnMaterial*>(RenderIndex.GetSprim(pxr::HdPrimTypeTokens->material, Subset.materialId)));
SupportedPrimvars.insert(SubsetPrimvars.begin(), SubsetPrimvars.end());
}
Expand Down Expand Up @@ -672,21 +673,52 @@ void HnMesh::GetPrimvarsInfo(pxr::HdSceneDelegate& SceneDelegate,
{
const pxr::SdfPath& Id = GetId();

const HnRenderPass::SupportedVertexInputsSetType SupportedPrimvars = GetSupportedPrimvars(SceneDelegate.GetRenderIndex(), GetMaterialId(), m_Topology);
const HnRenderPass::SupportedVertexInputsMapType SupportedPrimvars = GetSupportedPrimvars(SceneDelegate.GetRenderIndex(), GetMaterialId(), m_Topology);

HnRenderPass::SupportedVertexInputsMapType SupportedPrimvarsByRole;
for (const auto& it : SupportedPrimvars)
{
const pxr::TfToken& Role = it.second;
if (Role == pxr::HdPrimvarSchemaTokens->point ||
Role == pxr::HdPrimvarSchemaTokens->normal ||
Role == pxr::HdPrimvarSchemaTokens->textureCoordinate)
{
SupportedPrimvarsByRole[Role] = it.first;
}
}

auto UpdatePrimvarsInfo = [&](const pxr::HdInterpolation Interpolation,
PrimvarsInfo& PrimvarsInfo) {
pxr::HdPrimvarDescriptorVector PrimVarDescs = GetPrimvarDescriptors(&SceneDelegate, Interpolation);
for (const pxr::HdPrimvarDescriptor& PrimDesc : PrimVarDescs)
{
if (SupportedPrimvars.find(PrimDesc.name) == SupportedPrimvars.end())
continue;
pxr::TfToken Name = PrimDesc.name;
if (SupportedPrimvars.find(Name) == SupportedPrimvars.end())
{
const auto RoleIt = SupportedPrimvarsByRole.find(PrimDesc.role);
if (RoleIt != SupportedPrimvarsByRole.end())
{
LOG_WARNING_MESSAGE("Primvar '", Name, "' in mesh ", Id, " is not recognized by the material, but matches primvar '",
RoleIt->second, "' by role '", PrimDesc.role, "'.");
Name = RoleIt->second;
}
else
{
continue;
}
}

++PrimvarsInfo.Count;

if (pxr::HdChangeTracker::IsPrimvarDirty(DirtyBits, Id, PrimDesc.name))
if (pxr::HdChangeTracker::IsPrimvarDirty(DirtyBits, Id, Name))
{
PrimvarsInfo.Dirty.push_back(PrimDesc);
auto it_inserted = PrimvarsInfo.Dirty.emplace(Name, PrimDesc);
if (!it_inserted.second && Name == PrimDesc.name)
{
// We previously found a primvar with a different name but same role.
// Now we found a primvar with the same name, so we need to update the descriptor.
it_inserted.first->second = PrimDesc;
}
}
}
};
Expand Down Expand Up @@ -848,16 +880,19 @@ void HnMesh::UpdateVertexAndVaryingPrimvars(pxr::HdSceneDelegate& SceneDelegate,
const PrimvarsInfo& VertexPrimvarsInfo,
StagingVertexData& StagingVerts)
{
for (const pxr::HdPrimvarDescriptor& PrimDesc : VertexPrimvarsInfo.Dirty)
for (const auto& it : VertexPrimvarsInfo.Dirty)
{
const pxr::TfToken& Name = it.first;
const pxr::HdPrimvarDescriptor& PrimDesc = it.second;

pxr::VtValue PrimValue = GetPrimvar(&SceneDelegate, PrimDesc.name);
if (PrimValue.IsEmpty())
return;
continue;

if (PrimDesc.name == pxr::HdTokens->points)
StagingVerts.Points = PrimValue;

AddStagingBufferSourceForPrimvar(StagingVerts, PrimDesc.name, std::move(PrimValue), PrimDesc.interpolation);
AddStagingBufferSourceForPrimvar(StagingVerts, Name, std::move(PrimValue), PrimDesc.interpolation);
}

for (const pxr::HdExtComputationPrimvarDescriptor& ExtCompPrimDesc : VertexPrimvarsInfo.ExtComp)
Expand All @@ -877,10 +912,13 @@ void HnMesh::UpdateFaceVaryingPrimvars(pxr::HdSceneDelegate& SceneDelegate,
const PrimvarsInfo& FacePrimvarsInfo,
StagingVertexData& StagingVerts)
{
for (const pxr::HdPrimvarDescriptor& PrimDesc : FacePrimvarsInfo.Dirty)
for (const auto& it : FacePrimvarsInfo.Dirty)
{
const pxr::TfToken& Name = it.first;
const pxr::HdPrimvarDescriptor& PrimDesc = it.second;

pxr::VtValue PrimValue = GetPrimvar(&SceneDelegate, PrimDesc.name);
AddStagingBufferSourceForPrimvar(StagingVerts, PrimDesc.name, std::move(PrimValue), PrimDesc.interpolation);
AddStagingBufferSourceForPrimvar(StagingVerts, Name, std::move(PrimValue), PrimDesc.interpolation);
}
}

Expand Down
11 changes: 8 additions & 3 deletions Hydrogent/src/HnRenderPass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include <unordered_map>

#include "pxr/imaging/hd/renderIndex.h"
#include "pxr/imaging/hd/primvarSchema.h"

#include "USD_Renderer.hpp"
#include "GLTF_PBR_Renderer.hpp"
Expand Down Expand Up @@ -937,16 +938,20 @@ void HnRenderPass::UpdateDrawListGPUResources(RenderState& State)
m_DrawListItemsDirtyFlags = DRAW_LIST_ITEM_DIRTY_FLAG_NONE;
}

HnRenderPass::SupportedVertexInputsSetType HnRenderPass::GetSupportedVertexInputs(const HnMaterial* Material)
HnRenderPass::SupportedVertexInputsMapType HnRenderPass::GetSupportedVertexInputs(const HnMaterial* Material)
{
SupportedVertexInputsSetType SupportedInputs{{pxr::HdTokens->points, pxr::HdTokens->normals, pxr::HdTokens->displayColor}};
SupportedVertexInputsMapType SupportedInputs{
{pxr::HdTokens->points, pxr::HdPrimvarSchemaTokens->point},
{pxr::HdTokens->normals, pxr::HdPrimvarSchemaTokens->normal},
{pxr::HdTokens->displayColor, pxr::HdPrimvarSchemaTokens->color},
};
if (Material != nullptr)
{
const auto& TexCoordSets = Material->GetTextureCoordinateSets();
for (const auto& TexCoordSet : TexCoordSets)
{
if (!TexCoordSet.PrimVarName.IsEmpty())
SupportedInputs.emplace(TexCoordSet.PrimVarName);
SupportedInputs.emplace(TexCoordSet.PrimVarName, pxr::HdPrimvarSchemaTokens->textureCoordinate);
}
}

Expand Down

0 comments on commit a333ad9

Please sign in to comment.