Panagiotis Christopoulos Charitos пре 13 година
родитељ
комит
602a8f9a4c
3 измењених фајлова са 152 додато и 150 уклоњено
  1. 6 18
      include/anki/resource/Material.h
  2. 143 128
      include/anki/util/Visitor.h
  3. 3 4
      src/scene/Renderable.cpp

+ 6 - 18
include/anki/resource/Material.h

@@ -43,9 +43,8 @@ public:
 	MaterialVariable(
 		const char* shaderProgVarName,
 		PassLevelToShaderProgramHashMap& sProgs,
-		bool init_,
-		uint8_t type_)
-		: type(type_), initialized(init_)
+		bool init_)
+		: initialized(init_)
 	{
 		init(shaderProgVarName, sProgs);
 	}
@@ -58,14 +57,14 @@ public:
 	template<typename T>
 	const T& getValue() const
 	{
-		ANKI_ASSERT(Base::getTypeId<T>() == type);
+		ANKI_ASSERT(Base::getVariadicTypeId<T>() == Base::getVisitableTypeId());
 		return static_cast<const MaterialVariableTemplate<T>*>(this)->get();
 	}
 
 	template<typename T>
 	void setValue(const T& x)
 	{
-		ANKI_ASSERT(Base::getTypeId<T>() == type);
+		ANKI_ASSERT(Base::getVariadicTypeId<T>() == Base::getVisitableTypeId());
 		static_cast<MaterialVariableTemplate<T>*>(this)->set(x);
 	}
 
@@ -91,8 +90,6 @@ public:
 	/// @}
 
 private:
-	uint8_t type; ///< Type id
-
 	/// If not initialized then there is no value given in the XML so it is
 	/// probably build in and the renderer should set the value on the shader
 	/// program setup
@@ -120,9 +117,9 @@ public:
 		PassLevelToShaderProgramHashMap& sProgs,
 		const Data& val,
 		bool init_)
-		: MaterialVariable(shaderProgVarName, sProgs, init_,
-			MaterialVariable::Base::getTypeId<Data>())
+		: MaterialVariable(shaderProgVarName, sProgs, init_)
 	{
+		setupVisitable(&data);
 		data = val;
 	}
 
@@ -143,15 +140,6 @@ public:
 	}
 	/// @}
 
-	void accept(MutableVisitor& v)
-	{
-		v.visit(data);
-	}
-	void accept(ConstVisitor& v) const
-	{
-		v.visit(data);
-	}
-
 private:
 	Data data;
 };

+ 143 - 128
include/anki/util/Visitor.h

@@ -4,157 +4,135 @@
 #ifndef ANKI_UTIL_VISITOR_H
 #define ANKI_UTIL_VISITOR_H
 
