Skip to content

Commit

Permalink
HnGeometryPool: a few updates/fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
TheMostDiligent committed Oct 5, 2024
1 parent d9a2cd6 commit 7a9b47a
Showing 1 changed file with 81 additions and 82 deletions.
163 changes: 81 additions & 82 deletions Hydrogent/src/HnGeometryPool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,14 @@ class GeometryPoolData
VERIFY(m_UseCount.load() == 0, "Use count is not 0");
}

int AddUse()
{
VERIFY(IsInitialized(), "Adding use for uninitialized data. This is a bug.");
return m_UseCount.fetch_add(1) + 1;
}
int RemoveUse()
{
VERIFY(IsInitialized(), "Removing use for uninitialized data. This is a bug.");
VERIFY(m_UseCount.load() > 0, "Use count is already 0");
return m_UseCount.fetch_add(-1) - 1;
}
Expand All @@ -77,6 +83,10 @@ class GeometryPoolData
}
int AddPendingUse()
{
VERIFY(!IsInitialized(), "Adding pending use for initialized data. This is a bug.");
VERIFY(m_UseCount.load() == 0,
"Adding pending use for data that is already in use. This should never happen as the data is only initialized once, which is when "
"all pending uses are committed. After data is initialized, it can never be in pending state again.");
return m_PendingUseCount.fetch_add(1) + 1;
}
int GetPendingUseCount() const
Expand All @@ -88,6 +98,8 @@ class GeometryPoolData
m_UseCount.fetch_add(m_PendingUseCount.exchange(0));
}

virtual bool IsInitialized() const = 0;

private:
std::atomic<int> m_UseCount{0};
std::atomic<int> m_PendingUseCount{0};
Expand Down Expand Up @@ -122,7 +134,7 @@ class HnGeometryPool::VertexData final : public GeometryPoolData
std::shared_ptr<VertexData> ExistingData) :
m_Name{std::move(Name)},
m_NumVertices{!Sources.empty() ? static_cast<Uint32>(Sources.begin()->second->GetNumElements()) : 0},
m_StagingData{std::make_unique<StagingData>(pResMgr)}
m_StagingData{std::make_unique<StagingData>(pResMgr, ExistingData)}
{
if (Sources.empty() || m_NumVertices == 0)
{
Expand Down Expand Up @@ -187,14 +199,12 @@ class HnGeometryPool::VertexData final : public GeometryPoolData
{
VERIFY_EXPR(ExistingStream.Buffer);
AddStream(SourceName, ExistingStream.ElementSize, nullptr, ExistingStream.Buffer);
if (!m_StagingData->ExistingData)
m_StagingData->ExistingData = ExistingData;
}
}
}

// If there is existing data, we will check if it is not used by other
// handles in the Update() method and hence its buffers can be reused.
// handles in the Initialize() method and hence its buffers can be reused.
if (!ExistingData || DisallowPoolAllocationReuse)
{
InitPoolAllocation();
Expand All @@ -217,12 +227,17 @@ class HnGeometryPool::VertexData final : public GeometryPoolData
return m_PoolAllocation ? m_PoolAllocation->GetStartVertex() : 0;
}

void Update(IRenderDevice* pDevice,
IDeviceContext* pContext)
virtual bool IsInitialized() const override final
{
return !m_StagingData;
}

