Panagiotis Christopoulos Charitos 5 年 前
コミット
9597139c03

+ 114 - 0
src/anki/gr/ShaderProgram.cpp

@@ -0,0 +1,114 @@
+// Copyright (C) 2009-2020, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#include <anki/gr/ShaderProgram.h>
+
+namespace anki
+{
+
+Bool ShaderProgramInitInfo::isValid() const
+{
+	ShaderTypeBit graphicsMask = ShaderTypeBit::NONE;
+	for(ShaderType i = ShaderType::FIRST_GRAPHICS; i <= ShaderType::LAST_GRAPHICS; ++i)
+	{
+		if(m_graphicsShaders[i])
+		{
+			if(m_graphicsShaders[i]->getShaderType() != i)
+			{
+				return false;
+			}
+			graphicsMask |= ShaderTypeBit(1 << i);
+		}
+	}
+
+	if(!!graphicsMask
+	   && (graphicsMask & (ShaderTypeBit::VERTEX | ShaderTypeBit::FRAGMENT))
+			  != (ShaderTypeBit::VERTEX | ShaderTypeBit::FRAGMENT))
+	{
+		return false;
+	}
+
+	Bool compute = false;
+	if(m_computeShader)
+	{
+		if(m_computeShader->getShaderType() != ShaderType::COMPUTE)
+		{
+			return false;
+		}
+		compute = true;
+	}
+
+	if(compute && !!graphicsMask)
+	{
+		return false;
+	}
+
+	ShaderTypeBit rtMask = ShaderTypeBit::NONE;
+	if(m_rayTracingShaders.m_rayGenShader)
+	{
+		if(m_rayTracingShaders.m_rayGenShader->getShaderType() != ShaderType::RAY_GEN)
+		{
+			return false;
+		}
+		rtMask |= ShaderTypeBit::RAY_GEN;
+	}
+
+	for(const ShaderPtr& s : m_rayTracingShaders.m_missShaders)
+	{
+		if(s->getShaderType() != ShaderType::MISS)
+		{
+			return false;
+		}
+		rtMask |= ShaderTypeBit::MISS;
+	}
+
+	for(const RayTracingHitGroup& group : m_rayTracingShaders.m_hitGroups)
+	{
+		ShaderTypeBit localRtMask = ShaderTypeBit::NONE;
+		if(group.m_anyHitShader)
+		{
+			if(group.m_anyHitShader->getShaderType() != ShaderType::ANY_HIT)
+			{
+				return false;
+			}
+			localRtMask |= ShaderTypeBit::ANY_HIT;
+		}
+
+		if(group.m_closestHitShader)
+		{
+			if(group.m_closestHitShader->getShaderType() != ShaderType::CLOSEST_HIT)
+			{
+				return false;
+			}
+			localRtMask |= ShaderTypeBit::CLOSEST_HIT;
+		}
+
+		if(!localRtMask)
+		{
+			return false;
+		}
+
+		rtMask |= localRtMask;
+	}
+
+	if(!!rtMask && (!!graphicsMask || compute))
+	{
+		return false;
+	}
+
+	if(!graphicsMask && !compute && !rtMask)
+	{
+		return false;
+	}
+
+	if(!!rtMask && m_rayTracingShaders.m_maxRecursionDepth == 0)
+	{
+		return false;
+	}
+
+	return true;
+}
+
+} // end namespace anki

+ 2 - 97
src/anki/gr/ShaderProgram.h

@@ -29,6 +29,7 @@ public:
 	ShaderPtr m_rayGenShader;
 	ShaderPtr m_rayGenShader;
 	WeakArray<ShaderPtr> m_missShaders;
 	WeakArray<ShaderPtr> m_missShaders;
 	WeakArray<RayTracingHitGroup> m_hitGroups;
 	WeakArray<RayTracingHitGroup> m_hitGroups;
+	U32 m_maxRecursionDepth = 1;
 };
 };
 
 
 /// ShaderProgram init info.
 /// ShaderProgram init info.
@@ -49,103 +50,7 @@ public:
 	{
 	{
 	}
 	}
 
 
