Przeglądaj źródła

Complete the RT work on material and shader program resources

Panagiotis Christopoulos Charitos 5 lat temu
rodzic
commit
361046898e

+ 1 - 0
.gitattributes

@@ -8,6 +8,7 @@
 *.cmake text eol=lf
 *.txt text eol=lf
 *.md text eol=lf
+*.sh text eol=lf
 *.ankiprog text eol=lf
 *.ankimtl text eol=lf
 *.ankimdl text eol=lf

+ 135 - 9
anki/resource/MaterialResource.cpp

@@ -122,6 +122,38 @@ public:
 
 } // namespace
 
+class GpuMaterialTexture
+{
+public:
+	const char* m_name;
+	U32 m_textureSlot;
+};
+
+static const Array<GpuMaterialTexture, TEXTURE_CHANNEL_COUNT> GPU_MATERIAL_TEXTURES = {
+	{{"TEXTURE_CHANNEL_DIFFUSE", TEXTURE_CHANNEL_DIFFUSE},
+	 {"TEXTURE_CHANNEL_NORMAL", TEXTURE_CHANNEL_NORMAL},
+	 {"TEXTURE_CHANNEL_ROUGHNESS_METALNESS", TEXTURE_CHANNEL_ROUGHNESS_METALNESS},
+	 {"TEXTURE_CHANNEL_EMISSION", TEXTURE_CHANNEL_EMISSION},
+	 {"TEXTURE_CHANNEL_HEIGHT", TEXTURE_CHANNEL_HEIGHT},
+	 {"TEXTURE_CHANNEL_AUX_0", TEXTURE_CHANNEL_AUX_0},
+	 {"TEXTURE_CHANNEL_AUX_1", TEXTURE_CHANNEL_AUX_1},
+	 {"TEXTURE_CHANNEL_AUX_2", TEXTURE_CHANNEL_AUX_2}}};
+
+class GpuMaterialFloats
+{
+public:
+	const char* m_name;
+	U32 m_offsetof;
+	U32 m_floatCount;
+};
+
+static const Array<GpuMaterialFloats, 5> GPU_MATERIAL_FLOATS = {
+	{{"diffuseColor", offsetof(GpuMaterial, m_diffuseColor), 3},
+	 {"specularColor", offsetof(GpuMaterial, m_specularColor), 3},
+	 {"emissiveColor", offsetof(GpuMaterial, m_emissiveColor), 3},
+	 {"roughness", offsetof(GpuMaterial, m_roughness), 1},
+	 {"metalness", offsetof(GpuMaterial, m_metalness), 1}}};
+
 MaterialVariable::MaterialVariable()
 {
 	m_Mat4 = Mat4::getZero();
@@ -211,6 +243,14 @@ Error MaterialResource::load(const ResourceFilename& filename, Bool async)
 		ANKI_CHECK(parseInputs(el, async));
 	}
 
+	// <rtMaterial>
+	XmlElement rtMaterialEl;
+	ANKI_CHECK(doc.getChildElementOptional("rtMaterial", rtMaterialEl));
+	if(rtMaterialEl && getManager().getGrManager().getDeviceCapabilities().m_rayTracingEnabled)
+	{
+		ANKI_CHECK(parseRtMaterial(rtMaterialEl));
+	}
+
 	return Error::NONE;
 }
 
@@ -991,15 +1031,8 @@ U32 MaterialResource::getInstanceGroupIdx(U32 instanceCount)
 	return U32(std::log2(F32(instanceCount)));
 }
 
-Error MaterialResource::parseRtMaterial(XmlElement rootEl)
+Error MaterialResource::parseRtMaterial(XmlElement rtMaterialEl)
 {
-	XmlElement rtMaterialEl;
-	ANKI_CHECK(rootEl.getChildElementOptional("rtMaterial", rtMaterialEl));
-	if(!rtMaterialEl)
-	{
-		return Error::NONE;
-	}
-
 	// type
 	CString typeStr;
 	ANKI_CHECK(rtMaterialEl.getAttributeText("type", typeStr));
@@ -1069,7 +1102,7 @@ Error MaterialResource::parseRtMaterial(XmlElement rootEl)
 				return Error::USER_DATA;
 			}
 
