ソースを参照

More work on RT in scene

Panagiotis Christopoulos Charitos 5 年 前
コミット
168978c9aa

+ 1 - 1
CMakeLists.txt

@@ -74,7 +74,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
 option(ANKI_EXTRA_CHECKS "Debugging checks (assertions)" OFF)
 option(ANKI_LTO "LTO compilation" OFF)
 
-option(ANKI_BUILD_TOOLS "Build tools" OFF)
+option(ANKI_BUILD_TOOLS "Build tools" ON)
 option(ANKI_BUILD_TESTS "Build unit tests" OFF)
 option(ANKI_BUILD_SANDBOX "Build sandbox application" ON)
 option(ANKI_BUILD_BENCH "Build benchmark application" OFF)

+ 2 - 1
anki/collision/CMakeLists.txt

@@ -1,2 +1,3 @@
 file(GLOB SOURCES *.cpp)
-addAnkiSourceFiles(${SOURCES})
+file(GLOB HEADERS *.h)
+addAnkiSourceFiles(${SOURCES} ${HEADERS})

+ 2 - 1
anki/core/CMakeLists.txt

@@ -1,4 +1,5 @@
 set(SOURCES App.cpp ConfigSet.cpp StagingGpuMemoryManager.cpp DeveloperConsole.cpp CoreTracer.cpp)
+file(GLOB HEADERS *.h)
 
 if(SDL)
 	set(SOURCES ${SOURCES} NativeWindowSdl.cpp)
@@ -7,5 +8,5 @@ else()
 endif()
 
 foreach(S ${SOURCES})
-	addAnkiSourceFiles("${CMAKE_CURRENT_SOURCE_DIR}/${S}")
+	addAnkiSourceFiles("${CMAKE_CURRENT_SOURCE_DIR}/${S}" ${HEADERS})
 endforeach()

+ 1 - 1
anki/math/Mat.h

@@ -241,7 +241,7 @@ public:
 
 	ANKI_ENABLE_METHOD(J == 3 && I == 4)
 	explicit TMat(const TTransform<T>& t)
-		: TMat(t.getOrigin().xyz(), t.getRotation(), t.getScale())
+		: TMat(t.getOrigin().xyz(), t.getRotation().getRotationPart(), t.getScale())
 	{
 	}
 	/// @}

+ 4 - 2
anki/renderer/RenderQueue.h

