Skip to content

Commit

Permalink
UPBGE: Refactor render node system.
Browse files Browse the repository at this point in the history
The refactor is caused by the following observation: the current system doesn't
manage inter-node arguments, for example display array bucket can't pass its
member pointer to mesh slots directly, the mesh slot has to get the pointer
itself. This restriction is very blocking with the futur work on blender2.8 were
the mesh slot will need to know the current shader used to bind the modelview
matrix.

To do so each node should be allowed to send a structure to its children node in
addition to the global data structure. This will add a argument to every node
bind/unbind functions, but instead of having all the arguments passed to mesh
slot bind/unbind function (global, material, dab), a tuple structure is used, it
contains all the arguments which will be passed to a node.

This tuple structure is unique per node type and sub node use a tuple based on
parent node tuple but with a pointer to node data. For example mesh slot tuple
constructor is:
RAS_MeshSlotNodeTuple(const RAS_DisplayArrayNodeTuple& displayArrayTuple,
RAS_DisplayArrayNodeData *displayArrayData)

It uses the DAB tuple of its parent node (which contains only data from
materials node) and the parent node data. The type of the tuple, the data passed
and the previous template arguments are now put in a info structure containing
only aliases.
The node data used to construct the tuple is gave to the node construct under a
pointer to allow share same node data for different node, for example the
instancing and non-instancing nodes in DAB sharing the same data.

The building of the tuple is made for the downward and upward tree, the downward
tree is the easiest. In this tree each node call its children node and before
calling they initialize a tuple of the child tuple type with the tuple passed to
the RAS_DownwardNode::Execute functions and the internal node data.

On the other hand upward tree required to refactor the iterator used. Firstly
the iterator bind the first node at its construction and unbind the last node at
its destruction, it makes the tuple passed to node always valid in the iterator.
Secondly the iterator use a conditional type as parent iterator, if the parent
of parent node type is not RAS_DummyNode then we use
RAS_UpwardNodeIterator<ParentNode> else RAS_DummyUpwardNodeIterator<ParentNode>.
The last type is a iterator without any member to parent iterator, by this
method we avoid using a pointer to avoid iterator recursion.

The inter-node data are already used for mesh slot and display array bucket,
mainly to get material data and vertex storage (VBO).
  • Loading branch information
panzergame committed May 25, 2017
1 parent e7ef47b commit 0aad135
Show file tree
Hide file tree
Showing 19 changed files with 483 additions and 300 deletions.
6 changes: 3 additions & 3 deletions source/gameengine/Ketsji/KX_BlenderMaterial.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -328,9 +328,9 @@ void KX_BlenderMaterial::DesactivateInstancing()
}
}

bool KX_BlenderMaterial::UsesLighting(RAS_Rasterizer *rasty) const
bool KX_BlenderMaterial::UsesLighting() const
{
if (!RAS_IPolyMaterial::UsesLighting(rasty))
if (!RAS_IPolyMaterial::UsesLighting())
return false;

if (m_shader && m_shader->Ok())
Expand Down Expand Up @@ -914,7 +914,7 @@ KX_PYMETHODDEF_DOC(KX_BlenderMaterial, getShader, "getShader()")
if (!m_shader->GetError()) {
// Set the material to use custom shader.
m_flag &= ~RAS_BLENDERGLSL;
m_scene->GetBucketManager()->ReleaseDisplayLists(this);
m_scene->GetBucketManager()->UpdateShaders(this);
}
}

