Skip to content

Commit

Permalink
Hydrogent: use texture coordinate primvar name from material instead …
Browse files Browse the repository at this point in the history
…of the hardcoded st0
  • Loading branch information
TheMostDiligent committed Oct 2, 2023
1 parent 4b33030 commit d1606a3
Show file tree
Hide file tree
Showing 7 changed files with 114 additions and 62 deletions.
14 changes: 13 additions & 1 deletion Hydrogent/include/HnMaterial.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

#include <memory>
#include <unordered_map>
#include <vector>

#include "HnMaterialNetwork.hpp"
#include "HnTextureRegistry.hpp"
Expand Down Expand Up @@ -82,10 +83,19 @@ class HnMaterial final : public pxr::HdMaterial

const HLSL::PBRMaterialShaderInfo& GetShaderAttribs() const { return m_ShaderAttribs; }

/// Texture coordinate set info
struct TextureCoordinateSetInfo
{
/// Texture coordinate set primvar name (e.g. "st")
pxr::TfToken PrimVarName;
};
const auto& GetTextureCoordinateSets() const { return m_TexCoords; }

private:
HnMaterial(pxr::SdfPath const& id);

void AllocateTextures(HnTextureRegistry& TexRegistry);
using TexNameToCoordSetMapType = std::unordered_map<pxr::TfToken, size_t, pxr::TfToken::HashFunctor>;
void AllocateTextures(HnTextureRegistry& TexRegistry, TexNameToCoordSetMapType& TexNameToCoordSetMap);

private:
HnMaterialNetwork m_Network;
Expand All @@ -95,6 +105,8 @@ class HnMaterial final : public pxr::HdMaterial
RefCntAutoPtr<IShaderResourceBinding> m_SRB;

HLSL::PBRMaterialShaderInfo m_ShaderAttribs{};

std::vector<TextureCoordinateSetInfo> m_TexCoords;
};

} // namespace USD
Expand Down
14 changes: 4 additions & 10 deletions Hydrogent/include/HnMesh.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@

#include <memory>
#include <unordered_map>
#include <array>

// NoteL tbb.h must be included before mesh.h to avoid compilation errors in tbb headers.
#include "tbb/tbb.h"
Expand Down Expand Up @@ -74,15 +73,10 @@ class HnMesh final : public pxr::HdMesh

void CommitGPUResources(IRenderDevice* pDevice);

enum VERTEX_BUFFER_ID
{
VERTEX_BUFFER_ID_POSITION = 0,
VERTEX_BUFFER_ID_NORMAL,
VERTEX_BUFFER_ID_TEXCOORD,
VERTEX_BUFFER_ID_COUNT
};
/// Returns vertex buffer for the given primvar name (e.g. "points", "normals", etc.).
/// If the buffer doesn't exist, returns nullptr.
IBuffer* GetVertexBuffer(const pxr::TfToken& Name) const;

IBuffer* GetVertexBuffer(VERTEX_BUFFER_ID BufferId) const { return m_pVertexBuffers[BufferId]; }
IBuffer* GetTriangleIndexBuffer() const { return m_pTriangleIndexBuffer; }
IBuffer* GetEdgeIndexBuffer() const { return m_pEdgeIndexBuffer; }

Expand Down Expand Up @@ -153,7 +147,7 @@ class HnMesh final : public pxr::HdMesh
RefCntAutoPtr<IBuffer> m_pTriangleIndexBuffer;
RefCntAutoPtr<IBuffer> m_pEdgeIndexBuffer;

std::array<RefCntAutoPtr<IBuffer>, VERTEX_BUFFER_ID_COUNT> m_pVertexBuffers;
std::unordered_map<pxr::TfToken, RefCntAutoPtr<IBuffer>, pxr::TfToken::HashFunctor> m_VertexBuffers;
};

} // namespace USD
Expand Down
2 changes: 1 addition & 1 deletion Hydrogent/include/HnTokens.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ namespace USD
(roughness) \
(normal) \
(occlusion) \
(st0)
(emissive)

#define HN_MATERIAL_TAG_TOKENS \
(defaultTag) \
Expand Down
53 changes: 45 additions & 8 deletions Hydrogent/src/HnMaterial.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,9 @@ void HnMaterial::Sync(pxr::HdSceneDelegate* SceneDelegate,
}