@@ -352,12 +352,14 @@ using FillCoverageBufferCallback = void (*)(void* userData, F32* depthValues, U3
 class RayTracingInstanceQueueElement final
 {
 public:
+	AccelerationStructure* m_bottomLevelAccelerationStructure;
 	ModelGpuDescriptor m_modelDescriptor;
-	Array<ConstWeakArray<U8>, U(RayTracingMaterialType::COUNT)> m_shaderGroupHandles;
+	Array<const U8*, U(RayType::COUNT)> m_shaderGroupHandles;
 
 	/// This points to the GR objects that are m_modelDescriptor is referencing. Use this to add a refcount to avoid
 	/// accidential deletions.
-	WeakArray<GrObject*> m_grObjects;
+	Array<GrObject*, 8> m_grObjects;
+	U32 m_grObjectCount;
 };
 
 static_assert(std::is_trivially_destructible<RayTracingInstanceQueueElement>::value == true,

+ 12 - 2
anki/resource/Common.h

@@ -54,7 +54,7 @@ enum class VertexAttributeLocation : U8
 };
 ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(VertexAttributeLocation)
 
-enum class RayTracingMaterialType : U8
+enum class RayType : U8
 {
 	SHADOWS,
 	GI,
@@ -64,7 +64,17 @@ enum class RayTracingMaterialType : U8
 	COUNT,
 	FIRST = 0
 };
-ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(RayTracingMaterialType)
+ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(RayType)
+
+enum class RayTypeBit : U8
+{
+	NONE,
+	SHADOWS = 1 << 0,
+	GI = 1 << 1,
+	REFLECTIONS = 1 << 2,
+	PATH_TRACING = 1 << 3
+};
+ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(RayTypeBit)
 /// @}
 
 /// Deleter for ResourcePtr.

+ 117 - 102
anki/resource/MaterialResource.cpp

@@ -166,6 +166,7 @@ MaterialVariable::~MaterialVariable()
 MaterialResource::MaterialResource(ResourceManager* manager)
 	: ResourceObject(manager)
 {
+	memset(&m_materialGpuDescriptor, 0, sizeof(m_materialGpuDescriptor));
 }
 
 MaterialResource::~MaterialResource()
@@ -1033,102 +1034,128 @@ U32 MaterialResource::getInstanceGroupIdx(U32 instanceCount)
 
 Error MaterialResource::parseRtMaterial(XmlElement rtMaterialEl)
 {
-	// type
-	CString typeStr;
-	ANKI_CHECK(rtMaterialEl.getAttributeText("type", typeStr));
-	RayTracingMaterialType type = RayTracingMaterialType::COUNT;
-	if(typeStr == "SHADOWS")
-	{
-		type = RayTracingMaterialType::SHADOWS;
-	}
-	else if(typeStr == "GI")
-	{
-		type = RayTracingMaterialType::GI;
-	}
-	else if(typeStr == "REFLECTIONS")
-	{
-		type = RayTracingMaterialType::REFLECTIONS;
-	}
-	else if(typeStr == "PATH_TRACING")
-	{
-		type = RayTracingMaterialType::PATH_TRACING;
-	}
-	else
+	// rayType
+	XmlElement rayTypeEl;
+	ANKI_CHECK(rtMaterialEl.getChildElement("rayType", rayTypeEl));
+	do
 	{
-		ANKI_RESOURCE_LOGE("Uknown ray tracing type: %s", typeStr.cstr());
-		return Error::USER_DATA;
-	}
+		// type
+		CString typeStr;
+		ANKI_CHECK(rayTypeEl.getAttributeText("type", typeStr));
+		RayType type = RayType::COUNT;
+		if(typeStr == "shadows")
+		{
+			type = RayType::SHADOWS;
+		}
+		else if(typeStr == "gi")
+		{
+			type = RayType::GI;
+		}
+		else if(typeStr == "reflections")
+		{
+			type = RayType::REFLECTIONS;
+		}
+		else if(typeStr == "pathTracing")
+		{
+			type = RayType::PATH_TRACING;
+		}
+		else
+		{
+			ANKI_RESOURCE_LOGE("Uknown ray tracing type: %s", typeStr.cstr());
+			return Error::USER_DATA;
+		}
 
-	// shaderProgram
-	CString fname;
-	ANKI_CHECK(rtMaterialEl.getAttributeText("shaderProgram", fname));
-	ANKI_CHECK(getManager().loadResource(fname, m_rt[type].m_prog, false));
-
-	// mutation
-	XmlElement mutationEl;
-	ANKI_CHECK(rtMaterialEl.getChildElementOptional("mutation", mutationEl));
-	DynamicArrayAuto<SubMutation> mutatorValues(getTempAllocator());
-	if(mutationEl)
-	{
-		XmlElement mutatorEl;
-		ANKI_CHECK(mutationEl.getChildElement("mutator", mutatorEl));
-		U32 mutatorCount = 0;
-		ANKI_CHECK(mutatorEl.getSiblingElementsCount(mutatorCount));
-		++mutatorCount;
+		if(m_rtPrograms[type].isCreated())
+		{
+			ANKI_RESOURCE_LOGE("Ray tracing type already set: %s", typeStr.cstr());
+			return Error::USER_DATA;
+		}
 
-		mutatorValues.resize(mutatorCount);
+		m_rayTypes |= RayTypeBit(1 << type);
 
-		mutatorCount = 0;
-		do
+		// shaderProgram
+		CString fname;
+		ANKI_CHECK(rayTypeEl.getAttributeText("shaderProgram", fname));
+		ANKI_CHECK(getManager().loadResource(fname, m_rtPrograms[type], false));
+
+		// mutation
+		XmlElement mutationEl;
+		ANKI_CHECK(rayTypeEl.getChildElementOptional("mutation", mutationEl));
+		DynamicArrayAuto<SubMutation> mutatorValues(getTempAllocator());
+		if(mutationEl)
 		{
-			// name
-			CString mutatorName;
-			ANKI_CHECK(mutatorEl.getAttributeText("name", mutatorName));
-			if(mutatorName.isEmpty())
-			{
-				ANKI_RESOURCE_LOGE("Mutator name is empty");
-				return Error::USER_DATA;
-			}
+			XmlElement mutatorEl;
+			ANKI_CHECK(mutationEl.getChildElement("mutator", mutatorEl));
+			U32 mutatorCount = 0;
+			ANKI_CHECK(mutatorEl.getSiblingElementsCount(mutatorCount));
+			++mutatorCount;
 
-			// value
-			MutatorValue mutatorValue;
-			ANKI_CHECK(mutatorEl.getAttributeNumber("value", mutatorValue));
+			mutatorValues.resize(mutatorCount);
 
-			// Check
-			const ShaderProgramResourceMutator* mutatorPtr = m_rt[type].m_prog->tryFindMutator(mutatorName);
-			if(mutatorPtr == nullptr)
+			mutatorCount = 0;
+			do
 			{
-				ANKI_RESOURCE_LOGE("Mutator not found: %s", mutatorName.cstr());
-				return Error::USER_DATA;
-			}
+				// name
+				CString mutatorName;
+				ANKI_CHECK(mutatorEl.getAttributeText("name", mutatorName));
+				if(mutatorName.isEmpty())
+				{
+					ANKI_RESOURCE_LOGE("Mutator name is empty");
+					return Error::USER_DATA;
+				}
 
-			if(!mutatorPtr->valueExists(mutatorValue))
-			{
-				ANKI_RESOURCE_LOGE("Mutator value doesn't exist: %s", mutatorName.cstr());
-				return Error::USER_DATA;
-			}
+				// value
+				MutatorValue mutatorValue;
+				ANKI_CHECK(mutatorEl.getAttributeNumber("value", mutatorValue));
 
-			// All good
-			mutatorValues[mutatorCount].m_mutator = mutatorPtr;
-			mutatorValues[mutatorCount].m_value = mutatorValue;
+				// Check
+				const ShaderProgramResourceMutator* mutatorPtr = m_rtPrograms[type]->tryFindMutator(mutatorName);
+				if(mutatorPtr == nullptr)
+				{
+					ANKI_RESOURCE_LOGE("Mutator not found: %s", mutatorName.cstr());
+					return Error::USER_DATA;
+				}
 
-			// Advance
-			++mutatorCount;
-			ANKI_CHECK(mutatorEl.getNextSiblingElement("mutator", mutatorEl));
-		} while(mutatorEl);
+				if(!mutatorPtr->valueExists(mutatorValue))
+				{
+					ANKI_RESOURCE_LOGE("Mutator value doesn't exist: %s", mutatorName.cstr());
+					return Error::USER_DATA;
+				}
 
-		ANKI_ASSERT(mutatorCount == mutatorValues.getSize());
-	}
+				// All good
+				mutatorValues[mutatorCount].m_mutator = mutatorPtr;
+				mutatorValues[mutatorCount].m_value = mutatorValue;
 
-	if(mutatorValues.getSize() != m_rt[type].m_prog->getMutators().getSize())
-	{
-		ANKI_RESOURCE_LOGE("Forgot to set all mutators on some RT mutation");
-		return Error::USER_DATA;
-	}
+				// Advance
+				++mutatorCount;
+				ANKI_CHECK(mutatorEl.getNextSiblingElement("mutator", mutatorEl));
+			} while(mutatorEl);
+
+			ANKI_ASSERT(mutatorCount == mutatorValues.getSize());
+		}
+
+		if(mutatorValues.getSize() != m_rtPrograms[type]->getMutators().getSize())
+		{
+			ANKI_RESOURCE_LOGE("Forgot to set all mutators on some RT mutation");
+			return Error::USER_DATA;
+		}
+
+		// Get the shader group handle
+		ShaderProgramResourceVariantInitInfo variantInitInfo(m_rtPrograms[type]);
+		for(const SubMutation& subMutation : mutatorValues)
+		{
+			variantInitInfo.addMutation(subMutation.m_mutator->m_name, subMutation.m_value);
+		}
+
+		const ShaderProgramResourceVariant* progVariant;
+		m_rtPrograms[type]->getOrCreateVariant(variantInitInfo, progVariant);
+		m_rtShaderGroupHandles[type] = progVariant->getHitShaderGroupHandle();
+
+		// Advance
+		ANKI_CHECK(rayTypeEl.getNextSiblingElement("rayType", rayTypeEl));
+	} while(rayTypeEl);
 
 	// input
