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

Initial support for unified shading language across all render APIs

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

+ 8 - 6
Data/Raw/Engine/Includes/ImageBasedLighting.bslinc

@@ -11,15 +11,17 @@ Technique
 			// Arbitrary limit, increase if needed
 			#define MAX_PROBES 512
 		
+			// Note: Size must be multiple of largest element, because of std430 rules
 			struct ReflProbeData
 			{
 				float3 position;
 				float radius;
 				float3 boxExtents;
-				float4x4 invBoxTransform;
 				float transitionDistance;
+				float4x4 invBoxTransform;
 				uint cubemapIdx;
 				uint type; // 0 - Sphere, 1 - Box
+				float2 padding;
 			};
 		
 			TextureCube gSkyReflectionTex;
@@ -175,10 +177,10 @@ Technique
 							correctedDir = getLookupForBoxProxy(worldPos, dir, probeData.position, probeData.boxExtents, probeData.invBoxTransform, probeData.transitionDistance, contribution);
 						}
 						
-						float4 sample = gReflProbeCubemaps.SampleLevel(gReflProbeSamp, float4(correctedDir, probeData.cubemapIdx), mipLevel);
-						sample *= contribution;
+						float4 probeSample = gReflProbeCubemaps.SampleLevel(gReflProbeSamp, float4(correctedDir, probeData.cubemapIdx), mipLevel);
+						probeSample *= contribution;
 						
-						output += sample.rgb * leftoverContribution; 
+						output += probeSample.rgb * leftoverContribution; 
 						leftoverContribution *= (1.0f - contribution);
 					}
 				}
@@ -186,9 +188,9 @@ Technique
 				if(gSkyCubemapAvailable > 0)
 				{
 					float skyMipLevel = mapRoughnessToMipLevel(roughness, gSkyCubemapNumMips);
-					float4 sample = gSkyReflectionTex.SampleLevel(gSkyReflectionSamp, dir, skyMipLevel) * gSkyBrightness;
+					float4 skySample = gSkyReflectionTex.SampleLevel(gSkyReflectionSamp, dir, skyMipLevel) * gSkyBrightness;
 					
-					output += sample.rgb * leftoverContribution; 
+					output += skySample.rgb * leftoverContribution; 
 				}
 						
 				return output;

+ 5 - 0
Data/Raw/Engine/Includes/LightGridCommon.bslinc

@@ -47,6 +47,11 @@ Technique : base("LightGridCommon") =
 			
 			uint calcCellIdx(uint2 pixelPos, float deviceZ)
 			{
+				// OpenGL uses lower left for window space origin
+				#ifdef OPENGL
+					pixelPos.y = gViewportRectangle.w - pixelPos.y;
+				#endif			
+			
 				// Note: Use bitshift to divide since gGridPixelSize will be a power of 2
 				uint2 cellXY = pixelPos / gGridPixelSize;
 				uint cellZ = calcCellZFromViewZ(convertFromDeviceZ(deviceZ));

+ 3 - 1
Data/Raw/Engine/Includes/LightingCommon.bslinc

@@ -14,17 +14,19 @@ Technique
 			#define PI 3.1415926
 			#define HALF_PI 1.5707963
 			
+			// Note: Size must be multiple of largest element, because of std430 rules
 			struct LightData
 			{
 				float3 position;
 				float attRadius;
-				float srcRadius;
 				float3 direction;
 				float luminance;
 				float3 spotAngles;
 				float attRadiusSqrdInv;
 				float3 color;
+				float srcRadius;
 				float3 shiftedLightPosition;
+				float padding;
 			};
 			
 			float3 calcMicrofacetFresnelShlick(float3 F0, float LoH)

+ 5 - 1
Data/Raw/Engine/Shaders/LightGridLLCreation.bsl

@@ -22,11 +22,15 @@ Technique
 	{
 		Compute = 
 		{
+			[layout(r32ui)]
 			RWBuffer<uint> gLightsCounter;
+			[layout(r32ui)]
 			RWBuffer<uint> gLightsLLHeads;
 			RWBuffer<uint4> gLightsLL;
-				
+			
+			[layout(r32ui)]
 			RWBuffer<uint> gProbesCounter;
+			[layout(r32ui)]
 			RWBuffer<uint> gProbesLLHeads;
 			RWBuffer<uint2> gProbesLL;
 				

+ 1 - 0
Data/Raw/Engine/Shaders/LightGridLLReduction.bsl

@@ -17,6 +17,7 @@ Technique
 			Buffer<uint> gProbesLLHeads;
 			Buffer<uint2> gProbesLL;
 			
+			[layout(r32ui)]
 			RWBuffer<uint> gGridDataCounter;
 			
 			RWBuffer<uint4> gGridLightOffsetAndSize;

+ 3 - 3
Data/Raw/Engine/Shaders/PPDownsample.bsl

@@ -40,12 +40,12 @@ Technique : inherits("PPBase") =
 				UV[2] = input.uv0 + gInvTexSize * float2(-1,  1);
 				UV[3] = input.uv0 + gInvTexSize * float2( 1,  1);
 
-				float4 sample[4];
+				float4 samples[4];
 
 				for(uint i = 0; i < 4; i++)
-					sample[i] = gInputTex.Sample(gInputSamp, UV[i]);
+					samples[i] = gInputTex.Sample(gInputSamp, UV[i]);
 
-				return (sample[0] + sample[1] + sample[2] + sample[3]) * 0.25f;
+				return (samples[0] + samples[1] + samples[2] + samples[3]) * 0.25f;
 			}	
 		};
 	};