HnTextureRegistry& TexRegistry = static_cast<HnRenderDelegate*>(SceneDelegate->GetRenderIndex().GetRenderDelegate())->GetTextureRegistry();
AllocateTextures(TexRegistry);

TexNameToCoordSetMapType TexNameToCoordSetMap;
AllocateTextures(TexRegistry, TexNameToCoordSetMap);

m_ShaderAttribs.BaseColorFactor = float4{1, 1, 1, 1};
m_ShaderAttribs.EmissiveFactor = float4{0, 0, 0, 0};
Expand Down Expand Up @@ -121,12 +123,14 @@ void HnMaterial::Sync(pxr::HdSceneDelegate* SceneDelegate,
m_ShaderAttribs.OcclusionFactor = Val.Get<float>();
});

m_ShaderAttribs.Workflow = PBR_Renderer::PBR_WORKFLOW_METALL_ROUGH;
m_ShaderAttribs.UVSelector0 = 0;
m_ShaderAttribs.UVSelector1 = 0;
m_ShaderAttribs.UVSelector2 = 0;
m_ShaderAttribs.UVSelector3 = 0;
m_ShaderAttribs.UVSelector4 = 0;
m_ShaderAttribs.Workflow = PBR_Renderer::PBR_WORKFLOW_METALL_ROUGH;
m_ShaderAttribs.UVSelector0 = static_cast<float>(TexNameToCoordSetMap[HnTokens->diffuseColor]);
m_ShaderAttribs.UVSelector1 = static_cast<float>(TexNameToCoordSetMap[HnTokens->metallic]);
if (TexNameToCoordSetMap[HnTokens->metallic] != TexNameToCoordSetMap[HnTokens->roughness])
LOG_ERROR_MESSAGE("Metallic and roughness textures must use the same texture coordinates");
m_ShaderAttribs.UVSelector2 = static_cast<float>(TexNameToCoordSetMap[HnTokens->normal]);
m_ShaderAttribs.UVSelector3 = static_cast<float>(TexNameToCoordSetMap[HnTokens->occlusion]);
m_ShaderAttribs.UVSelector4 = static_cast<float>(TexNameToCoordSetMap[HnTokens->emissive]);
m_ShaderAttribs.TextureSlice0 = 0;
m_ShaderAttribs.TextureSlice1 = 0;
m_ShaderAttribs.TextureSlice2 = 0;
Expand All @@ -148,13 +152,46 @@ void HnMaterial::Sync(pxr::HdSceneDelegate* SceneDelegate,
*DirtyBits = HdMaterial::Clean;
}

