Skip to content

Commit

Permalink
Traktor: HiZ GPU culling implemented of instance meshes.
Browse files Browse the repository at this point in the history
  • Loading branch information
apistol78 committed Feb 21, 2024
1 parent 0af30e6 commit 46aa8d4
Show file tree
Hide file tree
Showing 20 changed files with 520 additions and 181 deletions.
41 changes: 27 additions & 14 deletions code/Mesh/Instance/InstanceMesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "Render/Context/RenderContext.h"
#include "Render/Mesh/Mesh.h"
#include "World/IWorldRenderPass.h"
#include "World/WorldHandles.h"
#include "World/WorldRenderView.h"

namespace traktor::mesh
Expand All @@ -29,8 +30,6 @@ render::Handle s_handleInstanceWorld(L"InstanceWorld");
render::Handle s_handleInstanceWorldLast(L"InstanceWorldLast");
render::Handle s_handleBoundingBoxMin(L"InstanceMesh_BoundingBoxMin");
render::Handle s_handleBoundingBoxMax(L"InstanceMesh_BoundingBoxMax");
render::Handle s_handleView(L"InstanceMesh_View");
render::Handle s_handleViewInverse(L"InstanceMesh_ViewInverse");
render::Handle s_handleVisibility(L"InstanceMesh_Visibility");
render::Handle s_handleCullFrustum(L"InstanceMesh_CullFrustum");
render::Handle s_handleDraw(L"InstanceMesh_Draw");
Expand Down Expand Up @@ -87,7 +86,7 @@ void InstanceMesh::build(
const AlignedVector< Part >& parts = it->second;
const auto& meshParts = m_renderMesh->getParts();

const uint32_t bufferItemCount = alignUp(m_instances.size(), 16);
const uint32_t bufferItemCount = (uint32_t)alignUp(m_instances.size(), 16);

// Lazy create the buffers.
if (!m_instanceBuffer || bufferItemCount > m_instanceAllocatedCount)
Expand All @@ -100,11 +99,11 @@ void InstanceMesh::build(
}

const uint32_t peakCascade = worldRenderView.getCascade();
const uint32_t vbSize = m_visibilityBuffers.size();
const uint32_t vbSize = (uint32_t)m_visibilityBuffers.size();
for (uint32_t i = vbSize; i < peakCascade + 1; ++i)
m_visibilityBuffers.push_back(m_renderSystem->createBuffer(render::BufferUsage::BuStructured, bufferItemCount * sizeof(float), false));

const uint32_t dbSize = m_drawBuffers.size();
const uint32_t dbSize = (uint32_t)m_drawBuffers.size();
for (uint32_t i = dbSize; i < (peakCascade + 1) * parts.size(); ++i)
m_drawBuffers.push_back(m_renderSystem->createBuffer(render::BufferUsage::BuStructured | render::BufferUsage::BuIndirect, bufferItemCount * sizeof(render::IndexedIndirectDraw), false));

Expand All @@ -128,29 +127,42 @@ void InstanceMesh::build(

const Frustum& cf = worldRenderView.getCullFrustum();
T_FATAL_ASSERT(cf.planes.size() <= sizeof_array(cullFrustum));
for (int32_t i = 0; i < cf.planes.size(); ++i)
for (int32_t i = 0; i < (int32_t)cf.planes.size(); ++i)
cullFrustum[i] = cf.planes[i].normal().xyz0() + Vector4(0.0f, 0.0f, 0.0f, cf.planes[i].distance());
for (int32_t i = cf.planes.size(); i < sizeof_array(cullFrustum); ++i)
for (int32_t i = (int32_t)cf.planes.size(); i < sizeof_array(cullFrustum); ++i)
cullFrustum[i] = Vector4::zero();

auto renderBlock = renderContext->allocNamed< render::ComputeRenderBlock >(
str(L"InstanceMesh cull %d", worldRenderView.getCascade())
);

renderBlock->program = m_shaderCull->getProgram().program;
render::Shader::Permutation perm;
if (worldRenderPass.getTechnique() == world::s_techniqueDeferredGBufferWrite)
{
// Deferred g-buffer pass has access to HiZ texture.
m_shaderCull->setCombination(render::getParameterHandle(L"InstanceMesh_HiZ"), true, perm);
}
else
{
// All other paths use simple frustum culling only.
m_shaderCull->setCombination(render::getParameterHandle(L"InstanceMesh_HiZ"), false, perm);
}

renderBlock->program = m_shaderCull->getProgram(perm).program;

renderBlock->programParams = renderContext->alloc< render::ProgramParameters >();
renderBlock->programParams->beginParameters(renderContext);

worldRenderPass.setProgramParameters(renderBlock->programParams);

renderBlock->programParams->setVectorParameter(s_handleBoundingBoxMin, m_renderMesh->getBoundingBox().mn);
renderBlock->programParams->setVectorParameter(s_handleBoundingBoxMax, m_renderMesh->getBoundingBox().mx);
renderBlock->programParams->setVectorArrayParameter(s_handleCullFrustum, cullFrustum, sizeof_array(cullFrustum));
renderBlock->programParams->setMatrixParameter(s_handleView, worldRenderView.getView());
renderBlock->programParams->setMatrixParameter(s_handleViewInverse, worldRenderView.getView().inverse());
renderBlock->programParams->setBufferViewParameter(s_handleInstanceWorld, m_instanceBuffer->getBufferView());
renderBlock->programParams->setBufferViewParameter(s_handleVisibility, visibilityBuffer->getBufferView());
renderBlock->programParams->endParameters(renderContext);

renderBlock->workSize[0] = m_instances.size();
renderBlock->workSize[0] = (int32_t)m_instances.size();

renderContext->compute(renderBlock);
renderContext->compute< render::BarrierRenderBlock >(render::Stage::Compute, render::Stage::Compute);
Expand Down Expand Up @@ -185,7 +197,7 @@ void InstanceMesh::build(
renderBlock->programParams->setBufferViewParameter(s_handleDraw, drawBuffer->getBufferView());
renderBlock->programParams->endParameters(renderContext);

renderBlock->workSize[0] = m_instances.size();
renderBlock->workSize[0] = (int32_t)m_instances.size();

renderContext->compute(renderBlock);
}
Expand Down Expand Up @@ -217,7 +229,7 @@ void InstanceMesh::build(
renderBlock->vertexLayout = m_renderMesh->getVertexLayout();
renderBlock->primitive = meshParts[part.meshPart].primitives.type;
renderBlock->drawBuffer = drawBuffer->getBufferView();
renderBlock->drawCount = m_instances.size();
renderBlock->drawCount = (uint32_t)m_instances.size();

renderBlock->programParams->beginParameters(renderContext);

Expand Down Expand Up @@ -248,12 +260,13 @@ InstanceMesh::Instance* InstanceMesh::allocateInstance()
return instance;
}

void InstanceMesh::releaseInstance(Instance* instance)
void InstanceMesh::releaseInstance(Instance*& instance)
{
T_FATAL_ASSERT(instance->mesh == this);
auto it = std::find(m_instances.begin(), m_instances.end(), instance);
m_instances.erase(it);
delete instance;
instance = nullptr;
}

void InstanceMesh::Instance::setTransform(const Transform& transform)
Expand Down
2 changes: 1 addition & 1 deletion code/Mesh/Instance/InstanceMesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ class T_DLLCLASS InstanceMesh : public IMesh

Instance* allocateInstance();

void releaseInstance(Instance* instance);
void releaseInstance(Instance*& instance);

//

Expand Down
11 changes: 9 additions & 2 deletions code/Mesh/Instance/InstanceMeshComponent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,24 @@ InstanceMeshComponent::InstanceMeshComponent(const resource::Proxy< InstanceMesh
m_meshInstance = m_mesh->allocateInstance();
}

InstanceMeshComponent::~InstanceMeshComponent()
{
// Need to call destroy here since editor doesn't always call destroy on components
// but instead rely on reference counting to do the cleanup.
destroy();
}

void InstanceMeshComponent::destroy()
{
m_mesh->releaseInstance(m_meshInstance);
if (m_mesh && m_meshInstance != nullptr)
m_mesh->releaseInstance(m_meshInstance);
m_mesh.clear();
MeshComponent::destroy();
}

void InstanceMeshComponent::setTransform(const Transform& transform)
{
MeshComponent::setTransform(transform);

m_meshInstance->setTransform(transform);
}

Expand Down
2 changes: 2 additions & 0 deletions code/Mesh/Instance/InstanceMeshComponent.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ class T_DLLCLASS InstanceMeshComponent : public MeshComponent
public:
explicit InstanceMeshComponent(const resource::Proxy< InstanceMesh >& mesh);

virtual ~InstanceMeshComponent();

virtual void destroy() override final;

virtual void setTransform(const Transform& transform) override;
Expand Down
19 changes: 14 additions & 5 deletions code/Render/Frame/RenderGraph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,18 @@ handle_t RenderGraph::addTransientTexture(const wchar_t* const name, const Rende
return resourceId;
}

handle_t RenderGraph::addPersistentTexture(const wchar_t* const name, handle_t persistentHandle, const RenderGraphTextureDesc& textureDesc)
{
const handle_t resourceId = m_nextResourceId++;

auto& tr = m_textures[resourceId];
tr.name = name;
tr.persistentHandle = persistentHandle;
tr.textureDesc = textureDesc;

return resourceId;
}

IRenderTargetSet* RenderGraph::getTargetSet(handle_t resource) const
{
auto it = m_targets.find(resource);
Expand Down Expand Up @@ -355,10 +367,7 @@ bool RenderGraph::build(RenderContext* renderContext, int32_t width, int32_t hei
auto& sbuffer = it.second;
if (sbuffer.buffer == nullptr)
{
sbuffer.buffer = m_bufferPool->acquire(
sbuffer.bufferSize,
sbuffer.persistentHandle
);
sbuffer.buffer = m_bufferPool->acquire(sbuffer.bufferSize, sbuffer.persistentHandle);
if (!sbuffer.buffer)
return false;
}
Expand All @@ -369,7 +378,7 @@ bool RenderGraph::build(RenderContext* renderContext, int32_t width, int32_t hei
auto& texture = it.second;
if (texture.texture == nullptr)
{
texture.texture = m_texturePool->acquire(texture.textureDesc);
texture.texture = m_texturePool->acquire(texture.textureDesc, texture.persistentHandle);
if (!texture.texture)
return false;
}
Expand Down
5 changes: 5 additions & 0 deletions code/Render/Frame/RenderGraph.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ class T_DLLCLASS RenderGraph : public Object
struct TextureResource
{
const wchar_t* name = nullptr;
handle_t persistentHandle = 0;
RenderGraphTextureDesc textureDesc;
Ref< ITexture > texture;
};
Expand Down Expand Up @@ -192,6 +193,10 @@ class T_DLLCLASS RenderGraph : public Object
*/
handle_t addTransientTexture(const wchar_t* const name, const RenderGraphTextureDesc& textureDesc);

/*!
*/
handle_t addPersistentTexture(const wchar_t* const name, handle_t persistentHandle, const RenderGraphTextureDesc& textureDesc);

/*! Get target set from resource handle.
*
* \param resource Opaque resource handle.
Expand Down
6 changes: 5 additions & 1 deletion code/Render/Frame/RenderGraphTexturePool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,16 @@ void RenderGraphTexturePool::destroy()
m_renderSystem = nullptr;
}

Ref< ITexture > RenderGraphTexturePool::acquire(const RenderGraphTextureDesc& textureDesc)
Ref< ITexture > RenderGraphTexturePool::acquire(const RenderGraphTextureDesc& textureDesc, uint32_t persistentHandle)
{
auto it = std::find_if(
m_pool.begin(),
m_pool.end(),
[&](const RenderGraphTexturePool::Pool& p)
{
if (p.persistentHandle != persistentHandle)
return false;

return std::memcmp(&p.textureDesc, &textureDesc, sizeof(textureDesc)) == 0;
}
);
Expand All @@ -45,6 +48,7 @@ Ref< ITexture > RenderGraphTexturePool::acquire(const RenderGraphTextureDesc& te
{
pool = &m_pool.push_back();
pool->textureDesc = textureDesc;
pool->persistentHandle = persistentHandle;
}

// Acquire free texture, if no one left we need to create a new texture.
Expand Down
3 changes: 2 additions & 1 deletion code/Render/Frame/RenderGraphTexturePool.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class RenderGraphTexturePool : public Object

void destroy();

Ref< ITexture > acquire(const RenderGraphTextureDesc& textureDesc);
Ref< ITexture > acquire(const RenderGraphTextureDesc& textureDesc, uint32_t persistentHandle);

void release(Ref< ITexture >& texture);

Expand All @@ -40,6 +40,7 @@ class RenderGraphTexturePool : public Object
{
// Pool identification.
RenderGraphTextureDesc textureDesc;
uint32_t persistentHandle;

// Pool buffers.
RefArray< ITexture > free;
Expand Down
Loading

0 comments on commit 46aa8d4

Please sign in to comment.