-	RayTracingMaterialVariant& variant = m_rt[type].m_variant;
-	MaterialGpuDescriptor& gpuMaterial = variant.m_materialGpuDescriptor;
 	XmlElement inputsEl;
 	ANKI_CHECK(rtMaterialEl.getChildElementOptional("inputs", inputsEl));
 	if(inputsEl)
@@ -1154,15 +1181,14 @@ Error MaterialResource::parseRtMaterial(XmlElement rtMaterialEl)
 					ANKI_CHECK(inputEl.getAttributeText("value", fname));
 
 					const U32 textureIdx = GPU_MATERIAL_TEXTURES[i].m_textureSlot;
-					ANKI_CHECK(getManager().loadResource(fname, variant.m_textureResources[textureIdx], false));
+					ANKI_CHECK(getManager().loadResource(fname, m_textureResources[textureIdx], false));
 
-					variant.m_textureViews[variant.m_textureViewCount] =
-						variant.m_textureResources[textureIdx]->getGrTextureView();
+					m_textureViews[m_textureViewCount] = m_textureResources[textureIdx]->getGrTextureView();
 
-					gpuMaterial.m_bindlessTextureIndices[textureIdx] =
-						U16(variant.m_textureViews[variant.m_textureViewCount]->getOrCreateBindlessTextureIndex());
+					m_materialGpuDescriptor.m_bindlessTextureIndices[textureIdx] =
+						U16(m_textureViews[m_textureViewCount]->getOrCreateBindlessTextureIndex());
 
-					++variant.m_textureViewCount;
+					++m_textureViewCount;
 					found = true;
 					break;
 				}
