Browse Source

Speed up reading of heightfield data. (#1083)

Reading arrays of simple types in a single read instead of per element.

Fixes #1080
Jorrit Rouwe 1 year ago
parent
commit
2473382d3c
3 changed files with 30 additions and 15 deletions
  1. 13 4
      Jolt/Core/StreamIn.h
  2. 15 4
      Jolt/Core/StreamOut.h
  3. 2 7
      Jolt/Math/Vector.h

+ 13 - 4
Jolt/Core/StreamIn.h

@@ -25,14 +25,14 @@ public:
 	virtual bool		IsFailed() const = 0;
 
 	/// Read a primitive (e.g. float, int, etc.) from the binary stream
-	template <class T>
+	template <class T, std::enable_if_t<std::is_trivially_copyable_v<T>, bool> = true>
 	void				Read(T &outT)
 	{
 		ReadBytes(&outT, sizeof(outT));
 	}
 
 	/// Read a vector of primitives from the binary stream
-	template <class T, class A>
+	template <class T, class A, std::enable_if_t<std::is_trivially_copyable_v<T>, bool> = true>
 	void				Read(std::vector<T, A> &outT)
 	{
 		typename Array<T>::size_type len = outT.size(); // Initialize to previous array size, this is used for validation in the StateRecorder class
@@ -40,8 +40,17 @@ public:
 		if (!IsEOF() && !IsFailed())
 		{
 			outT.resize(len);
-			for (typename Array<T>::size_type i = 0; i < len; ++i)
-				Read(outT[i]);
+			if constexpr (std::is_same_v<T, Vec3> || std::is_same_v<T, DVec3> || std::is_same_v<T, DMat44>)
+			{
+				// These types have unused components that we don't want to read
+				for (typename Array<T>::size_type i = 0; i < len; ++i)
+					Read(outT[i]);
+			}
+			else
+			{
+				// Read all elements at once
+				ReadBytes(outT.data(), len * sizeof(T));
+			}
 		}
 		else
 			outT.clear();

+ 15 - 4
Jolt/Core/StreamOut.h

@@ -22,21 +22,32 @@ public:
 	virtual bool		IsFailed() const = 0;
 
 	/// Write a primitive (e.g. float, int, etc.) to the binary stream
-	template <class T>
+	template <class T, std::enable_if_t<std::is_trivially_copyable_v<T>, bool> = true>
 	void				Write(const T &inT)
 	{
 		WriteBytes(&inT, sizeof(inT));
 	}
 
 	/// Write a vector of primitives to the binary stream
-	template <class T, class A>
+	template <class T, class A, std::enable_if_t<std::is_trivially_copyable_v<T>, bool> = true>
 	void				Write(const std::vector<T, A> &inT)
 	{
 		typename Array<T>::size_type len = inT.size();
 		Write(len);
 		if (!IsFailed())
-			for (typename Array<T>::size_type i = 0; i < len; ++i)
-				Write(inT[i]);
+		{
+			if constexpr (std::is_same_v<T, Vec3> || std::is_same_v<T, DVec3> || std::is_same_v<T, DMat44>)
+			{
+				// These types have unused components that we don't want to write
+				for (typename Array<T>::size_type i = 0; i < len; ++i)
+					Write(inT[i]);
+			}
+			else
+			{
+				// Write all elements at once
+				WriteBytes(inT.data(), len * sizeof(T));
+			}
+		}
 	}
 
 	/// Write a string to the binary stream (writes the number of characters and then the characters)

+ 2 - 7
Jolt/Math/Vector.h

@@ -13,7 +13,7 @@ class [[nodiscard]] Vector
 public:
 	/// Constructor
 	inline						Vector() = default;
-	inline						Vector(const Vector &inRHS)								{ *this = inRHS; }
+	inline						Vector(const Vector &) = default;
 
 	/// Dimensions
 	inline uint					GetRows() const											{ return Rows; }
@@ -81,12 +81,7 @@ public:
 	}
 
 	/// Assignment
-	inline Vector &				operator = (const Vector &inV2)
-	{
-		for (uint r = 0; r < Rows; ++r)
-			mF32[r] = inV2.mF32[r];
-		return *this;
-	}
+	inline Vector &				operator = (const Vector &) = default;
 
 	/// Multiply vector with float
 	inline Vector				operator * (const float inV2) const