Browse Source

Fix the motion vectors of moving objects

Panagiotis Christopoulos Charitos 3 years ago
parent
commit
148e477600

+ 1 - 1
.clang-format

@@ -124,7 +124,7 @@ PenaltyReturnTypeOnItsOwnLine: 60
 PenaltyIndentedWhitespace: 0
 PointerAlignment: Left
 ReflowComments:  true
-SortIncludes:    true
+SortIncludes:    false
 SortJavaStaticImport: Before
 SortUsingDeclarations: false
 SpaceAfterCStyleCast: false

+ 3 - 0
.gitignore

@@ -2,3 +2,6 @@ build*/*
 out/*
 .*
 CMakeSettings.json
+*.TMP
+AndroidProject_*
+*diff*

+ 5 - 0
AnKi/Importer/TinyExr.cpp

@@ -15,10 +15,15 @@
 #	pragma GCC diagnostic ignored "-Wunused-function"
 #	pragma GCC diagnostic ignored "-Wconversion"
 #	pragma GCC diagnostic ignored "-Wunused-variable"
+#elif ANKI_COMPILER_MSVC
+#	pragma warning(push)
+#	pragma warning(disable : 4018 4389 4189 4505 4706)
 #endif
 
 #include <ThirdParty/TinyExr/tinyexr.h>
 
 #if ANKI_COMPILER_GCC_COMPATIBLE
 #	pragma GCC diagnostic pop
+#elif ANKI_COMPILER_MSVC
+#	pragma warning(pop)
 #endif

+ 55 - 165
AnKi/Math/Mat.h

@@ -36,8 +36,8 @@ public:
 	using RowVec = TVec<T, I>;
 	using ColumnVec = TVec<T, J>;
 
-	static constexpr U ROW_SIZE = J; ///< Number of rows
-	static constexpr U COLUMN_SIZE = I; ///< Number of columns
+	static constexpr U ROW_COUNT = J; ///< Number of rows
+	static constexpr U COLUMN_COUNT = I; ///< Number of columns
 	static constexpr U SIZE = J * I; ///< Number of total elements
 	static constexpr Bool HAS_SIMD = I == 4 && std::is_same<T, F32>::value && ANKI_ENABLE_SIMD;
 	static constexpr Bool HAS_MAT4_SIMD = J == 4 && I == 4 && std::is_same<T, F32>::value && ANKI_ENABLE_SIMD;
@@ -50,46 +50,21 @@ public:
 	}
 
 	/// Copy.
-	TMat(ANKI_ENABLE_ARG(const TMat&, !HAS_SIMD) b)
+	TMat(const TMat& b)
 	{
-		for(U i = 0; i < N; i++)
-		{
-			m_arr1[i] = b.m_arr1[i];
-		}
-	}
-
-	/// Copy.
-	TMat(ANKI_ENABLE_ARG(const TMat&, HAS_SIMD) b)
-	{
-		for(U i = 0; i < J; i++)
-		{
-			m_simd[i] = b.m_simd[i];
-		}
-	}
-
-	ANKI_ENABLE_METHOD(!HAS_SIMD)
-	explicit TMat(const T f)
-	{
-		for(T& x : m_arr1)
+		for(U i = 0; i < ROW_COUNT; i++)
 		{
-			x = f;
+			m_rows[i] = b.m_rows[i];
 		}
 	}
 
-#if ANKI_ENABLE_SIMD
-	ANKI_ENABLE_METHOD(HAS_SIMD)
 	explicit TMat(const T f)
 	{
-		for(U i = 0; i < J; i++)
+		for(U i = 0; i < ROW_COUNT; i++)
 		{
-#	if ANKI_SIMD_SSE
-			m_simd[i] = _mm_set1_ps(f);
-#	else
-			m_simd[i] = {f, f, f, f};
-#	endif
+			m_rows[i] = RowVec(f);
 		}
 	}
-#endif
 
 	explicit TMat(const T arr[])
 	{
@@ -182,6 +157,16 @@ public:
 	{
 	}
 
+	/// Set a 4x4 matrix using a 3x4 for the first 3 rows and a vec4 for the 4rth row.
+	ANKI_ENABLE_METHOD(J == 4 && I == 4)
+	explicit TMat(const TMat<T, 3, 4>& m3, const TVec<T, 4>& row3)
+	{
+		setRow(0, m3.getRow(0));
+		setRow(1, m3.getRow(1));
+		setRow(2, m3.getRow(2));
+		setRow(3, row3);
+	}
+
 	// 3x4 specific constructors
 
 	ANKI_ENABLE_METHOD(J == 3 && I == 4)
@@ -287,132 +272,52 @@ public:
 	/// @{
 
 	/// Copy.
-	TMat& operator=(ANKI_ENABLE_ARG(const TMat&, !HAS_SIMD) b)
-	{
-		for(U n = 0; n < N; n++)
-		{
-			m_arr1[n] = b.m_arr1[n];
-		}
-		return *this;
-	}
-
-	/// Copy.
-	TMat& operator=(ANKI_ENABLE_ARG(const TMat&, HAS_SIMD) b)
+	TMat& operator=(const TMat& b)
 	{
-		for(U i = 0; i < J; i++)
+		for(U i = 0; i < ROW_COUNT; ++i)
 		{
-			m_simd[i] = b.m_simd[i];
+			m_rows[i] = b.m_rows[i];
 		}
 		return *this;
 	}
 
-	ANKI_ENABLE_METHOD(!HAS_SIMD)
-	TMat operator+(const TMat& b) const
-	{
-		TMat c;
-		for(U n = 0; n < N; n++)
-		{
-			c.m_arr1[n] = m_arr1[n] + b.m_arr1[n];
-		}
-		return c;
-	}
-
-#if ANKI_ENABLE_SIMD
-	ANKI_ENABLE_METHOD(HAS_SIMD)
 	TMat operator+(const TMat& b) const
 	{
 		TMat c;
-		for(U i = 0; i < J; i++)
+		for(U i = 0; i < ROW_COUNT; ++i)
 		{
-#	if ANKI_SIMD_SSE
-			c.m_simd[i] = _mm_add_ps(m_simd[i], b.m_simd[i]);
-#	else
-			c.m_simd[i] = m_simd[i] + b.m_simd[i];
-#	endif
+			c.m_rows[i] = m_rows[i] + b.m_rows[i];
 		}
 		return c;
 	}
-#endif
 
-	ANKI_ENABLE_METHOD(!HAS_SIMD)
-	TMat& operator+=(const TMat& b)
-	{
-		for(U n = 0; n < N; n++)
-		{
-			m_arr1[n] += b.m_arr1[n];
-		}
-		return *this;
-	}
-
-#if ANKI_ENABLE_SIMD
-	ANKI_ENABLE_METHOD(HAS_SIMD)
 	TMat& operator+=(const TMat& b)
 	{
-		for(U i = 0; i < J; i++)
+		for(U i = 0; i < ROW_COUNT; ++i)
 		{
-#	if ANKI_SIMD_SSE
-			m_simd[i] = _mm_add_ps(m_simd[i], b.m_simd[i]);
-#	else
-			m_simd[i] += b.m_simd[i];
-#	endif
+			m_rows[i] += b.m_rows[i];
 		}
 		return *this;
 	}
-#endif
 
-	ANKI_ENABLE_METHOD(!HAS_SIMD)
-	TMat operator-(const TMat& b) const
-	{
-		TMat c;
-		for(U n = 0; n < N; n++)
-		{
-			c.m_arr1[n] = m_arr1[n] - b.m_arr1[n];
-		}
-		return c;
-	}
-
-#if ANKI_ENABLE_SIMD
-	ANKI_ENABLE_METHOD(HAS_SIMD)
 	TMat operator-(const TMat& b) const
 	{
 		TMat c;
-		for(U i = 0; i < J; i++)
+		for(U i = 0; i < ROW_COUNT; ++i)
 		{
-#	if ANKI_SIMD_SSE
-			c.m_simd[i] = _mm_sub_ps(m_simd[i], b.m_simd[i]);
-#	else
-			c.m_simd[i] = m_simd[i] - b.m_simd[i];
-#	endif
+			c.m_rows[i] = m_rows[i] - b.m_rows[i];
 		}
 		return c;
 	}
-#endif
 
-	ANKI_ENABLE_METHOD(!HAS_SIMD)
-	TMat& operator-=(const TMat& b)
-	{
-		for(U n = 0; n < N; n++)
-		{
-			m_arr1[n] -= b.m_arr1[n];
-		}
-		return *this;
-	}
-
-#if ANKI_ENABLE_SIMD
-	ANKI_ENABLE_METHOD(HAS_SIMD)
 	TMat& operator-=(const TMat& b)
 	{
-		for(U i = 0; i < J; i++)
+		for(U i = 0; i < ROW_COUNT; ++i)
 		{
-#	if ANKI_SIMD_SSE
-			m_simd[i] = _mm_sub_ps(m_simd[i], b.m_simd[i]);
-#	else
-			m_simd[i] -= b.m_simd[i];
-#	endif
+			m_rows[i] -= b.m_rows[i];
 		}
 		return *this;
 	}
-#endif
 
 	ANKI_ENABLE_METHOD(J == I && !HAS_MAT4_SIMD)
 	TMat operator*(const TMat& b) const
@@ -510,18 +415,18 @@ public:
 	TMat operator+(const T f) const
 	{
 		TMat out;
-		for(U i = 0; i < N; i++)
+		for(U i = 0; i < ROW_COUNT; ++i)
 		{
-			out.m_arr1[i] = m_arr1[i] + f;
+			out.m_rows[i] = m_rows[i] + f;
 		}
 		return out;
 	}
 
 	TMat& operator+=(const T f)
 	{
-		for(U i = 0; i < N; i++)
+		for(U i = 0; i < ROW_COUNT; ++i)
 		{
-			m_arr1[i] += f;
+			m_rows[i] += f;
 		}
 		return *this;
 	}
@@ -529,18 +434,18 @@ public:
 	TMat operator-(const T f) const
 	{
 		TMat out;
-		for(U i = 0; i < N; i++)
+		for(U i = 0; i < ROW_COUNT; ++i)
 		{
-			out.m_arr1[i] = m_arr1[i] - f;
+			out.m_rows[i] = m_rows[i] - f;
 		}
 		return out;
 	}
 
 	TMat& operator-=(const T f)
 	{
-		for(U i = 0; i < N; i++)
+		for(U i = 0; i < ROW_COUNT; ++i)
 		{
-			m_arr1[i] -= f;
+			m_rows[i] -= f;
 		}
 		return *this;
 	}
@@ -548,18 +453,18 @@ public:
 	TMat operator*(const T f) const
 	{
 		TMat out;
-		for(U i = 0; i < N; i++)
+		for(U i = 0; i < ROW_COUNT; ++i)
 		{
-			out.m_arr1[i] = m_arr1[i] * f;
+			out.m_rows[i] = m_rows[i] * f;
 		}
 		return out;
 	}
 
 	TMat& operator*=(const T f)
 	{
-		for(U i = 0; i < N; i++)
+		for(U i = 0; i < ROW_COUNT; ++i)
 		{
-			m_arr1[i] *= f;
+			m_rows[i] *= f;
 		}
 		return *this;
 	}
@@ -568,9 +473,9 @@ public:
 	{
 		ANKI_ASSERT(f != T(0));
 		TMat out;
-		for(U i = 0; i < N; i++)
+		for(U i = 0; i < ROW_COUNT; ++i)
 		{
-			out.m_arr1[i] = m_arr1[i] / f;
+			out.m_rows[i] = m_rows[i] / f;
 		}
 		return out;
 	}
@@ -578,9 +483,9 @@ public:
 	TMat& operator/=(const T f)
 	{
 		ANKI_ASSERT(f != T(0));
-		for(U i = 0; i < N; i++)
+		for(U i = 0; i < ROW_COUNT; ++i)
 		{
-			m_arr1[i] /= f;
+			m_rows[i] /= f;
 		}
 		return *this;
 	}
@@ -628,19 +533,9 @@ public:
 
 	/// @name Other
 	/// @{
-	ANKI_ENABLE_METHOD(!HAS_SIMD)
 	void setRow(const U j, const RowVec& v)
 	{
-		for(U i = 0; i < I; i++)
-		{
-			m_arr2[j][i] = v[i];
-		}
-	}
-
-	ANKI_ENABLE_METHOD(HAS_SIMD)
-	void setRow(const U j, const RowVec& v)
-	{
-		m_simd[j] = v.getSimd();
+		m_rows[j] = v;
 	}
 
 	void setRows(const RowVec& a, const RowVec& b, const RowVec& c)
@@ -657,14 +552,9 @@ public:
 		setRow(3, d);
 	}
 
-	RowVec getRow(const U j) const
+	const RowVec& getRow(const U j) const
 	{
-		RowVec out;
-		for(U i = 0; i < I; i++)
-		{
-			out[i] = m_arr2[j][i];
-		}
-		return out;
+		return m_rows[j];
 	}
 
 	void getRows(RowVec& a, RowVec& b, RowVec& c) const
@@ -674,9 +564,9 @@ public:
 		c = getRow(2);
 	}
 
+	ANKI_ENABLE_METHOD(J > 3)
 	void getRows(RowVec& a, RowVec& b, RowVec& c, RowVec& d) const
 	{
-		static_assert(J > 3, "Wrong matrix");
 		getRows(a, b, c);
 		d = getRow(3);
 	}
@@ -696,9 +586,9 @@ public:
 		setColumn(2, c);
 	}
 
+	ANKI_ENABLE_METHOD(I > 3)
 	void setColumns(const ColumnVec& a, const ColumnVec& b, const ColumnVec& c, const ColumnVec& d)
 	{
-		static_assert(I > 3, "Check column number");
 		setColumns(a, b, c);
 		setColumn(3, d);
 	}
@@ -720,9 +610,9 @@ public:
 		c = getColumn(2);
 	}
 
+	ANKI_ENABLE_METHOD(I > 3)
 	void getColumns(ColumnVec& a, ColumnVec& b, ColumnVec& c, ColumnVec& d) const
 	{
-		static_assert(I > 3, "Check column number");
 		getColumns(a, b, c);
 		d = getColumn(3);
 	}
@@ -814,8 +704,7 @@ public:
 		m(2, 2) = T(1);
 	}
 
-	/// It rotates "this" in the axis defined by the rotation AND not the
-	/// world axis
+	/// It rotates "this" in the axis defined by the rotation AND not the world axis.
 	void rotateXAxis(const T rad)
 	{
 		TMat& m = *this;
@@ -1008,7 +897,7 @@ public:
 
 	void setTranslationPart(const ColumnVec& v)
 	{
-		if(ROW_SIZE == 4)
+		if(ROW_COUNT == 4)
 		{
 			ANKI_ASSERT(isZero<T>(v[3] - T(1)) && "w should be 1");
 		}
@@ -1578,11 +1467,12 @@ protected:
 	/// @{
 	union
 	{
-		Array<T, N> m_arr1;
-		Array2d<T, J, I> m_arr2;
 		T m_carr1[N]; ///< For easier debugging with gdb
 		T m_carr2[J][I]; ///< For easier debugging with gdb
+		Array<T, N> m_arr1;
+		Array2d<T, J, I> m_arr2;
 		SimdArray m_simd;
+		Array<RowVec, J> m_rows;
 	};
 	/// @}
 };

+ 1 - 1
AnKi/Renderer/Dbg.cpp

@@ -67,7 +67,7 @@ void Dbg::run(RenderPassWorkContext& rgraphCtx, const RenderingContext& ctx)
 	dctx.m_viewMatrix = ctx.m_renderQueue->m_viewMatrix;
 	dctx.m_viewProjectionMatrix = ctx.m_renderQueue->m_viewProjectionMatrix;
 	dctx.m_projectionMatrix = ctx.m_renderQueue->m_projectionMatrix;
-	dctx.m_cameraTransform = ctx.m_renderQueue->m_viewMatrix.getInverse();
+	dctx.m_cameraTransform = ctx.m_renderQueue->m_cameraTransform;
 	dctx.m_stagingGpuAllocator = &m_r->getStagingGpuMemory();
 	dctx.m_frameAllocator = ctx.m_tempAllocator;
 	dctx.m_commandBuffer = cmdb;

+ 20 - 20
AnKi/Renderer/Drawer.cpp

@@ -14,7 +14,7 @@
 namespace anki {
 
 /// Drawer's context
-class DrawContext
+class RenderableDrawer::Context
 {
 public:
 	RenderQueueDrawContext m_queueCtx;
@@ -39,10 +39,9 @@ RenderableDrawer::~RenderableDrawer()
 {
 }
 
-void RenderableDrawer::drawRange(RenderingTechnique technique, const Mat4& viewMat, const Mat4& viewProjMat,
-								 const Mat4& prevViewProjMat, CommandBufferPtr cmdb, SamplerPtr sampler,
-								 const RenderableQueueElement* begin, const RenderableQueueElement* end, U32 minLod,
-								 U32 maxLod)
+void RenderableDrawer::drawRange(RenderingTechnique technique, const RenderableDrawerArguments& args,
+								 const RenderableQueueElement* begin, const RenderableQueueElement* end,
+								 CommandBufferPtr& cmdb)
 {
 	ANKI_ASSERT(begin && end && begin < end);
 
@@ -52,10 +51,11 @@ void RenderableDrawer::drawRange(RenderingTechnique technique, const Mat4& viewM
 		MaterialGlobalUniforms* globalUniforms =
 			static_cast<MaterialGlobalUniforms*>(m_r->getStagingGpuMemory().allocateFrame(
 				sizeof(MaterialGlobalUniforms), StagingGpuMemoryType::UNIFORM, globalUniformsToken));
-		globalUniforms->m_viewProjectionMatrix = viewProjMat;
 
-		globalUniforms->m_viewMatrix = Mat3x4(viewMat);
-		globalUniforms->m_cameraTransform = Mat3x4(viewMat.getInverse());
+		globalUniforms->m_viewProjectionMatrix = args.m_viewProjectionMatrix;
+		globalUniforms->m_previousViewProjectionMatrix = args.m_previousViewProjectionMatrix;
+		globalUniforms->m_viewMatrix = args.m_viewMatrix;
+		globalUniforms->m_cameraTransform = args.m_cameraTransform;
 
 		cmdb->bindUniformBuffer(MATERIAL_SET_GLOBAL, MATERIAL_BINDING_GLOBAL_UNIFORMS, globalUniformsToken.m_buffer,
 								globalUniformsToken.m_offset, globalUniformsToken.m_range);
@@ -63,24 +63,24 @@ void RenderableDrawer::drawRange(RenderingTechnique technique, const Mat4& viewM
 
 	// More globals
 	cmdb->bindAllBindless(MATERIAL_SET_BINDLESS);
-	cmdb->bindSampler(MATERIAL_SET_GLOBAL, MATERIAL_BINDING_TRILINEAR_REPEAT_SAMPLER, sampler);
+	cmdb->bindSampler(MATERIAL_SET_GLOBAL, MATERIAL_BINDING_TRILINEAR_REPEAT_SAMPLER, args.m_sampler);
 
 	// Set a few things
-	DrawContext ctx;
-	ctx.m_queueCtx.m_viewMatrix = viewMat;
-	ctx.m_queueCtx.m_viewProjectionMatrix = viewProjMat;
+	Context ctx;
+	ctx.m_queueCtx.m_viewMatrix = args.m_viewMatrix;
+	ctx.m_queueCtx.m_viewProjectionMatrix = args.m_viewProjectionMatrix;
 	ctx.m_queueCtx.m_projectionMatrix = Mat4::getIdentity(); // TODO
-	ctx.m_queueCtx.m_previousViewProjectionMatrix = prevViewProjMat;
-	ctx.m_queueCtx.m_cameraTransform = ctx.m_queueCtx.m_viewMatrix.getInverse();
+	ctx.m_queueCtx.m_previousViewProjectionMatrix = args.m_previousViewProjectionMatrix;
+	ctx.m_queueCtx.m_cameraTransform = args.m_cameraTransform;
 	ctx.m_queueCtx.m_stagingGpuAllocator = &m_r->getStagingGpuMemory();
 	ctx.m_queueCtx.m_commandBuffer = cmdb;
 	ctx.m_queueCtx.m_key = RenderingKey(technique, 0, 1, false, false);
 	ctx.m_queueCtx.m_debugDraw = false;
-	ctx.m_queueCtx.m_sampler = sampler;
+	ctx.m_queueCtx.m_sampler = args.m_sampler;
 
-	ANKI_ASSERT(minLod < MAX_LOD_COUNT && maxLod < MAX_LOD_COUNT);
-	ctx.m_minLod = U8(minLod);
-	ctx.m_maxLod = U8(maxLod);
+	ANKI_ASSERT(args.m_minLod < MAX_LOD_COUNT && args.m_maxLod < MAX_LOD_COUNT && args.m_minLod <= args.m_maxLod);
+	ctx.m_minLod = U8(args.m_minLod);
+	ctx.m_maxLod = U8(args.m_maxLod);
 
 	for(; begin != end; ++begin)
 	{
@@ -93,7 +93,7 @@ void RenderableDrawer::drawRange(RenderingTechnique technique, const Mat4& viewM
 	flushDrawcall(ctx);
 }
 
-void RenderableDrawer::flushDrawcall(DrawContext& ctx)
+void RenderableDrawer::flushDrawcall(Context& ctx)
 {
 	ctx.m_queueCtx.m_key.setLod(ctx.m_cachedRenderElementLods[0]);
 	ctx.m_queueCtx.m_key.setInstanceCount(ctx.m_cachedRenderElementCount);
@@ -109,7 +109,7 @@ void RenderableDrawer::flushDrawcall(DrawContext& ctx)
 	ctx.m_cachedRenderElementCount = 0;
 }
 
-void RenderableDrawer::drawSingle(DrawContext& ctx)
+void RenderableDrawer::drawSingle(Context& ctx)
 {
 	if(ctx.m_cachedRenderElementCount == MAX_INSTANCE_COUNT)
 	{

+ 21 - 7
AnKi/Renderer/Drawer.h

@@ -13,11 +13,25 @@ namespace anki {
 
 // Forward
 class Renderer;
-class DrawContext;
 
 /// @addtogroup renderer
 /// @{
 
+/// @memberof RenderableDrawer.
+class RenderableDrawerArguments
+{
+public:
+	// The matrices are whatever the drawing needs. Sometimes they contain jittering and sometimes they don't.
+	Mat3x4 m_viewMatrix;
+	Mat3x4 m_cameraTransform;
+	Mat4 m_viewProjectionMatrix;
+	Mat4 m_previousViewProjectionMatrix;
+
+	SamplerPtr m_sampler;
+	U32 m_minLod = 0;
+	U32 m_maxLod = MAX_LOD_COUNT - 1;
+};
+
 /// It uses the render queue to batch and render.
 class RenderableDrawer
 {
@@ -31,17 +45,17 @@ public:
 
 	~RenderableDrawer();
 
-	void drawRange(RenderingTechnique technique, const Mat4& viewMat, const Mat4& viewProjMat,
-				   const Mat4& prevViewProjMat, CommandBufferPtr cmdb, SamplerPtr sampler,
-				   const RenderableQueueElement* begin, const RenderableQueueElement* end, U32 minLod = 0,
-				   U32 maxLod = MAX_LOD_COUNT - 1);
+	void drawRange(RenderingTechnique technique, const RenderableDrawerArguments& args,
+				   const RenderableQueueElement* begin, const RenderableQueueElement* end, CommandBufferPtr& cmdb);
 
 private:
+	class Context;
+
 	Renderer* m_r;
 
-	void flushDrawcall(DrawContext& ctx);
+	void flushDrawcall(Context& ctx);
 
-	void drawSingle(DrawContext& ctx);
+	void drawSingle(Context& ctx);
 };
 /// @}
 

+ 9 - 5
AnKi/Renderer/ForwardShading.cpp

@@ -49,13 +49,17 @@ void ForwardShading::run(const RenderingContext& ctx, RenderPassWorkContext& rgr
 								   m_r->getShadowMapping().getShadowmapRt());
 		bindStorage(cmdb, set, MATERIAL_BINDING_CLUSTERS, rsrc.m_clustersToken);
 
+		RenderableDrawerArguments args;
+		args.m_viewMatrix = ctx.m_matrices.m_view;
+		args.m_cameraTransform = ctx.m_matrices.m_cameraTransform;
+		args.m_viewProjectionMatrix = ctx.m_matrices.m_viewProjectionJitter;
+		args.m_previousViewProjectionMatrix = ctx.m_prevMatrices.m_viewProjectionJitter; // Not sure about that
+		args.m_sampler = m_r->getSamplers().m_trilinearRepeatAnisoResolutionScalingBias;
+
 		// Start drawing
-		m_r->getSceneDrawer().drawRange(RenderingTechnique::FORWARD, ctx.m_matrices.m_view,
-										ctx.m_matrices.m_viewProjectionJitter,
-										ctx.m_prevMatrices.m_viewProjectionJitter, cmdb,
-										m_r->getSamplers().m_trilinearRepeatAnisoResolutionScalingBias,
+		m_r->getSceneDrawer().drawRange(RenderingTechnique::FORWARD, args,
 										ctx.m_renderQueue->m_forwardShadingRenderables.getBegin() + start,
-										ctx.m_renderQueue->m_forwardShadingRenderables.getBegin() + end);
+										ctx.m_renderQueue->m_forwardShadingRenderables.getBegin() + end, cmdb);
 
 		// Restore state
 		cmdb->setDepthWrite(true);

+ 11 - 10
AnKi/Renderer/GBuffer.cpp

@@ -120,6 +120,13 @@ void GBuffer::runInThread(const RenderingContext& ctx, RenderPassWorkContext& rg
 		cmdb->setVrsRate(VrsRate::_1x1);
 	}
 
+	RenderableDrawerArguments args;
+	args.m_viewMatrix = ctx.m_matrices.m_view;
+	args.m_cameraTransform = ctx.m_matrices.m_cameraTransform;
+	args.m_viewProjectionMatrix = ctx.m_matrices.m_viewProjectionJitter;
+	args.m_previousViewProjectionMatrix = ctx.m_matrices.m_jitter * ctx.m_prevMatrices.m_viewProjection;
+	args.m_sampler = m_r->getSamplers().m_trilinearRepeatAnisoResolutionScalingBias;
+
 	// First do early Z (if needed)
 	if(earlyZStart < earlyZEnd)
 	{
@@ -129,12 +136,9 @@ void GBuffer::runInThread(const RenderingContext& ctx, RenderPassWorkContext& rg
 		}
 
 		ANKI_ASSERT(earlyZStart < earlyZEnd && earlyZEnd <= I32(earlyZCount));
-		m_r->getSceneDrawer().drawRange(RenderingTechnique::GBUFFER_EARLY_Z, ctx.m_matrices.m_view,
-										ctx.m_matrices.m_viewProjectionJitter,
-										ctx.m_matrices.m_jitter * ctx.m_prevMatrices.m_viewProjection, cmdb,
-										m_r->getSamplers().m_trilinearRepeatAnisoResolutionScalingBias,
+		m_r->getSceneDrawer().drawRange(RenderingTechnique::GBUFFER_EARLY_Z, args,
 										ctx.m_renderQueue->m_earlyZRenderables.getBegin() + earlyZStart,
-										ctx.m_renderQueue->m_earlyZRenderables.getBegin() + earlyZEnd);
+										ctx.m_renderQueue->m_earlyZRenderables.getBegin() + earlyZEnd, cmdb);
 
 		// Restore state for the color write
 		if(colorStart < colorEnd)
@@ -152,12 +156,9 @@ void GBuffer::runInThread(const RenderingContext& ctx, RenderPassWorkContext& rg
 		cmdb->setDepthCompareOperation(CompareOperation::LESS_EQUAL);
 
 		ANKI_ASSERT(colorStart < colorEnd && colorEnd <= I32(ctx.m_renderQueue->m_renderables.getSize()));
-		m_r->getSceneDrawer().drawRange(RenderingTechnique::GBUFFER, ctx.m_matrices.m_view,
-										ctx.m_matrices.m_viewProjectionJitter,
-										ctx.m_matrices.m_jitter * ctx.m_prevMatrices.m_viewProjection, cmdb,
-										m_r->getSamplers().m_trilinearRepeatAnisoResolutionScalingBias,
+		m_r->getSceneDrawer().drawRange(RenderingTechnique::GBUFFER, args,
 										ctx.m_renderQueue->m_renderables.getBegin() + colorStart,
-										ctx.m_renderQueue->m_renderables.getBegin() + colorEnd);
+										ctx.m_renderQueue->m_renderables.getBegin() + colorEnd, cmdb);
 	}
 }
 

+ 25 - 12
AnKi/Renderer/IndirectDiffuseProbes.cpp

@@ -569,11 +569,18 @@ void IndirectDiffuseProbes::runGBufferInThread(RenderPassWorkContext& rgraphCtx,
 			const RenderQueue& rqueue = *probe.m_renderQueues[faceIdx];
 
 			ANKI_ASSERT(localStart >= 0 && localEnd <= faceDrawcallCount);
-			m_r->getSceneDrawer().drawRange(
-				RenderingTechnique::GBUFFER, rqueue.m_viewMatrix, rqueue.m_viewProjectionMatrix,
-				Mat4::getIdentity(), // Don't care about prev mats since we don't care about velocity
-				cmdb, m_r->getSamplers().m_trilinearRepeat, rqueue.m_renderables.getBegin() + localStart,
-				rqueue.m_renderables.getBegin() + localEnd, MAX_LOD_COUNT - 1, MAX_LOD_COUNT - 1);
+
+			RenderableDrawerArguments args;
+			args.m_viewMatrix = rqueue.m_viewMatrix;
+			args.m_cameraTransform = Mat3x4::getIdentity(); // Don't care
+			args.m_viewProjectionMatrix = rqueue.m_viewProjectionMatrix;
+			args.m_previousViewProjectionMatrix = Mat4::getIdentity(); // Don't care
+			args.m_sampler = m_r->getSamplers().m_trilinearRepeat;
+			args.m_minLod = args.m_maxLod = MAX_LOD_COUNT - 1;
+
+			m_r->getSceneDrawer().drawRange(RenderingTechnique::GBUFFER, args,
+											rqueue.m_renderables.getBegin() + localStart,
+											rqueue.m_renderables.getBegin() + localEnd, cmdb);
 		}
 
 		drawcallCount += faceDrawcallCount;
@@ -620,12 +627,18 @@ void IndirectDiffuseProbes::runShadowmappingInThread(RenderPassWorkContext& rgra
 			cmdb->setScissor(rez * faceIdx, 0, rez, rez);
 
 			ANKI_ASSERT(localStart >= 0 && localEnd <= faceDrawcallCount);
-			m_r->getSceneDrawer().drawRange(
-				RenderingTechnique::SHADOW, cascadeRenderQueue.m_viewMatrix, cascadeRenderQueue.m_viewProjectionMatrix,
-				Mat4::getIdentity(), // Don't care about prev matrices here
-				cmdb, m_r->getSamplers().m_trilinearRepeatAniso,
-				cascadeRenderQueue.m_renderables.getBegin() + localStart,
-				cascadeRenderQueue.m_renderables.getBegin() + localEnd, MAX_LOD_COUNT - 1, MAX_LOD_COUNT - 1);
+
+			RenderableDrawerArguments args;
+			args.m_viewMatrix = cascadeRenderQueue.m_viewMatrix;
+			args.m_cameraTransform = Mat3x4::getIdentity(); // Don't care
+			args.m_viewProjectionMatrix = cascadeRenderQueue.m_viewProjectionMatrix;
+			args.m_previousViewProjectionMatrix = Mat4::getIdentity(); // Don't care
+			args.m_sampler = m_r->getSamplers().m_trilinearRepeatAniso;
+			args.m_maxLod = args.m_minLod = MAX_LOD_COUNT - 1;
+
+			m_r->getSceneDrawer().drawRange(RenderingTechnique::SHADOW, args,
+											cascadeRenderQueue.m_renderables.getBegin() + localStart,
+											cascadeRenderQueue.m_renderables.getBegin() + localEnd, cmdb);
 		}
 	}
 
@@ -654,7 +667,7 @@ void IndirectDiffuseProbes::runLightShading(RenderPassWorkContext& rgraphCtx, In
 		TraditionalDeferredLightShadingDrawInfo dsInfo;
 		dsInfo.m_viewProjectionMatrix = rqueue.m_viewProjectionMatrix;
 		dsInfo.m_invViewProjectionMatrix = rqueue.m_viewProjectionMatrix.getInverse();
-		dsInfo.m_cameraPosWSpace = rqueue.m_cameraTransform.getTranslationPart();
+		dsInfo.m_cameraPosWSpace = rqueue.m_cameraTransform.getTranslationPart().xyz1();
 		dsInfo.m_viewport = UVec4(faceIdx * m_tileSize, 0, m_tileSize, m_tileSize);
 		dsInfo.m_gbufferTexCoordsScale = Vec2(1.0f / F32(m_tileSize * 6), 1.0f / F32(m_tileSize));
 		dsInfo.m_gbufferTexCoordsBias = Vec2(0.0f, 0.0f);

+ 1 - 1
AnKi/Renderer/LensFlare.cpp

@@ -150,7 +150,7 @@ void LensFlare::runDrawFlares(const RenderingContext& ctx, CommandBufferPtr& cmd
 
 		// Compute position
 		Vec4 lfPos = Vec4(flareEl.m_worldPosition, 1.0);
-		Vec4 posClip = ctx.m_renderQueue->m_viewProjectionMatrix * lfPos;
+		Vec4 posClip = ctx.m_matrices.m_viewProjectionJitter * lfPos;
 
 		/*if(posClip.x() > posClip.w() || posClip.x() < -posClip.w() || posClip.y() > posClip.w()
 			|| posClip.y() < -posClip.w())

+ 27 - 14
AnKi/Renderer/ProbeReflections.cpp

@@ -326,7 +326,7 @@ void ProbeReflections::runGBuffer(RenderPassWorkContext& rgraphCtx)
 	ANKI_ASSERT(m_ctx.m_probe);
 	ANKI_TRACE_SCOPED_EVENT(R_CUBE_REFL);
 	const ReflectionProbeQueueElement& probe = *m_ctx.m_probe;
-	const CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
+	CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
 
 	I32 start, end;
 	U32 startu, endu;
@@ -350,11 +350,18 @@ void ProbeReflections::runGBuffer(RenderPassWorkContext& rgraphCtx)
 
 			const RenderQueue& rqueue = *probe.m_renderQueues[faceIdx];
 			ANKI_ASSERT(localStart >= 0 && localEnd <= faceDrawcallCount);
-			m_r->getSceneDrawer().drawRange(
-				RenderingTechnique::GBUFFER, rqueue.m_viewMatrix, rqueue.m_viewProjectionMatrix,
-				Mat4::getIdentity(), // Don't care about prev mats
-				cmdb, m_r->getSamplers().m_trilinearRepeat, rqueue.m_renderables.getBegin() + localStart,
-				rqueue.m_renderables.getBegin() + localEnd, MAX_LOD_COUNT - 1, MAX_LOD_COUNT - 1);
+
+			RenderableDrawerArguments args;
+			args.m_viewMatrix = rqueue.m_viewMatrix;
+			args.m_cameraTransform = rqueue.m_cameraTransform;
+			args.m_viewProjectionMatrix = rqueue.m_viewProjectionMatrix;
+			args.m_previousViewProjectionMatrix = Mat4::getIdentity(); // Don't care about prev mats
+			args.m_sampler = m_r->getSamplers().m_trilinearRepeat;
+			args.m_minLod = args.m_maxLod = MAX_LOD_COUNT - 1;
+
+			m_r->getSceneDrawer().drawRange(RenderingTechnique::GBUFFER, args,
+											rqueue.m_renderables.getBegin() + localStart,
+											rqueue.m_renderables.getBegin() + localEnd, cmdb);
 		}
 	}
 
@@ -377,7 +384,7 @@ void ProbeReflections::runLightShading(U32 faceIdx, const RenderingContext& rctx
 	TraditionalDeferredLightShadingDrawInfo dsInfo;
 	dsInfo.m_viewProjectionMatrix = rqueue.m_viewProjectionMatrix;
 	dsInfo.m_invViewProjectionMatrix = rqueue.m_viewProjectionMatrix.getInverse();
-	dsInfo.m_cameraPosWSpace = rqueue.m_cameraTransform.getTranslationPart();
+	dsInfo.m_cameraPosWSpace = rqueue.m_cameraTransform.getTranslationPart().xyz1();
 	dsInfo.m_viewport = UVec4(0, 0, m_lightShading.m_tileSize, m_lightShading.m_tileSize);
 	dsInfo.m_gbufferTexCoordsScale =
 		Vec2(1.0f / F32(m_lightShading.m_tileSize * 6), 1.0f / F32(m_lightShading.m_tileSize));
@@ -696,7 +703,7 @@ void ProbeReflections::runShadowMapping(RenderPassWorkContext& rgraphCtx)
 	start = I32(startu);
 	end = I32(endu);
 
-	const CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
+	CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
 	cmdb->setPolygonOffset(1.0f, 1.0f);
 
 	I32 drawcallCount = 0;
@@ -720,12 +727,18 @@ void ProbeReflections::runShadowMapping(RenderPassWorkContext& rgraphCtx)
 			cmdb->setScissor(rez * faceIdx, 0, rez, rez);
 
 			ANKI_ASSERT(localStart >= 0 && localEnd <= faceDrawcallCount);
-			m_r->getSceneDrawer().drawRange(
-				RenderingTechnique::SHADOW, cascadeRenderQueue.m_viewMatrix, cascadeRenderQueue.m_viewProjectionMatrix,
-				Mat4::getIdentity(), // Don't care about prev matrices here
-				cmdb, m_r->getSamplers().m_trilinearRepeatAniso,
-				cascadeRenderQueue.m_renderables.getBegin() + localStart,
-				cascadeRenderQueue.m_renderables.getBegin() + localEnd, MAX_LOD_COUNT - 1, MAX_LOD_COUNT - 1);
+
+			RenderableDrawerArguments args;
+			args.m_viewMatrix = cascadeRenderQueue.m_viewMatrix;
+			args.m_cameraTransform = Mat3x4::getIdentity(); // Don't care
+			args.m_viewProjectionMatrix = cascadeRenderQueue.m_viewProjectionMatrix;
+			args.m_previousViewProjectionMatrix = Mat4::getIdentity(); // Don't care
+			args.m_sampler = m_r->getSamplers().m_trilinearRepeatAniso;
+			args.m_minLod = args.m_maxLod = MAX_LOD_COUNT - 1;
+
+			m_r->getSceneDrawer().drawRange(RenderingTechnique::SHADOW, args,
+											cascadeRenderQueue.m_renderables.getBegin() + localStart,
+											cascadeRenderQueue.m_renderables.getBegin() + localEnd, cmdb);
 		}
 	}
 }

+ 2 - 2
AnKi/Renderer/RenderQueue.h

@@ -19,8 +19,8 @@ namespace anki {
 class RenderingMatrices
 {
 public:
-	Mat4 m_cameraTransform;
-	Mat4 m_viewMatrix;
+	Mat3x4 m_cameraTransform;
+	Mat3x4 m_viewMatrix;
 	Mat4 m_projectionMatrix;
 	Mat4 m_viewProjectionMatrix;
 	Mat4 m_previousViewProjectionMatrix;

+ 2 - 2
AnKi/Renderer/Renderer.cpp

@@ -310,11 +310,11 @@ Error Renderer::populateRenderGraph(RenderingContext& ctx)
 
 	ctx.m_matrices.m_jitter = m_jitteredMats8x[m_frameCount & (m_jitteredMats8x.getSize() - 1)];
 	ctx.m_matrices.m_projectionJitter = ctx.m_matrices.m_jitter * ctx.m_matrices.m_projection;
-	ctx.m_matrices.m_viewProjectionJitter = ctx.m_matrices.m_projectionJitter * ctx.m_matrices.m_view;
+	ctx.m_matrices.m_viewProjectionJitter =
+		ctx.m_matrices.m_projectionJitter * Mat4(ctx.m_matrices.m_view, Vec4(0.0f, 0.0f, 0.0f, 1.0f));
 	ctx.m_matrices.m_invertedViewProjectionJitter = ctx.m_matrices.m_viewProjectionJitter.getInverse();
 	ctx.m_matrices.m_invertedViewProjection = ctx.m_matrices.m_viewProjection.getInverse();
 	ctx.m_matrices.m_invertedProjectionJitter = ctx.m_matrices.m_projectionJitter.getInverse();
-	ctx.m_matrices.m_invertedView = ctx.m_matrices.m_view.getInverse();
 
 	ctx.m_matrices.m_reprojection =
 		ctx.m_matrices.m_jitter * ctx.m_prevMatrices.m_viewProjection * ctx.m_matrices.m_invertedViewProjectionJitter;

+ 11 - 6
AnKi/Renderer/ShadowMapping.cpp

@@ -221,14 +221,19 @@ void ShadowMapping::runShadowMapping(RenderPassWorkContext& rgraphCtx)
 		cmdb->setViewport(work.m_viewport[0], work.m_viewport[1], work.m_viewport[2], work.m_viewport[3]);
 		cmdb->setScissor(work.m_viewport[0], work.m_viewport[1], work.m_viewport[2], work.m_viewport[3]);
 
-		m_r->getSceneDrawer().drawRange(RenderingTechnique::SHADOW, work.m_renderQueue->m_viewMatrix,
-										work.m_renderQueue->m_viewProjectionMatrix,
-										Mat4::getIdentity(), // Don't care about prev matrices here
-										cmdb, m_r->getSamplers().m_trilinearRepeatAniso,
+		RenderableDrawerArguments args;
+		args.m_viewMatrix = work.m_renderQueue->m_viewMatrix;
+		args.m_cameraTransform = Mat3x4::getIdentity(); // Don't care
+		args.m_viewProjectionMatrix = work.m_renderQueue->m_viewProjectionMatrix;
+		args.m_previousViewProjectionMatrix = Mat4::getIdentity(); // Don't care
+		args.m_sampler = m_r->getSamplers().m_trilinearRepeatAniso;
+		args.m_minLod = args.m_maxLod = work.m_renderQueueElementsLod;
+
+		m_r->getSceneDrawer().drawRange(RenderingTechnique::SHADOW, args,
 										work.m_renderQueue->m_renderables.getBegin() + work.m_firstRenderableElement,
 										work.m_renderQueue->m_renderables.getBegin() + work.m_firstRenderableElement
 											+ work.m_renderableElementCount,
-										work.m_renderQueueElementsLod, work.m_renderQueueElementsLod);
+										cmdb);
 	}
 }
 
@@ -708,7 +713,7 @@ void ShadowMapping::processLights(RenderingContext& ctx, U32& threadCountForScra
 
 		// Allocate tiles
 		U32 faceIdx = 0;
-		TileAllocatorResult subResult;
+		TileAllocatorResult subResult = TileAllocatorResult::ALLOCATION_FAILED;
 		UVec4 atlasViewport;
 		UVec4 scratchViewport;
 		const U32 localDrawcallCount = light.m_shadowRenderQueue->m_renderables.getSize();

+ 2 - 2
AnKi/Scene/Components/FrustumComponent.cpp

@@ -96,13 +96,13 @@ Bool FrustumComponent::updateInternal()
 	if(m_trfMarkedForUpdate)
 	{
 		updated = true;
-		m_viewMat = Mat4(m_trf.getInverse());
+		m_viewMat = Mat3x4(m_trf.getInverse());
 	}
 
 	// Updates that are affected by transform & shape updates
 	if(updated)
 	{
-		m_viewProjMat = m_projMat * m_viewMat;
+		m_viewProjMat = m_projMat * Mat4(m_viewMat, Vec4(0.0f, 0.0f, 0.0f, 1.0f));
 		m_shapeMarkedForUpdate = false;
 		m_trfMarkedForUpdate = false;
 

+ 2 - 2
AnKi/Scene/Components/FrustumComponent.h

@@ -237,7 +237,7 @@ public:
 		return m_projMat;
 	}
 
-	const Mat4& getViewMatrix() const
+	const Mat3x4& getViewMatrix() const
 	{
 		return m_viewMat;
 	}
@@ -414,7 +414,7 @@ private:
 
 	Transform m_trf = Transform::getIdentity();
 	Mat4 m_projMat = Mat4::getIdentity(); ///< Projection matrix
-	Mat4 m_viewMat = Mat4::getIdentity(); ///< View matrix
+	Mat3x4 m_viewMat = Mat3x4::getIdentity(); ///< View matrix
 	Mat4 m_viewProjMat = Mat4::getIdentity(); ///< View projection matrix
 	Mat4 m_prevViewProjMat = Mat4::getIdentity();
 

+ 3 - 3
AnKi/Scene/DebugDrawer.cpp

@@ -218,7 +218,7 @@ void DebugDrawer2::drawLines(ConstWeakArray<Mat4> mvps, const Vec4& color, F32 l
 	cmdb->drawArrays(PrimitiveTopology::LINES, linePositions.getSize(), mvps.getSize());
 }
 
-void DebugDrawer2::drawBillboardTextures(const Mat4& projMat, const Mat4& viewMat, ConstWeakArray<Vec3> positions,
+void DebugDrawer2::drawBillboardTextures(const Mat4& projMat, const Mat3x4& viewMat, ConstWeakArray<Vec3> positions,
 										 const Vec4& color, Bool ditherFailedDepth, TextureViewPtr tex,
 										 SamplerPtr sampler, Vec2 billboardSize,
 										 StagingGpuMemoryPool& stagingGpuAllocator, CommandBufferPtr& cmdb) const
@@ -246,7 +246,7 @@ void DebugDrawer2::drawBillboardTextures(const Mat4& projMat, const Mat4& viewMa
 	Mat4* pmvps = static_cast<Mat4*>(stagingGpuAllocator.allocateFrame(
 		sizeof(Mat4) * positions.getSize() + sizeof(Vec4), StagingGpuMemoryType::UNIFORM, unisToken));
 
-	const Mat4 camTrf = viewMat.getInverse();
+	const Mat4 camTrf = Mat4(viewMat, Vec4(0.0f, 0.0f, 0.0f, 1.0f)).getInverse();
 	const Vec3 zAxis = camTrf.getZAxis().xyz().getNormalized();
 	Vec3 yAxis = Vec3(0.0f, 1.0f, 0.0f);
 	const Vec3 xAxis = yAxis.cross(zAxis).getNormalized();
@@ -260,7 +260,7 @@ void DebugDrawer2::drawBillboardTextures(const Mat4& projMat, const Mat4& viewMa
 		scale(0, 0) *= billboardSize.x();
 		scale(1, 1) *= billboardSize.y();
 
-		*pmvps = projMat * viewMat * Mat4(pos.xyz1(), rot * scale, 1.0f);
+		*pmvps = projMat * Mat4(viewMat, Vec4(0.0f, 0.0f, 0.0f, 1.0f)) * Mat4(pos.xyz1(), rot * scale, 1.0f);
 		++pmvps;
 	}
 

+ 2 - 2
AnKi/Scene/DebugDrawer.h

@@ -58,12 +58,12 @@ public:
 		drawLines(ConstWeakArray<Mat4>(&mvp, 1), color, lineSize, ditherFailedDepth, points, stagingGpuAllocator, cmdb);
 	}
 
-	void drawBillboardTextures(const Mat4& projMat, const Mat4& viewMat, ConstWeakArray<Vec3> positions,
+	void drawBillboardTextures(const Mat4& projMat, const Mat3x4& viewMat, ConstWeakArray<Vec3> positions,
 							   const Vec4& color, Bool ditherFailedDepth, TextureViewPtr tex, SamplerPtr sampler,
 							   Vec2 billboardSize, StagingGpuMemoryPool& stagingGpuAllocator,
 							   CommandBufferPtr& cmdb) const;
 
-	void drawBillboardTexture(const Mat4& projMat, const Mat4& viewMat, Vec3 position, const Vec4& color,
+	void drawBillboardTexture(const Mat4& projMat, const Mat3x4& viewMat, Vec3 position, const Vec4& color,
 							  Bool ditherFailedDepth, TextureViewPtr tex, SamplerPtr sampler, Vec2 billboardSize,
 							  StagingGpuMemoryPool& stagingGpuAllocator, CommandBufferPtr& cmdb) const
 	{

+ 42 - 27
AnKi/Scene/Visibility.cpp

@@ -83,7 +83,7 @@ void VisibilityContext::submitNewWork(const FrustumComponent& frc, const Frustum
 		return;
 	}
 
-	rqueue.m_cameraTransform = Mat4(frc.getWorldTransform());
+	rqueue.m_cameraTransform = Mat3x4(frc.getWorldTransform());
 	rqueue.m_viewMatrix = frc.getViewMatrix();
 	rqueue.m_projectionMatrix = frc.getProjectionMatrix();
 	rqueue.m_viewProjectionMatrix = frc.getViewProjectionMatrix();
@@ -181,7 +181,8 @@ void FillRasterizerWithCoverageTask::fill()
 	// 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);
+	m_frcCtx->m_r->prepare(Mat4(m_frcCtx->m_frc->getViewMatrix(), Vec4(0.0f, 0.0f, 0.0f, 1.0f)),
+						   m_frcCtx->m_frc->getProjectionMatrix(), width, height);
 
 	// Do the work
 	m_frcCtx->m_r->fillDepthBuffer(depthBuff);
@@ -288,52 +289,66 @@ void VisibilityTestTask::test(ThreadHive& hive, U32 taskId)
 		Bool wantNode = false;
 
 		const RenderComponent* rc = nullptr;
-		wantNode |= !!(enabledVisibilityTests & FrustumComponentVisibilityTestFlag::RENDER_COMPONENTS)
-					&& (rc = node.tryGetFirstComponentOfType<RenderComponent>());
+		wantNode = wantNode
+				   || !!(enabledVisibilityTests & FrustumComponentVisibilityTestFlag::RENDER_COMPONENTS)
+						  && (rc = node.tryGetFirstComponentOfType<RenderComponent>()) != nullptr;
 
-		wantNode |= !!(enabledVisibilityTests & FrustumComponentVisibilityTestFlag::SHADOW_CASTERS)
-					&& (rc = node.tryGetFirstComponentOfType<RenderComponent>())
-					&& !!(rc->getFlags() & RenderComponentFlag::CASTS_SHADOW);
+		wantNode = wantNode
+				   || !!(enabledVisibilityTests & FrustumComponentVisibilityTestFlag::SHADOW_CASTERS)
+						  && (rc = node.tryGetFirstComponentOfType<RenderComponent>()) != nullptr
+						  && !!(rc->getFlags() & RenderComponentFlag::CASTS_SHADOW);
 
 		const RenderComponent* rtRc = nullptr;
-		wantNode |= !!(enabledVisibilityTests & FrustumComponentVisibilityTestFlag::ALL_RAY_TRACING)
-					&& (rtRc = node.tryGetFirstComponentOfType<RenderComponent>()) && rtRc->getSupportsRayTracing();
+		wantNode = wantNode
+				   || !!(enabledVisibilityTests & FrustumComponentVisibilityTestFlag::ALL_RAY_TRACING)
+						  && (rtRc = node.tryGetFirstComponentOfType<RenderComponent>()) != nullptr
+						  && rtRc->getSupportsRayTracing();
 
 		const LightComponent* lc = nullptr;
-		wantNode |= !!(enabledVisibilityTests & FrustumComponentVisibilityTestFlag::LIGHT_COMPONENTS)
-					&& (lc = node.tryGetFirstComponentOfType<LightComponent>());
+		wantNode = wantNode
+				   || !!(enabledVisibilityTests & FrustumComponentVisibilityTestFlag::LIGHT_COMPONENTS)
+						  && (lc = node.tryGetFirstComponentOfType<LightComponent>()) != nullptr;
 
 		const LensFlareComponent* lfc = nullptr;
-		wantNode |= !!(enabledVisibilityTests & FrustumComponentVisibilityTestFlag::LENS_FLARE_COMPONENTS)
-					&& (lfc = node.tryGetFirstComponentOfType<LensFlareComponent>());
+		wantNode = wantNode
+				   || !!(enabledVisibilityTests & FrustumComponentVisibilityTestFlag::LENS_FLARE_COMPONENTS)
+						  && (lfc = node.tryGetFirstComponentOfType<LensFlareComponent>()) != nullptr;
 
 		const ReflectionProbeComponent* reflc = nullptr;
-		wantNode |= !!(enabledVisibilityTests & FrustumComponentVisibilityTestFlag::REFLECTION_PROBES)
-					&& (reflc = node.tryGetFirstComponentOfType<ReflectionProbeComponent>());
+		wantNode = wantNode
+				   || !!(enabledVisibilityTests & FrustumComponentVisibilityTestFlag::REFLECTION_PROBES)
+						  && (reflc = node.tryGetFirstComponentOfType<ReflectionProbeComponent>()) != nullptr;
 
 		DecalComponent* decalc = nullptr;
-		wantNode |= !!(enabledVisibilityTests & FrustumComponentVisibilityTestFlag::DECALS)
-					&& (decalc = node.tryGetFirstComponentOfType<DecalComponent>());
+		wantNode = wantNode
+				   || !!(enabledVisibilityTests & FrustumComponentVisibilityTestFlag::DECALS)
+						  && (decalc = node.tryGetFirstComponentOfType<DecalComponent>()) != nullptr;
 
 		const FogDensityComponent* fogc = nullptr;
-		wantNode |= !!(enabledVisibilityTests & FrustumComponentVisibilityTestFlag::FOG_DENSITY_COMPONENTS)
-					&& (fogc = node.tryGetFirstComponentOfType<FogDensityComponent>());
+		wantNode = wantNode
+				   || !!(enabledVisibilityTests & FrustumComponentVisibilityTestFlag::FOG_DENSITY_COMPONENTS)
+						  && (fogc = node.tryGetFirstComponentOfType<FogDensityComponent>()) != nullptr;
 
 		GlobalIlluminationProbeComponent* giprobec = nullptr;
-		wantNode |= !!(enabledVisibilityTests & FrustumComponentVisibilityTestFlag::GLOBAL_ILLUMINATION_PROBES)
-					&& (giprobec = node.tryGetFirstComponentOfType<GlobalIlluminationProbeComponent>());
+		wantNode =
+			wantNode
+			|| !!(enabledVisibilityTests & FrustumComponentVisibilityTestFlag::GLOBAL_ILLUMINATION_PROBES)
+				   && (giprobec = node.tryGetFirstComponentOfType<GlobalIlluminationProbeComponent>()) != nullptr;
 
 		GenericGpuComputeJobComponent* computec = nullptr;
-		wantNode |= !!(enabledVisibilityTests & FrustumComponentVisibilityTestFlag::GENERIC_COMPUTE_JOB_COMPONENTS)
-					&& (computec = node.tryGetFirstComponentOfType<GenericGpuComputeJobComponent>());
+		wantNode = wantNode
+				   || !!(enabledVisibilityTests & FrustumComponentVisibilityTestFlag::GENERIC_COMPUTE_JOB_COMPONENTS)
+						  && (computec = node.tryGetFirstComponentOfType<GenericGpuComputeJobComponent>()) != nullptr;
 
 		UiComponent* uic = nullptr;
-		wantNode |= !!(enabledVisibilityTests & FrustumComponentVisibilityTestFlag::UI_COMPONENTS)
-					&& (uic = node.tryGetFirstComponentOfType<UiComponent>());
+		wantNode = wantNode
+				   || !!(enabledVisibilityTests & FrustumComponentVisibilityTestFlag::UI_COMPONENTS)
+						  && (uic = node.tryGetFirstComponentOfType<UiComponent>()) != nullptr;
 
 		SkyboxComponent* skyboxc = nullptr;
-		wantNode |= !!(enabledVisibilityTests & FrustumComponentVisibilityTestFlag::SKYBOX)
-					&& (skyboxc = node.tryGetFirstComponentOfType<SkyboxComponent>());
+		wantNode = wantNode
+				   || !!(enabledVisibilityTests & FrustumComponentVisibilityTestFlag::SKYBOX)
+						  && (skyboxc = node.tryGetFirstComponentOfType<SkyboxComponent>()) != nullptr;
 
 		if(ANKI_UNLIKELY(!wantNode))
 		{

+ 4 - 2
AnKi/Shaders/GBufferCommon.glsl

@@ -62,7 +62,8 @@ layout(location = 6) out Vec3 out_normalTangentSpace;
 #		endif
 
 #		if ANKI_VELOCITY || ANKI_BONES
-layout(location = 7) out Vec2 out_velocity;
+layout(location = 7) out Vec3 out_prevClipXyw;
+layout(location = 8) out Vec3 out_crntClipXyw;
 #		endif
 #	endif // ANKI_TECHNIQUE == RENDERING_TECHNIQUE_GBUFFER
 
@@ -89,7 +90,8 @@ layout(location = 6) in Vec3 in_normalTangentSpace;
 #		endif
 
 #		if ANKI_VELOCITY || ANKI_BONES
-layout(location = 7) in Vec2 in_velocity;
+layout(location = 7) in Vec3 in_prevClipXyw;
+layout(location = 8) in Vec3 in_crntClipXyw;
 #		endif
 #	endif // ANKI_TECHNIQUE == RENDERING_TECHNIQUE_GBUFFER
 

+ 10 - 8
AnKi/Shaders/GBufferGeneric.ankiprog

@@ -164,19 +164,17 @@ void velocity()
 	const Vec3 prevLocalPos = g_prevPosition;
 
 #	if ANKI_VELOCITY
+	// Object is also moving
 	const Mat3x4 trf = u_renderableGpuViews[gl_InstanceIndex].m_previousWorldTransform;
 #	else
+	// Object is a skin that is not moving
 	const Mat3x4 trf = u_renderableGpuViews[gl_InstanceIndex].m_worldTransform;
 #	endif
 
-	const Vec4 v4 = u_globalUniforms.m_viewProjectionMatrix * Vec4(trf * Vec4(prevLocalPos, 1.0), 1.0);
+	const Vec4 v4 = u_globalUniforms.m_previousViewProjectionMatrix * Vec4(trf * Vec4(prevLocalPos, 1.0), 1.0);
 
-	const Vec2 prevNdc = v4.xy / v4.w;
-
-	const Vec2 crntNdc = gl_Position.xy / gl_Position.w;
-
-	// It's NDC_TO_UV(prevNdc) - NDC_TO_UV(crntNdc) or:
-	out_velocity = (prevNdc - crntNdc) * 0.5;
+	out_prevClipXyw = v4.xyw;
+	out_crntClipXyw = gl_Position.xyw;
 }
 #endif
 
@@ -361,7 +359,11 @@ void main()
 #	endif
 
 #	if ANKI_VELOCITY || ANKI_BONES
-	const Vec2 velocity = in_velocity;
+	const Vec2 prevNdc = in_prevClipXyw.xy / in_prevClipXyw.z;
+	const Vec2 crntNdc = in_crntClipXyw.xy / in_crntClipXyw.z;
+
+	// It's NDC_TO_UV(prevNdc) - NDC_TO_UV(crntNdc) or:
+	const Vec2 velocity = (prevNdc - crntNdc) * 0.5;
 #	else
 	const Vec2 velocity = Vec2(1.0);
 #	endif

+ 13 - 14
AnKi/Shaders/Include/ClusteredShadingTypes.h

@@ -189,25 +189,24 @@ ANKI_SHADER_STATIC_ASSERT(sizeof(GlobalIlluminationProbe) == _ANKI_SIZEOF_Global
 /// Common matrices.
 struct CommonMatrices
 {
-	Mat4 m_cameraTransform ANKI_CPP_CODE(= Mat4::getIdentity());
-	Mat4 m_view ANKI_CPP_CODE(= Mat4::getIdentity());
-	Mat4 m_projection ANKI_CPP_CODE(= Mat4::getIdentity());
-	Mat4 m_viewProjection ANKI_CPP_CODE(= Mat4::getIdentity());
+	Mat3x4 m_cameraTransform;
+	Mat3x4 m_view;
+	Mat4 m_projection;
+	Mat4 m_viewProjection;
 
-	Mat4 m_jitter ANKI_CPP_CODE(= Mat4::getIdentity());
-	Mat4 m_projectionJitter ANKI_CPP_CODE(= Mat4::getIdentity());
-	Mat4 m_viewProjectionJitter ANKI_CPP_CODE(= Mat4::getIdentity());
+	Mat4 m_jitter;
+	Mat4 m_projectionJitter;
+	Mat4 m_viewProjectionJitter;
 
-	Mat4 m_invertedViewProjectionJitter ANKI_CPP_CODE(= Mat4::getIdentity()); ///< To unproject in world space.
-	Mat4 m_invertedViewProjection ANKI_CPP_CODE(= Mat4::getIdentity());
-	Mat4 m_invertedProjectionJitter ANKI_CPP_CODE(= Mat4::getIdentity()); ///< To unproject in view space.
-	Mat4 m_invertedView ANKI_CPP_CODE(= Mat4::getIdentity());
+	Mat4 m_invertedViewProjectionJitter; ///< To unproject in world space.
+	Mat4 m_invertedViewProjection;
+	Mat4 m_invertedProjectionJitter; ///< To unproject in view space.
 
 	/// It's being used to reproject a clip space position of the current frame to the previous frame. Its value should
 	/// be m_jitter * m_prevFrame.m_viewProjection * m_invertedViewProjectionJitter. At first it unprojects the current
 	/// position to world space, all fine here. Then it projects to the previous frame as if the previous frame was
 	/// using the current frame's jitter matrix.
-	Mat4 m_reprojection ANKI_CPP_CODE(= Mat4::getIdentity());
+	Mat4 m_reprojection;
 
 	/// To unproject to view space. Jitter not considered.
 	/// @code
@@ -215,9 +214,9 @@ struct CommonMatrices
 	/// const Vec2 xy = ndc * m_unprojectionParameters.xy * z;
 	/// pos = Vec3(xy, z);
 	/// @endcode
-	Vec4 m_unprojectionParameters ANKI_CPP_CODE(= Vec4(0.0f));
+	Vec4 m_unprojectionParameters;
 };
-const U32 _ANKI_SIZEOF_CommonMatrices = 12u * ANKI_SIZEOF(Mat4) + 1u * ANKI_SIZEOF(Vec4);
+const U32 _ANKI_SIZEOF_CommonMatrices = 43u * ANKI_SIZEOF(Vec4);
 ANKI_SHADER_STATIC_ASSERT(sizeof(CommonMatrices) == _ANKI_SIZEOF_CommonMatrices);
 
 /// Common uniforms for light shading passes.

+ 2 - 1
AnKi/Shaders/Include/MaterialTypes.h

@@ -13,10 +13,11 @@ ANKI_BEGIN_NAMESPACE
 struct MaterialGlobalUniforms
 {
 	Mat4 m_viewProjectionMatrix;
+	Mat4 m_previousViewProjectionMatrix;
 	Mat3x4 m_viewMatrix;
 	Mat3x4 m_cameraTransform;
 };
-ANKI_SHADER_STATIC_ASSERT(sizeof(MaterialGlobalUniforms) == 10 * sizeof(Vec4));
+ANKI_SHADER_STATIC_ASSERT(sizeof(MaterialGlobalUniforms) == 14 * sizeof(Vec4));
 
 const U32 MATERIAL_SET_BINDLESS = 0u;
 const U32 MATERIAL_SET_GLOBAL = 1u;

+ 1 - 2
AnKi/Shaders/VolumetricLightingAccumulation.ankiprog

@@ -71,8 +71,7 @@ Vec3 worldPosInsideClusterAndZViewSpace(Vec3 relativePos, out F32 negativeZViewS
 	const Vec2 xyViewSpace = UV_TO_NDC(uv) * u_clusteredShading.m_matrices.m_unprojectionParameters.xy * zViewSpace;
 
 	// Get the final world pos
-	const Vec4 worldPos4 = u_clusteredShading.m_matrices.m_invertedView * Vec4(xyViewSpace, zViewSpace, 1.0);
-	const Vec3 worldPos = worldPos4.xyz;
+	const Vec3 worldPos = u_clusteredShading.m_matrices.m_cameraTransform * Vec4(xyViewSpace, zViewSpace, 1.0);
 
 	return worldPos;
 }

+ 6 - 3
AnKi/Util/Logger.cpp

@@ -180,21 +180,24 @@ void Logger::defaultSystemMessageHandler(void*, const LoggerMessageInfo& info)
 			info.m_tid, endTerminalColor, terminalColor, info.m_msg, info.m_file, info.m_line, info.m_func,
 			endTerminalColor);
 #elif ANKI_OS_WINDOWS
-	WORD attribs = BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED;
+	WORD attribs = 0;
 	FILE* out = NULL;
 	switch(info.m_type)
 	{
 	case LoggerMessageType::NORMAL:
-	case LoggerMessageType::VERBOSE:
 		attribs |= FOREGROUND_GREEN;
 		out = stdout;
 		break;
+	case LoggerMessageType::VERBOSE:
+		attribs |= FOREGROUND_BLUE;
+		out = stdout;
+		break;
 	case LoggerMessageType::ERROR:
 		attribs |= FOREGROUND_RED;
 		out = stderr;
 		break;
 	case LoggerMessageType::WARNING:
-		attribs |= FOREGROUND_RED;
+		attribs |= FOREGROUND_RED | FOREGROUND_GREEN;
 		out = stderr;
 		break;
 	case LoggerMessageType::FATAL:

+ 39 - 35
AnKi/Util/SparseArray.inl.h

@@ -63,54 +63,58 @@ template<typename T, typename TIndex>
 template<typename TAlloc>
 TIndex SparseArray<T, TIndex>::insert(TAlloc& alloc, Index idx, Value& val)
 {
-start:
-	const Index desiredPos = mod(idx);
-	const Index endPos = mod(desiredPos + m_probeCount);
-	Index pos = desiredPos;
-
-	while(pos != endPos)
+	while(true)
 	{
-		Metadata& meta = m_metadata[pos];
-		Value& crntVal = m_elements[pos];
+		const Index desiredPos = mod(idx);
+		const Index endPos = mod(desiredPos + m_probeCount);
+		Index pos = desiredPos;
 
-		if(!meta.m_alive)
+		while(pos != endPos)
 		{
-			// Empty slot was found, construct in-place
+			Metadata& meta = m_metadata[pos];
+			Value& crntVal = m_elements[pos];
 
-			meta.m_alive = true;
-			meta.m_idx = idx;
-			alloc.construct(&crntVal, std::move(val));
+			if(!meta.m_alive)
+			{
+				// Empty slot was found, construct in-place
 
-			return 1;
-		}
-		else if(meta.m_idx == idx)
-		{
-			// Same index was found, replace
+				meta.m_alive = true;
+				meta.m_idx = idx;
+				alloc.construct(&crntVal, std::move(val));
+
+				return 1;
+			}
+			else if(meta.m_idx == idx)
+			{
+				// Same index was found, replace
+
+				meta.m_idx = idx;
+				destroyElement(crntVal);
+				alloc.construct(&crntVal, std::move(val));
+
+				return 0;
+			}
 
-			meta.m_idx = idx;
-			destroyElement(crntVal);
-			alloc.construct(&crntVal, std::move(val));
+			// Do the robin-hood
+			const Index otherDesiredPos = mod(meta.m_idx);
+			if(distanceFromDesired(pos, otherDesiredPos) < distanceFromDesired(pos, desiredPos))
+			{
+				// Swap
+				std::swap(val, crntVal);
+				std::swap(idx, meta.m_idx);
+				break;
+			}
 
-			return 0;
+			pos = mod(pos + 1u);
 		}
 
-		// Do the robin-hood
-		const Index otherDesiredPos = mod(meta.m_idx);
-		if(distanceFromDesired(pos, otherDesiredPos) < distanceFromDesired(pos, desiredPos))
+		if(pos == endPos)
 		{
-			// Swap
-			std::swap(val, crntVal);
-			std::swap(idx, meta.m_idx);
-			goto start;
+			// Didn't found an empty place, need to grow and try again
+			grow(alloc);
 		}
-
-		pos = mod(pos + 1u);
 	}
 
-	// Didn't found an empty place, need to grow and try again
-	grow(alloc);
-	goto start;
-
 	return 0;
 }
 

+ 4 - 4
Tests/Math/Math.cpp

@@ -253,9 +253,9 @@ void transpose()
 	Mat a = getNonEmptyMat<Mat>();
 	Mat b = a.getTransposed();
 
-	for(U j = 0; j < Mat::ROW_SIZE; j++)
+	for(U j = 0; j < Mat::ROW_COUNT; j++)
 	{
-		for(U i = 0; i < Mat::COLUMN_SIZE; i++)
+		for(U i = 0; i < Mat::COLUMN_COUNT; i++)
 		{
 			ANKI_TEST_EXPECT_EQ(a(j, i), b(i, j));
 		}
@@ -286,10 +286,10 @@ void matVecMul()
 
 	VecOut out = m * v;
 	VecOut out1;
-	for(U j = 0; j < Mat::ROW_SIZE; j++)
+	for(U j = 0; j < Mat::ROW_COUNT; j++)
 	{
 		T sum = 0;
-		for(U i = 0; i < Mat::COLUMN_SIZE; i++)
+		for(U i = 0; i < Mat::COLUMN_COUNT; i++)
 		{
 			sum += m(j, i) * v[j];
 		}

+ 0 - 1
Tests/Util/Filesystem.cpp

@@ -47,7 +47,6 @@ ANKI_TEST(Util, Directory)
 	ANKI_TEST_EXPECT_EQ(fileExists("./dir/rid/tmp"), true);
 
 	ANKI_TEST_EXPECT_NO_ERR(removeDirectory("./dir", alloc));
-	return;
 	ANKI_TEST_EXPECT_EQ(fileExists("./dir/rid/tmp"), false);
 	ANKI_TEST_EXPECT_EQ(directoryExists("./dir/rid"), false);
 	ANKI_TEST_EXPECT_EQ(directoryExists("./dir"), false);

+ 1 - 1
Tests/Util/SparseArray.cpp

@@ -343,7 +343,7 @@ ANKI_TEST(Util, SparseArrayBench)
 			int v;
 			do
 			{
-				v = rand();
+				v = int(getRandom());
 			} while(tmpMap.find(v) != tmpMap.end() && v != 0);
 			tmpMap[v] = 1;