@@ -1181,16 +1207,16 @@ Error MaterialResource::parseRtMaterial(XmlElement rtMaterialEl)
 						{
 							Vec3 val;
 							ANKI_CHECK(inputEl.getAttributeNumbers("value", val));
-							memcpy(reinterpret_cast<U8*>(&gpuMaterial) + GPU_MATERIAL_FLOATS[i].m_offsetof, &val,
-								   sizeof(val));
+							memcpy(reinterpret_cast<U8*>(&m_materialGpuDescriptor) + GPU_MATERIAL_FLOATS[i].m_offsetof,
+								   &val, sizeof(val));
 						}
 						else
 						{
 							ANKI_ASSERT(GPU_MATERIAL_FLOATS[i].m_floatCount == 1);
 							F32 val;
 							ANKI_CHECK(inputEl.getAttributeNumber("value", val));
-							memcpy(reinterpret_cast<U8*>(&gpuMaterial) + GPU_MATERIAL_FLOATS[i].m_offsetof, &val,
-								   sizeof(val));
+							memcpy(reinterpret_cast<U8*>(&m_materialGpuDescriptor) + GPU_MATERIAL_FLOATS[i].m_offsetof,
+								   &val, sizeof(val));
 						}
 
 						found = true;
@@ -1210,17 +1236,6 @@ Error MaterialResource::parseRtMaterial(XmlElement rtMaterialEl)
 		} while(inputEl);
 	}
 
-	// Finally get the shader group handle
-	ShaderProgramResourceVariantInitInfo variantInitInfo(m_rt[type].m_prog);
-	for(const SubMutation& subMutation : mutatorValues)
-	{
-		variantInitInfo.addMutation(subMutation.m_mutator->m_name, subMutation.m_value);
-	}
-
-	const ShaderProgramResourceVariant* progVariant;
-	m_rt[type].m_prog->getOrCreateVariant(variantInitInfo, progVariant);
-	variant.m_shaderGroupHandle = progVariant->getHitShaderGroupHandle();
-
 	return Error::NONE;
 }
 

+ 34 - 59
anki/resource/MaterialResource.h

@@ -250,48 +250,6 @@ private:
 	U32 m_uniBlockSize = 0;
 };
 
-/// Ray tracing material variant.
-class RayTracingMaterialVariant
-{
-	friend class MaterialResource;
-	template<typename, PtrSize>
-	friend class Array;
-
-public:
-	RayTracingMaterialVariant(const RayTracingMaterialVariant&) = delete;
-	RayTracingMaterialVariant& operator=(const RayTracingMaterialVariant&) = delete;
-
-	ConstWeakArray<U8> getHitShaderGroupHandle() const
-	{
-		return m_shaderGroupHandle;
-	}
-
-	const MaterialGpuDescriptor& getMaterialGpuDescriptor() const
-	{
-		return m_materialGpuDescriptor;
-	}
-
-	/// Get the texture views that are referenced by what getMaterialGpuDescriptor() returned. Used for life tracking.
-	const ConstWeakArray<TextureViewPtr> getTextureViews() const
-	{
-		return ConstWeakArray<TextureViewPtr>((m_textureViewCount) ? &m_textureViews[0] : nullptr, m_textureViewCount);
-	}
-
-private:
-	ConstWeakArray<U8> m_shaderGroupHandle;
-	MaterialGpuDescriptor m_materialGpuDescriptor;
-	Array<TextureResourcePtr, TEXTURE_CHANNEL_COUNT> m_textureResources; ///< Keep the resources alive.
-	Array<TextureViewPtr, TEXTURE_CHANNEL_COUNT> m_textureViews; ///< Cache the GPU objects.
-	U8 m_textureViewCount = 0;
-
-	RayTracingMaterialVariant()
-	{
-		memset(&m_materialGpuDescriptor, 0, sizeof(m_materialGpuDescriptor));
-	}
-
-	~RayTracingMaterialVariant() = default;
-};
-
 /// Material resource.
 ///
 /// Material XML file format:
@@ -306,10 +264,12 @@ private:
 ///		</inputs>]
 /// </material>
 ///
-/// [<rtMaterial shaderProgram="path" type="shadows|gi|reflections|pathTracing">
-///		[<mutation>
-///			<mutator name="str" value="value"/>
-///		</mutation>]
+/// [<rtMaterial>
+///		<rayType shaderProgram="path" type="shadows|gi|reflections|pathTracing">
+///			[<mutation>
+///				<mutator name="str" value="value"/>
+///			</mutation>]
+///		</rayType>
 ///
 /// 	[<inputs>
 /// 		<input name="name" value="value" />
@@ -382,16 +342,28 @@ public:
 
 	const MaterialVariant& getOrCreateVariant(const RenderingKey& key) const;
 
-	const RayTracingMaterialVariant& getRayTracingVariant(U32 lod, RayTracingMaterialType type) const
+	ConstWeakArray<U8> getShaderGroupHandle(RayType type) const
 	{
-		(void)lod; // Not supported for now
-		ANKI_ASSERT(m_rt[type].m_prog.isCreated());
-		return m_rt[type].m_variant;
+		ANKI_ASSERT(!!(m_rayTypes & RayTypeBit(1 << type)));
+		ANKI_ASSERT(m_rtShaderGroupHandles[type].getSize());
+		return m_rtShaderGroupHandles[type];
 	}
 