+ 4 - 2
Data/Raw/Engine/Shaders/TiledDeferredImageBasedLighting.bsl

@@ -94,9 +94,11 @@ Technique
 			
 			void calcTileAABB(uint2 tileId, float viewZMin, float viewZMax, out float3 center, out float3 extent)
 			{
+				uint2 pixelPos = tileId * TILE_SIZE;
+			
 				// Convert threat XY coordinates to NDC coordinates
-				float2 uvTopLeft = (tileId * TILE_SIZE + 0.5f) / gFramebufferSize;
-				float2 uvBottomRight = ((tileId + uint2(1, 1)) * TILE_SIZE - 0.5f) / gFramebufferSize;
+				float2 uvTopLeft = (pixelPos + 0.5f) / gFramebufferSize;
+				float2 uvBottomRight = (pixelPos + uint2(TILE_SIZE, TILE_SIZE) - 0.5f) / gFramebufferSize;
 			
 				float3 ndcMin;
 				float3 ndcMax;

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

@@ -162,11 +162,18 @@ Technique
 				// This will yield a bias ranging from [-(tileScale - 1), tileScale - 1]. Every second bias is skipped as
 				// corresponds to a point in-between two tiles, overlapping existing frustums.
 				
+				float flipSign = 1.0f;
+				
+				// Adjust for OpenGL's upside down texture system
+				#if OPENGL
+					flipSign = -1;
+				#endif
+				
 				float At = gMatProj[0][0] * tileScale.x;
 				float Ctt = gMatProj[0][2] * tileScale.x - tileBias.x;
 				
-				float Bt = gMatProj[1][1] * tileScale.y;
-				float Dtt = gMatProj[1][2] * tileScale.y + tileBias.y;
+				float Bt = gMatProj[1][1] * tileScale.y * flipSign;
+				float Dtt = (gMatProj[1][2] * tileScale.y + flipSign * tileBias.y) * flipSign;
 				
 				// Extract left/right/top/bottom frustum planes from scaled projection matrix
 				// Note: Do this on the CPU? Since they're shared among all entries in a tile. Plus they don't change across frames.
@@ -242,8 +249,8 @@ Technique
 				float2 screenUv = ((float2)(gViewportRectangle.xy + pixelPos) + 0.5f) / (float2)gViewportRectangle.zw;
 				float2 clipSpacePos = (screenUv - gClipToUVScaleOffset.zw) / gClipToUVScaleOffset.xy;
 			
-				uint2 viewportMax = gViewportRectangle.xy + gViewportRectangle.zw;
-
+				uint2 viewportMax = gViewportRectangle.xy + gViewportRectangle.zw;			
+				
 				// Ignore pixels out of valid range
 				if (all(dispatchThreadId.xy < viewportMax))
 				{

+ 7 - 1
Source/BansheeD3D11RenderAPI/Source/BsD3D11GpuProgram.cpp

@@ -124,11 +124,17 @@ namespace bs { namespace ct
 		const String& source = mProperties.getSource();
 		const String& entryPoint = mProperties.getEntryPoint();
 
+		const D3D_SHADER_MACRO defines[] = 
+		{ 
+			{ "HLSL", "1" },
+			{ nullptr, nullptr }
+		};
+
 		HRESULT hr = D3DCompile(
 			source.c_str(),		// [in] Pointer to the shader in memory. 
 			source.size(),		// [in] Size of the shader in memory.  
 			nullptr,			// [in] The name of the file that contains the shader code. 
-			nullptr,			// [in] Optional. Pointer to a NULL-terminated array of macro definitions. See D3D_SHADER_MACRO. If not used, set this to NULL. 
+			defines,			// [in] Optional. Pointer to a NULL-terminated array of macro definitions. See D3D_SHADER_MACRO. If not used, set this to NULL. 
 			nullptr,			// [in] Optional. Pointer to an ID3DInclude Interface interface for handling include files. Setting this to NULL will cause a compile error if a shader contains a #include. 
 			entryPoint.c_str(),	// [in] Name of the shader-entrypoint function where shader execution begins. 
 			profile.c_str(),// [in] A string that specifies the shader model; can be any profile in shader model 4 or higher. 

+ 1 - 0
Source/BansheeGLRenderAPI/Source/BsGLRenderAPI.cpp

@@ -427,6 +427,7 @@ namespace bs { namespace ct
 					textureUnits.clear();
 					imageUnits.clear();
 					uniformUnits.clear();
+					sharedStorageUnits.clear();
 
 					GpuProgramType type = (GpuProgramType)i;
 

+ 9 - 1
Source/BansheeGLRenderAPI/Source/BsGLSLParamParser.cpp

@@ -103,7 +103,15 @@ namespace bs { namespace ct
 			GLSLAttribute("bs_texcoord", VES_TEXCOORD),
 			GLSLAttribute("bs_color", VES_COLOR),
 			GLSLAttribute("bs_blendweights", VES_BLEND_WEIGHTS),
-			GLSLAttribute("bs_blendindices", VES_BLEND_INDICES)
+			GLSLAttribute("bs_blendindices", VES_BLEND_INDICES),
+			GLSLAttribute("POSITION", VES_POSITION),
+			GLSLAttribute("NORMAL", VES_NORMAL),
+			GLSLAttribute("TANGENT", VES_TANGENT),
+			GLSLAttribute("BITANGENT", VES_BITANGENT),
+			GLSLAttribute("TEXCOORD", VES_TEXCOORD),
+			GLSLAttribute("COLOR", VES_COLOR),
+			GLSLAttribute("BLENDWEIGHT", VES_BLEND_WEIGHTS),
+			GLSLAttribute("BLENDINDICES", VES_BLEND_INDICES)
 		};
 
 		static const UINT32 numAttribs = sizeof(attributes) / sizeof(attributes[0]);

+ 58 - 22
Source/BansheeGLRenderAPI/Source/GLSL/src/BsGLSLGpuProgram.cpp

@@ -86,7 +86,7 @@ namespace bs { namespace ct
 
 	void GLSLGpuProgram::initialize()
 	{
-		static const char* EXTRA_LINES[] = { "#version 440\n", "#define OPENGL\n" };
+		static const char* VERSION_LINE = "#version 450\n";
 		
 		if (!isSupported())
 		{
@@ -132,35 +132,41 @@ namespace bs { namespace ct
 		{
 			Vector<GLchar*> lines;
 
-			UINT32 numExtraLines = sizeof(EXTRA_LINES) / sizeof(EXTRA_LINES[0]);
-			for(UINT32 i = 0; i < numExtraLines; i++)
-			{
-				UINT32 length = (UINT32)strlen(EXTRA_LINES[i]) + 1;
-
-				GLchar* extraLineData = (GLchar*)bs_stack_alloc(length);
-				memcpy(extraLineData, EXTRA_LINES[i], length);
-
-				lines.push_back(extraLineData);
-			}
+			const char* versionStr = "#version ";
+			UINT32 versionStrLen = (UINT32)strlen(versionStr);
 
 			UINT32 lineLength = 0;
+			INT32 versionLine = -1;
 			for (UINT32 i = 0; i < source.size(); i++)
 			{
 				if (source[i] == '\n' || source[i] == '\r')
 				{
-					if (lineLength > 0)
-					{
-						assert(sizeof(source[i]) == sizeof(GLchar));
+					assert(sizeof(source[i]) == sizeof(GLchar));
 
-						GLchar* lineData = (GLchar*)bs_stack_alloc(sizeof(GLchar) * (lineLength + 2));
-						memcpy(lineData, &source[i - lineLength], sizeof(GLchar) * lineLength);
+					GLchar* lineData = (GLchar*)bs_stack_alloc(sizeof(GLchar) * (lineLength + 2));
+					memcpy(lineData, &source[i - lineLength], sizeof(GLchar) * lineLength);
 
-						lineData[lineLength] = '\n';
-						lineData[lineLength + 1] = '\0';
+					lineData[lineLength] = '\n';
+					lineData[lineLength + 1] = '\0';
 
-						lines.push_back(lineData);
-						lineLength = 0;
+					if(versionLine == -1 && lineLength >= versionStrLen)
+					{
+						bool isEqual = true;
+						for (UINT32 j = 0; j < versionStrLen; ++j)
+						{
+							if(lineData[j] != versionStr[j])
+							{
+								isEqual = false;
+								break;
+							}
+						}
+
+						if (isEqual)
+							versionLine = (INT32)lines.size();
 					}
+
+					lines.push_back(lineData);
+					lineLength = 0;
 				}
 				else
 				{
@@ -181,12 +187,42 @@ namespace bs { namespace ct
 				lineLength = 0;
 			}
 
+			int numInsertedLines = 0;
+			if(versionLine == -1)
+			{
+				UINT32 length = (UINT32)strlen(VERSION_LINE) + 1;
+
+				GLchar* extraLineData = (GLchar*)bs_stack_alloc(length);
+				memcpy(extraLineData, VERSION_LINE, length);
+
+				lines.insert(lines.begin(), extraLineData);
+				numInsertedLines++;
+			}
+
+			static const char* EXTRA_LINES[] = { "#define OPENGL\n" };
+			UINT32 numExtraLines = sizeof(EXTRA_LINES) / sizeof(EXTRA_LINES[0]);
+			UINT32 extraLineOffset = versionLine != -1 ? versionLine + 1 : 0;
+			for (UINT32 i = 0; i < numExtraLines; i++)
+			{
+				UINT32 length = (UINT32)strlen(EXTRA_LINES[i]) + 1;
+
+				GLchar* extraLineData = (GLchar*)bs_stack_alloc(length);
+				memcpy(extraLineData, EXTRA_LINES[i], length);
+
+				lines.insert(lines.begin() + extraLineOffset + numInsertedLines, extraLineData);
+				numInsertedLines++;
+			}
+
 			mGLHandle = glCreateShaderProgramv(shaderType, (GLsizei)lines.size(), (const GLchar**)lines.data());
 
+			for (INT32 i = numInsertedLines - 1; i >= 0; i--)
+				bs_stack_free(lines[extraLineOffset + i]);
+
+			if (numInsertedLines > 0)
+				lines.erase(lines.begin() + extraLineOffset, lines.begin() + extraLineOffset + numInsertedLines);
+
 			for (auto iter = lines.rbegin(); iter != lines.rend(); ++iter)
-			{
 				bs_stack_free(*iter);
-			}
 
 			mCompileError = "";
 			mIsCompiled = !checkForGLSLError(mGLHandle, mCompileError);

+ 2 - 2
Source/BansheeSL/CMakeLists.txt

@@ -25,9 +25,9 @@ else()
 endif()
 
 set(DEPENDENCY_BUILD_DIR "${CMAKE_SOURCE_DIR}/../Dependencies/Build/${DEPENDENCY_NAME}")
-set(DEPENDENCY_PARAMS -DXSC_BUILD_SHELL=OFF)
+set(DEPENDENCY_PARAMS -DXSC_BUILD_SHELL=OFF -DXSC_ENABLE_LANGUAGE_EXT=ON)
 
-find_package_or_build(XShaderCompiler inc/Xsc/Xsc.h ${DEPENDENCY_PARAMS})
+find_package_or_build(XShaderCompiler inc/Xsc/Xsc.h "${DEPENDENCY_PARAMS}")
 
 # Source files and their filters
 include(CMakeSources.cmake)

+ 210 - 48
Source/BansheeSL/Source/BsSLFXCompiler.cpp

@@ -14,6 +14,7 @@
 #include "BsMatrix4.h"
 #include "BsBuiltinResources.h"
 
+#define XSC_ENABLE_LANGUAGE_EXT 1
 #include "Xsc/Xsc.h"
 
 //DEBUG ONLY
@@ -74,16 +75,147 @@ namespace bs
 		}
 	}
 
+	class XscLog : public Xsc::Log
+	{
+	public:
+		void SumitReport(const Xsc::Report& report) override
+		{
+			switch (report.Type())
+			{
+			case Xsc::Report::Types::Info:
+				mInfos.push_back({ FullIndent(), report });
+				break;
+			case Xsc::Report::Types::Warning:
+				mWarnings.push_back({ FullIndent(), report });
+				break;
+			case Xsc::Report::Types::Error:
+				mErrors.push_back({ FullIndent(), report });
+				break;
+			}
+		}
+
+		void getMessages(StringStream& output)
+		{
+			printAndClearReports(output, mInfos);
+			printAndClearReports(output, mWarnings, (mWarnings.size() == 1 ? "WARNING" : "WARNINGS"));
+			printAndClearReports(output, mErrors, (mErrors.size() == 1 ? "ERROR" : "ERRORS"));
+		}
+
+	private:
+		struct IndentReport
+		{
+			std::string indent;
+			Xsc::Report      report;
+		};
+
+		static void printMultiLineString(StringStream& output, const std::string& str, const std::string& indent)
+		{
+			// Determine at which position the actual text begins (excluding the "error (X:Y) : " or the like) 
+			auto textStartPos = str.find(" : ");
+			if (textStartPos != std::string::npos)
+				textStartPos += 3;
+			else
+				textStartPos = 0;
+
+			std::string newLineIndent(textStartPos, ' ');
+
+			size_t start = 0;
+			bool useNewLineIndent = false;
+			while (start < str.size())
+			{
+				output << indent;
+
+				if (useNewLineIndent)
+					output << newLineIndent;
+
+				// Print next line
+				auto end = str.find('\n', start);
+
+				if (end != std::string::npos)
+				{
+					output << str.substr(start, end - start);
+					start = end + 1;
+				}
+				else
+				{
+					output << str.substr(start);
+					start = end;
+				}
+
+				output << std::endl;
+				useNewLineIndent = true;
+			}
+		}
+
+		void printReport(StringStream& output, const IndentReport& r)
+		{
+			// Print optional context description
+			if (!r.report.Context().empty())
+				printMultiLineString(output, r.report.Context(), r.indent);
+
+			// Print report message
+			const auto& msg = r.report.Message();
+			printMultiLineString(output, msg, r.indent);
+
+			// Print optional line and line-marker
+			if (r.report.HasLine())
+			{
+				const auto& line = r.report.Line();
+				const auto& marker = r.report.Marker();
+
+				// Print line
+				output << r.indent << line << std::endl;
+
+				// Print line marker
+				output << r.indent << marker << std::endl;
+			}
+
+			// Print optional hints
+			for (const auto& hint : r.report.GetHints())
+				output << r.indent << hint << std::endl;
+		}
+
+		void printAndClearReports(StringStream& output, Vector<IndentReport>& reports, const String& headline = "")
+		{
+			if (!reports.empty())
+			{
+				if (!headline.empty())
+				{
+					String s = toString(reports.size()) + " " + headline;
+					output << s << std::endl;
+					output << String(s.size(), '-') << std::endl;
+				}
+
+				for (const auto& r : reports)
+					printReport(output, r);
+
+				reports.clear();
+			}
+		}
+
+		Vector<IndentReport> mInfos;
+		Vector<IndentReport> mWarnings;
+		Vector<IndentReport> mErrors;
+
+	};
+
 	// Convert HLSL code to GLSL
-	String HLSLtoGLSL(const String& hlsl, GpuProgramType type, UINT32& startBindingSlot)
+	String HLSLtoGLSL(const String& hlsl, GpuProgramType type, bool vulkan, UINT32& startBindingSlot)
 	{
 		SPtr<StringStream> input = bs_shared_ptr_new<StringStream>();
+
+		if (vulkan)
+			*input << "#define VULKAN 1" << std::endl;
+		else
+			*input << "#define OPENGL 1" << std::endl;
+
 		*input << hlsl;
 
 		Xsc::ShaderInput inputDesc;
 		inputDesc.entryPoint = "main";
 		inputDesc.shaderVersion = Xsc::InputShaderVersion::HLSL5;
 		inputDesc.sourceCode = input;
+		inputDesc.extensions = Xsc::Extensions::LayoutAttribute;
 
 		switch (type)
 		{
@@ -102,23 +234,36 @@ namespace bs
 		case GPT_FRAGMENT_PROGRAM:
 			inputDesc.shaderTarget = Xsc::ShaderTarget::FragmentShader;
 			break;
+		case GPT_COMPUTE_PROGRAM:
+			inputDesc.shaderTarget = Xsc::ShaderTarget::ComputeShader;
+			break;
 		}
 
 		StringStream output;
 
 		Xsc::ShaderOutput outputDesc;
-		outputDesc.shaderVersion = Xsc::OutputShaderVersion::VKSL450;
 		outputDesc.sourceCode = &output;
-		outputDesc.options.autoBinding = true;
+		outputDesc.options.autoBinding = vulkan;
 		outputDesc.options.autoBindingStartSlot = startBindingSlot;
+		outputDesc.options.separateShaders = true;
+		outputDesc.options.separateSamplers = false;
 		outputDesc.nameMangling.inputPrefix = "bs_";
 		outputDesc.nameMangling.useAlwaysSemantics = true;
+		outputDesc.nameMangling.renameBufferFields = true;
+
+		if (vulkan)
+			outputDesc.shaderVersion = Xsc::OutputShaderVersion::VKSL450;
+		else
+			outputDesc.shaderVersion = Xsc::OutputShaderVersion::GLSL450;
 
-		Xsc::StdLog log;
+		XscLog log;
 		Xsc::Reflection::ReflectionData reflectionData;
 		if (!Xsc::CompileShader(inputDesc, outputDesc, &log, &reflectionData))
 		{
-			LOGERR("Shader cross compilation failed.");
+			StringStream logOutput;
+			log.getMessages(logOutput);
+
+			LOGERR("Shader cross compilation failed. Log: \n\n" + logOutput.str());
 			return "";
 		}
 
@@ -136,6 +281,17 @@ namespace bs
 		return output.str();
 	}
 
+	/* Remove non-standard HLSL attributes. */
+	void cleanNonStandardHLSL(GPU_PROGRAM_DESC& progDesc)
+	{
+		static std::regex regex("\\[.*layout.*\\(.*\\).*\\]");
+
+		if (progDesc.language != "hlsl")
+			return;
+
+		progDesc.source = regex_replace(progDesc.source, regex, "");
+	}
+
 	BSLFXCompileResult BSLFXCompiler::compile(const String& name, const String& source, 
 		const UnorderedMap<String, String>& defines)
 	{
@@ -1429,7 +1585,7 @@ namespace bs
 		bs_stack_free(techniqueWasParsed);
 
 		// If no GLSL technique, auto-generate them for each non-base technique
-		if(false /*!hasGLSLTechnique*/) // TODO : Disabled for now
+		if(!hasGLSLTechnique)
 		{
 			UINT32 end = (UINT32)techniqueData.size();
 			for(UINT32 i = 0; i < end; i++)
@@ -1438,60 +1594,60 @@ namespace bs
 				if (!metaData.baseName.empty())
 					continue;
 
-				TechniqueData copy = techniqueData[i].second;
-				copy.metaData.language = "glsl";
-				for(auto& passData : copy.passes)
+				auto createTechniqueForLanguage = [](const String& name, const TechniqueData& orig, bool vulkan)
 				{
-					UINT32 nextFreeBindingSlot = 0;
-					if (!passData.vertexCode.empty())
+					TechniqueData copy = orig;
+					copy.metaData.language = vulkan ? "vksl" : "glsl";
+					for (auto& passData : copy.passes)
 					{
-						String hlslCode = passData.commonCode + passData.vertexCode;
-						passData.vertexCode = HLSLtoGLSL(hlslCode, GPT_VERTEX_PROGRAM, nextFreeBindingSlot);
+						UINT32 nextFreeBindingSlot = 0;
+						if (!passData.vertexCode.empty())
+						{
+							String hlslCode = passData.commonCode + passData.vertexCode;
+							passData.vertexCode = HLSLtoGLSL(hlslCode, GPT_VERTEX_PROGRAM, vulkan, nextFreeBindingSlot);
+						}
 
-						auto ds = FileSystem::createAndOpenFile("E:\\GenShaders\\" + name + "_VS.glsl");
-						ds->writeString(passData.vertexCode);
-					}
+						if (!passData.fragmentCode.empty())
+						{
+							String hlslCode = passData.commonCode + passData.fragmentCode;
+							passData.fragmentCode = HLSLtoGLSL(hlslCode, GPT_FRAGMENT_PROGRAM, vulkan, nextFreeBindingSlot);
+						}
 
-					if (!passData.fragmentCode.empty())
-					{
-						String hlslCode = passData.commonCode + passData.fragmentCode;
-						passData.fragmentCode = HLSLtoGLSL(hlslCode, GPT_FRAGMENT_PROGRAM, nextFreeBindingSlot);
+						if (!passData.geometryCode.empty())
+						{
+							String hlslCode = passData.commonCode + passData.geometryCode;
+							passData.geometryCode = HLSLtoGLSL(hlslCode, GPT_GEOMETRY_PROGRAM, vulkan, nextFreeBindingSlot);
+						}
 
-						auto ds = FileSystem::createAndOpenFile("E:\\GenShaders\\" + name + "_FS.glsl");
-						ds->writeString(passData.fragmentCode);
-					}
+						if (!passData.hullCode.empty())
+						{
+							String hlslCode = passData.commonCode + passData.hullCode;
+							passData.hullCode = HLSLtoGLSL(hlslCode, GPT_HULL_PROGRAM, vulkan, nextFreeBindingSlot);
+						}
 
-					if (!passData.geometryCode.empty())
-					{
-						String hlslCode = passData.commonCode + passData.geometryCode;
-						passData.geometryCode = HLSLtoGLSL(hlslCode, GPT_GEOMETRY_PROGRAM, nextFreeBindingSlot);
-					}
+						if (!passData.domainCode.empty())
+						{
+							String hlslCode = passData.commonCode + passData.domainCode;
+							passData.domainCode = HLSLtoGLSL(hlslCode, GPT_DOMAIN_PROGRAM, vulkan, nextFreeBindingSlot);
+						}
 
-					if (!passData.hullCode.empty())
-					{
-						String hlslCode = passData.commonCode + passData.hullCode;
-						passData.hullCode = HLSLtoGLSL(hlslCode, GPT_HULL_PROGRAM, nextFreeBindingSlot);
-					}
+						if (!passData.computeCode.empty())
+						{
+							String hlslCode = passData.commonCode + passData.computeCode;
+							passData.computeCode = HLSLtoGLSL(hlslCode, GPT_COMPUTE_PROGRAM, vulkan, nextFreeBindingSlot);
+						}
 
-					if (!passData.domainCode.empty())
-					{
-						String hlslCode = passData.commonCode + passData.domainCode;
-						passData.domainCode = HLSLtoGLSL(hlslCode, GPT_DOMAIN_PROGRAM, nextFreeBindingSlot);
+						passData.commonCode = "";
 					}
 
-					if (!passData.computeCode.empty())
-					{
-						String hlslCode = passData.commonCode + passData.computeCode;
-						passData.computeCode = HLSLtoGLSL(hlslCode, GPT_COMPUTE_PROGRAM, nextFreeBindingSlot);
+					return copy;
+				};
 
-						auto ds = FileSystem::createAndOpenFile("E:\\GenShaders\\" + name + "_CS.glsl");
-						ds->writeString(passData.computeCode);
-					}
-
-					passData.commonCode = "";
-				}
+				TechniqueData glslTechnique = createTechniqueForLanguage(name, techniqueData[i].second, false);
+				techniqueData.push_back(std::make_pair(techniqueData[i].first, glslTechnique));
 
-				techniqueData.push_back(std::make_pair(techniqueData[i].first, copy));
+				TechniqueData vkslTechnique = createTechniqueForLanguage(name, techniqueData[i].second, true);
+				techniqueData.push_back(std::make_pair(techniqueData[i].first, vkslTechnique));
 			}
 		}
 
@@ -1525,6 +1681,7 @@ namespace bs
 					desc.source = passData.commonCode + passData.vertexCode;
 					desc.type = GPT_VERTEX_PROGRAM;
 
+					cleanNonStandardHLSL(desc);
 					passDesc.vertexProgram = GpuProgram::create(desc);
 				}
 
@@ -1533,6 +1690,7 @@ namespace bs
 					desc.source = passData.commonCode + passData.fragmentCode;
 					desc.type = GPT_FRAGMENT_PROGRAM;
 
+					cleanNonStandardHLSL(desc);
 					passDesc.fragmentProgram = GpuProgram::create(desc);
 				}
 
@@ -1541,6 +1699,7 @@ namespace bs
 					desc.source = passData.commonCode + passData.geometryCode;
 					desc.type = GPT_GEOMETRY_PROGRAM;
 
+					cleanNonStandardHLSL(desc);
 					passDesc.geometryProgram = GpuProgram::create(desc);
 				}
 
@@ -1549,6 +1708,7 @@ namespace bs
 					desc.source = passData.commonCode + passData.hullCode;
 					desc.type = GPT_HULL_PROGRAM;
 
+					cleanNonStandardHLSL(desc);
 					passDesc.hullProgram = GpuProgram::create(desc);
 				}
 
@@ -1557,6 +1717,7 @@ namespace bs
 					desc.source = passData.commonCode + passData.domainCode;
 					desc.type = GPT_DOMAIN_PROGRAM;
 
+					cleanNonStandardHLSL(desc);
 					passDesc.domainProgram = GpuProgram::create(desc);
 				}
 
@@ -1565,6 +1726,7 @@ namespace bs
 					desc.source = passData.commonCode + passData.computeCode;
 					desc.type = GPT_COMPUTE_PROGRAM;
 
+					cleanNonStandardHLSL(desc);
 					passDesc.computeProgram = GpuProgram::create(desc);
 				}
 

+ 3 - 3
Source/CMake/FindPackageOrBuild.cmake

@@ -46,11 +46,11 @@ function(find_package_or_build DEPENDENCY_NAME DEPENDENCY_INCLUDE_PATH BUILD_OPT
 		endif()
 
 		# Build
-		build_dependency(${DEPENDENCY_NAME} Release ${BUILD_OPTIONS})
-		build_dependency(${DEPENDENCY_NAME} Debug ${BUILD_OPTIONS})
+		build_dependency(${DEPENDENCY_NAME} Release "${BUILD_OPTIONS}")
+		build_dependency(${DEPENDENCY_NAME} Debug "${BUILD_OPTIONS}")
 		
 		# Update the dependencies version
-		file(WRITE ${DEPENDENCIES_BUILD_DIR}/.version ${BS_DEPENDENCIES_VERSION})
+		file(WRITE ${DEPENDENCIES_BUILD_DIR}/.version ${BS_SRC_DEPENDENCIES_VERSION})
 		
 		# Now try finding the package again, this time it's required
 		find_package(${DEPENDENCY_NAME} REQUIRED)

+ 6 - 5
Source/CMakeLists.txt

@@ -5,7 +5,8 @@ project (Banshee)
 set (BS_VERSION_MAJOR 0)
 set (BS_VERSION_MINOR 4)
 
-set (BS_DEPENDENCIES_VERSION 1)
+set (BS_PREBUILT_DEPENDENCIES_VERSION 1)
+set (BS_SRC_DEPENDENCIES_VERSION 4)
 
 # Configuration types
 if(CMAKE_CONFIGURATION_TYPES) # Multiconfig generator?
@@ -67,7 +68,7 @@ if(NOT EXISTS ${BUILTIN_DEP_VERSION_FILE})
 	message(FATAL_ERROR "Precompiled dependencies package is missing our out of date. Re-run setup or manually re-download and extract dependencies.")
 else()
 	file (STRINGS ${BUILTIN_DEP_VERSION_FILE} CURRENT_BUILTIN_DEP_VERSION)
-	if(${BS_DEPENDENCIES_VERSION} GREATER ${CURRENT_BUILTIN_DEP_VERSION})
+	if(${BS_PREBUILT_DEPENDENCIES_VERSION} GREATER ${CURRENT_BUILTIN_DEP_VERSION})
 		message(FATAL_ERROR "Your precomiled dependencies package is out of date. Re-run setup or manually re-download and extract dependencies.")
 	endif()
 endif()
@@ -77,7 +78,7 @@ set(SOURCE_DEP_BUILD_DIR ${PROJECT_SOURCE_DIR}/../Dependencies/Build)
 set(SOURCE_DEP_BUILD_VERSION_FILE ${SOURCE_DEP_BUILD_DIR}/.version)
 if(EXISTS ${SOURCE_DEP_BUILD_VERSION_FILE})
 	file (STRINGS ${SOURCE_DEP_BUILD_VERSION_FILE} CURRENT_SOURCE_DEP_VERSION)
-	if(${BS_DEPENDENCIES_VERSION} GREATER ${CURRENT_SOURCE_DEP_VERSION})
+	if(${BS_SRC_DEPENDENCIES_VERSION} GREATER ${CURRENT_SOURCE_DEP_VERSION})
 		message(STATUS "Built dependencies are out of date, forcing recompile.")
 		execute_process(COMMAND "${CMAKE_COMMAND}" 
 			-E remove_directory "${SOURCE_DEP_BUILD_DIR}")	
@@ -122,7 +123,7 @@ if(MSVC)
 	set(CMAKE_EXE_LINKER_FLAGS_RELEASE ${BS_LINKER_FLAGS_RELEASE})
 	
 	# Compiler
-	set(BS_COMPILER_FLAGS_COMMON "/GS- /W3 /GR- /WX- /nologo /bigobj /wd\"4577\"")
+	set(BS_COMPILER_FLAGS_COMMON "/GS- /W3 /GR- /WX- /nologo /bigobj /wd\"4577\" /wd\"4530\"")
 	set(CMAKE_CXX_FLAGS "/DWIN32 /D_WINDOWS")
 	
 	set(CMAKE_CXX_FLAGS_DEBUG "${BS_COMPILER_FLAGS_COMMON} /Gm /Od /RTC1 /MDd")
@@ -137,7 +138,7 @@ if(MSVC)
 	set(CMAKE_CXX_FLAGS_RELEASE "${BS_COMPILER_FLAGS_COMMON} /GL /Gy /O2 /Oi /MD")
 	
 	# Global defines
-	add_definitions(-D_HAS_EXCEPTIONS=0)
+	#add_definitions(-D_HAS_EXCEPTIONS=0)
 	
 elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
 	# Note: Optionally add -ffunction-sections, -fdata-sections, but with linker option --gc-sections

+ 1 - 1
Source/External/XShaderCompiler

@@ -1 +1 @@
-Subproject commit ea36e2685f55ef7fa54822fc751b1dd1c47d4a84
+Subproject commit 6d9d6a9d36170cf6a5f0660a1b32be4b709b81c9

+ 2 - 1
Source/RenderBeast/Include/BsImageBasedLighting.h

@@ -18,10 +18,11 @@ namespace bs { namespace ct
 		Vector3 position;
 		float radius;
 		Vector3 boxExtents;
-		Matrix4 invBoxTransform;
 		float transitionDistance;
+		Matrix4 invBoxTransform;
 		UINT32 cubemapIdx;
 		UINT32 type;
+		Vector2 padding;
 	};
 
 	/** Contains GPU buffers used by the renderer to manipulate reflection probes. */

+ 2 - 1
Source/RenderBeast/Include/BsLightRendering.h

@@ -17,13 +17,14 @@ namespace bs { namespace ct
 	{
 		Vector3 position;
 		float attRadius;
-		float srcRadius;
 		Vector3 direction;
 		float luminance;
 		Vector3 spotAngles;
 		float attRadiusSqrdInv;
 		Vector3 color;
+        float srcRadius;
 		Vector3 shiftedLightPosition;
+		float padding;
 	};
 
 	/**	Renderer information specific to a single light. */