Skip to content

Commit

Permalink
Traktor: Begun implementing GPU culling of terrain patches.
Browse files Browse the repository at this point in the history
  • Loading branch information
apistol78 committed Mar 4, 2024
1 parent 903d9a9 commit 3809b55
Show file tree
Hide file tree
Showing 4 changed files with 498 additions and 2 deletions.
53 changes: 51 additions & 2 deletions code/Terrain/TerrainComponent.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* TRAKTOR
* Copyright (c) 2022 Anders Pistol.
* Copyright (c) 2022-2024 Anders Pistol.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
Expand All @@ -22,6 +22,7 @@
#include "Terrain/TerrainSurfaceCache.h"
#include "World/IWorldRenderPass.h"
#include "World/WorldBuildContext.h"
#include "World/WorldHandles.h"
#include "World/WorldRenderView.h"
#include "World/WorldSetupContext.h"

Expand All @@ -30,6 +31,8 @@ namespace traktor::terrain
namespace
{

const resource::Id< render::Shader > c_shaderCull(L"{8BA73DD8-0FD9-4C15-A772-EACC14014AEC}");

const render::Handle c_handleTerrain_VisualizeLods(L"Terrain_VisualizeLods");
const render::Handle c_handleTerrain_VisualizeMap(L"Terrain_VisualizeMap");
const render::Handle c_handleTerrain_SurfaceAlbedo(L"Terrain_SurfaceAlbedo");
Expand All @@ -49,6 +52,10 @@ const render::Handle c_handleTerrain_DebugMap(L"Terrain_DebugMap");
const render::Handle c_handleTerrain_CutEnable(L"Terrain_CutEnable");
const render::Handle c_handleTerrain_PatchData(L"Terrain_PatchData");

const render::Handle c_handleTerrain_TargetSize(L"Terrain_TargetSize");
const render::Handle c_handleTerrain_DrawBuffer(L"Terrain_DrawBuffer");
const render::Handle c_handleTerrain_CulledDrawBuffer(L"Terrain_CulledDrawBuffer");

const int32_t c_patchLodSteps = 3;
const int32_t c_surfaceLodSteps = 3;

Expand Down Expand Up @@ -101,6 +108,9 @@ bool TerrainComponent::create(const TerrainComponentData& data)
if (!m_resourceManager->bind(data.getTerrain(), m_terrain))
return false;

if (!m_resourceManager->bind(c_shaderCull, m_shaderCull))
return false;

m_heightfield = m_terrain->getHeightfield();

m_patchLodDistance = data.getPatchLodDistance();
Expand Down Expand Up @@ -430,6 +440,32 @@ void TerrainComponent::build(
m_dataBuffer->unlock();
}

// Cull draw buffer to HiZ target.
if (worldRenderPass.getTechnique() == world::s_techniqueDeferredGBufferWrite)
{
const Vector2 viewSize = worldRenderView.getViewSize();

auto renderBlock = renderContext->allocNamed< render::ComputeRenderBlock >(L"Terrain cull");

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

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

worldRenderPass.setProgramParameters(renderBlock->programParams);

renderBlock->programParams->setVectorParameter(c_handleTerrain_TargetSize, Vector4(viewSize.x, viewSize.y, 0.0f, 0.0f));
renderBlock->programParams->setBufferViewParameter(c_handleTerrain_DrawBuffer, m_drawBuffer->getBufferView());
renderBlock->programParams->setBufferViewParameter(c_handleTerrain_CulledDrawBuffer, m_culledDrawBuffer->getBufferView());
renderBlock->programParams->setBufferViewParameter(c_handleTerrain_PatchData, m_dataBuffer->getBufferView());
renderBlock->programParams->endParameters(renderContext);

renderBlock->workSize[0] = (int32_t)m_view[viewIndex].visiblePatches.size();

renderContext->compute(renderBlock);
renderContext->compute< render::BarrierRenderBlock >(render::Stage::Compute, render::Stage::Compute, nullptr, 0);
}

// Render all patches using indirect draw.
{
auto rb = renderContext->allocNamed< render::IndirectRenderBlock >(L"Terrain patches");
Expand All @@ -441,7 +477,12 @@ void TerrainComponent::build(
rb->vertexBuffer = m_vertexBuffer->getBufferView();
rb->vertexLayout = m_vertexLayout;
rb->primitive = render::PrimitiveType::Triangles;
rb->drawBuffer = m_drawBuffer->getBufferView();

if (worldRenderPass.getTechnique() == world::s_techniqueDeferredGBufferWrite)
rb->drawBuffer = m_culledDrawBuffer->getBufferView();
else
rb->drawBuffer = m_drawBuffer->getBufferView();

rb->drawCount = m_view[viewIndex].visiblePatches.size();

rb->programParams->beginParameters(renderContext);
Expand Down Expand Up @@ -801,6 +842,14 @@ bool TerrainComponent::createPatches()
if (!m_drawBuffer)
return false;

m_culledDrawBuffer = m_renderSystem->createBuffer(
render::BuIndirect,
(uint32_t)m_patches.size() * sizeof(render::IndexedIndirectDraw),
false
);
if (!m_culledDrawBuffer)
return false;

m_dataBuffer = m_renderSystem->createBuffer(
render::BuStructured,
(uint32_t)m_patches.size() * sizeof(DrawData),
Expand Down
4 changes: 4 additions & 0 deletions code/Terrain/TerrainComponent.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,13 +164,17 @@ class T_DLLCLASS TerrainComponent : public world::IEntityComponent
world::Entity* m_owner;
resource::Proxy< Terrain > m_terrain;
resource::Proxy< hf::Heightfield > m_heightfield;

resource::Proxy< render::Shader > m_shaderCull;

AlignedVector< Patch > m_patches;
uint32_t m_patchCount;
uint32_t m_cacheSize;
Ref< const render::IVertexLayout > m_vertexLayout;
Ref< render::Buffer > m_indexBuffer;
Ref< render::Buffer > m_vertexBuffer;
Ref< render::Buffer > m_drawBuffer;
Ref< render::Buffer > m_culledDrawBuffer;
Ref< render::Buffer > m_dataBuffer;
Ref< render::ITexture > m_defaultColorMap;
Ref< render::ITexture > m_defaultCutMap;
Expand Down
Loading

0 comments on commit 3809b55

Please sign in to comment.