+#include "anki/util/Assert.h"
+#include <array>
+
 namespace anki {
 
 /// @addtogroup util
 /// @{
 
-namespace detail {
+namespace visitor_detail {
 
-//==============================================================================
-// ConstVisitor                                                                =
-//==============================================================================
-
-// Forward declaration
+/// A smart struct that given a type and a list of types finds a const integer
+/// indicating the type's position from the back of the list.
+///
+/// Example of usage:
+/// @code
+/// GetVariadicTypeId<int, float, std::string>::get<float> == 1
+/// GetVariadicTypeId<int, float, std::string>::get<int> == 0
+/// GetVariadicTypeId<int, float, std::string>::get<char> // Compiler error
+/// @endcode
 template<typename... Types>
-struct ConstVisitor;
-
-// Specialized for one and many
-template<typename First, typename... Types>
-struct ConstVisitor<First, Types...>: ConstVisitor<Types...>
-{
-	using ConstVisitor<Types...>::visit;
-	virtual void visit(const First&) = 0;
-};
-
-// Specialized for one
-template<typename First>
-struct ConstVisitor<First>
+struct GetVariadicTypeId
 {
-	virtual void visit(const First&) = 0;
-};
-
-//==============================================================================
-// MutableVisitor                                                              =
-//==============================================================================
+	// Forward
+	template<typename Type, typename... Types_>
+	struct Helper;
 
-// Forward declaration
-template<typename... Types>
-struct MutableVisitor;
+	// Declaration
+	template<typename Type, typename TFirst, typename... Types_>
+	struct Helper<Type, TFirst, Types_...>: Helper<Type, Types_...>
+	{};
 
-// Specialized for one and many
-template<typename First, typename... Types>
-struct MutableVisitor<First, Types...>: MutableVisitor<Types...>
-{
-	using MutableVisitor<Types...>::visit;
-	virtual void visit(First&) = 0;
-};
+	// Specialized
+	template<typename Type, typename... Types_>
+	struct Helper<Type, Type, Types_...>
+	{
+		static const int ID = sizeof...(Types_);
+	};
 
-// Specialized for one
-template<typename First>
-struct MutableVisitor<First>
-{
-	virtual void visit(First&) = 0;
+	/// Get the id
+	template<typename Type>
+	static constexpr int get()
+	{
+		return sizeof...(Types) - Helper<Type, Types...>::ID - 1;
+	}
 };
 
-//==============================================================================
-// GetTypeIdVisitor                                                            =
-//==============================================================================
-
-/// Visitor for getting the type id
+/// A struct that from a variadic arguments list it returnes the type using an
+/// ID.
+/// Example of usage:
+/// @code GetTypeUsingId<double, int, float>::DataType<0> @endcode
 template<typename... Types>
-struct GetTypeIdVisitor
+struct GetTypeUsingId
 {
-	// Forward
-	template<typename... Types_>
+	// Forward declaration
+	template<int id, typename... Types_>
 	struct Helper;
 
-	// Specialized for one and many
-	template<typename First, typename... Types_>
-	struct Helper<First, Types_...>: Helper<Types_...>
-	{
-		using Helper<Types_...>::visit;
-
-		void visit(const First& x)
-		{
-			Helper<Types_...>::id = sizeof...(Types_);
-		}
-	};
+	// Declaration
+	template<int id, typename TFirst, typename... Types_>
+	struct Helper<id, TFirst, Types_...>: Helper<id - 1, Types_...>
+	{};
 
-	// Specialized for one
-	template<typename First>
-	struct Helper<First>: ConstVisitor<Types...>
+	// Specialized
+	template<typename TFirst, typename... Types_>
+	struct Helper<0, TFirst, Types_...>
 	{
-		int id;
-
-		void visit(const First&)
-		{
-			id = 0;
-		}
+		typedef TFirst DataType;
 	};
 
-	typedef Helper<Types...> Type;
+	template<int id>
+	using DataType = typename Helper<id, Types...>::DataType;
 };
 
-//==============================================================================
-// DummyVisitor                                                                =
-//==============================================================================
-
-/// Implements the visit() function. The new visit() does nothing
-template<typename... Types>
-struct DummyVisitor
+/// A simple struct that creates an array of pointers to functions that have
+/// the same arguments but different body
+template<typename TVisitor, typename... Types>
+class JumpTable
 {
-	// Forward
-	template<typename... Types_>
-	struct Helper;
+public:
+	using FuncPtr = void (*)(TVisitor&, void*);
 
-	// Declare
-	template<typename First, typename... Types_>
-	struct Helper<First, Types_...>: Helper<Types_...>
+	JumpTable()
 	{
-		void visit(const First&)
-		{}
-	};
+		init<Types...>();
+	}
 
-	// Specialized for one
-	template<typename First>
-	struct Helper<First>: ConstVisitor<Types...>
+	/// Accessor
+	FuncPtr operator[](int i) const
 	{
-		void visit(const First&)
-		{}
-	};
+		return jumps[i];
+	}
 
-	typedef Helper<Types...> Type;
-};
+private:
+	/// Pointers to JumpPoint::visit static methods
+	std::array<FuncPtr, sizeof...(Types)> jumps;
 
-//==============================================================================
-// GetVisitableId                                                              =
-//==============================================================================
+	template<typename T>
+	static void visit(TVisitor& v, void* address)
+	{
+		v.template visit(*reinterpret_cast<T*>(address));
+	}
 
-// Forward
-template<typename Type, typename... Types>
-struct GetVisitableId;
+	template<typename TFirst>
+	void init()
+	{
+		jumps[0] = &visit<TFirst>;
+	}
 
-/// A smart struct that given a @a Type and a list of types defines a const
-/// integer indicating the @a Type's position from the back of the list. The
-/// integer is named ID
-/// @code
-/// GetVisitableId<float, int, float, std::string>::ID == 1
-/// GetVisitableId<int, int, float, std::string>::ID == 2
-/// GetVisitableId<std::string, int, float, std::string>::ID == 0
-/// @endcode
-template<typename Type, typename First, typename... Types>
-struct GetVisitableId<Type, First, Types...>: GetVisitableId<Type, Types...>
-{};
+	template<typename TFirst, typename TSecond, typename... Types_>
+	void init()
+	{
+		constexpr int i = sizeof...(Types) - sizeof...(Types_) - 1;
+		jumps[i] = &visit<TSecond>;
+		init<TFirst, Types_...>();
+	}
+};
 
