|
@@ -3,7 +3,6 @@
|
|
|
// Code licensed under the BSD License.
|
|
// Code licensed under the BSD License.
|
|
|
// http://www.anki3d.org/LICENSE
|
|
// http://www.anki3d.org/LICENSE
|
|
|
|
|
|
|
|
-#include <anki/scene/Visibility.h>
|
|
|
|
|
#include <anki/scene/VisibilityInternal.h>
|
|
#include <anki/scene/VisibilityInternal.h>
|
|
|
#include <anki/scene/SceneGraph.h>
|
|
#include <anki/scene/SceneGraph.h>
|
|
|
#include <anki/scene/SectorNode.h>
|
|
#include <anki/scene/SectorNode.h>
|
|
@@ -24,8 +23,10 @@
|
|
|
namespace anki
|
|
namespace anki
|
|
|
{
|
|
{
|
|
|
|
|
|
|
|
-void VisibilityContext::submitNewWork(FrustumComponent& frc, RenderQueue& rqueue, ThreadHive& hive)
|
|
|
|
|
|
|
+void VisibilityContext::submitNewWork(const FrustumComponent& frc, RenderQueue& rqueue, ThreadHive& hive)
|
|
|
{
|
|
{
|
|
|
|
|
+ ANKI_TRACE_SCOPED_EVENT(SCENE_VIS_SUBMIT_WORK);
|
|
|
|
|
+
|
|
|
// Check enabled and make sure that the results are null (this can happen on multiple on circular viewing)
|
|
// Check enabled and make sure that the results are null (this can happen on multiple on circular viewing)
|
|
|
if(ANKI_UNLIKELY(!frc.anyVisibilityTestEnabled()))
|
|
if(ANKI_UNLIKELY(!frc.anyVisibilityTestEnabled()))
|
|
|
{
|
|
{
|
|
@@ -58,171 +59,158 @@ void VisibilityContext::submitNewWork(FrustumComponent& frc, RenderQueue& rqueue
|
|
|
m_testedFrcs.pushBack(alloc, &frc);
|
|
m_testedFrcs.pushBack(alloc, &frc);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // Prepare the ctx
|
|
|
|
|
+ FrustumVisibilityContext* frcCtx = alloc.newInstance<FrustumVisibilityContext>();
|
|
|
|
|
+ frcCtx->m_visCtx = this;
|
|
|
|
|
+ frcCtx->m_frc = &frc;
|
|
|
|
|
+ frcCtx->m_queueViews.create(alloc, hive.getThreadCount());
|
|
|
|
|
+ frcCtx->m_visTestsSignalSem = hive.newSemaphore(1);
|
|
|
|
|
+ frcCtx->m_renderQueue = &rqueue;
|
|
|
|
|
+
|
|
|
// Submit new work
|
|
// Submit new work
|
|
|
//
|
|
//
|
|
|
|
|
|
|
|
- // Software rasterizer tasks
|
|
|
|
|
- SoftwareRasterizer* r = nullptr;
|
|
|
|
|
- Array<ThreadHiveDependencyHandle, ThreadHive::MAX_THREADS> rasterizeDeps;
|
|
|
|
|
- if(frc.visibilityTestsEnabled(FrustumComponentVisibilityTestFlag::OCCLUDERS))
|
|
|
|
|
|
|
+ // Software rasterizer task
|
|
|
|
|
+ ThreadHiveSemaphore* prepareRasterizerSem = nullptr;
|
|
|
|
|
+ if(frc.visibilityTestsEnabled(FrustumComponentVisibilityTestFlag::OCCLUDERS) && frc.hasCoverageBuffer())
|
|
|
{
|
|
{
|
|
|
// Gather triangles task
|
|
// Gather triangles task
|
|
|
- GatherVisibleTrianglesTask* gather = alloc.newInstance<GatherVisibleTrianglesTask>();
|
|
|
|
|
- gather->m_visCtx = this;
|
|
|
|
|
- gather->m_frc = &frc;
|
|
|
|
|
- gather->m_vertCount = 0;
|
|
|
|
|
-
|
|
|
|
|
- r = &gather->m_r;
|
|
|
|
|
|
|
+ ThreadHiveTask fillDepthTask;
|
|
|
|
|
+ fillDepthTask.m_callback = FillRasterizerWithCoverageTask::callback;
|
|
|
|
|
+ fillDepthTask.m_argument = alloc.newInstance<FillRasterizerWithCoverageTask>(frcCtx);
|
|
|
|
|
+ fillDepthTask.m_signalSemaphore = hive.newSemaphore(1);
|
|
|
|
|
|
|
|
- ThreadHiveTask gatherTask;
|
|
|
|
|
- gatherTask.m_callback = GatherVisibleTrianglesTask::callback;
|
|
|
|
|
- gatherTask.m_argument = gather;
|
|
|
|
|
|
|
+ hive.submitTasks(&fillDepthTask, 1);
|
|
|
|
|
|
|
|
- hive.submitTasks(&gatherTask, 1);
|
|
|
|
|
-
|
|
|
|
|
- // Rasterize triangles task
|
|
|
|
|
- U count = hive.getThreadCount();
|
|
|
|
|
- RasterizeTrianglesTask* rasterize = alloc.newArray<RasterizeTrianglesTask>(count);
|
|
|
|
|
-
|
|
|
|
|
- Array<ThreadHiveTask, ThreadHive::MAX_THREADS> rastTasks;
|
|
|
|
|
- while(count--)
|
|
|
|
|
- {
|
|
|
|
|
- RasterizeTrianglesTask& rast = rasterize[count];
|
|
|
|
|
- rast.m_gatherTask = gather;
|
|
|
|
|
- rast.m_taskIdx = count;
|
|
|
|
|
- rast.m_taskCount = hive.getThreadCount();
|
|
|
|
|
-
|
|
|
|
|
- rastTasks[count].m_callback = RasterizeTrianglesTask::callback;
|
|
|
|
|
- rastTasks[count].m_argument = &rast;
|
|
|
|
|
- rastTasks[count].m_inDependencies = WeakArray<ThreadHiveDependencyHandle>(&gatherTask.m_outDependency, 1);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- count = hive.getThreadCount();
|
|
|
|
|
- hive.submitTasks(&rastTasks[0], count);
|
|
|
|
|
- while(count--)
|
|
|
|
|
- {
|
|
|
|
|
- rasterizeDeps[count] = rastTasks[count].m_outDependency;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ prepareRasterizerSem = fillDepthTask.m_signalSemaphore;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // Gather visibles from sector
|
|
|
|
|
- GatherVisiblesFromSectorsTask* gather = alloc.newInstance<GatherVisiblesFromSectorsTask>();
|
|
|
|
|
- gather->m_visCtx = this;
|
|
|
|
|
- gather->m_frc = &frc;
|
|
|
|
|
- gather->m_r = r;
|
|
|
|
|
-
|
|
|
|
|
- ThreadHiveTask gatherTask;
|
|
|
|
|
- gatherTask.m_callback = GatherVisiblesFromSectorsTask::callback;
|
|
|
|
|
- gatherTask.m_argument = gather;
|
|
|
|
|
- if(r)
|
|
|
|
|
|
|
+ if(frc.visibilityTestsEnabled(FrustumComponentVisibilityTestFlag::OCCLUDERS))
|
|
|
{
|
|
{
|
|
|
- gatherTask.m_inDependencies = WeakArray<ThreadHiveDependencyHandle>(&rasterizeDeps[0], hive.getThreadCount());
|
|
|
|
|
|
|
+ rqueue.m_fillCoverageBufferCallback = FrustumComponent::fillCoverageBufferCallback;
|
|
|
|
|
+ rqueue.m_fillCoverageBufferCallbackUserData = static_cast<void*>(const_cast<FrustumComponent*>(&frc));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- hive.submitTasks(&gatherTask, 1);
|
|
|
|
|
-
|
|
|
|
|
- // Test tasks
|
|
|
|
|
- U testCount = hive.getThreadCount();
|
|
|
|
|
- WeakArray<VisibilityTestTask> tests(alloc.newArray<VisibilityTestTask>(testCount), testCount);
|
|
|
|
|
- WeakArray<ThreadHiveTask> testTasks(alloc.newArray<ThreadHiveTask>(testCount), testCount);
|
|
|
|
|
-
|
|
|
|
|
- for(U i = 0; i < testCount; ++i)
|
|
|
|
|
- {
|
|
|
|
|
- auto& test = tests[i];
|
|
|
|
|
- test.m_visCtx = this;
|
|
|
|
|
- test.m_frc = &frc;
|
|
|
|
|
- test.m_sectorsCtx = &gather->m_sectorsCtx;
|
|
|
|
|
- test.m_taskIdx = i;
|
|
|
|
|
- test.m_taskCount = testCount;
|
|
|
|
|
- test.m_r = r;
|
|
|
|
|
-
|
|
|
|
|
- auto& task = testTasks[i];
|
|
|
|
|
- task.m_callback = VisibilityTestTask::callback;
|
|
|
|
|
- task.m_argument = &test;
|
|
|
|
|
- task.m_inDependencies = WeakArray<ThreadHiveDependencyHandle>(&gatherTask.m_outDependency, 1);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ // Gather visibles from the octree
|
|
|
|
|
+ ThreadHiveTask gatherTask;
|
|
|
|
|
+ gatherTask.m_callback = GatherVisiblesFromOctreeTask::callback;
|
|
|
|
|
+ gatherTask.m_argument = alloc.newInstance<GatherVisiblesFromOctreeTask>(frcCtx);
|
|
|
|
|
+ gatherTask.m_signalSemaphore = nullptr; // No need to signal anything because it will spawn new tasks
|
|
|
|
|
+ gatherTask.m_waitSemaphore = prepareRasterizerSem;
|
|
|
|
|
|
|
|
- hive.submitTasks(&testTasks[0], testCount);
|
|
|
|
|
|
|
+ hive.submitTasks(&gatherTask, 1);
|
|
|
|
|
|
|
|
// Combind results task
|
|
// Combind results task
|
|
|
- CombineResultsTask* combine = alloc.newInstance<CombineResultsTask>();
|
|
|
|
|
- combine->m_visCtx = this;
|
|
|
|
|
- combine->m_frc = &frc;
|
|
|
|
|
- combine->m_results = &rqueue;
|
|
|
|
|
- combine->m_tests = tests;
|
|
|
|
|
- combine->m_swRast = r;
|
|
|
|
|
-
|
|
|
|
|
ThreadHiveTask combineTask;
|
|
ThreadHiveTask combineTask;
|
|
|
combineTask.m_callback = CombineResultsTask::callback;
|
|
combineTask.m_callback = CombineResultsTask::callback;
|
|
|
- combineTask.m_argument = combine;
|
|
|
|
|
- combineTask.m_inDependencies =
|
|
|
|
|
- WeakArray<ThreadHiveDependencyHandle>(alloc.newArray<ThreadHiveDependencyHandle>(testCount), testCount);
|
|
|
|
|
- for(U i = 0; i < testCount; ++i)
|
|
|
|
|
- {
|
|
|
|
|
- combineTask.m_inDependencies[i] = testTasks[i].m_outDependency;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ combineTask.m_argument = alloc.newInstance<CombineResultsTask>(frcCtx);
|
|
|
|
|
+ ANKI_ASSERT(frcCtx->m_visTestsSignalSem);
|
|
|
|
|
+ combineTask.m_waitSemaphore = frcCtx->m_visTestsSignalSem;
|
|
|
|
|
|
|
|
hive.submitTasks(&combineTask, 1);
|
|
hive.submitTasks(&combineTask, 1);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-void GatherVisibleTrianglesTask::gather()
|
|
|
|
|
|
|
+void FillRasterizerWithCoverageTask::fill()
|
|
|
{
|
|
{
|
|
|
- ANKI_TRACE_SCOPED_EVENT(SCENE_VISIBILITY_GATHER_TRIANGLES);
|
|
|
|
|
|
|
+ ANKI_TRACE_SCOPED_EVENT(SCENE_VIS_FILL_DEPTH);
|
|
|
|
|
|
|
|
- auto alloc = m_visCtx->m_scene->getFrameAllocator();
|
|
|
|
|
- m_verts.create(alloc, TRIANGLES_INITIAL_SIZE);
|
|
|
|
|
- SceneComponentLists& lists = m_visCtx->m_scene->getSceneComponentLists();
|
|
|
|
|
|
|
+ auto alloc = m_frcCtx->m_visCtx->m_scene->getFrameAllocator();
|
|
|
|
|
|
|
|
- ANKI_ASSERT(m_vertCount == 0);
|
|
|
|
|
- lists.iterateComponents<OccluderComponent>([&](OccluderComponent& comp) {
|
|
|
|
|
- if(m_frc->insideFrustum(comp.getBoundingVolume()))
|
|
|
|
|
- {
|
|
|
|
|
- U32 count, stride;
|
|
|
|
|
- const Vec3* it;
|
|
|
|
|
- comp.getVertices(it, count, stride);
|
|
|
|
|
- while(count--)
|
|
|
|
|
|
|
+ // Get the C-Buffer
|
|
|
|
|
+ ConstWeakArray<F32> depthBuff;
|
|
|
|
|
+ U32 width;
|
|
|
|
|
+ U32 height;
|
|
|
|
|
+ m_frcCtx->m_frc->getCoverageBufferInfo(depthBuff, width, height);
|
|
|
|
|
+ ANKI_ASSERT(width > 0 && height > 0 && depthBuff.getSize() > 0);
|
|
|
|
|
+
|
|
|
|
|
+ // Init the rasterizer
|
|
|
|
|
+ m_frcCtx->m_r = alloc.newInstance<SoftwareRasterizer>();
|
|
|
|
|
+ m_frcCtx->m_r->init(alloc);
|
|
|
|
|
+ m_frcCtx->m_r->prepare(m_frcCtx->m_frc->getViewMatrix(), m_frcCtx->m_frc->getProjectionMatrix(), width, height);
|
|
|
|
|
+
|
|
|
|
|
+ // Do the work
|
|
|
|
|
+ m_frcCtx->m_r->fillDepthBuffer(depthBuff);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void GatherVisiblesFromOctreeTask::gather(ThreadHive& hive, ThreadHiveSemaphore& sem)
|
|
|
|
|
+{
|
|
|
|
|
+ ANKI_TRACE_SCOPED_EVENT(SCENE_VIS_OCTREE);
|
|
|
|
|
+
|
|
|
|
|
+ U testIdx = m_frcCtx->m_visCtx->m_testsCount.fetchAdd(1);
|
|
|
|
|
+
|
|
|
|
|
+ // Walk the tree
|
|
|
|
|
+ m_frcCtx->m_visCtx->m_scene->getOctree().walkTree(testIdx,
|
|
|
|
|
+ [&](const Aabb& box) {
|
|
|
|
|
+ Bool visible = m_frcCtx->m_frc->insideFrustum(box);
|
|
|
|
|
+ if(visible && m_frcCtx->m_r)
|
|
|
{
|
|
{
|
|
|
- // Grow the array
|
|
|
|
|
- if(m_vertCount + 1 > m_verts.getSize())
|
|
|
|
|
- {
|
|
|
|
|
- m_verts.resize(alloc, m_verts.getSize() * 2);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ visible = m_frcCtx->m_r->visibilityTest(box, box);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- m_verts[m_vertCount++] = *it;
|
|
|
|
|
|
|
+ return visible;
|
|
|
|
|
+ },
|
|
|
|
|
+ [&](void* placeableUserData) {
|
|
|
|
|
+ ANKI_ASSERT(placeableUserData);
|
|
|
|
|
+ SpatialComponent* scomp = static_cast<SpatialComponent*>(placeableUserData);
|
|
|
|
|
|
|
|
- it = reinterpret_cast<const Vec3*>(reinterpret_cast<const U8*>(it) + stride);
|
|
|
|
|
|
|
+ ANKI_ASSERT(m_spatialCount < m_spatials.getSize());
|
|
|
|
|
+
|
|
|
|
|
+ m_spatials[m_spatialCount++] = scomp;
|
|
|
|
|
+
|
|
|
|
|
+ if(m_spatialCount == m_spatials.getSize())
|
|
|
|
|
+ {
|
|
|
|
|
+ flush(hive, sem);
|
|
|
}
|
|
}
|
|
|
- }
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // Flush the remaining
|
|
|
|
|
+ flush(hive, sem);
|
|
|
|
|
|
|
|
- m_r.init(alloc);
|
|
|
|
|
- m_r.prepare(m_frc->getViewMatrix(), m_frc->getProjectionMatrix(), 80, 50);
|
|
|
|
|
|
|
+ // Fire an additional dummy task to decrease the semaphore to zero
|
|
|
|
|
+ ThreadHiveTask task;
|
|
|
|
|
+ task.m_callback = dummyCallback;
|
|
|
|
|
+ task.m_argument = nullptr;
|
|
|
|
|
+ task.m_signalSemaphore = m_frcCtx->m_visTestsSignalSem;
|
|
|
|
|
+ hive.submitTasks(&task, 1);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-void RasterizeTrianglesTask::rasterize()
|
|
|
|
|
|
|
+void GatherVisiblesFromOctreeTask::flush(ThreadHive& hive, ThreadHiveSemaphore& sem)
|
|
|
{
|
|
{
|
|
|
- ANKI_TRACE_SCOPED_EVENT(SCENE_VISIBILITY_RASTERIZE);
|
|
|
|
|
|
|
+ if(m_spatialCount)
|
|
|
|
|
+ {
|
|
|
|
|
+ // Create the task
|
|
|
|
|
+ VisibilityTestTask* vis =
|
|
|
|
|
+ m_frcCtx->m_visCtx->m_scene->getFrameAllocator().newInstance<VisibilityTestTask>(m_frcCtx);
|
|
|
|
|
+ memcpy(&vis->m_spatialsToTest[0], &m_spatials[0], sizeof(m_spatials[0]) * m_spatialCount);
|
|
|
|
|
+ vis->m_spatialToTestCount = m_spatialCount;
|
|
|
|
|
|
|
|
- const U totalVertCount = m_gatherTask->m_vertCount;
|
|
|
|
|
|
|
+ // Increase the semaphore to block the CombineResultsTask
|
|
|
|
|
+ m_frcCtx->m_visTestsSignalSem->increaseSemaphore(1);
|
|
|
|
|
|
|
|
- U32 idx;
|
|
|
|
|
- while((idx = m_gatherTask->m_rasterizedVertCount.fetchAdd(3)) < totalVertCount)
|
|
|
|
|
- {
|
|
|
|
|
- m_gatherTask->m_r.draw(&m_gatherTask->m_verts[idx][0], 3, sizeof(Vec3), false);
|
|
|
|
|
|
|
+ // Submit task
|
|
|
|
|
+ ThreadHiveTask task;
|
|
|
|
|
+ task.m_callback = VisibilityTestTask::callback;
|
|
|
|
|
+ task.m_argument = vis;
|
|
|
|
|
+ task.m_signalSemaphore = m_frcCtx->m_visTestsSignalSem;
|
|
|
|
|
+ hive.submitTasks(&task, 1);
|
|
|
|
|
+
|
|
|
|
|
+ // Clear count
|
|
|
|
|
+ m_spatialCount = 0;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-void VisibilityTestTask::test(ThreadHive& hive)
|
|
|
|
|
|
|
+void VisibilityTestTask::test(ThreadHive& hive, U32 taskId)
|
|
|
{
|
|
{
|
|
|
- ANKI_TRACE_SCOPED_EVENT(SCENE_VISIBILITY_TEST);
|
|
|
|
|
|
|
+ ANKI_TRACE_SCOPED_EVENT(SCENE_VIS_TEST);
|
|
|
|
|
|
|
|
- FrustumComponent& testedFrc = *m_frc;
|
|
|
|
|
|
|
+ const FrustumComponent& testedFrc = *m_frcCtx->m_frc;
|
|
|
ANKI_ASSERT(testedFrc.anyVisibilityTestEnabled());
|
|
ANKI_ASSERT(testedFrc.anyVisibilityTestEnabled());
|
|
|
|
|
|
|
|
- SceneNode& testedNode = testedFrc.getSceneNode();
|
|
|
|
|
- auto alloc = m_visCtx->m_scene->getFrameAllocator();
|
|
|
|
|
|
|
+ const SceneNode& testedNode = testedFrc.getSceneNode();
|
|
|
|
|
+ auto alloc = m_frcCtx->m_visCtx->m_scene->getFrameAllocator();
|
|
|
|
|
|
|
|
- m_timestamp = testedNode.getComponentMaxTimestamp();
|
|
|
|
|
|
|
+ Timestamp& timestamp = m_frcCtx->m_queueViews[taskId].m_timestamp;
|
|
|
|
|
+ timestamp = testedNode.getComponentMaxTimestamp();
|
|
|
|
|
|
|
|
const Bool wantsRenderComponents =
|
|
const Bool wantsRenderComponents =
|
|
|
testedFrc.visibilityTestsEnabled(FrustumComponentVisibilityTestFlag::RENDER_COMPONENTS);
|
|
testedFrc.visibilityTestsEnabled(FrustumComponentVisibilityTestFlag::RENDER_COMPONENTS);
|
|
@@ -244,24 +232,27 @@ void VisibilityTestTask::test(ThreadHive& hive)
|
|
|
|
|
|
|
|
const Bool wantsDecals = testedFrc.visibilityTestsEnabled(FrustumComponentVisibilityTestFlag::DECALS);
|
|
const Bool wantsDecals = testedFrc.visibilityTestsEnabled(FrustumComponentVisibilityTestFlag::DECALS);
|
|
|
|
|
|
|
|
- const Bool wantsEarlyZ =
|
|
|
|
|
- testedFrc.visibilityTestsEnabled(FrustumComponentVisibilityTestFlag::EARLY_Z) && m_visCtx->m_earlyZDist > 0.0f;
|
|
|
|
|
|
|
+ const Bool wantsEarlyZ = testedFrc.visibilityTestsEnabled(FrustumComponentVisibilityTestFlag::EARLY_Z)
|
|
|
|
|
+ && m_frcCtx->m_visCtx->m_earlyZDist > 0.0f;
|
|
|
|
|
|
|
|
- // Chose the test range and a few other things
|
|
|
|
|
- PtrSize start, end;
|
|
|
|
|
- ThreadPoolTask::choseStartEnd(m_taskIdx, m_taskCount, m_sectorsCtx->getVisibleSceneNodeCount(), start, end);
|
|
|
|
|
|
|
+ // Iterate
|
|
|
|
|
+ RenderQueueView& result = m_frcCtx->m_queueViews[taskId];
|
|
|
|
|
+ for(U i = 0; i < m_spatialToTestCount; ++i)
|
|
|
|
|
+ {
|
|
|
|
|
+ const SpatialComponent* spatialC = m_spatialsToTest[i];
|
|
|
|
|
+ ANKI_ASSERT(spatialC);
|
|
|
|
|
+ const SceneNode& node = spatialC->getSceneNode();
|
|
|
|
|
|
|
|
- m_sectorsCtx->iterateVisibleSceneNodes(start, end, [&](SceneNode& node) {
|
|
|
|
|
// Skip if it is the same
|
|
// Skip if it is the same
|
|
|
if(ANKI_UNLIKELY(&testedNode == &node))
|
|
if(ANKI_UNLIKELY(&testedNode == &node))
|
|
|
{
|
|
{
|
|
|
- return;
|
|
|
|
|
|
|
+ continue;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Check what components the frustum needs
|
|
// Check what components the frustum needs
|
|
|
Bool wantNode = false;
|
|
Bool wantNode = false;
|
|
|
|
|
|
|
|
- RenderComponent* rc = node.tryGetComponent<RenderComponent>();
|
|
|
|
|
|
|
+ const RenderComponent* rc = node.tryGetComponent<RenderComponent>();
|
|
|
if(rc && wantsRenderComponents)
|
|
if(rc && wantsRenderComponents)
|
|
|
{
|
|
{
|
|
|
wantNode = true;
|
|
wantNode = true;
|
|
@@ -272,31 +263,31 @@ void VisibilityTestTask::test(ThreadHive& hive)
|
|
|
wantNode = true;
|
|
wantNode = true;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- LightComponent* lc = node.tryGetComponent<LightComponent>();
|
|
|
|
|
|
|
+ const LightComponent* lc = node.tryGetComponent<LightComponent>();
|
|
|
if(lc && wantsLightComponents)
|
|
if(lc && wantsLightComponents)
|
|
|
{
|
|
{
|
|
|
wantNode = true;
|
|
wantNode = true;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- LensFlareComponent* lfc = node.tryGetComponent<LensFlareComponent>();
|
|
|
|
|
|
|
+ const LensFlareComponent* lfc = node.tryGetComponent<LensFlareComponent>();
|
|
|
if(lfc && wantsFlareComponents)
|
|
if(lfc && wantsFlareComponents)
|
|
|
{
|
|
{
|
|
|
wantNode = true;
|
|
wantNode = true;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- ReflectionProbeComponent* reflc = node.tryGetComponent<ReflectionProbeComponent>();
|
|
|
|
|
|
|
+ const ReflectionProbeComponent* reflc = node.tryGetComponent<ReflectionProbeComponent>();
|
|
|
if(reflc && wantsReflectionProbes)
|
|
if(reflc && wantsReflectionProbes)
|
|
|
{
|
|
{
|
|
|
wantNode = true;
|
|
wantNode = true;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- ReflectionProxyComponent* proxyc = node.tryGetComponent<ReflectionProxyComponent>();
|
|
|
|
|
|
|
+ const ReflectionProxyComponent* proxyc = node.tryGetComponent<ReflectionProxyComponent>();
|
|
|
if(proxyc && wantsReflectionProxies)
|
|
if(proxyc && wantsReflectionProxies)
|
|
|
{
|
|
{
|
|
|
wantNode = true;
|
|
wantNode = true;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- DecalComponent* decalc = node.tryGetComponent<DecalComponent>();
|
|
|
|
|
|
|
+ const DecalComponent* decalc = node.tryGetComponent<DecalComponent>();
|
|
|
if(decalc && wantsDecals)
|
|
if(decalc && wantsDecals)
|
|
|
{
|
|
{
|
|
|
wantNode = true;
|
|
wantNode = true;
|
|
@@ -305,7 +296,7 @@ void VisibilityTestTask::test(ThreadHive& hive)
|
|
|
if(ANKI_UNLIKELY(!wantNode))
|
|
if(ANKI_UNLIKELY(!wantNode))
|
|
|
{
|
|
{
|
|
|
// Skip node
|
|
// Skip node
|
|
|
- return;
|
|
|
|
|
|
|
+ continue;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Test all spatial components of that node
|
|
// Test all spatial components of that node
|
|
@@ -325,8 +316,6 @@ void VisibilityTestTask::test(ThreadHive& hive)
|
|
|
// Inside
|
|
// Inside
|
|
|
ANKI_ASSERT(spIdx < MAX_U8);
|
|
ANKI_ASSERT(spIdx < MAX_U8);
|
|
|
sps[count++] = SpatialTemp{&sp, static_cast<U8>(spIdx), sp.getSpatialOrigin()};
|
|
sps[count++] = SpatialTemp{&sp, static_cast<U8>(spIdx), sp.getSpatialOrigin()};
|
|
|
-
|
|
|
|
|
- sp.setVisibleByCamera(true);
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
++spIdx;
|
|
++spIdx;
|
|
@@ -337,7 +326,7 @@ void VisibilityTestTask::test(ThreadHive& hive)
|
|
|
|
|
|
|
|
if(ANKI_UNLIKELY(count == 0))
|
|
if(ANKI_UNLIKELY(count == 0))
|
|
|
{
|
|
{
|
|
|
- return;
|
|
|
|
|
|
|
+ continue;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
ANKI_ASSERT(count == 1 && "TODO: Support sub-spatials");
|
|
ANKI_ASSERT(count == 1 && "TODO: Support sub-spatials");
|
|
@@ -363,11 +352,11 @@ void VisibilityTestTask::test(ThreadHive& hive)
|
|
|
RenderableQueueElement* el;
|
|
RenderableQueueElement* el;
|
|
|
if(rc->getMaterial().isForwardShading())
|
|
if(rc->getMaterial().isForwardShading())
|
|
|
{
|
|
{
|
|
|
- el = m_result.m_forwardShadingRenderables.newElement(alloc);
|
|
|
|
|
|
|
+ el = result.m_forwardShadingRenderables.newElement(alloc);
|
|
|
}
|
|
}
|
|
|
else
|
|
else
|
|
|
{
|
|
{
|
|
|
- el = m_result.m_renderables.newElement(alloc);
|
|
|
|
|
|
|
+ el = result.m_renderables.newElement(alloc);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
rc->setupRenderableQueueElement(*el);
|
|
rc->setupRenderableQueueElement(*el);
|
|
@@ -376,10 +365,10 @@ void VisibilityTestTask::test(ThreadHive& hive)
|
|
|
const Plane& nearPlane = testedFrc.getFrustum().getPlanesWorldSpace()[FrustumPlaneType::NEAR];
|
|
const Plane& nearPlane = testedFrc.getFrustum().getPlanesWorldSpace()[FrustumPlaneType::NEAR];
|
|
|
el->m_distanceFromCamera = max(0.0f, sps[0].m_sp->getAabb().testPlane(nearPlane));
|
|
el->m_distanceFromCamera = max(0.0f, sps[0].m_sp->getAabb().testPlane(nearPlane));
|
|
|
|
|
|
|
|
- if(wantsEarlyZ && el->m_distanceFromCamera < m_visCtx->m_earlyZDist
|
|
|
|
|
|
|
+ if(wantsEarlyZ && el->m_distanceFromCamera < m_frcCtx->m_visCtx->m_earlyZDist
|
|
|
&& !rc->getMaterial().isForwardShading())
|
|
&& !rc->getMaterial().isForwardShading())
|
|
|
{
|
|
{
|
|
|
- RenderableQueueElement* el2 = m_result.m_earlyZRenderables.newElement(alloc);
|
|
|
|
|
|
|
+ RenderableQueueElement* el2 = result.m_earlyZRenderables.newElement(alloc);
|
|
|
*el2 = *el;
|
|
*el2 = *el;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -391,7 +380,7 @@ void VisibilityTestTask::test(ThreadHive& hive)
|
|
|
{
|
|
{
|
|
|
case LightComponentType::POINT:
|
|
case LightComponentType::POINT:
|
|
|
{
|
|
{
|
|
|
- PointLightQueueElement* el = m_result.m_pointLights.newElement(alloc);
|
|
|
|
|
|
|
+ PointLightQueueElement* el = result.m_pointLights.newElement(alloc);
|
|
|
lc->setupPointLightQueueElement(*el);
|
|
lc->setupPointLightQueueElement(*el);
|
|
|
|
|
|
|
|
if(lc->getShadowEnabled())
|
|
if(lc->getShadowEnabled())
|
|
@@ -406,8 +395,8 @@ void VisibilityTestTask::test(ThreadHive& hive)
|
|
|
el->m_shadowRenderQueues[4] = &nextQueues[4];
|
|
el->m_shadowRenderQueues[4] = &nextQueues[4];
|
|
|
el->m_shadowRenderQueues[5] = &nextQueues[5];
|
|
el->m_shadowRenderQueues[5] = &nextQueues[5];
|
|
|
|
|
|
|
|
- U32* p = m_result.m_shadowPointLights.newElement(alloc);
|
|
|
|
|
- *p = m_result.m_pointLights.m_elementCount - 1;
|
|
|
|
|
|
|
+ U32* p = result.m_shadowPointLights.newElement(alloc);
|
|
|
|
|
+ *p = result.m_pointLights.m_elementCount - 1;
|
|
|
}
|
|
}
|
|
|
else
|
|
else
|
|
|
{
|
|
{
|
|
@@ -418,7 +407,7 @@ void VisibilityTestTask::test(ThreadHive& hive)
|
|
|
}
|
|
}
|
|
|
case LightComponentType::SPOT:
|
|
case LightComponentType::SPOT:
|
|
|
{
|
|
{
|
|
|
- SpotLightQueueElement* el = m_result.m_spotLights.newElement(alloc);
|
|
|
|
|
|
|
+ SpotLightQueueElement* el = result.m_spotLights.newElement(alloc);
|
|
|
lc->setupSpotLightQueueElement(*el);
|
|
lc->setupSpotLightQueueElement(*el);
|
|
|
|
|
|
|
|
if(lc->getShadowEnabled())
|
|
if(lc->getShadowEnabled())
|
|
@@ -427,8 +416,8 @@ void VisibilityTestTask::test(ThreadHive& hive)
|
|
|
nextQueues = WeakArray<RenderQueue>(a, 1);
|
|
nextQueues = WeakArray<RenderQueue>(a, 1);
|
|
|
el->m_shadowRenderQueue = a;
|
|
el->m_shadowRenderQueue = a;
|
|
|
|
|
|
|
|
- U32* p = m_result.m_shadowSpotLights.newElement(alloc);
|
|
|
|
|
- *p = m_result.m_spotLights.m_elementCount - 1;
|
|
|
|
|
|
|
+ U32* p = result.m_shadowSpotLights.newElement(alloc);
|
|
|
|
|
+ *p = result.m_spotLights.m_elementCount - 1;
|
|
|
}
|
|
}
|
|
|
else
|
|
else
|
|
|
{
|
|
{
|
|
@@ -444,13 +433,13 @@ void VisibilityTestTask::test(ThreadHive& hive)
|
|
|
|
|
|
|
|
if(lfc && wantsFlareComponents)
|
|
if(lfc && wantsFlareComponents)
|
|
|
{
|
|
{
|
|
|
- LensFlareQueueElement* el = m_result.m_lensFlares.newElement(alloc);
|
|
|
|
|
|
|
+ LensFlareQueueElement* el = result.m_lensFlares.newElement(alloc);
|
|
|
lfc->setupLensFlareQueueElement(*el);
|
|
lfc->setupLensFlareQueueElement(*el);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if(reflc && wantsReflectionProbes)
|
|
if(reflc && wantsReflectionProbes)
|
|
|
{
|
|
{
|
|
|
- ReflectionProbeQueueElement* el = m_result.m_reflectionProbes.newElement(alloc);
|
|
|
|
|
|
|
+ ReflectionProbeQueueElement* el = result.m_reflectionProbes.newElement(alloc);
|
|
|
reflc->setupReflectionProbeQueueElement(*el);
|
|
reflc->setupReflectionProbeQueueElement(*el);
|
|
|
|
|
|
|
|
if(reflc->getMarkedForRendering())
|
|
if(reflc->getMarkedForRendering())
|
|
@@ -478,7 +467,7 @@ void VisibilityTestTask::test(ThreadHive& hive)
|
|
|
|
|
|
|
|
if(decalc && wantsDecals)
|
|
if(decalc && wantsDecals)
|
|
|
{
|
|
{
|
|
|
- DecalQueueElement* el = m_result.m_decals.newElement(alloc);
|
|
|
|
|
|
|
+ DecalQueueElement* el = result.m_decals.newElement(alloc);
|
|
|
decalc->setupDecalQueueElement(*el);
|
|
decalc->setupDecalQueueElement(*el);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -487,42 +476,45 @@ void VisibilityTestTask::test(ThreadHive& hive)
|
|
|
{
|
|
{
|
|
|
count = 0;
|
|
count = 0;
|
|
|
err = node.iterateComponentsOfType<FrustumComponent>([&](FrustumComponent& frc) {
|
|
err = node.iterateComponentsOfType<FrustumComponent>([&](FrustumComponent& frc) {
|
|
|
- m_visCtx->submitNewWork(frc, nextQueues[count++], hive);
|
|
|
|
|
|
|
+ m_frcCtx->m_visCtx->submitNewWork(frc, nextQueues[count++], hive);
|
|
|
return Error::NONE;
|
|
return Error::NONE;
|
|
|
});
|
|
});
|
|
|
(void)err;
|
|
(void)err;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Update timestamp
|
|
// Update timestamp
|
|
|
- m_timestamp = max(m_timestamp, node.getComponentMaxTimestamp());
|
|
|
|
|
- }); // end for
|
|
|
|
|
|
|
+ timestamp = max(timestamp, node.getComponentMaxTimestamp());
|
|
|
|
|
+ } // end for
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void CombineResultsTask::combine()
|
|
void CombineResultsTask::combine()
|
|
|
{
|
|
{
|
|
|
- ANKI_TRACE_SCOPED_EVENT(SCENE_VISIBILITY_COMBINE_RESULTS);
|
|
|
|
|
|
|
+ ANKI_TRACE_SCOPED_EVENT(SCENE_VIS_COMBINE_RESULTS);
|
|
|
|
|
|
|
|
- auto alloc = m_visCtx->m_scene->getFrameAllocator();
|
|
|
|
|
|
|
+ auto alloc = m_frcCtx->m_visCtx->m_scene->getFrameAllocator();
|
|
|
|
|
+ RenderQueue& results = *m_frcCtx->m_renderQueue;
|
|
|
|
|
|
|
|
- m_results->m_shadowRenderablesLastUpdateTimestamp = 0;
|
|
|
|
|
- for(U i = 0; i < m_tests.getSize(); ++i)
|
|
|
|
|
|
|
+ // Compute the timestamp
|
|
|
|
|
+ const U threadCount = m_frcCtx->m_queueViews.getSize();
|
|
|
|
|
+ results.m_shadowRenderablesLastUpdateTimestamp = 0;
|
|
|
|
|
+ for(U i = 0; i < threadCount; ++i)
|
|
|
{
|
|
{
|
|
|
- m_results->m_shadowRenderablesLastUpdateTimestamp =
|
|
|
|
|
- max(m_results->m_shadowRenderablesLastUpdateTimestamp, m_tests[i].m_timestamp);
|
|
|
|
|
|
|
+ results.m_shadowRenderablesLastUpdateTimestamp =
|
|
|
|
|
+ max(results.m_shadowRenderablesLastUpdateTimestamp, m_frcCtx->m_queueViews[i].m_timestamp);
|
|
|
}
|
|
}
|
|
|
- ANKI_ASSERT(m_results->m_shadowRenderablesLastUpdateTimestamp);
|
|
|
|
|
|
|
+ ANKI_ASSERT(results.m_shadowRenderablesLastUpdateTimestamp);
|
|
|
|
|
|
|
|
#define ANKI_VIS_COMBINE(t_, member_) \
|
|
#define ANKI_VIS_COMBINE(t_, member_) \
|
|
|
{ \
|
|
{ \
|
|
|
Array<TRenderQueueElementStorage<t_>, 64> subStorages; \
|
|
Array<TRenderQueueElementStorage<t_>, 64> subStorages; \
|
|
|
- for(U i = 0; i < m_tests.getSize(); ++i) \
|
|
|
|
|
|
|
+ for(U i = 0; i < threadCount; ++i) \
|
|
|
{ \
|
|
{ \
|
|
|
- subStorages[i] = m_tests[i].m_result.member_; \
|
|
|
|
|
|
|
+ subStorages[i] = m_frcCtx->m_queueViews[i].member_; \
|
|
|
} \
|
|
} \
|
|
|
combineQueueElements<t_>(alloc, \
|
|
combineQueueElements<t_>(alloc, \
|
|
|
- WeakArray<TRenderQueueElementStorage<t_>>(&subStorages[0], m_tests.getSize()), \
|
|
|
|
|
|
|
+ WeakArray<TRenderQueueElementStorage<t_>>(&subStorages[0], threadCount), \
|
|
|
nullptr, \
|
|
nullptr, \
|
|
|
- m_results->member_, \
|
|
|
|
|
|
|
+ results.member_, \
|
|
|
nullptr); \
|
|
nullptr); \
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -530,17 +522,17 @@ void CombineResultsTask::combine()
|
|
|
{ \
|
|
{ \
|
|
|
Array<TRenderQueueElementStorage<t_>, 64> subStorages; \
|
|
Array<TRenderQueueElementStorage<t_>, 64> subStorages; \
|
|
|
Array<TRenderQueueElementStorage<U32>, 64> ptrSubStorages; \
|
|
Array<TRenderQueueElementStorage<U32>, 64> ptrSubStorages; \
|
|
|
- for(U i = 0; i < m_tests.getSize(); ++i) \
|
|
|
|
|
|
|
+ for(U i = 0; i < threadCount; ++i) \
|
|
|
{ \
|
|
{ \
|
|
|
- subStorages[i] = m_tests[i].m_result.member_; \
|
|
|
|
|
- ptrSubStorages[i] = m_tests[i].m_result.ptrMember_; \
|
|
|
|
|
|
|
+ subStorages[i] = m_frcCtx->m_queueViews[i].member_; \
|
|
|
|
|
+ ptrSubStorages[i] = m_frcCtx->m_queueViews[i].ptrMember_; \
|
|
|
} \
|
|
} \
|
|
|
- WeakArray<TRenderQueueElementStorage<U32>> arr(&ptrSubStorages[0], m_tests.getSize()); \
|
|
|
|
|
|
|
+ WeakArray<TRenderQueueElementStorage<U32>> arr(&ptrSubStorages[0], threadCount); \
|
|
|
combineQueueElements<t_>(alloc, \
|
|
combineQueueElements<t_>(alloc, \
|
|
|
- WeakArray<TRenderQueueElementStorage<t_>>(&subStorages[0], m_tests.getSize()), \
|
|
|
|
|
|
|
+ WeakArray<TRenderQueueElementStorage<t_>>(&subStorages[0], threadCount), \
|
|
|
&arr, \
|
|
&arr, \
|
|
|
- m_results->member_, \
|
|
|
|
|
- &m_results->ptrMember_); \
|
|
|
|
|
|
|
+ results.member_, \
|
|
|
|
|
+ &results.ptrMember_); \
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
ANKI_VIS_COMBINE(RenderableQueueElement, m_renderables);
|
|
ANKI_VIS_COMBINE(RenderableQueueElement, m_renderables);
|
|
@@ -556,32 +548,32 @@ void CombineResultsTask::combine()
|
|
|
#undef ANKI_VIS_COMBINE_AND_PTR
|
|
#undef ANKI_VIS_COMBINE_AND_PTR
|
|
|
|
|
|
|
|
#if ANKI_EXTRA_CHECKS
|
|
#if ANKI_EXTRA_CHECKS
|
|
|
- for(PointLightQueueElement* light : m_results->m_shadowPointLights)
|
|
|
|
|
|
|
+ for(PointLightQueueElement* light : results.m_shadowPointLights)
|
|
|
{
|
|
{
|
|
|
ANKI_ASSERT(light->hasShadow());
|
|
ANKI_ASSERT(light->hasShadow());
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- for(SpotLightQueueElement* light : m_results->m_shadowSpotLights)
|
|
|
|
|
|
|
+ for(SpotLightQueueElement* light : results.m_shadowSpotLights)
|
|
|
{
|
|
{
|
|
|
ANKI_ASSERT(light->hasShadow());
|
|
ANKI_ASSERT(light->hasShadow());
|
|
|
}
|
|
}
|
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
// Sort some of the arrays
|
|
// Sort some of the arrays
|
|
|
- std::sort(
|
|
|
|
|
- m_results->m_renderables.getBegin(), m_results->m_renderables.getEnd(), MaterialDistanceSortFunctor(20.0f));
|
|
|
|
|
|
|
+ std::sort(results.m_renderables.getBegin(), results.m_renderables.getEnd(), MaterialDistanceSortFunctor(20.0f));
|
|
|
|
|
|
|
|
- std::sort(m_results->m_earlyZRenderables.getBegin(),
|
|
|
|
|
- m_results->m_earlyZRenderables.getEnd(),
|
|
|
|
|
|
|
+ std::sort(results.m_earlyZRenderables.getBegin(),
|
|
|
|
|
+ results.m_earlyZRenderables.getEnd(),
|
|
|
DistanceSortFunctor<RenderableQueueElement>());
|
|
DistanceSortFunctor<RenderableQueueElement>());
|
|
|
|
|
|
|
|
- std::sort(m_results->m_forwardShadingRenderables.getBegin(),
|
|
|
|
|
- m_results->m_forwardShadingRenderables.getEnd(),
|
|
|
|
|
|
|
+ std::sort(results.m_forwardShadingRenderables.getBegin(),
|
|
|
|
|
+ results.m_forwardShadingRenderables.getEnd(),
|
|
|
RevDistanceSortFunctor<RenderableQueueElement>());
|
|
RevDistanceSortFunctor<RenderableQueueElement>());
|
|
|
|
|
|
|
|
- if(m_swRast)
|
|
|
|
|
|
|
+ // Cleanup
|
|
|
|
|
+ if(m_frcCtx->m_r)
|
|
|
{
|
|
{
|
|
|
- m_swRast->~SoftwareRasterizer();
|
|
|
|
|
|
|
+ m_frcCtx->m_r->~SoftwareRasterizer();
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -681,9 +673,9 @@ void CombineResultsTask::combineQueueElements(SceneFrameAllocator<U8>& alloc,
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-void doVisibilityTests(SceneNode& fsn, SceneGraph& scene, RenderQueue& rqueue)
|
|
|
|
|
|
|
+void SceneGraph::doVisibilityTests(SceneNode& fsn, SceneGraph& scene, RenderQueue& rqueue)
|
|
|
{
|
|
{
|
|
|
- ANKI_TRACE_SCOPED_EVENT(SCENE_VISIBILITY_TESTS);
|
|
|
|
|
|
|
+ ANKI_TRACE_SCOPED_EVENT(SCENE_VIS_TESTS);
|
|
|
|
|
|
|
|
ThreadHive& hive = scene.getThreadHive();
|
|
ThreadHive& hive = scene.getThreadHive();
|
|
|
scene.getSectorGroup().prepareForVisibilityTests();
|
|
scene.getSectorGroup().prepareForVisibilityTests();
|