Просмотр исходного кода

Improvements to the shading language in order to make managing complex shaders easier:
- Techniques no longer need to be defined in order
- Multiple techniques in the inheritance chain can now inherit from the same base, in order to make dependencies easier
- Techniques can be overriden

BearishSun 8 лет назад
Родитель
Сommit
cbf82c9146

+ 8 - 4
Data/Raw/Engine/DataList.json

@@ -48,10 +48,6 @@
         }
     ],
     "Includes": [
-        {
-            "Path": "GBuffer.bslinc",
-            "UUID": "ef1a179a-4bf9-4dbd-b62a-e18524d959b6"
-        },
         {
             "Path": "NormalVertexInput.bslinc",
             "UUID": "967325e7-262b-49bf-8c90-032a8bbc8ce2"
@@ -123,6 +119,14 @@
         {
             "Path": "ImageBasedLighting.bslinc",
             "UUID": "ff162afd-ed4d-4460-8982-ad6c0f7be19c"
+        },
+        {
+            "Path": "GBufferInput.bslinc",
+            "UUID": "d481b49b-a60b-4d0d-bd8c-c3ed9c53fc6c"
+        },
+        {
+            "Path": "GBufferOutput.bslinc",
+            "UUID": "46df32e8-6400-46d5-9ac2-beefdc9016ad"
         }
     ],
     "Shaders": [

+ 9 - 9
Data/Raw/Engine/Includes/BasePass.bslinc

@@ -1,4 +1,4 @@
-#include "$ENGINE$\GBuffer.bslinc"
+#include "$ENGINE$\GBufferOutput.bslinc"
 #include "$ENGINE$\PerCameraData.bslinc"
 #include "$ENGINE$\PerObjectData.bslinc"
 
@@ -51,7 +51,7 @@ Technique : base("BasePassCommon") =
 
 Technique
  : base("BasePass")
- : inherits("GBuffer")
+ : inherits("GBufferOutput")
  : inherits("PerCameraData")
  : inherits("PerObjectData")
  : inherits("NormalVertexInput")
@@ -62,7 +62,7 @@ Technique
 
 Technique
  : base("BasePassSkinned")
- : inherits("GBuffer")
+ : inherits("GBufferOutput")
  : inherits("PerCameraData")
  : inherits("PerObjectData")
  : inherits("SkinnedVertexInput")
@@ -73,7 +73,7 @@ Technique
 
 Technique
  : base("BasePassMorph")
- : inherits("GBuffer")
+ : inherits("GBufferOutput")
  : inherits("PerCameraData")
  : inherits("PerObjectData")
  : inherits("MorphVertexInput")
@@ -84,7 +84,7 @@ Technique
 
 Technique
  : base("BasePassSkinnedMorph")
- : inherits("GBuffer")
+ : inherits("GBufferOutput")
  : inherits("PerCameraData")
  : inherits("PerObjectData")
  : inherits("SkinnedMorphVertexInput")
@@ -134,7 +134,7 @@ Technique
 
 Technique
  : base("BasePass")
- : inherits("GBuffer")
+ : inherits("GBufferOutput")
  : inherits("PerCameraData")
  : inherits("PerObjectData")
  : inherits("NormalVertexInput")
@@ -145,7 +145,7 @@ Technique
 
 Technique
  : base("BasePassSkinned")
- : inherits("GBuffer")
+ : inherits("GBufferOutput")
  : inherits("PerCameraData")
  : inherits("PerObjectData")
  : inherits("SkinnedVertexInput")
@@ -156,7 +156,7 @@ Technique
 
 Technique
  : base("BasePassMorph")
- : inherits("GBuffer")
+ : inherits("GBufferOutput")
  : inherits("PerCameraData")
  : inherits("PerObjectData")
  : inherits("MorphVertexInput")
@@ -167,7 +167,7 @@ Technique
 
 Technique
  : base("BasePassSkinnedMorph")
- : inherits("GBuffer")
+ : inherits("GBufferOutput")
  : inherits("PerCameraData")
  : inherits("PerObjectData")
  : inherits("SkinnedMorphVertexInput")

+ 83 - 0
Data/Raw/Engine/Includes/GBufferInput.bslinc

@@ -0,0 +1,83 @@
+#include "$ENGINE$\SurfaceData.bslinc"
+
+Parameters =
+{
+	Sampler2D 	gGBufferASamp : alias("gGBufferATex");
+	Sampler2D 	gGBufferBSamp : alias("gGBufferBTex");
+	Sampler2D 	gGBufferCSamp : alias("gGBufferCTex");
+	Sampler2D 	gDepthBufferSamp : alias("gDepthBufferTex");
+	
+	Texture2D 	gGBufferATex : auto("GBufferA");
+	Texture2D	gGBufferBTex : auto("GBufferB");
+	Texture2D	gGBufferCTex : auto("GBufferC");
+	Texture2D 	gDepthBufferTex : auto("GBufferDepth");
+};
+
+Technique 
+ : inherits("SurfaceData")
+ : inherits("PerCameraData")
+ : base("GBufferInput") =
+{
+	Language = "HLSL11";
+
+	Pass =
+	{
+		Common = 
+		{
+			SamplerState gGBufferASamp : register(s0);
+			SamplerState gGBufferBSamp : register(s1);
+			SamplerState gGBufferCSamp : register(s2);
+			SamplerState gDepthBufferSamp : register(s3);
+	
+			#if MSAA_COUNT > 1
+			Texture2DMS<float4, MSAA_COUNT> gGBufferATex : register(t0);
+			Texture2DMS<float4, MSAA_COUNT>	gGBufferBTex : register(t1);
+			Texture2DMS<float2, MSAA_COUNT>	gGBufferCTex : register(t2);
+			Texture2DMS<float4, MSAA_COUNT> gDepthBufferTex : register(t3);
+			#else
+			Texture2D gGBufferATex : register(t0);
+			Texture2D gGBufferBTex : register(t1);
+			Texture2D gGBufferCTex : register(t2);
+			Texture2D gDepthBufferTex : register(t3);
+			#endif
+			
+			SurfaceData decodeGBuffer(float4 GBufferAData, float4 GBufferBData, float2 GBufferCData, float deviceZ)
+			{
+				SurfaceData output;
+				
+				output.albedo.xyz = GBufferAData.xyz;
+				output.albedo.w = 1.0f;
+				output.worldNormal = GBufferBData * float4(2, 2, 2, 1) - float4(1, 1, 1, 0);
+				output.worldNormal.xyz = normalize(output.worldNormal.xyz);
+				output.depth = convertFromDeviceZ(deviceZ);
+				output.roughness = GBufferCData.x;
+				output.metalness = GBufferCData.y;
+				
+				return output;
+			}
+			
+			#if MSAA_COUNT > 1
+			SurfaceData getGBufferData(uint2 pixelPos, uint sampleIndex)
+			{
+				float4 GBufferAData = gGBufferATex.Load(pixelPos, sampleIndex);
+				float4 GBufferBData = gGBufferBTex.Load(pixelPos, sampleIndex);
+				float2 GBufferCData = gGBufferCTex.Load(pixelPos, sampleIndex).rg;
+				float deviceZ = gDepthBufferTex.Load(pixelPos, sampleIndex).r;
+				
+				return decodeGBuffer(GBufferAData, GBufferBData, GBufferCData, deviceZ);
+			}
+			
+			#else
+			SurfaceData getGBufferData(uint2 pixelPos)
+			{
+				float4 GBufferAData = gGBufferATex.Load(int3(pixelPos, 0));
+				float4 GBufferBData = gGBufferBTex.Load(int3(pixelPos, 0));
+				float2 GBufferCData = gGBufferCTex.Load(int3(pixelPos, 0)).rg;
+				float deviceZ = gDepthBufferTex.Load(int3(pixelPos, 0)).r;
+				
+				return decodeGBuffer(GBufferAData, GBufferBData, GBufferCData, deviceZ);
+			}			
+			#endif			
+		};
+	};
+};

+ 2 - 2
Data/Raw/Engine/Includes/GBuffer.bslinc → Data/Raw/Engine/Includes/GBufferOutput.bslinc

@@ -2,7 +2,7 @@
 
 Technique 
  : inherits("SurfaceData")
- : base("GBuffer") =
+ : base("GBufferOutput") =
 {
 	Language = "HLSL11";
 
@@ -24,7 +24,7 @@ Technique
 
 Technique 
  : inherits("SurfaceData")
- : base("GBuffer") =
+ : base("GBufferOutput") =
 {
 	Language = "GLSL";
 

+ 6 - 2
Data/Raw/Engine/Includes/LightingCommon.bslinc

@@ -1,5 +1,8 @@
+#include "$ENGINE$\SurfaceData.bslinc"
+
 Technique
- : base("LightingCommon") =
+ : base("LightingCommon")
+ : inherits("SurfaceData") =
 {
 	Language = "HLSL11";
 	
@@ -375,7 +378,8 @@ Technique
 };
 
 Technique
- : base("LightingCommon") =
+ : base("LightingCommon")
+ : inherits("SurfaceData") =
 {
 	Language = "GLSL";
 	

+ 25 - 0
Data/Raw/Engine/Includes/SurfaceData.bslinc

@@ -14,6 +14,31 @@ Technique : base("SurfaceData") =
 				float roughness;
 				float metalness;
 			};
+			
+#if MSAA_COUNT > 1
+			bool needsPerSampleShading(SurfaceData samples[MSAA_COUNT])
+			{
+				float3 albedo = samples[0].albedo.xyz;
+				float3 normal = samples[0].worldNormal.xyz;
+				float depth = samples[0].depth;
+
+				[unroll]
+				for(int i = 1; i < MSAA_COUNT; i++)
+				{
+					float3 otherAlbedo = samples[i].albedo.xyz;
+					float3 otherNormal = samples[i].worldNormal.xyz;
+					float otherDepth = samples[i].depth;
+
+					[branch]
+					if(abs(depth - otherDepth) > 0.1f || abs(dot(abs(normal - otherNormal), float3(1, 1, 1))) > 0.1f || abs(dot(albedo - otherAlbedo, float3(1, 1, 1))) > 0.1f)
+					{
+						return true;
+					}
+				}
+				
+				return false;
+			}
+#endif			
 		};
 	};
 };

+ 2 - 3
Data/Raw/Engine/Shaders/Default.bsl

@@ -1,4 +1,5 @@
 #include "$ENGINE$\BasePass.bslinc"
+#include "$ENGINE$\Surface.bslinc"
 
 Technique : base("Surface") =
 {
@@ -52,6 +53,4 @@ Technique : base("Surface") =
 			}	
 		};
 	};