Expand Down
2 changes: 1 addition & 1 deletion source/gameengine/Ketsji/KX_BlenderMaterial.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class KX_BlenderMaterial : public CValue, public RAS_IPolyMaterial
virtual bool UseInstancing() const;
virtual const std::string GetTextureName() const;
virtual Material *GetBlenderMaterial() const;
virtual bool UsesLighting(RAS_Rasterizer *rasty) const;
virtual bool UsesLighting() const;
virtual void GetRGBAColor(unsigned char *rgba) const;
virtual Scene *GetBlenderScene() const;
virtual SCA_IScene *GetScene() const;
Expand Down
2 changes: 1 addition & 1 deletion source/gameengine/Ketsji/KX_PythonInit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1092,7 +1092,7 @@ static PyObject *gPySetGLSLMaterialSetting(PyObject *,
// temporarily store the glsl settings in the scene for the GLSL materials
scene->GetBlenderScene()->gm.flag = gs->glslflag;
if (scene->GetBucketManager()) {
scene->GetBucketManager()->ReleaseDisplayLists();
scene->GetBucketManager()->UpdateShaders();
scene->GetBucketManager()->ReleaseMaterials();
}
}
Expand Down
44 changes: 26 additions & 18 deletions source/gameengine/Rasterizer/Node/RAS_BaseNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,59 +27,67 @@

/** RAS_BaseNode is a class wrapping a rendering class by simulating it with a
* binding and unbinding function.
* \param InfoType The class to wrap functions from.
* \param Leaf True if the node is a leaf of the tree.
* \param Args The arguments type to pass to the binding and unbinding functions.
* \param NodeInfo The node information.
*/
template <class InfoType, bool Leaf, class Args>
template <class NodeInfo>
class RAS_BaseNode
{
public:
using OwnerType = typename NodeInfo::OwnerType;
using TupleType = typename NodeInfo::TupleType;
using DataType = typename NodeInfo::DataType;
using Leaf = typename NodeInfo::Leaf;

/** The type of function to call for binding and unbinding.
* It takes as arguments the class the node is wrapping and the structure
* containing the arguments.
* It takes as arguments the class the node is wrapping and the tuple
* containing the data of the parent nodes.
*/
typedef std::function<void(InfoType *, const Args&)> Function;
typedef std::function<void(OwnerType *, const TupleType&)> Function;

protected:
/// An instance of the wrapped class.
InfoType *m_info;
OwnerType *m_owner;
DataType *m_data;

Function m_bind;
Function m_unbind;

public:
RAS_BaseNode(InfoType *info, Function bind, Function unbind)
:m_info(info),
RAS_BaseNode(OwnerType *owner, DataType *data, Function bind, Function unbind)
:m_owner(owner),
m_data(data),
m_bind(bind),
m_unbind(unbind)
{
}

RAS_BaseNode()
RAS_BaseNode() = default;

~RAS_BaseNode()
{
}

~RAS_BaseNode()
inline OwnerType *GetOwner() const
{
return m_owner;
}

inline InfoType *GetInfo() const
inline DataType *GetData() const
{
return m_info;
return m_data;
}

inline void Bind(const Args& args)
inline void Bind(const TupleType& tuple)
{
if (m_bind) {
m_bind(m_info, args);
m_bind(m_owner, tuple);
}
}

inline void Unbind(const Args& args)
inline void Unbind(const TupleType& tuple)
{
if (m_unbind) {
m_unbind(m_info, args);
m_unbind(m_owner, tuple);
}
}
};
Expand Down
52 changes: 35 additions & 17 deletions source/gameengine/Rasterizer/Node/RAS_DownwardNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#define __RAS_DOWNWARD_NODE_H__

#include "RAS_BaseNode.h"
#include "RAS_DummyNode.h"

#include <vector>