void Initialize(IRenderDevice* pDevice,
IDeviceContext* pContext)
{
if (!m_StagingData)
{
UNEXPECTED("No staging data. This may indicate the Update() method is called more than once, which is a bug.");
UNEXPECTED("No staging data. This may indicate the Initialize() method is called more than once, which is a bug.");
return;
}

Expand All @@ -242,8 +257,9 @@ class HnGeometryPool::VertexData final : public GeometryPoolData
auto src_stream_it = ExistingData->m_Streams.find(StreamName);
if (src_stream_it != ExistingData->m_Streams.end())
{
VERIFY_EXPR(Stream.ElementSize == src_stream_it->second.ElementSize);
VERIFY_EXPR(src_stream_it->second.Buffer);
Stream.Buffer = std::move(src_stream_it->second.Buffer);
VERIFY_EXPR(Stream.Buffer);
}
else
{
Expand Down Expand Up @@ -441,6 +457,7 @@ class HnGeometryPool::VertexData final : public GeometryPoolData
struct StagingData
{
GLTF::ResourceManager* const pResMgr;
std::shared_ptr<VertexData> ExistingData;

struct SourceData
{
Expand All @@ -455,59 +472,38 @@ class HnGeometryPool::VertexData final : public GeometryPoolData

std::unordered_map<pxr::TfToken, SourceData, pxr::TfToken::HashFunctor> Sources;

std::shared_ptr<VertexData> ExistingData;

StagingData(GLTF::ResourceManager* _pResMgr) :
pResMgr{_pResMgr}
StagingData(GLTF::ResourceManager* _pResMgr, std::shared_ptr<VertexData> _ExistingData) :
pResMgr{_pResMgr},
ExistingData{std::move(_ExistingData)}
{}
};
std::unique_ptr<StagingData> m_StagingData;
};


// Vertex handle keeps a reference to the vertex data.
// Multiple handles can reference the same data.
class HnGeometryPool::VertexHandleImpl final : public HnGeometryPool::VertexHandle
template <typename T, typename Base>
class PoolDataHandle : public Base
{
public:
VertexHandleImpl(std::shared_ptr<VertexData> Data) :
m_Data{std::move(Data)}
PoolDataHandle(std::shared_ptr<T> Data)
{
if (m_Data)
{
m_Data->AddPendingUse();
}
SetData(std::move(Data));
}

~VertexHandleImpl()
~PoolDataHandle()
{
if (m_Data)
{
m_Data->RemoveUse();
}
}

virtual IBuffer* GetBuffer(const pxr::TfToken& Name) const override final
{
return m_Data ? m_Data->GetBuffer(Name) : nullptr;
}

virtual Uint32 GetNumVertices() const override final
{
return m_Data ? m_Data->GetNumVertices() : 0;
}

virtual Uint32 GetStartVertex() const override final
{
return m_Data ? m_Data->GetStartVertex() : 0;
}

std::shared_ptr<VertexData> GetData() const
std::shared_ptr<T> GetData() const
{
return m_Data;
}

void SetData(std::shared_ptr<VertexData> Data)
void SetData(std::shared_ptr<T> Data)
{
if (m_Data == Data)
return;
Expand All @@ -516,16 +512,46 @@ class HnGeometryPool::VertexHandleImpl final : public HnGeometryPool::VertexHand
{
m_Data->RemoveUse();
}

if (Data)
{
Data->AddPendingUse();
if (!Data->IsInitialized())
Data->AddPendingUse();
else
Data->AddUse();
}

m_Data = std::move(Data);
}

private:
std::shared_ptr<VertexData> m_Data;
protected:
std::shared_ptr<T> m_Data;
};

// Vertex handle keeps a reference to the vertex data.
// Multiple handles can reference the same data.
class HnGeometryPool::VertexHandleImpl final : public PoolDataHandle<VertexData, HnGeometryPool::VertexHandle>
{
public:
VertexHandleImpl(std::shared_ptr<VertexData> Data) :
PoolDataHandle<VertexData, HnGeometryPool::VertexHandle>{std::move(Data)}
{
}

virtual IBuffer* GetBuffer(const pxr::TfToken& Name) const override final
{
return m_Data ? m_Data->GetBuffer(Name) : nullptr;
}

virtual Uint32 GetNumVertices() const override final
{
return m_Data ? m_Data->GetNumVertices() : 0;
}

virtual Uint32 GetStartVertex() const override final
{
return m_Data ? m_Data->GetStartVertex() : 0;
}
};


Expand Down Expand Up @@ -553,7 +579,7 @@ class HnGeometryPool::IndexData final : public GeometryPoolData

m_NumIndices = static_cast<Uint32>(m_StagingData->Size / sizeof(Uint32));
// If there is existing data, we will check if it is not used by other
// handles in the Update() method and hence its buffer can be reused.
// handles in the Initialize() method and hence its buffer can be reused.
if (!ExistingData)
{
InitPoolAllocation();
Expand All @@ -575,12 +601,17 @@ class HnGeometryPool::IndexData final : public GeometryPoolData
return m_NumIndices;
}

void Update(IRenderDevice* pDevice,
IDeviceContext* pContext)
virtual bool IsInitialized() const override final
{
return !m_StagingData;
}

void Initialize(IRenderDevice* pDevice,
IDeviceContext* pContext)
{
if (!m_StagingData)
{
UNEXPECTED("No staging data. This may indicate the Update() method is called more than once, which is a bug.");
UNEXPECTED("No staging data. This may indicate the Initialize() method is called more than once, which is a bug.");
return;
}

Expand Down Expand Up @@ -750,24 +781,12 @@ class HnGeometryPool::IndexData final : public GeometryPoolData

// Index handle keeps a reference to the index data.
// Multiple handles can reference the same data.
class HnGeometryPool::IndexHandleImpl final : public HnGeometryPool::IndexHandle
class HnGeometryPool::IndexHandleImpl final : public PoolDataHandle<IndexData, HnGeometryPool::IndexHandle>
{
public:
IndexHandleImpl(std::shared_ptr<IndexData> Data) :
m_Data{std::move(Data)}
PoolDataHandle<IndexData, HnGeometryPool::IndexHandle>{std::move(Data)}
{
if (m_Data)
{
m_Data->AddPendingUse();
}
}

~IndexHandleImpl()
{
if (m_Data)
{
m_Data->RemoveUse();
}
}

virtual IBuffer* GetBuffer() const override final
Expand All @@ -789,26 +808,6 @@ class HnGeometryPool::IndexHandleImpl final : public HnGeometryPool::IndexHandle
{
return m_Data;
}

void SetData(std::shared_ptr<IndexData> Data)
{
if (m_Data == Data)
return;

if (m_Data)
{
m_Data->RemoveUse();
}
if (Data)
{
Data->AddPendingUse();
}

m_Data = std::move(Data);
}

private:
std::shared_ptr<IndexData> m_Data;
};


Expand Down Expand Up @@ -920,7 +919,7 @@ void HnGeometryPool::Commit(IDeviceContext* pContext)
std::lock_guard<std::mutex> Guard{m_PendingVertexDataMtx};
for (auto& Data : m_PendingVertexData)
{
Data->Update(m_pDevice, pContext);
Data->Initialize(m_pDevice, pContext);
}
m_PendingVertexData.clear();
}
Expand All @@ -929,7 +928,7 @@ void HnGeometryPool::Commit(IDeviceContext* pContext)
std::lock_guard<std::mutex> Guard{m_PendingIndexDataMtx};
for (auto& Data : m_PendingIndexData)
{
Data->Update(m_pDevice, pContext);
Data->Initialize(m_pDevice, pContext);
}
m_PendingIndexData.clear();
}
Expand Down

0 comments on commit 7a9b47a

Please sign in to comment.