-	Bool isValid() const
-	{
-		ShaderTypeBit graphicsMask = ShaderTypeBit::NONE;
-		for(ShaderType i = ShaderType::FIRST_GRAPHICS; i <= ShaderType::LAST_GRAPHICS; ++i)
-		{
-			if(m_graphicsShaders[i])
-			{
-				if(m_graphicsShaders[i]->getShaderType() != i)
-				{
-					return false;
-				}
-				graphicsMask |= ShaderTypeBit(1 << i);
-			}
-		}
-
-		if(!!graphicsMask
-		   && (graphicsMask & (ShaderTypeBit::VERTEX | ShaderTypeBit::FRAGMENT))
-				  != (ShaderTypeBit::VERTEX | ShaderTypeBit::FRAGMENT))
-		{
-			return false;
-		}
-
-		Bool compute = false;
-		if(m_computeShader)
-		{
-			if(m_computeShader->getShaderType() != ShaderType::COMPUTE)
-			{
-				return false;
-			}
-			compute = true;
-		}
-
-		if(compute && !!graphicsMask)
-		{
-			return false;
-		}
-
-		ShaderTypeBit rtMask = ShaderTypeBit::NONE;
-		if(m_rayTracingShaders.m_rayGenShader)
-		{
-			if(m_rayTracingShaders.m_rayGenShader->getShaderType() != ShaderType::RAY_GEN)
-			{
-				return false;
-			}
-			rtMask |= ShaderTypeBit::RAY_GEN;
-		}
-
-		for(const ShaderPtr& s : m_rayTracingShaders.m_missShaders)
-		{
-			if(s->getShaderType() != ShaderType::MISS)
-			{
-				return false;
-			}
-			rtMask |= ShaderTypeBit::MISS;
-		}
-
-		for(const RayTracingHitGroup& group : m_rayTracingShaders.m_hitGroups)
-		{
-			ShaderTypeBit localRtMask = ShaderTypeBit::NONE;
-			if(group.m_anyHitShader)
-			{
-				if(group.m_anyHitShader->getShaderType() != ShaderType::ANY_HIT)
-				{
-					return false;
-				}
-				localRtMask |= ShaderTypeBit::ANY_HIT;
-			}
-
-			if(group.m_closestHitShader)
-			{
-				if(group.m_closestHitShader->getShaderType() != ShaderType::CLOSEST_HIT)
-				{
-					return false;
-				}
-				localRtMask |= ShaderTypeBit::CLOSEST_HIT;
-			}
-
-			if(!localRtMask)
-			{
-				return false;
-			}
-
-			rtMask |= localRtMask;
-		}
-
-		if(!!rtMask && (!!graphicsMask || compute))
-		{
-			return false;
-		}
-
-		if(!graphicsMask && !compute && !rtMask)
-		{
-			return false;
-		}
-
-		return true;
-	}
+	Bool isValid() const;
 };
 };
 
 
 /// GPU program.
 /// GPU program.

+ 1 - 1
src/anki/gr/vulkan/ShaderProgramImpl.cpp

@@ -314,7 +314,7 @@ Error ShaderProgramImpl::init(const ShaderProgramInitInfo& inf)
 		ci.pStages = &stages[0];
 		ci.pStages = &stages[0];
 		ci.groupCount = groups.getSize();
 		ci.groupCount = groups.getSize();
 		ci.pGroups = &groups[0];
 		ci.pGroups = &groups[0];
-		ci.maxRecursionDepth = 1;
+		ci.maxRecursionDepth = inf.m_rayTracingShaders.m_maxRecursionDepth;
 		ci.libraries.sType = VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR;
 		ci.libraries.sType = VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR;
 		ci.layout = m_pplineLayout.getHandle();
 		ci.layout = m_pplineLayout.getHandle();
 
 

+ 57 - 21
tests/gr/Gr.cpp

@@ -2754,6 +2754,8 @@ ANKI_TEST(Gr, RayGen)
 		const CString commonSrcPart = R"(
 		const CString commonSrcPart = R"(
 %s
 %s
 
 