void HnMaterial::AllocateTextures(HnTextureRegistry& TexRegistry)
void HnMaterial::AllocateTextures(HnTextureRegistry& TexRegistry, TexNameToCoordSetMapType& TexNameToCoordSetMap)
{
std::unordered_map<pxr::TfToken, size_t, pxr::TfToken::HashFunctor> TexCoordMapping;
for (const HnMaterialNetwork::TextureDescriptor& TexDescriptor : m_Network.GetTextures())
{
if (auto pTex = TexRegistry.Allocate(TexDescriptor.TextureId, TexDescriptor.SamplerParams))
{
m_Textures[TexDescriptor.Name] = pTex;
// Find texture coordinate
size_t TexCoordIdx = ~size_t{0};
for (const HnMaterialParameter& Param : m_Network.GetParameters())
{
if (Param.Type == HnMaterialParameter::ParamType::Texture && Param.Name == TexDescriptor.Name)
{
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];

auto it_inserted = TexCoordMapping.emplace(TexCoordName, TexCoordMapping.size());
TexCoordIdx = it_inserted.first->second;
if (it_inserted.second)
{
m_TexCoords.resize(TexCoordIdx + 1);
m_TexCoords[TexCoordIdx] = {TexCoordName};
}
}
else
{
LOG_ERROR_MESSAGE("Texture '", TexDescriptor.Name, "' has no texture coordinates");
}
break;
}
}

if (TexCoordIdx == ~size_t{0})
{
LOG_ERROR_MESSAGE("Failed to find texture coordinates for texture '", TexDescriptor.Name, "'");
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion Hydrogent/src/HnMaterialNetwork.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1034,7 +1034,7 @@ void HnMaterialNetwork::AddTextureParam(const pxr::HdMaterialNetwork2& Network,
}
else if (SdrRole == pxr::SdrNodeRole->Math)
{
UNSUPPORTED("Transform2D is not currently supported");
LOG_ERROR_MESSAGE("Transform2D is not currently supported");
#if 0
HdSt_MaterialParamVector transform2dParams;

Expand Down
43 changes: 12 additions & 31 deletions Hydrogent/src/HnMesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -232,20 +232,6 @@ void HnMesh::UpdateVertexPrims(pxr::HdSceneDelegate& SceneDelegate,
m_BufferSources.emplace(PrimDesc.name, std::move(BufferSource));
}

// Create dummy texture coordinates if they are not present
if (m_BufferSources.find(HnTokens->st0) == m_BufferSources.end())
{
pxr::VtValue DummyUVs;
DummyUVs = pxr::VtArray<pxr::GfVec2f>{static_cast<size_t>(NumPoints), pxr::GfVec2f{0}};
auto BufferSource = std::make_shared<pxr::HdVtBufferSource>(
HnTokens->st0,
DummyUVs,
1, // values per element
false // whether doubles are supported or must be converted to floats
);
m_BufferSources.emplace(HnTokens->st0, std::move(BufferSource));
}

DirtyBits &= ~pxr::HdChangeTracker::DirtyPrimvar;
}

Expand All @@ -256,18 +242,7 @@ void HnMesh::UpdateVertexBuffers(const RenderDeviceX_N& Device)
for (auto source_it : m_BufferSources)
{
const auto& PrimName = source_it.first;

VERTEX_BUFFER_ID BufferId = VERTEX_BUFFER_ID_COUNT;
if (PrimName == pxr::HdTokens->points)
BufferId = VERTEX_BUFFER_ID_POSITION;
else if (PrimName == pxr::HdTokens->normals)
BufferId = VERTEX_BUFFER_ID_NORMAL;
else if (PrimName == HnTokens->st0)
BufferId = VERTEX_BUFFER_ID_TEXCOORD;
else
continue;

auto pSource = source_it.second.get();
const auto pSource = source_it.second.get();
if (pSource == nullptr)
return;

Expand All @@ -276,10 +251,10 @@ void HnMesh::UpdateVertexBuffers(const RenderDeviceX_N& Device)

const auto ElementType = pSource->GetTupleType().type;
const auto ElementSize = HdDataSizeOfType(ElementType);
VERIFY((BufferId == VERTEX_BUFFER_ID_POSITION && ElementSize == sizeof(float) * 3 ||
BufferId == VERTEX_BUFFER_ID_NORMAL && ElementSize == sizeof(float) * 3 ||
BufferId == VERTEX_BUFFER_ID_TEXCOORD && ElementSize == sizeof(float) * 2),
"Unexpected element size");
if (PrimName == pxr::HdTokens->points)
VERIFY(ElementSize == sizeof(float) * 3, "Unexpected vertex size");
else if (PrimName == pxr::HdTokens->normals)
VERIFY(ElementSize == sizeof(float) * 3, "Unexpected normal size");

const auto Name = GetId().GetString() + " - " + PrimName.GetString();
BufferDesc Desc{
Expand All @@ -290,7 +265,7 @@ void HnMesh::UpdateVertexBuffers(const RenderDeviceX_N& Device)
};

BufferData InitData{pSource->GetData(), Desc.Size};
m_pVertexBuffers[BufferId] = Device.CreateBuffer(Desc, &InitData);
m_VertexBuffers[PrimName] = Device.CreateBuffer(Desc, &InitData);
}

m_BufferSources.clear();
Expand Down Expand Up @@ -349,6 +324,12 @@ void HnMesh::CommitGPUResources(IRenderDevice* pDevice)
}
}

IBuffer* HnMesh::GetVertexBuffer(const pxr::TfToken& Name) const
{
auto it = m_VertexBuffers.find(Name);
return it != m_VertexBuffers.end() ? it->second.RawPtr() : nullptr;
}

} // namespace USD

} // namespace Diligent
48 changes: 38 additions & 10 deletions Hydrogent/src/HnRendererImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,14 +187,20 @@ class SyncTask final : public pxr::HdTask