-};
-
-#include "$ENGINE$\Surface.bslinc"
+};

+ 2 - 3
Data/Raw/Engine/Shaders/Diffuse.bsl

@@ -1,4 +1,5 @@
 #include "$ENGINE$\BasePass.bslinc"
+#include "$ENGINE$\Surface.bslinc"
 
 Parameters =
 {
@@ -86,6 +87,4 @@ Technique : base("Surface") =
 			}	
 		};
 	};
-};
-
-#include "$ENGINE$\Surface.bslinc"
+};

+ 0 - 3
Data/Raw/Engine/Shaders/LightGridLLCreation.bsl

@@ -1,4 +1,3 @@
-#include "$ENGINE$\GBuffer.bslinc"
 #include "$ENGINE$\PerCameraData.bslinc"
 #include "$ENGINE$\LightingCommon.bslinc"
 #include "$ENGINE$\LightGridCommon.bslinc"
@@ -10,7 +9,6 @@ Blocks =
 };
 
 Technique
- : inherits("GBuffer")
  : inherits("PerCameraData")
  : inherits("LightingCommon")
  : inherits("LightGridCommon") =
@@ -134,7 +132,6 @@ Technique
 };
 
 Technique
- : inherits("GBuffer")
  : inherits("PerCameraData")
  : inherits("LightingCommon")
  : inherits("LightGridCommon") =