-	Bool getRayTracingTypeSupported(RayTracingMaterialType type) const
+	RayTypeBit getSupportedRayTracingTypes() const
 	{
-		return m_rt[type].m_prog.isCreated();
+		return m_rayTypes;
+	}
+
+	const MaterialGpuDescriptor& getMaterialGpuDescriptor() const
+	{
+		return m_materialGpuDescriptor;
+	}
+
+	/// Get all texture views that the MaterialGpuDescriptor returned by getMaterialGpuDescriptor(), references. Used
+	/// for lifetime management.
+	ConstWeakArray<TextureViewPtr> getAllTextureViews() const
+	{
+		return ConstWeakArray<TextureViewPtr>((m_textureViewCount) ? &m_textureViews[0] : nullptr, m_textureViewCount);
 	}
 
 private:
@@ -423,13 +395,16 @@ private:
 
 	DynamicArray<SubMutation> m_nonBuiltinsMutation;
 
-	class Rt
-	{
-	public:
-		ShaderProgramResourcePtr m_prog;
-		RayTracingMaterialVariant m_variant;
-	};
-	Array<Rt, U(RayTracingMaterialType::COUNT)> m_rt;
+	Array<ShaderProgramResourcePtr, U(RayType::COUNT)> m_rtPrograms;
+	Array<ConstWeakArray<U8>, U(RayType::COUNT)> m_rtShaderGroupHandles;
+
+	MaterialGpuDescriptor m_materialGpuDescriptor;
+
+	Array<TextureResourcePtr, TEXTURE_CHANNEL_COUNT> m_textureResources; ///< Keep the resources alive.
+	Array<TextureViewPtr, TEXTURE_CHANNEL_COUNT> m_textureViews; ///< Cache the GPU objects.
+	U8 m_textureViewCount = 0;
+
+	RayTypeBit m_rayTypes = RayTypeBit::NONE;
 
 	ANKI_USE_RESULT Error createVars();
 

+ 13 - 12
anki/resource/ModelResource.cpp

@@ -104,13 +104,9 @@ void ModelPatch::getRenderingInfo(const RenderingKey& key, WeakArray<U8> subMesh
 	inf.m_indicesCountArray[0] = indexCount;
 }
 
-Bool ModelPatch::getRayTracingInfo(U32 lod, RayTracingMaterialType type, ModelRayTracingInfo& info) const
+void ModelPatch::getRayTracingInfo(U32 lod, ModelRayTracingInfo& info) const
 {
-	const Bool supported = m_mtl->getRayTracingTypeSupported(type);
-	if(!supported)
-	{
-		return false;
-	}
+	ANKI_ASSERT(m_mtl->getSupportedRayTracingTypes() != RayTypeBit::NONE);
 
 	info.m_grObjectReferenceCount = 0;
 	memset(&info.m_descriptor, 0, sizeof(info.m_descriptor));
@@ -123,15 +119,20 @@ Bool ModelPatch::getRayTracingInfo(U32 lod, RayTracingMaterialType type, ModelRa
 	info.m_grObjectReferences[info.m_grObjectReferenceCount++] = mesh->getVertexBuffer();
 
 	// Material
-	const RayTracingMaterialVariant& materialVariant = m_mtl->getRayTracingVariant(lod, type);
-	info.m_descriptor.m_material = materialVariant.getMaterialGpuDescriptor();
-	info.m_shaderGroupHandle = materialVariant.getHitShaderGroupHandle();
-	for(U32 i = 0; i < materialVariant.getTextureViews().getSize(); ++i)
+	info.m_descriptor.m_material = m_mtl->getMaterialGpuDescriptor();
+	for(RayType rayType : EnumIterable<RayType>())
 	{
-		info.m_grObjectReferences[info.m_grObjectReferenceCount++] = materialVariant.getTextureViews()[i];
+		if(!!(m_mtl->getSupportedRayTracingTypes() & RayTypeBit(1 << rayType)))
+		{
+			info.m_shaderGroupHandles[rayType] = m_mtl->getShaderGroupHandle(rayType);
+		}
 	}
 
-	return true;
+	ConstWeakArray<TextureViewPtr> textureViews = m_mtl->getAllTextureViews();
+	for(U32 i = 0; i < textureViews.getSize(); ++i)
+	{
+		info.m_grObjectReferences[info.m_grObjectReferenceCount++] = textureViews[i];
+	}
 }
 
 U32 ModelPatch::getLodCount() const

+ 4 - 5
anki/resource/ModelResource.h

@@ -86,7 +86,7 @@ class ModelRayTracingInfo
 public:
 	ModelGpuDescriptor m_descriptor;
 	AccelerationStructurePtr m_bottomLevelAccelerationStructure;
-	ConstWeakArray<U8> m_shaderGroupHandle;
+	Array<ConstWeakArray<U8>, U(RayType::COUNT)> m_shaderGroupHandles;
 
 	/// Get some pointers that the m_descriptor is pointing to. Use these pointers for life tracking.
 	Array<GrObjectPtr, TEXTURE_CHANNEL_COUNT + 2> m_grObjectReferences;
@@ -138,12 +138,11 @@ public:
 	void getRenderingInfo(const RenderingKey& key, WeakArray<U8> subMeshIndicesArray, ModelRenderingInfo& inf) const;
 
 	/// Get the ray tracing info.
-	/// @return Return's false if the @a type is not supported.
-	Bool getRayTracingInfo(U32 lod, RayTracingMaterialType type, ModelRayTracingInfo& info) const;
+	void getRayTracingInfo(U32 lod, ModelRayTracingInfo& info) const;
 
-	Bool getRayTracingTypeSupported(RayTracingMaterialType type) const
+	RayTypeBit getSupportedRayTracingTypes() const
 	{
-		return m_mtl->getRayTracingTypeSupported(type);
+		return m_mtl->getSupportedRayTracingTypes();
 	}
 
 private:

+ 1 - 1
anki/scene/GpuParticleEmitterNode.cpp

@@ -149,7 +149,7 @@ Error GpuParticleEmitterNode::init(const CString& filename)
 		},
 		this);
 	RenderComponent* rcomp = newComponent<RenderComponent>();
