Subversion Repository Public Repository

Divide-Framework

This repository has no backups
This repository's network speed is throttled to 100KB/sec

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
#include "config.h"

#include "Headers/RenderPassCuller.h"

#include "Core/Headers/TaskPool.h"
#include "Scenes/Headers/SceneState.h"
#include "Graphs/Headers/SceneGraph.h"
#include "Platform/Video/Headers/GFXDevice.h"

namespace Divide {

namespace {
    static const U32 g_nodesPerCullingPartition = Config::MAX_VISIBLE_NODES / 4u;

    template <typename T>
    constexpr T&&
        wrap_lval(typename std::remove_reference<T>::type &&obj) noexcept
    {
        return static_cast<T&&>(obj);
    }

    template <typename T>
    constexpr std::reference_wrapper<typename std::remove_reference<T>::type>
        wrap_lval(typename std::remove_reference<T>::type &obj) noexcept
    {
        return std::ref(obj);
    }
};

RenderPassCuller::RenderPassCuller() {
    for (VisibleNodeList& cache : _visibleNodes) {
        cache.reserve(Config::MAX_VISIBLE_NODES);
    }
}

RenderPassCuller::~RenderPassCuller() {
    clear();
}

void RenderPassCuller::clear() {
    for (VisibleNodeList& cache : _visibleNodes) {
        cache.clear();
    }
}

U32 RenderPassCuller::stageToCacheIndex(RenderStage stage) const {
    switch (stage) {
        case RenderStage::REFLECTION:  return 1;
        case RenderStage::REFRACTION: return 2;
        case RenderStage::SHADOW:  return 3;
    };

    return 0;
}

RenderPassCuller::VisibleNodeList&
RenderPassCuller::getNodeCache(RenderStage stage) {
    return _visibleNodes[stageToCacheIndex(stage)];
}

const RenderPassCuller::VisibleNodeList&
RenderPassCuller::getNodeCache(RenderStage stage) const {
    return _visibleNodes[stageToCacheIndex(stage)];
}

bool RenderPassCuller::wasNodeInView(I64 GUID, RenderStage stage) const {
    const VisibleNodeList& cache = getNodeCache(stage);

    VisibleNodeList::const_iterator it;
    it = std::find_if(std::cbegin(cache), std::cend(cache),
        [GUID](VisibleNode node) {
            SceneGraphNode_cptr nodePtr = node.second.lock();
            return (nodePtr != nullptr && nodePtr->getGUID() == GUID);
        });

    return it != std::cend(cache);
}

void RenderPassCuller::frustumCull(SceneGraph& sceneGraph,
                                   const SceneState& sceneState,
                                   RenderStage stage,
                                   bool async,
                                   const CullingFunction& cullingFunction)
{
    VisibleNodeList& nodeCache = getNodeCache(stage);
    vectorImpl<VisibleNodeList>& nodeList = _perThreadNodeList[to_uint(stage)];
    nodeCache.resize(0);
    const SceneRenderState& renderState = sceneState.renderState();
    if (renderState.isEnabledOption(SceneRenderState::RenderOptions::RENDER_GEOMETRY)) {
        _cullingFunction[to_uint(stage)] = cullingFunction;
        // No point in updating visual information if the scene disabled object
        // rendering or rendering of their bounding boxes
        SceneGraphNode& root = sceneGraph.getRoot();
        U32 childCount = root.getChildCount();
        nodeList.resize(childCount);
        const Camera& camera = renderState.getCameraConst();
        F32 cullMaxDistance = renderState.generalVisibility();
        parallel_for(DELEGATE_BIND(&RenderPassCuller::frumstumPartitionCuller,
                                   this,
                                   std::placeholders::_1,
                                   std::placeholders::_2,
                                   std::placeholders::_3,
                                   std::ref(root),
                                   std::cref(camera),
                                   stage,
                                   cullMaxDistance),
                     childCount,
                     g_nodesPerCullingPartition,
                     Task::TaskPriority::MAX);

        for (const VisibleNodeList& nodeListEntry : nodeList) {
            nodeCache.insert(std::end(nodeCache), std::cbegin(nodeListEntry), std::cend(nodeListEntry));
        }
    }
}

void RenderPassCuller::frumstumPartitionCuller(const std::atomic_bool& stopRequested,
                                               U32 start,
                                               U32 end,
                                               SceneGraphNode& root,
                                               const Camera& camera,
                                               RenderStage stage,
                                               F32 cullMaxDistance)
{
    U32 childCount = 0;
    for (U32 i = start; i < end; ++i) {
        frustumCullNode(stopRequested, root.getChild(i, childCount), camera, stage, cullMaxDistance, i, true);
    }
}
/// This method performs the visibility check on the given node and all of its
/// children and adds them to the RenderQueue
void RenderPassCuller::frustumCullNode(const std::atomic_bool&stopRequested,
                                       const SceneGraphNode& currentNode,
                                       const Camera& currentCamera,
                                       RenderStage currentStage,
                                       F32 cullMaxDistance,
                                       U32 nodeListIndex,
                                       bool clearList)
{
    VisibleNodeList& nodes = _perThreadNodeList[to_uint(currentStage)][nodeListIndex];
    if (clearList) {
        nodes.resize(0);
    }
    // Early out for inactive nodes
    if (!currentNode.isActive()) {
        return;
    }

    // Early out for non-shadow casters during shadow pass
    if (currentStage == RenderStage::SHADOW && !currentNode.get<RenderingComponent>()->castsShadows()) {
        return;
    }

    bool isVisible = !_cullingFunction[to_uint(currentStage)](currentNode);

    Frustum::FrustCollision collisionResult = Frustum::FrustCollision::FRUSTUM_OUT;
    isVisible = isVisible && !currentNode.cullNode(currentCamera, cullMaxDistance, currentStage, collisionResult);

    if (isVisible && !stopRequested) {
        vectorAlg::emplace_back(nodes, 0, currentNode.shared_from_this());
        if (collisionResult == Frustum::FrustCollision::FRUSTUM_INTERSECT) {
            // Parent node intersects the view, so check children
            U32 childCount = currentNode.getChildCount();
            for (U32 i = 0; i < childCount; ++i) {
                frustumCullNode(stopRequested,
                                currentNode.getChild(i, childCount),
                                currentCamera,
                                currentStage,
                                cullMaxDistance,
                                nodeListIndex,
                                false);
            }
        } else {
            // All nodes are in view entirely
            addAllChildren(currentNode, currentStage, nodes);
        }
    }
}

void RenderPassCuller::addAllChildren(const SceneGraphNode& currentNode, RenderStage currentStage, VisibleNodeList& nodes) {
    U32 childCount = currentNode.getChildCount();
    for (U32 i = 0; i < childCount; ++i) {
        SceneGraphNode_cptr child = currentNode.getChild(i, childCount).shared_from_this();
        if (!(currentStage == RenderStage::SHADOW &&
              !currentNode.get<RenderingComponent>()->castsShadows())) {
        
            if (child->isActive() && !_cullingFunction[to_uint(currentStage)](*child)) {
                vectorAlg::emplace_back(nodes, 0, child);
                addAllChildren(*child, currentStage, nodes);
            }
        }
    }
}

};