-// Specialized
-template<typename Type, typename... Types>
-struct GetVisitableId<Type, Type, Types...>
+/// A simple struct that contains a static field with jump points
+template<typename TDerived, typename... Types>
+struct VisitorWrapper
 {
-	static const int ID = sizeof...(Types);
+	static const JumpTable<TDerived, Types...> jumpTable;
 };
 
-} // end namespace detail
+template<typename TDerived, typename... Types>
+const JumpTable<TDerived, Types...>
+	VisitorWrapper<TDerived, Types...>::jumpTable;
+
+} // end namespace visitor_detail
 
 //==============================================================================
 // Visitable                                                                   =
@@ -162,27 +140,64 @@ struct GetVisitableId<Type, Type, Types...>
 
 /// Visitable class
 template<typename... Types>
-struct Visitable
+class Visitable
 {
-	using MutableVisitor = detail::MutableVisitor<Types...>;
-	using ConstVisitor = detail::ConstVisitor<Types...>;
-	using GetTypeIdVisitor = typename detail::GetTypeIdVisitor<Types...>::Type;
-	using DummyVisitor = typename detail::DummyVisitor<Types...>::Type;
+public:
+	Visitable()
+	{}
+
+	template<typename T>
+	Visitable(T* t)
+	{
+		setupVisitable(t);
+	}
+
+	int getVisitableTypeId() const
+	{
+		return what;
+	}
+
+	template<typename T>
+	static constexpr int getVariadicTypeId()
+	{
+		return visitor_detail::GetVariadicTypeId<Types...>::template get<T>();
+	}
 
-	/// Visitor accept
-	virtual void accept(MutableVisitor& v) = 0;
-	/// Visitor accept
-	virtual void accept(ConstVisitor& v) const = 0;
+	/// Apply visitor
+	template<typename TVisitor>
+	void acceptVisitor(TVisitor& v)
+	{
+		ANKI_ASSERT(what != -1 && address != nullptr);
+		visitor_detail::VisitorWrapper<TVisitor, Types...>::
+			jumpTable[what](v, address);
+	}
 
-	/// Using the GetVisitableId get the id of the @a T
+	/// Apply visitor (const version)
+	template<typename TVisitor>
+	void acceptVisitor(TVisitor& v) const
+	{
+		ANKI_ASSERT(what != -1 && address != nullptr);
+		visitor_detail::VisitorWrapper<TVisitor, Types...>::
+			jumpTable[what](v, address);
+	}
+
+	/// Setup the data
 	template<typename T>
-	static constexpr int getTypeId()
+	void setupVisitable(T* t)
 	{
-		return sizeof...(Types) - detail::GetVisitableId<T, Types...>::ID - 1;
+		ANKI_ASSERT(t != nullptr); // Null arg
+		// Setting for second time? Now allowed
+		ANKI_ASSERT(address == nullptr && what == -1);
+		address = t;
+		what = visitor_detail::GetVariadicTypeId<Types...>::template get<T>();
 	}
+
+private:
+	int what = -1; ///< The type ID
+	void* address = nullptr; ///< The address to the data
 };
 /// @}
 
-} // end namespace
+} // end namespace anki
 
 #endif

+ 3 - 4
src/scene/Renderable.cpp

@@ -1,7 +1,6 @@
 #include "anki/scene/Renderable.h"
 #include "anki/resource/Material.h"
 #include "anki/resource/TextureResource.h"
-#include <boost/variant.hpp>
 
 namespace anki {
 
@@ -10,14 +9,14 @@ namespace anki {
 //==============================================================================
 
 /// Create a new property given a material variable
-struct CreateNewPropertyVisitor: boost::static_visitor<void>
+struct CreateNewPropertyVisitor
 {
 	const MaterialVariable* mvar;
 	PropertyMap* pmap;
 	Renderable::Properties* rprops;
 
 	template<typename T>
-	void operator()(const T&) const
+	void visit(const T&) const
 	{
 		MaterialVariableProperty<T>* prop = new MaterialVariableProperty<T>(
 			mvar->getName().c_str(),
@@ -45,7 +44,7 @@ void Renderable::init(PropertyMap& pmap)
 	for(const MaterialVariable& mv : mtl.getVariables())
 	{
 		vis.mvar = &mv;
-		boost::apply_visitor(vis, mv.getVariant());
+		mv.acceptVisitor(vis);
 	}
 }