-			if(mutatorPtr->valueExists(mutatorValue))
+			if(!mutatorPtr->valueExists(mutatorValue))
 			{
 				ANKI_RESOURCE_LOGE("Mutator value doesn't exist: %s", mutatorName.cstr());
 				return Error::USER_DATA;
@@ -1093,6 +1126,99 @@ Error MaterialResource::parseRtMaterial(XmlElement rootEl)
 		return Error::USER_DATA;
 	}
 
+	// input
+	RayTracingMaterialVariant& variant = m_rt[type].m_variant;
+	GpuMaterial& gpuMaterial = variant.m_gpuMaterialDescr;
+	XmlElement inputsEl;
+	ANKI_CHECK(rtMaterialEl.getChildElementOptional("inputs", inputsEl));
+	if(inputsEl)
+	{
+		XmlElement inputEl;
+		ANKI_CHECK(inputsEl.getChildElement("input", inputEl));
+
+		do
+		{
+			// name
+			CString inputName;
+			ANKI_CHECK(inputEl.getAttributeText("name", inputName));
+
+			// Check if texture
+			Bool found = false;
+			for(U32 i = 0; i < GPU_MATERIAL_TEXTURES.getSize(); ++i)
+			{
+				if(GPU_MATERIAL_TEXTURES[i].m_name == inputName)
+				{
+					// Found, load the texture
+
+					CString fname;
+					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));
+
+					variant.m_textureViews[textureIdx] = variant.m_textureResources[textureIdx]->getGrTextureView();
+
+					gpuMaterial.m_bindlessTextureIndices[textureIdx] =
+						U16(variant.m_textureViews[textureIdx]->getOrCreateBindlessTextureIndex());
+
+					found = true;
+					break;
+				}
+			}
+
+			// Check floats
+			if(!found)
+			{
+				for(U32 i = 0; i < GPU_MATERIAL_FLOATS.getSize(); ++i)
+				{
+					if(GPU_MATERIAL_FLOATS[i].m_name == inputName)
+					{
+						// Found it, set the value
+
+						if(GPU_MATERIAL_FLOATS[i].m_floatCount == 3)
+						{
+							Vec3 val;
+							ANKI_CHECK(inputEl.getAttributeNumbers("value", val));
+							memcpy(reinterpret_cast<U8*>(&gpuMaterial) + 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));
+						}
+
+						found = true;
+						break;
+					}
+				}
+			}
+
+			if(!found)
+			{
+				ANKI_RESOURCE_LOGE("Input name is incorrect: %s", inputName.cstr());
+				return Error::USER_DATA;
+			}
+
+			// Advance
+			ANKI_CHECK(inputEl.getNextSiblingElement("input", inputEl));
+		} 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;
 }
 

+ 12 - 1
anki/resource/MaterialResource.h

@@ -283,11 +283,22 @@ public:
 		return m_gpuMaterialDescr;
 	}
 
+	const Array<TextureViewPtr, TEXTURE_CHANNEL_COUNT>& getTextureViews() const
+	{
+		return m_textureViews;
+	}
+
 private:
 	ConstWeakArray<U8> m_shaderGroupHandle;
 	GpuMaterial m_gpuMaterialDescr;
+	Array<TextureResourcePtr, TEXTURE_CHANNEL_COUNT> m_textureResources; ///< Keep the resources alive.
+	Array<TextureViewPtr, TEXTURE_CHANNEL_COUNT> m_textureViews; ///< Cache the GPU objects.
+
+	RayTracingMaterialVariant()
+	{
+		memset(&m_gpuMaterialDescr, 0, sizeof(m_gpuMaterialDescr));
+	}
 