-	rcomp->setupRaster(
+	rcomp->initRaster(
 		[](RenderQueueDrawContext& ctx, ConstWeakArray<void*> userData) {
 			ANKI_ASSERT(userData.getSize() == 1);
 			static_cast<const GpuParticleEmitterNode*>(userData[0])->draw(ctx);

+ 48 - 1
anki/scene/ModelNode.cpp

@@ -104,7 +104,7 @@ Error ModelNode::init(ModelResourcePtr resource, U32 modelPatchIdx)
 	newComponent<MoveFeedbackComponent>();
 	newComponent<SpatialComponent>(this, &m_obbWorld);
 	RenderComponent* rcomp = newComponent<RenderComponent>();
-	rcomp->setupRaster(
+	rcomp->initRaster(
 		[](RenderQueueDrawContext& ctx, ConstWeakArray<void*> userData) {
 			const ModelNode& self = *static_cast<const ModelNode*>(userData[0]);
 			self.draw(ctx, userData);
@@ -112,6 +112,11 @@ Error ModelNode::init(ModelResourcePtr resource, U32 modelPatchIdx)
 		this, m_mergeKey);
 	rcomp->setFlagsFromMaterial(m_model->getModelPatches()[m_modelPatchIdx].getMaterial());
 
+	if(m_model->getModelPatches()[m_modelPatchIdx].getSupportedRayTracingTypes() != RayTypeBit::NONE)
+	{
+		rcomp->initRayTracing(setupRayTracingInstanceQueueElement, this);
+	}
+
 	m_obbLocal = m_model->getModelPatches()[m_modelPatchIdx].getBoundingShape();
 
 	return Error::NONE;
@@ -333,4 +338,46 @@ void ModelNode::draw(RenderQueueDrawContext& ctx, ConstWeakArray<void*> userData
 	}
 }
 
+void ModelNode::setupRayTracingInstanceQueueElement(U32 lod, const void* userData, RayTracingInstanceQueueElement& el)
+{
+	const ModelNode& self = *static_cast<const ModelNode*>(userData);
+	const ModelPatch& patch = self.m_model->getModelPatches()[self.m_modelPatchIdx];
+
+	ModelRayTracingInfo info;
+	patch.getRayTracingInfo(lod, info);
+
+	memset(&el, 0, sizeof(el));
+
+	// AS
+	el.m_bottomLevelAccelerationStructure = info.m_bottomLevelAccelerationStructure.get();
+	info.m_bottomLevelAccelerationStructure->getRefcount().fetchAdd(1);
+
+	// Set the descriptor
+	el.m_modelDescriptor = info.m_descriptor;
+	const MoveComponent& movec = self.getFirstComponentOfType<MoveComponent>();
+	const Mat3x4 worldTrf(movec.getWorldTransform());
+	memcpy(&el.m_modelDescriptor.m_worldTransform, &worldTrf, sizeof(worldTrf));
+	el.m_modelDescriptor.m_worldRotation = movec.getWorldTransform().getRotation().getRotationPart();
+
+	// Handles
+	for(RayType type : EnumIterable<RayType>())
+	{
+		if(!(patch.getMaterial()->getSupportedRayTracingTypes() & RayTypeBit(1 << type)))
+		{
+			continue;
+		}
+
+		el.m_shaderGroupHandles[type] = &info.m_shaderGroupHandles[type][0];
+	}
+
+	// References
+	ANKI_ASSERT(info.m_grObjectReferenceCount <= el.m_grObjects.getSize());
+	el.m_grObjectCount = info.m_grObjectReferenceCount;
+	for(U32 i = 0; i < info.m_grObjectReferenceCount; ++i)
+	{
+		el.m_grObjects[i] = info.m_grObjectReferences[i].get();
+		el.m_grObjects[i]->getRefcount().fetchAdd(1);
+	}
+}
+
 } // end namespace anki

+ 2 - 0
anki/scene/ModelNode.h

@@ -54,6 +54,8 @@ private:
 	void updateSpatialComponent(const MoveComponent& move);
 
 	void draw(RenderQueueDrawContext& ctx, ConstWeakArray<void*> userData) const;
+
+	static void setupRayTracingInstanceQueueElement(U32 lod, const void* userData, RayTracingInstanceQueueElement& el);
 };
 /// @}
 

+ 1 - 1
anki/scene/ParticleEmitterNode.cpp

@@ -254,7 +254,7 @@ Error ParticleEmitterNode::init(const CString& filename)
 
 	// Render component
 	RenderComponent* rcomp = newComponent<RenderComponent>();
-	rcomp->setupRaster(drawCallback, this, 0); // No merging
+	rcomp->initRaster(drawCallback, this, 0); // No merging
 	rcomp->setFlagsFromMaterial(m_particleEmitterResource->getMaterial());
 
 	// Other

+ 3 - 3
anki/scene/PhysicsDebugNode.cpp

@@ -27,9 +27,9 @@ public:
 	{
 		ANKI_ASSERT(node);
 		setFlags(RenderComponentFlag::NONE);
-		setupRaster([](RenderQueueDrawContext& ctx,
-					   ConstWeakArray<void*> userData) { static_cast<MyRenderComponent*>(userData[0])->draw(ctx); },
-					this, 0);
+		initRaster([](RenderQueueDrawContext& ctx,
+					  ConstWeakArray<void*> userData) { static_cast<MyRenderComponent*>(userData[0])->draw(ctx); },
+				   this, 0);
 	}
 
 	ANKI_USE_RESULT Error init()

+ 21 - 4
anki/scene/components/RenderComponent.h

@@ -26,6 +26,9 @@ enum class RenderComponentFlag : U8
 };
 ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(RenderComponentFlag)
 
+using FillRayTracingInstanceQueueElementCallback = void (*)(U32 lod, const void* userData,
+															RayTracingInstanceQueueElement& el);
+
 /// Render component interface. Implemented by renderable scene nodes
 class RenderComponent : public SceneComponent
 {
@@ -55,7 +58,7 @@ public:
 		setFlags(flags);
 	}
 
-	void setupRaster(RenderQueueDrawCallback callback, const void* userData, U64 mergeKey)
+	void initRaster(RenderQueueDrawCallback callback, const void* userData, U64 mergeKey)
 	{
 		ANKI_ASSERT(callback != nullptr);
 		ANKI_ASSERT(userData != nullptr);
@@ -65,6 +68,12 @@ public:
 		m_mergeKey = mergeKey;
 	}
 
+	void initRayTracing(FillRayTracingInstanceQueueElementCallback callback, const void* userData)
+	{
+		m_rtCallback = callback;
+		m_rtCallbackUserData = userData;
+	}
+
 	void setupRenderableQueueElement(RenderableQueueElement& el) const
 	{
 		ANKI_ASSERT(el.m_callback != nullptr);
@@ -75,15 +84,23 @@ public:
 		el.m_mergeKey = m_mergeKey;
 	}
 
+	void setupRayTracingInstanceQueueElement(U32 lod, RayTracingInstanceQueueElement& el) const
+	{
+		ANKI_ASSERT(m_rtCallback);
+		m_rtCallback(lod, m_rtCallbackUserData, el);
+	}
+
 	/// Helper function.
 	static void allocateAndSetupUniforms(const MaterialResourcePtr& mtl, const RenderQueueDrawContext& ctx,
 										 ConstWeakArray<Mat4> transforms, ConstWeakArray<Mat4> prevTransforms,
 										 StagingGpuMemoryManager& alloc);
 
 private:
-	RenderQueueDrawCallback m_callback ANKI_DEBUG_CODE(= nullptr);
-	const void* m_userData ANKI_DEBUG_CODE(= nullptr);
-	U64 m_mergeKey ANKI_DEBUG_CODE(= MAX_U64);
+	RenderQueueDrawCallback m_callback = nullptr;
+	const void* m_userData = nullptr;
+	U64 m_mergeKey = MAX_U64;
+	FillRayTracingInstanceQueueElementCallback m_rtCallback = nullptr;
+	const void* m_rtCallbackUserData = nullptr;
 	RenderComponentFlag m_flags = RenderComponentFlag::NONE;
 };
 /// @}