+ 4 - 97
Data/Raw/Engine/Shaders/TiledDeferredLighting.bsl

@@ -1,30 +1,12 @@
-#include "$ENGINE$\GBuffer.bslinc"
+#include "$ENGINE$\GBufferInput.bslinc"
 #include "$ENGINE$\PerCameraData.bslinc"
 #define USE_COMPUTE_INDICES
 #include "$ENGINE$\LightingCommon.bslinc"
 #include "$ENGINE$\ReflectionCubemapCommon.bslinc"
 #include "$ENGINE$\ImageBasedLighting.bslinc"
 
-Parameters =
-{
-	Sampler2D 	gGBufferASamp : alias("gGBufferATex");
-	Sampler2D 	gGBufferBSamp : alias("gGBufferBTex");
-	Sampler2D 	gGBufferCSamp : alias("gGBufferCTex");
-	Sampler2D 	gDepthBufferSamp : alias("gDepthBufferTex");
-	
-	Texture2D 	gGBufferATex : auto("GBufferA");
-	Texture2D	gGBufferBTex : auto("GBufferB");
-	Texture2D	gGBufferCTex : auto("GBufferC");
-	Texture2D 	gDepthBufferTex : auto("GBufferDepth");
-};
-
-Blocks =
-{
-	Block PerCamera : auto("PerCamera");
-};
-
 Technique 