-	RayTracingMaterialVariant() = default;
 	~RayTracingMaterialVariant() = default;
 };
 

+ 4 - 8
anki/resource/ShaderProgramResource.cpp

@@ -168,15 +168,11 @@ Error ShaderProgramResource::load(const ResourceFilename& filename, Bool async)
 	// Do some RT checks
 	if(!!(m_shaderStages & ShaderTypeBit::ALL_RAY_TRACING))
 	{
-		if((m_shaderStages & ~(ShaderTypeBit::ANY_HIT | ShaderTypeBit::CLOSEST_HIT)) != ShaderTypeBit::NONE)
+		if(m_shaderStages != (ShaderTypeBit::ANY_HIT | ShaderTypeBit::CLOSEST_HIT)
+		   && m_shaderStages != ShaderTypeBit::MISS && m_shaderStages != ShaderTypeBit::RAY_GEN)
 		{
-			ANKI_RESOURCE_LOGE("Any and closest hit shaders shouldn't coexist with other stages");
-			return Error::USER_DATA;
-		}
-
-		if((m_shaderStages & ~(ShaderTypeBit::MISS | ShaderTypeBit::RAY_GEN)) != ShaderTypeBit::NONE)
-		{
-			ANKI_RESOURCE_LOGE("Miss and ray gen shaders shouldn't coexist with other stages");
+			ANKI_RESOURCE_LOGE("Any and closest hit shaders shouldn't coexist with other stages. Miss can't coexist "
+							   "with other stages. Raygen can't coexist with other stages as well");
 			return Error::USER_DATA;
 		}
 	}

+ 5 - 5
anki/shaders/ClusteredShadingCommon.glsl

@@ -46,12 +46,12 @@ layout(set = LIGHT_SET, binding = LIGHT_COMMON_UNIS_BINDING, std140, row_major)
 #if defined(LIGHT_LIGHTS_BINDING)
 layout(set = LIGHT_SET, binding = LIGHT_LIGHTS_BINDING, std140) uniform u1_
 {
-	PointLight u_pointLights[UBO_MAX_SIZE / SIZEOF_POINT_LIGHT];
+	PointLight u_pointLights[UBO_MAX_SIZE / ANKI_SIZEOF(PointLight)];
 };
 
 layout(set = LIGHT_SET, binding = LIGHT_LIGHTS_BINDING + 1, std140, row_major) uniform u2_
 {
-	SpotLight u_spotLights[UBO_MAX_SIZE / SIZEOF_SPOT_LIGHT];
+	SpotLight u_spotLights[UBO_MAX_SIZE / ANKI_SIZEOF(SpotLight)];
 };
 
 layout(set = LIGHT_SET, binding = LIGHT_LIGHTS_BINDING + 2) uniform highp texture2D u_shadowTex;
@@ -63,7 +63,7 @@ layout(set = LIGHT_SET, binding = LIGHT_LIGHTS_BINDING + 2) uniform highp textur
 #if defined(LIGHT_INDIRECT_SPECULAR_BINDING)
 layout(std140, row_major, set = LIGHT_SET, binding = LIGHT_INDIRECT_SPECULAR_BINDING) uniform u3_
 {
-	ReflectionProbe u_reflectionProbes[UBO_MAX_SIZE / SIZEOF_REFLECTION_PROBE];
+	ReflectionProbe u_reflectionProbes[UBO_MAX_SIZE / ANKI_SIZEOF(ReflectionProbe)];
 };
 
 layout(set = LIGHT_SET, binding = LIGHT_INDIRECT_SPECULAR_BINDING + 1) uniform textureCubeArray u_reflectionsTex;