void HnRendererImpl::Update()
{
m_ImagingDelegate->ApplyPendingUpdates();
pxr::HdTaskSharedPtrVector tasks = {
std::make_shared<SyncTask>(m_GeometryPass, m_RenderTags)};
m_Engine.Execute(&m_ImagingDelegate->GetRenderIndex(), &tasks);
if (m_ImagingDelegate)
{
m_ImagingDelegate->ApplyPendingUpdates();
pxr::HdTaskSharedPtrVector tasks = {
std::make_shared<SyncTask>(m_GeometryPass, m_RenderTags)};
m_Engine.Execute(&m_ImagingDelegate->GetRenderIndex(), &tasks);
}
}

void HnRendererImpl::Draw(IDeviceContext* pCtx, const HnDrawAttribs& Attribs)
{
if (!m_RenderDelegate)
return;

const auto& Meshes = m_RenderDelegate->GetMeshes();
if (Meshes.empty())
return;
Expand Down Expand Up @@ -249,22 +255,44 @@ void HnRendererImpl::Draw(IDeviceContext* pCtx, const HnDrawAttribs& Attribs)

void HnRendererImpl::RenderMesh(IDeviceContext* pCtx, const HnMesh& Mesh, const HnMaterial& Material, const HnDrawAttribs& Attribs)
{
auto* pSRB = Material.GetSRB();
auto* pVB0 = Mesh.GetVertexBuffer(HnMesh::VERTEX_BUFFER_ID_POSITION);
auto* pVB1 = Mesh.GetVertexBuffer(HnMesh::VERTEX_BUFFER_ID_NORMAL);
auto* pVB2 = Mesh.GetVertexBuffer(HnMesh::VERTEX_BUFFER_ID_TEXCOORD);
auto* pSRB = Material.GetSRB();
auto* pPosVB = Mesh.GetVertexBuffer(pxr::HdTokens->points);
auto* pNormalsVB = Mesh.GetVertexBuffer(pxr::HdTokens->normals);

const auto& TexCoordSets = Material.GetTextureCoordinateSets();
IBuffer* pTexCoordVBs[2] = {};
for (size_t i = 0; i < TexCoordSets.size(); ++i)
{
const auto& TexCoordSet = TexCoordSets[i];
if (!TexCoordSet.PrimVarName.IsEmpty())
{
pTexCoordVBs[i] = Mesh.GetVertexBuffer(TexCoordSet.PrimVarName);
if (!pTexCoordVBs[i])
{
LOG_ERROR_MESSAGE("Failed to find texture coordinates vertex buffer '", TexCoordSet.PrimVarName.GetText(), "' in mesh '", Mesh.GetId().GetText(), "'");
}
}
}

for (size_t i = 0; i < _countof(pTexCoordVBs); ++i)
{
// Temporary workaround - assign normals VB to texture coordinate VB if the latter is not available.
// Texture coordinates will not be used in the shader anyway, but we need to have valid VB bound.
if (pTexCoordVBs[i] == nullptr)
pTexCoordVBs[i] = pNormalsVB;
}

const auto& ShaderAttribs = Material.GetShaderAttribs();

auto* pIB = (Attribs.RenderMode == HN_RENDER_MODE_MESH_EDGES) ?
Mesh.GetEdgeIndexBuffer() :
Mesh.GetTriangleIndexBuffer();

if (pVB0 == nullptr || pVB1 == nullptr || pVB2 == nullptr || pIB == nullptr || pSRB == nullptr)
if (pPosVB == nullptr || pNormalsVB == nullptr || pTexCoordVBs[0] == nullptr || pTexCoordVBs[1] == nullptr || pIB == nullptr || pSRB == nullptr)
return;

// Bind vertex and index buffers
IBuffer* pBuffs[] = {pVB0, pVB1, pVB2, pVB2};
IBuffer* pBuffs[] = {pPosVB, pNormalsVB, pTexCoordVBs[0], pTexCoordVBs[1]};
pCtx->SetVertexBuffers(0, _countof(pBuffs), pBuffs, nullptr, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
pCtx->SetIndexBuffer(pIB, 0, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);

Expand Down

0 comments on commit d1606a3

Please sign in to comment.