-  : inherits("GBuffer")
+  : inherits("GBufferInput")
   : inherits("PerCameraData")
   : inherits("LightingCommon")
   : inherits("ReflectionCubemapCommon")
@@ -35,39 +17,7 @@ Technique
 	Pass =
 	{
 		Compute = 
-		{
-			SamplerState gGBufferASamp : register(s0);
-			SamplerState gGBufferBSamp : register(s1);
-			SamplerState gGBufferCSamp : register(s2);
-			SamplerState gDepthBufferSamp : register(s3);
-	
-			#if MSAA_COUNT > 1
-			Texture2DMS<float4, MSAA_COUNT> gGBufferATex : register(t0);
-			Texture2DMS<float4, MSAA_COUNT>	gGBufferBTex : register(t1);
-			Texture2DMS<float2, MSAA_COUNT>	gGBufferCTex : register(t2);
-			Texture2DMS<float4, MSAA_COUNT> gDepthBufferTex : register(t3);
-			#else
-			Texture2D gGBufferATex : register(t0);
-			Texture2D gGBufferBTex : register(t1);
-			Texture2D gGBufferCTex : register(t2);
-			Texture2D gDepthBufferTex : register(t3);
-			#endif
-			
-			SurfaceData decodeGBuffer(float4 GBufferAData, float4 GBufferBData, float2 GBufferCData, float deviceZ)
-			{
-				SurfaceData output;
-				
-				output.albedo.xyz = GBufferAData.xyz;
-				output.albedo.w = 1.0f;
-				output.worldNormal = GBufferBData * float4(2, 2, 2, 1) - float4(1, 1, 1, 0);
-				output.worldNormal.xyz = normalize(output.worldNormal.xyz);
-				output.depth = convertFromDeviceZ(deviceZ);
-				output.roughness = GBufferCData.x;
-				output.metalness = GBufferCData.y;
-				
-				return output;
-			}			
-						
+		{			
 			cbuffer Params : register(b0)
 			{
 				// Offsets at which specific light types begin in gLights buffer
@@ -90,52 +40,9 @@ Technique
 				uint idx = getLinearAddress(coord, sampleIndex);
 				gOutput[idx] = color;
 			}
-			
-			bool needsPerSampleShading(SurfaceData samples[MSAA_COUNT])
-			{
-				float3 albedo = samples[0].albedo.xyz;
-				float3 normal = samples[0].worldNormal.xyz;
-				float depth = samples[0].depth;
 
-				[unroll]
-				for(int i = 1; i < MSAA_COUNT; i++)
-				{
-					float3 otherAlbedo = samples[i].albedo.xyz;
-					float3 otherNormal = samples[i].worldNormal.xyz;
-					float otherDepth = samples[i].depth;
-
-					[branch]
-					if(abs(depth - otherDepth) > 0.1f || abs(dot(abs(normal - otherNormal), float3(1, 1, 1))) > 0.1f || abs(dot(albedo - otherAlbedo, float3(1, 1, 1))) > 0.1f)
-					{
-						return true;
-					}
-				}
-				
-				return false;
-			}
-			
-			SurfaceData getGBufferData(uint2 pixelPos, uint sampleIndex)
-			{
-				float4 GBufferAData = gGBufferATex.Load(pixelPos, sampleIndex);
-				float4 GBufferBData = gGBufferBTex.Load(pixelPos, sampleIndex);
-				float2 GBufferCData = gGBufferCTex.Load(pixelPos, sampleIndex).rg;
-				float deviceZ = gDepthBufferTex.Load(pixelPos, sampleIndex).r;
-				
-				return decodeGBuffer(GBufferAData, GBufferBData, GBufferCData, deviceZ);
-			}
-			
 			#else
 			RWTexture2D<float4>	gOutput : register(u0);
-			
-			SurfaceData getGBufferData(uint2 pixelPos)
-			{
-				float4 GBufferAData = gGBufferATex.Load(int3(pixelPos, 0));
-				float4 GBufferBData = gGBufferBTex.Load(int3(pixelPos, 0));
-				float2 GBufferCData = gGBufferCTex.Load(int3(pixelPos, 0)).rg;
-				float deviceZ = gDepthBufferTex.Load(int3(pixelPos, 0)).r;
-				
-				return decodeGBuffer(GBufferAData, GBufferBData, GBufferCData, deviceZ);
-			}			
 			#endif
 						
 			groupshared uint sTileMinZ;
@@ -374,7 +281,7 @@ Technique
 };
 
 Technique 
-  : inherits("GBuffer")
+  : inherits("SurfaceData")
   : inherits("PerCameraData")
   : inherits("LightingCommon") =
 {

+ 5 - 4
Data/Raw/Engine/Shaders/Transparent.bsl

@@ -1,6 +1,9 @@
 #include "$ENGINE$\BasePass.bslinc"
 #include "$ENGINE$\LightingCommon.bslinc"
 #include "$ENGINE$\LightGridCommon.bslinc"
+#include "$ENGINE$\ReflectionCubemapCommon.bslinc"
+#include "$ENGINE$\ImageBasedLighting.bslinc"
+#include "$ENGINE$\Surface.bslinc"
 
 Parameters =
 {
@@ -28,7 +31,7 @@ Technique
  : inherits("LightingCommon")
  : inherits("LightGridCommon")
  : inherits("ReflectionCubemapCommon")
- : inherits("ImageBasedLighting") = 
+ : inherits("ImageBasedLighting")
  : base("Surface") =
 {
 	Language = "HLSL11";
@@ -197,6 +200,4 @@ Technique
 			}	
 		};
 	};
-};
-
-#include "$ENGINE$\Surface.bslinc"
+};