@@ -76,7 +76,7 @@ layout(set = LIGHT_SET, binding = LIGHT_INDIRECT_SPECULAR_BINDING + 2) uniform t
 #if defined(LIGHT_DECALS_BINDING)
 layout(std140, row_major, set = LIGHT_SET, binding = LIGHT_DECALS_BINDING) uniform u4_
 {
-	Decal u_decals[UBO_MAX_SIZE / SIZEOF_DECAL];
+	Decal u_decals[UBO_MAX_SIZE / ANKI_SIZEOF(Decal)];
 };
 
 layout(set = LIGHT_SET, binding = LIGHT_DECALS_BINDING + 1) uniform texture2D u_diffDecalTex;
@@ -89,7 +89,7 @@ layout(set = LIGHT_SET, binding = LIGHT_DECALS_BINDING + 2) uniform texture2D u_
 #if defined(LIGHT_FOG_DENSITY_VOLUMES_BINDING)
 layout(std140, row_major, set = LIGHT_SET, binding = LIGHT_FOG_DENSITY_VOLUMES_BINDING) uniform u5_
 {
-	FogDensityVolume u_fogDensityVolumes[UBO_MAX_SIZE / SIZEOF_FOG_DENSITY_VOLUME];
+	FogDensityVolume u_fogDensityVolumes[UBO_MAX_SIZE / ANKI_SIZEOF(FogDensityVolume)];
 };
 #endif
 

+ 1 - 1
anki/shaders/RtShadowsHit.ankiprog

@@ -49,7 +49,7 @@ void main()
 	const Vec2 uv = vert0.m_uvs[UV_CHANNEL_0] * barycentrics.x + vert1.m_uvs[UV_CHANNEL_0] * barycentrics.y
 					+ vert2.m_uvs[UV_CHANNEL_0] * barycentrics.z;
 
-	const U32 texIdx = model.m_material.m_textureIds[TEXTURE_CHANNEL_DIFFUSE];
+	const U32 texIdx = model.m_material.m_bindlessTextureIndices[TEXTURE_CHANNEL_DIFFUSE];
 	const F32 alpha = textureLod(u_bindlessTextures2dF32[nonuniformEXT(texIdx)], u_ankiGlobalSampler, uv, 3).a;
 
 	g_payload += alpha;

+ 17 - 16
anki/shaders/include/ClusteredShading.h

@@ -37,8 +37,8 @@ struct PointLight
 	F32 m_radius; // Radius
 	Vec4 m_shadowAtlasTileOffsets[3u]; // It's a Vec4 because of the std140 limitations
 };
-const U32 SIZEOF_POINT_LIGHT = 6 * ANKI_SIZEOF(Vec4);
-ANKI_SHADER_STATIC_ASSERT(sizeof(PointLight) == SIZEOF_POINT_LIGHT)
+const U32 _ANKI_SIZEOF_PointLight = 6 * ANKI_SIZEOF(Vec4);
+ANKI_SHADER_STATIC_ASSERT(sizeof(PointLight) == _ANKI_SIZEOF_PointLight);
 
 // Spot light
 struct SpotLight
@@ -55,8 +55,8 @@ struct SpotLight
 	F32 m_padding1;
 	Mat4 m_texProjectionMat;
 };
-const U32 SIZEOF_SPOT_LIGHT = 4 * ANKI_SIZEOF(Vec4) + ANKI_SIZEOF(Mat4);
-ANKI_SHADER_STATIC_ASSERT(sizeof(SpotLight) == SIZEOF_SPOT_LIGHT)
+const U32 _ANKI_SIZEOF_SpotLight = 4 * ANKI_SIZEOF(Vec4) + ANKI_SIZEOF(Mat4);
+ANKI_SHADER_STATIC_ASSERT(sizeof(SpotLight) == _ANKI_SIZEOF_SpotLight);
 
 // Directional light (sun)
 struct DirectionalLight
@@ -70,8 +70,8 @@ struct DirectionalLight
 	F32 m_shadowCascadesDistancePower;
 	Mat4 m_textureMatrices[MAX_SHADOW_CASCADES];
 };