+ 11 - 2
anki/shaders/include/ModelTypes.h

@@ -17,10 +17,10 @@ struct MainVertex
 {
 	U32 m_normal; ///< Packed in a custom R11G11B10_SNorm
 	U32 m_tangent; ///< Packed in a custom R10G10B11A1_SNorm format
-	HVec2 m_uvs[UV_CHANNEL_COUNT];
+	Vec2 m_uvs[UV_CHANNEL_COUNT];
 };
 
-const U32 _ANKI_SIZEOF_MainVertex = 4 * 3;
+const U32 _ANKI_SIZEOF_MainVertex = 4 * 4;
 const U32 _ANKI_ALIGNOF_MainVertex = 4;
 ANKI_SHADER_STATIC_ASSERT(_ANKI_SIZEOF_MainVertex == sizeof(MainVertex));
 
@@ -48,6 +48,10 @@ struct MeshGpuDescriptor
 	Vec3 m_aabbMax;
 };
 
+const U32 _ANKI_SIZEOF_MeshGpuDescriptor = 4 * ANKI_SIZEOF(U64) + 8 * ANKI_SIZEOF(F32);
+const U32 _ANKI_ALIGNOF_MeshGpuDescriptor = 8;
+ANKI_SHADER_STATIC_ASSERT(_ANKI_SIZEOF_MeshGpuDescriptor == sizeof(MeshGpuDescriptor));
+
 const U32 TEXTURE_CHANNEL_DIFFUSE = 0;
 const U32 TEXTURE_CHANNEL_NORMAL = 1;
 const U32 TEXTURE_CHANNEL_ROUGHNESS_METALNESS = 2;