+const F32 PI = 3.14159265358979323846;
+
 struct PayLoad
 struct PayLoad
 {
 {
 	Vec3 m_emissiveColor;
 	Vec3 m_emissiveColor;
@@ -2779,6 +2781,61 @@ layout(set = 0, binding = 1, scalar) buffer b_01
 
 
 #define PAYLOAD_LOCATION 0
 #define PAYLOAD_LOCATION 0
 #define SHADOW_PAYLOAD_LOCATION 1
 #define SHADOW_PAYLOAD_LOCATION 1
+
+UVec3 rand3DPCG16(UVec3 v)
+{
+	v = v * 1664525u + 1013904223u;
+
+	v.x += v.y * v.z;
+	v.y += v.z * v.x;
+	v.z += v.x * v.y;
+	v.x += v.y * v.z;
+	v.y += v.z * v.x;
+	v.z += v.x * v.y;
+
+	return v >> 16u;
+}
+
+Vec2 hammersleyRandom16(U32 sampleIdx, U32 sampleCount, UVec2 random)
+{
+	const F32 e1 = fract(F32(sampleIdx) / sampleCount + F32(random.x) * (1.0 / 65536.0));
+	const F32 e2 = F32((bitfieldReverse(sampleIdx) >> 16) ^ random.y) * (1.0 / 65536.0);
+	return Vec2(e1, e2);
+}
+
+Vec3 hemisphereSampleUniform(Vec2 uv)
+{
+	const F32 phi = uv.y * 2.0 * PI;
+	const F32 cosTheta = 1.0 - uv.x;
+	const F32 sinTheta = sqrt(1.0 - cosTheta * cosTheta);
+	return Vec3(cos(phi) * sinTheta, sin(phi) * sinTheta, cosTheta);
+}
+
+Mat3 rotationFromDirection(Vec3 zAxis)
+{
+	Vec3 z = zAxis;
+	F32 sign = (z.z >= 0.0) ? 1.0 : -1.0;
+	F32 a = -1.0 / (sign + z.z);
+	F32 b = z.x * z.y * a;
+
+	Vec3 x = Vec3(1.0 + sign * a * pow(z.x, 2.0), sign * b, -sign * z.x);
+	Vec3 y = Vec3(b, sign + a * pow(z.y, 2.0), -z.y);
+
+	return Mat3(x, y, z);
+}
+
+void scatterLambertian(Vec3 normal, Vec2 uniformRandom01, out Vec3 scatterDir, out F32 pdf)
+{
+	scatterDir = normalize(rotationFromDirection(normal) * hemisphereSampleUniform(uniformRandom01));
+	pdf = dot(normal, scatterDir) / PI;
+}
+
+F32 scatteringPdfLambertian(Vec3 normal, Vec3 scatteredDir)
+{
+	F32 cosine = dot(normal, scatteredDir);
+	return max(cosine / PI, 0.0);
+}
+
 )";
 )";
 
 
 		const CString chit0Src = R"(
 		const CString chit0Src = R"(
@@ -2919,27 +2976,6 @@ layout(push_constant, scalar) uniform u_pc
 layout(location = PAYLOAD_LOCATION) rayPayloadEXT PayLoad s_payLoad;
 layout(location = PAYLOAD_LOCATION) rayPayloadEXT PayLoad s_payLoad;
 layout(location = SHADOW_PAYLOAD_LOCATION) rayPayloadEXT ShadowPayLoad s_shadowPayLoad;
 layout(location = SHADOW_PAYLOAD_LOCATION) rayPayloadEXT ShadowPayLoad s_shadowPayLoad;
 
 
-UVec3 rand3DPCG16(UVec3 v)
-{
-	v = v * 1664525u + 1013904223u;
-
-	v.x += v.y * v.z;
-	v.y += v.z * v.x;
-	v.z += v.x * v.y;
-	v.x += v.y * v.z;
-	v.y += v.z * v.x;
-	v.z += v.x * v.y;
-
-	return v >> 16u;
-}
-
-Vec2 hammersleyRandom16(U32 sampleIdx, U32 sampleCount, UVec2 random)
-{
-	const F32 e1 = fract(F32(sampleIdx) / sampleCount + F32(random.x) * (1.0 / 65536.0));
-	const F32 e2 = F32((bitfieldReverse(sampleIdx) >> 16) ^ random.y) * (1.0 / 65536.0);
-	return Vec2(e1, e2);
-}
-
 void main()
 void main()
 {
 {
 	Vec2 uv = (Vec2(gl_LaunchIDEXT.xy) + 0.5) / Vec2(gl_LaunchSizeEXT.xy);
 	Vec2 uv = (Vec2(gl_LaunchIDEXT.xy) + 0.5) / Vec2(gl_LaunchSizeEXT.xy);