Commits for Divide-Framework/trunk/Source Code/Rendering/RenderPass/RenderPassCuller.cpp

Diff revisions: vs.
Revision Author Commited Message
781 Diff Diff IonutCava picture IonutCava Wed 12 Oct, 2016 16:03:46 +0000

[IonutCava]
- ShaderComputeQueue <-> Material shader request bug fix (element stuck in QUEUED state)
- More Camera class cleanups
- Add a method of removing EnvironmentProbes from their Pool

773 Diff Diff IonutCava picture IonutCava Tue 04 Oct, 2016 15:53:18 +0000

[IonutCava]
- Split GenericDrawCommand gathering system into Init/Update to facilitate future threading support
- Fix drawCount() == 0 case in submitRenderCommand
- Make _cameraPool (more) threadsafe

766 Diff Diff IonutCava picture IonutCava Mon 22 Aug, 2016 15:54:49 +0000

[IonutCava]
- Descriptor/State cleanup part 2/3: SceneState/SceneRenderState cleanup

743 Diff Diff IonutCava picture IonutCava Tue 28 Jun, 2016 15:55:50 +0000

[IonutCava]
- More performance tuning:
— Move billboarding related camera variable calculation to shaders instead of CPU
— Replace some DIVIDE_ASSERT calls with regular assert calls in really low level code.
— Some cleanup of the GenericDrawCommand class
— glRegularBuffer does an invalidation call before updating
— Misc changes

740 Diff Diff IonutCava picture IonutCava Sat 25 Jun, 2016 17:09:50 +0000

[IonutCava]
- More scene changing related fixes
- GUIDWrapper is now a core feature instead of a utility

734 Diff Diff IonutCava picture IonutCava Tue 21 Jun, 2016 16:28:11 +0000

[IonutCava]
- Added a render target pool:
— All render targets are now allocated (and tracked) by the GFXDevice.
— Allocation routines return a slim RenderTargetHandle object that will be used later on in draw commands.

- Added a refraction render pass that will handle translucent objects that need refracted textures instead of clear transparency
— Both reflective nodes and refractive nodes are not gathered properly at this point

- All API specific objects (buffers, textures, etc) are now initialized in the GFXDevice class (see GFXDeviceObjects.cpp)
— This allowed for the slimming of the RenderAPIWrapper interface

- Improved ENABLE_GPU_VALIDATION macro utilization:
— It enabled shadow map split plane debugging
— It bypasses loading shaders from text cache

712 Diff Diff IonutCava picture IonutCava Tue 24 May, 2016 16:18:37 +0000

[IonutCava]
- Added the concept of “buffer” to be used by GenericVertexData and ShaderBuffer without caring if it’s persistent or not.
— Persistent buffers handle their own locking instead of relying on the parent class
- HiZ occlusion culling fixes and optimizations

711 Diff Diff IonutCava picture IonutCava Mon 23 May, 2016 14:31:55 +0000

[IonutCava]
- More scene change fixes: pending tasks, GUI elements, etc
- Singleton removal: AIManager is a per-scene member instead of a global singleton now

675 Diff Diff IonutCava picture IonutCava Tue 12 Apr, 2016 14:23:59 +0000

[IonutCava]
- Create a “reflection target pool” that reflective nodes can use instead of having a reflection render target per node
- Update particles at fixed time intervals instead of each update loop. 33ms for now (30FPS) seems like a decent balance.
- Add a “parallel_for” call that uses the task pool, a function to call, a total count and a partition size
- Frustum culling does not create a new task per node, instead the partition size is now customizable with the new parallel_for system

669 IonutCava picture IonutCava Mon 04 Apr, 2016 16:15:35 +0000

[IonutCava]
- Move Task creation calls to TaskPool.h
- Allow tasks to use any pool, but default behaviour is to use the Kernel’s main task pool
- Change image transparency check to use the task pool instead of OpenMP
— Perfect place for future parallel_for implementation
- Warning fixes
- Some method renaming for improved readability