+ 71 - 46
Source/BansheeSL/Source/BsSLFXCompiler.cpp

@@ -1266,58 +1266,13 @@ namespace bs
 				break;
 			case OT_Technique:
 			{
+				// We initially parse only meta-data, so we can handle out-of-order technique definitions
 				TechniqueMetaData metaData = parseTechniqueMetaData(option->value.nodePtr);
 
 				techniqueData.push_back(std::make_pair(option->value.nodePtr, TechniqueData()));
 				TechniqueData& data = techniqueData.back().second;
 				data.metaData = metaData;
 
-				if (data.metaData.baseName.empty())
-				{
-					std::function<bool(TechniqueMetaData&)> parseInherited = [&](TechniqueMetaData& metaData)
-					{
-						for (auto riter = metaData.inherits.rbegin(); riter != metaData.inherits.rend(); ++riter)
-						{
-							const String& inherits = *riter;
-
-							bool foundBase = false;
-							for (auto& entry : techniqueData)
-							{
-								if (entry.second.metaData.baseName == inherits)
-								{
-									bool matches = entry.second.metaData.language == metaData.language || entry.second.metaData.language == "Any";
-									matches &= entry.second.metaData.renderer == metaData.renderer || entry.second.metaData.renderer == RendererAny;
-
-									if (matches)
-									{
-										if (!parseInherited(entry.second.metaData))
-											return false;
-
-										parseTechnique(entry.first, codeBlocks, data);
-										foundBase = true;
-										break;
-									}
-								}
-							}
-
-							if (!foundBase)
-							{
-								output.errorMessage = "Base technique \"" + inherits + "\" cannot be found.";
-								return false;
-							}
-						}
-
-						return true;
-					};
-
-					if (!parseInherited(metaData))
-					{
-						parseStateDelete(parseState);
-						return output;
-					}
-
-					parseTechnique(option->value.nodePtr, codeBlocks, data);
-				}
 				break;
 			}
 			case OT_Parameters:
@@ -1331,6 +1286,76 @@ namespace bs
 			}
 		}
 
+		bool* techniqueWasParsed = bs_stack_alloc<bool>((UINT32)techniqueData.size());
+		std::function<bool(const TechniqueMetaData&, TechniqueData&)> parseInherited = 
+			[&](const TechniqueMetaData& metaData, TechniqueData& outTechnique)
+		{
+			for (auto riter = metaData.inherits.rbegin(); riter != metaData.inherits.rend(); ++riter)
+			{
+				const String& inherits = *riter;
+
+				UINT32 baseIdx = -1;
+				for(UINT32 i = 0; i < (UINT32)techniqueData.size(); i++)
+				{
+					auto& entry = techniqueData[i];
+
+					if (entry.second.metaData.baseName == inherits)
+					{
+						bool matches = entry.second.metaData.language == metaData.language || entry.second.metaData.language == "Any";
+						matches &= entry.second.metaData.renderer == metaData.renderer || entry.second.metaData.renderer == RendererAny;
+
+						// We want the last matching technique, in order to allow techniques to override each other
+						if (matches)
+							baseIdx = i;
+					}
+				}
+
+				if (baseIdx != -1)
+				{
+					auto& entry = techniqueData[baseIdx];
+
+					// Was already parsed previously, don't parse it multiple times (happens when multiple techniques 
+					// include the same base)
+					if (techniqueWasParsed[baseIdx])
+						continue;
+
+					if (!parseInherited(entry.second.metaData, outTechnique))
+						return false;
+
+					parseTechnique(entry.first, codeBlocks, outTechnique);
+					techniqueWasParsed[baseIdx] = true;
+					
+				}
+				else
+				{
+					output.errorMessage = "Base technique \"" + inherits + "\" cannot be found.";
+					return false;
+				}
+			}
+
+			return true;
+		};
+
+
+		// Actually parse techniques
+		for (auto& entry : techniqueData)
+		{
+			const TechniqueMetaData& metaData = entry.second.metaData;
+			if (!metaData.baseName.empty())
+				continue;
+
+			bs_zero_out(techniqueWasParsed, techniqueData.size());
+			if (!parseInherited(metaData, entry.second))
+			{
+				parseStateDelete(parseState);
+				return output;
+			}
+
+			parseTechnique(entry.first, codeBlocks, entry.second);
+		}
+
+		bs_stack_free(techniqueWasParsed);
+
 		Vector<SPtr<Technique>> techniques;
 		for(auto& entry : techniqueData)
 		{