Expand All @@ -41,26 +42,28 @@
*
* \param _ChildType The children node type.
*/
template <class _ChildType, class InfoType, bool Leaf, class Args>
class RAS_DownwardNode : public RAS_BaseNode<InfoType, Leaf, Args>
template <class NodeInfo, class _ChildType>
class RAS_DownwardNode : public RAS_BaseNode<NodeInfo>
{
public:
using typename RAS_BaseNode<InfoType, Leaf, Args>::Function;
using typename RAS_BaseNode<NodeInfo>::OwnerType;
using typename RAS_BaseNode<NodeInfo>::DataType;
using typename RAS_BaseNode<NodeInfo>::TupleType;
using typename RAS_BaseNode<NodeInfo>::Leaf;
using typename RAS_BaseNode<NodeInfo>::Function;
typedef _ChildType ChildType;
typedef std::vector<ChildType *> ChildTypeList;

private:
ChildTypeList m_children;

public:
RAS_DownwardNode(InfoType *info, Function bind, Function unbind)
:RAS_BaseNode<InfoType, Leaf, Args>(info, bind, unbind)
RAS_DownwardNode(OwnerType *owner, DataType *data, Function bind, Function unbind)
:RAS_BaseNode<NodeInfo>(owner, data, bind, unbind)
{
}

RAS_DownwardNode()
{
}
RAS_DownwardNode() = default;

~RAS_DownwardNode()
{
Expand All @@ -71,7 +74,7 @@ class RAS_DownwardNode : public RAS_BaseNode<InfoType, Leaf, Args>
*/
inline bool GetValid() const
{
if (!Leaf) {
if (!Leaf()) {
return m_children.size() > 0;
}
return true;
Expand All @@ -87,37 +90,52 @@ class RAS_DownwardNode : public RAS_BaseNode<InfoType, Leaf, Args>

inline void Clear()
{
if (!Leaf) {
if (!Leaf()) {
m_children.clear();
}
}

/** Recursive function calling the bind function, call itsefl in children nodes
* and calling unbind function.
* \param Args The function arguments to use for binding and unbinding.
* \param tuple The function tuple argument to use for binding and unbinding.
*/
void Execute(const Args& args)
template <class T = ChildType>
inline typename std::enable_if<!std::is_same<T, RAS_DummyNode>::value, void>::type
Execute(const TupleType& tuple)
{
this->Bind(args);
this->Bind(tuple);

typename ChildType::TupleType childTuple(tuple, this->m_data);
for (ChildType *child : m_children) {
child->Execute(args);
child->Execute(childTuple);
}

this->Unbind(args);
this->Unbind(tuple);

// In the same time we can remove the children nodes.
Clear();
}

/// Function override to avoid try creating a RAS_DummyNodeTuple with arguments.
template <class T = ChildType>
inline typename std::enable_if<std::is_same<T, RAS_DummyNode>::value, void>::type
Execute(const TupleType& tuple)
{
this->Bind(tuple);

this->Unbind(tuple);

// No need to clear as dummy node are never instanced.
}

#ifdef DEBUG
void Print(unsigned short level, bool recursive)
void Print(unsigned short level, bool recursive) const
{
for (unsigned short i = 0; i < level; ++i) {
std::cout << "\t";
}

std::cout << boost::typeindex::type_id<InfoType>().pretty_name() << "(" << this->m_info << ") "<< std::endl;
std::cout << boost::typeindex::type_id<OwnerType>().pretty_name() << "(" << this->m_owner << ") "<< std::endl;

if (recursive) {
for (ChildType *child : m_children) {
Expand Down
35 changes: 10 additions & 25 deletions source/gameengine/Rasterizer/Node/RAS_DummyNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,39 +23,24 @@
#ifndef __RAS_DUMMY_NODE_H__
#define __RAS_DUMMY_NODE_H__

struct RAS_DummyNodeData
{
};

struct RAS_DummyNodeTuple
{
};

class RAS_DummyNode
{
public:
using DataType = RAS_DummyNodeData;
using TupleType = RAS_DummyNodeTuple;
typedef RAS_DummyNode ParentType;

void Print(unsigned short level, bool recursive)
{
}

template <class Args>
void Bind(const Args& args)
{
}

template <class Args>
void Unbind(const Args& args)
{
}

template <class Args>
void Execute(const Args& args)
{
}

ParentType *GetParent()
{
return nullptr;
}

template <class NodeType>
void AddChild(NodeType subNode)
{
}
};

#endif // __RAS_DUMMY_NODE_H__
Loading

0 comments on commit 0aad135

Please sign in to comment.