@@ -69,6 +73,11 @@ struct MaterialGpuDescriptor
 	F32 m_metalness;
 };
 
+const U32 _ANKI_SIZEOF_MaterialGpuDescriptor =
+	TEXTURE_CHANNEL_COUNT * ANKI_SIZEOF(U16) + 3 * ANKI_SIZEOF(Vec3) + 2 * ANKI_SIZEOF(F32);
+const U32 _ANKI_ALIGNOF_MaterialGpuDescriptor = 4;
+ANKI_SHADER_STATIC_ASSERT(_ANKI_SIZEOF_MaterialGpuDescriptor == sizeof(MaterialGpuDescriptor));
+
 struct ModelGpuDescriptor
 {
 	MeshGpuDescriptor m_mesh;

+ 1 - 1
anki/util/Functions.h

@@ -283,7 +283,7 @@ struct RemovePointer;
 template<typename T>
 struct RemovePointer<T*>
 {
-	typedef T Type;
+	using Type = T;
 };
 
 /// Zero memory of an object

+ 1 - 1
anki/util/Logger.h

@@ -103,7 +103,7 @@ private:
 	static void fileMessageHandler(void* file, const LoggerMessageInfo& info);
 };
 
-typedef Singleton<Logger> LoggerSingleton;
+using LoggerSingleton = Singleton<Logger>;
 
 #define ANKI_LOG(subsystem_, t, ...) \
 	do \

+ 4 - 4
anki/util/Singleton.h

@@ -20,7 +20,7 @@ template<typename T>
 class Singleton
 {
 public:
-	typedef T Value;
+	using Value = T;
 
 	// Non copyable
 	Singleton(const Singleton&) = delete;
@@ -57,7 +57,7 @@ template<typename T>
 class SingletonInit
 {
 public:
-	typedef T Value;
+	using Value = T;
 
 	// Non copyable
 	SingletonInit(const SingletonInit&) = delete;
@@ -103,7 +103,7 @@ template<typename T>
 class SingletonThreadLocal
 {
 public:
-	typedef T Value;
+	using Value = T;
 
 	// Non copyable
 	SingletonThreadLocal(const SingletonThreadLocal&) = delete;
@@ -140,7 +140,7 @@ template<typename T>
 class SingletonThreadsafe
 {
 public:
-	typedef T Value;
+	using Value = T;
 
 	// Non copyable
 	SingletonThreadsafe(const SingletonThreadsafe&) = delete;

+ 12 - 0
anki/util/String.h

@@ -619,6 +619,18 @@ public:
 	/// Replace all occurrences of "from" with "to".
 	String& replaceAll(Allocator alloc, CString from, CString to);
 
+	/// @brief  Execute a functor for all characters of the string.
+	template<typename TFunc>
+	void transform(TFunc func)
+	{
+		U i = 0;
+		while(i < m_data.getSize() && m_data[i] != '\0')
+		{
+			func(m_data[i]);
+			++i;
+		}
+	}
+
 protected:
 	DynamicArray<Char, PtrSize> m_data;
 

+ 1 - 1
anki/util/Visitor.h

@@ -87,7 +87,7 @@ struct GetTypeUsingId
 	template<typename TFirst, typename... Types_>
 	struct Helper<0, TFirst, Types_...>
 	{
-		typedef TFirst DataType;
+		using DataType = TFirst;
 	};
 
 	template<I id>

+ 1 - 2
tests/util/Hierarchy.cpp

@@ -30,8 +30,7 @@ struct Deleter
 struct Foo2: public Object<Foo2, Allocator<Foo2>,
 	Deleter<Foo2, Allocator<Foo2>>>
 {
-	typedef Object<Foo2, Allocator<Foo2>,
-		Deleter<Foo2, Allocator<Foo2>>> Base;
+	using Base = Object<Foo2, Allocator<Foo2>, Deleter<Foo2, Allocator<Foo2>>>;
 
 	int x = 666;
 	static int constructorCallCount;