-const U32 SIZEOF_DIR_LIGHT = 3 * ANKI_SIZEOF(Vec4) + MAX_SHADOW_CASCADES * ANKI_SIZEOF(Mat4);
-ANKI_SHADER_STATIC_ASSERT(sizeof(DirectionalLight) == SIZEOF_DIR_LIGHT)
+const U32 _ANKI_SIZEOF_DirectionalLight = 3 * ANKI_SIZEOF(Vec4) + MAX_SHADOW_CASCADES * ANKI_SIZEOF(Mat4);
+ANKI_SHADER_STATIC_ASSERT(sizeof(DirectionalLight) == _ANKI_SIZEOF_DirectionalLight);
 
 // Representation of a reflection probe
 struct ReflectionProbe
@@ -83,8 +83,8 @@ struct ReflectionProbe
 	Vec3 m_aabbMax;
 	F32 m_padding1;
 };
-const U32 SIZEOF_REFLECTION_PROBE = 3 * ANKI_SIZEOF(Vec4);
-ANKI_SHADER_STATIC_ASSERT(sizeof(ReflectionProbe) == SIZEOF_REFLECTION_PROBE)
+const U32 _ANKI_SIZEOF_ReflectionProbe = 3 * ANKI_SIZEOF(Vec4);
+ANKI_SHADER_STATIC_ASSERT(sizeof(ReflectionProbe) == _ANKI_SIZEOF_ReflectionProbe);
 
 // Decal
 struct Decal
@@ -94,8 +94,8 @@ struct Decal
 	Mat4 m_texProjectionMat;
 	Vec4 m_blendFactors;
 };
-const U32 SIZEOF_DECAL = 3 * ANKI_SIZEOF(Vec4) + ANKI_SIZEOF(Mat4);
-ANKI_SHADER_STATIC_ASSERT(sizeof(Decal) == SIZEOF_DECAL)
+const U32 _ANKI_SIZEOF_Decal = 3 * ANKI_SIZEOF(Vec4) + ANKI_SIZEOF(Mat4);
+ANKI_SHADER_STATIC_ASSERT(sizeof(Decal) == _ANKI_SIZEOF_Decal);
 
 // Fog density volume
 struct FogDensityVolume
@@ -105,8 +105,8 @@ struct FogDensityVolume
 	Vec3 m_aabbMaxOrSphereRadiusSquared;
 	F32 m_density;
 };
-const U32 SIZEOF_FOG_DENSITY_VOLUME = 2u * ANKI_SIZEOF(Vec4);
-ANKI_SHADER_STATIC_ASSERT(sizeof(FogDensityVolume) == SIZEOF_FOG_DENSITY_VOLUME)
+const U32 _ANKI_SIZEOF_FogDensityVolume = 2u * ANKI_SIZEOF(Vec4);
+ANKI_SHADER_STATIC_ASSERT(sizeof(FogDensityVolume) == _ANKI_SIZEOF_FogDensityVolume);
 
 // Global illumination probe
 struct GlobalIlluminationProbe
@@ -123,8 +123,8 @@ struct GlobalIlluminationProbe
 	F32 m_padding1;
 	F32 m_padding2;
 };
-const U32 SIZEOF_GLOBAL_ILLUMINATION_PROBE = 3u * ANKI_SIZEOF(Vec4);
-ANKI_SHADER_STATIC_ASSERT(sizeof(GlobalIlluminationProbe) == SIZEOF_GLOBAL_ILLUMINATION_PROBE)
+const U32 _ANKI_SIZEOF_GlobalIlluminationProbe = 3u * ANKI_SIZEOF(Vec4);
+ANKI_SHADER_STATIC_ASSERT(sizeof(GlobalIlluminationProbe) == _ANKI_SIZEOF_GlobalIlluminationProbe);
 
 // Common uniforms for light shading passes
 struct LightingUniforms
@@ -157,8 +157,9 @@ struct LightingUniforms
 
 	DirectionalLight m_dirLight;
 };
-const U32 SIZEOF_LIGHTING_UNIFORMS = 9u * ANKI_SIZEOF(Vec4) + 8u * ANKI_SIZEOF(Mat4) + SIZEOF_DIR_LIGHT;
-ANKI_SHADER_STATIC_ASSERT(sizeof(LightingUniforms) == SIZEOF_LIGHTING_UNIFORMS)
+const U32 _ANKI_SIZEOF_LightingUniforms =
+	9u * ANKI_SIZEOF(Vec4) + 8u * ANKI_SIZEOF(Mat4) + ANKI_SIZEOF(DirectionalLight);
+ANKI_SHADER_STATIC_ASSERT(sizeof(LightingUniforms) == _ANKI_SIZEOF_LightingUniforms);
 
 ANKI_SHADER_FUNC_INLINE F32 computeClusterKf(ClustererMagicValues magic, Vec3 worldPos)
 {

+ 3 - 1
anki/shaders/include/Common.h

@@ -19,7 +19,9 @@
 #	define ANKI_SHADER_IN(type_) const type_&
 #	define ANKI_SHADER_OUT(type_) type_&
 
-#	define ANKI_SHADER_STATIC_ASSERT(cond_) static_assert(cond_, "See file");
+#	define ANKI_SHADER_STATIC_ASSERT(cond_) static_assert(cond_, "See file")
+
+#	define ANKI_SIZEOF(x) sizeof(x)
 
 ANKI_BEGIN_NAMESPACE
 template<typename T>

+ 3 - 1
anki/shaders/include/GpuModel.h

@@ -20,6 +20,8 @@ struct GpuVertex
 };
 
 const U32 _ANKI_SIZEOF_GpuVertex = 4 * 3;
+const U32 _ANKI_ALIGNOF_GpuVertex = 4;
+ANKI_SHADER_STATIC_ASSERT(_ANKI_SIZEOF_GpuVertex == sizeof(GpuVertex));
 
 struct GpuMesh
 {
@@ -43,7 +45,7 @@ const U32 TEXTURE_CHANNEL_COUNT = 8;
 
 struct GpuMaterial
 {
-	U16 m_textureIds[TEXTURE_CHANNEL_COUNT];
+	U16 m_bindlessTextureIndices[TEXTURE_CHANNEL_COUNT];
 	Vec3 m_diffuseColor;
 	Vec3 m_specularColor;
 	Vec3 m_emissiveColor;

+ 9 - 4
anki/util/Xml.cpp

@@ -156,18 +156,23 @@ Error XmlDocument::parse(CString xmlText, GenericMemoryPoolAllocator<U8> alloc)
 	return Error::NONE;
 }
 
-ANKI_USE_RESULT Error XmlDocument::getChildElement(CString name, XmlElement& out) const
+ANKI_USE_RESULT Error XmlDocument::getChildElementOptional(CString name, XmlElement& out) const
 {
-	Error err = Error::NONE;
 	out = XmlElement(m_doc.FirstChildElement(&name[0]), m_alloc);
+	return Error::NONE;
+}
+
+ANKI_USE_RESULT Error XmlDocument::getChildElement(CString name, XmlElement& out) const
+{
+	ANKI_CHECK(getChildElementOptional(name, out));
 
 	if(!out)
 	{
 		ANKI_UTIL_LOGE("Cannot find tag \"%s\"", &name[0]);
-		err = Error::USER_DATA;
+		return Error::USER_DATA;
 	}
 
-	return err;
+	return Error::NONE;
 }
 
 } // end namespace anki

+ 2 - 0
anki/util/Xml.h

@@ -205,6 +205,8 @@ public:
 
 	ANKI_USE_RESULT Error getChildElement(CString name, XmlElement& out) const;
 
+	ANKI_USE_RESULT Error getChildElementOptional(CString name, XmlElement& out) const;
+
 private:
 	tinyxml2::XMLDocument m_doc;
 	GenericMemoryPoolAllocator<U8> m_alloc;