소스 검색

Call DXC using the C++ API and not the executable

Panagiotis Christopoulos Charitos 1 년 전
부모
커밋
130ebadd82

+ 6 - 0
AnKi/Gr/D3D/D3DCommandBuffer.cpp

@@ -580,6 +580,12 @@ void CommandBuffer::traceRays([[maybe_unused]] const BufferView& sbtBuffer, [[ma
 	ANKI_ASSERT(!"TODO");
 }
 
+void CommandBuffer::traceRaysIndirect(const BufferView& sbtBuffer, U32 sbtRecordSize, U32 hitGroupSbtRecordCount, U32 rayTypeCount,
+									  BufferView argsBuffer)
+{
+	ANKI_ASSERT(!"TODO");
+}
+
 void CommandBuffer::blitTexture([[maybe_unused]] const TextureView& srcView, [[maybe_unused]] const TextureView& destView)
 {
 	ANKI_ASSERT(!"TODO");

+ 2 - 0
AnKi/ShaderCompiler.h

@@ -6,6 +6,8 @@
 #pragma once
 
 #include <AnKi/ShaderCompiler/ShaderCompiler.h>
+#include <AnKi/ShaderCompiler/Spirv.h>
+#include <AnKi/ShaderCompiler/Dxc.h>
 #include <AnKi/ShaderCompiler/MaliOfflineCompiler.h>
 
 /// @defgroup shader_compiler Shader compiler and shader tools

+ 429 - 127
AnKi/ShaderCompiler/Dxc.cpp

@@ -10,37 +10,109 @@
 #include <AnKi/Util/HighRezTimer.h>
 #include <AnKi/Util/StringList.h>
 
+#include <string>
+#if ANKI_OS_WINDOWS
+#	include <windows.h>
+#	include <wrl/client.h>
+#	include <ThirdParty/Dxc/d3d12shader.h>
+#	define CComPtr Microsoft::WRL::ComPtr
+#else
+#	pragma GCC diagnostic push
+#	pragma GCC diagnostic ignored "-Wimplicit-int-conversion"
+#	pragma GCC diagnostic ignored "-Wambiguous-reversed-operator"
+#	define __EMULATE_UUID
+#	include <ThirdParty/Dxc/WinAdapter.h>
+#	pragma GCC diagnostic pop
+#endif
+#include <ThirdParty/Dxc/dxcapi.h>
+
 namespace anki {
 
 static Atomic<U32> g_nextFileId = {1};
 
-static CString profile(ShaderType shaderType)
+static HMODULE g_dxilLib = 0;
+static HMODULE g_dxcLib = 0;
+static DxcCreateInstanceProc g_DxcCreateInstance = nullptr;
+static Mutex g_dxcLibMtx;
+
+#define ANKI_DXC_CHECK(x) \
+	do \
+	{ \
+		HRESULT rez; \
+		if((rez = (x)) < 0) [[unlikely]] \
+		{ \
+			errorMessage.sprintf("DXC function failed (HRESULT: %d): %s", rez, #x); \
+			return Error::kFunctionFailed; \
+		} \
+	} while(0)
+
+static Error lazyDxcInit(ShaderCompilerString& errorMessage)
+{
+	LockGuard lock(g_dxcLibMtx);
+
+	if(g_dxcLib == 0)
+	{
+		// Init DXC
+#if ANKI_OS_WINDOWS
+		g_dxilLib = LoadLibraryA(ANKI_SOURCE_DIRECTORY "/ThirdParty/Dxc/dxil.dll");
+		if(g_dxilLib == 0)
+		{
+			errorMessage = "dxil.dll missing or wrong architecture";
+			return Error::kFunctionFailed;
+		}
+
+		g_dxcLib = LoadLibraryA(ANKI_SOURCE_DIRECTORY "/ThirdParty/Dxc/dxcompiler.dll");
+#else
+		g_dxcLib = dlopen(ANKI_SOURCE_DIRECTORY "/ThirdParty/Dxc/libdxcompiler.so", RTLD_LAZY);
+#endif
+		if(g_dxcLib == 0)
+		{
+			errorMessage = "dxcompiler.dll/libdxcompiler.so missing or wrong architecture";
+			return Error::kFunctionFailed;
+		}
+
+#if ANKI_OS_WINDOWS
+		g_DxcCreateInstance = reinterpret_cast<DxcCreateInstanceProc>(GetProcAddress(g_dxcLib, "DxcCreateInstance"));
+#else
+		g_DxcCreateInstance = reinterpret_cast<DxcCreateInstanceProc>(dlsym(g_dxcLib, "DxcCreateInstance"));
+#endif
+		if(g_DxcCreateInstance == nullptr)
+		{
+			errorMessage = "DxcCreateInstance was not found in the dxcompiler.dll/libdxcompiler.so";
+			return Error::kFunctionFailed;
+		}
+	}
+
+	return Error::kNone;
+}
+
+static const WChar* profile(ShaderType shaderType)
 {
 	switch(shaderType)
 	{
 	case ShaderType::kVertex:
-		return "vs_6_8";
+		return L"vs_6_8";
 		break;
 	case ShaderType::kPixel:
-		return "ps_6_8";
+		return L"ps_6_8";
 		break;
 	case ShaderType::kDomain:
-		return "ds_6_8";
+		return L"ds_6_8";
 		break;
 	case ShaderType::kHull:
-		return "ds_6_8";
+		return L"ds_6_8";
 		break;
 	case ShaderType::kGeometry:
-		return "gs_6_8";
+		return L"gs_6_8";
 		break;
 	case ShaderType::kAmplification:
-		return "as_6_8";
+		return L"as_6_8";
 		break;
 	case ShaderType::kMesh:
-		return "ms_6_8";
+		return L"ms_6_8";
 		break;
 	case ShaderType::kCompute:
-		return "cs_6_8";
+		return L"cs_6_8";
 		break;
 	case ShaderType::kRayGen:
 	case ShaderType::kAnyHit:
@@ -49,194 +121,424 @@ static CString profile(ShaderType shaderType)
 	case ShaderType::kIntersection:
 	case ShaderType::kCallable:
 	case ShaderType::kWorkGraph:
-		return "lib_6_8";
+		return L"lib_6_8";
 		break;
 	default:
 		ANKI_ASSERT(0);
 	};
 
-	return "";
+	return L"";
 }
 
 static Error compileHlsl(CString src, ShaderType shaderType, Bool compileWith16bitTypes, Bool debugInfo, ConstWeakArray<CString> compilerArgs,
 						 Bool spirv, ShaderCompilerDynamicArray<U8>& bin, ShaderCompilerString& errorMessage)
 {
-	Array<U64, 3> toHash = {g_nextFileId.fetchAdd(1), getCurrentProcessId(), getRandom() & kMaxU32};
-	const U64 rand = computeHash(&toHash[0], sizeof(toHash));
-
-	String tmpDir;
-	ANKI_CHECK(getTempDirectory(tmpDir));
-
-	// Store HLSL to a file
-	ShaderCompilerString hlslFilename;
-	hlslFilename.sprintf("%s/%" PRIu64 ".hlsl", tmpDir.cstr(), rand);
-
-	File hlslFile;
-	ANKI_CHECK(hlslFile.open(hlslFilename, FileOpenFlag::kWrite));
-	CleanupFile hlslFileCleanup(hlslFilename);
-	ANKI_CHECK(hlslFile.writeText(src));
-	hlslFile.close();
+	ANKI_CHECK(lazyDxcInit(errorMessage));
 
 	// Call DXC
-	ShaderCompilerString binFilename;
-	binFilename.sprintf("%s/%" PRIu64 ".spvdxil", tmpDir.cstr(), rand);
-
-	ShaderCompilerStringList dxcArgs;
-	dxcArgs.emplaceBack("-Fo");
-	dxcArgs.emplaceBack(binFilename);
-	dxcArgs.emplaceBack("-Wall");
-	dxcArgs.emplaceBack("-Wextra");
-	dxcArgs.emplaceBack("-Wno-conversion");
-	dxcArgs.emplaceBack("-Werror");
-	dxcArgs.emplaceBack("-Wfatal-errors");
-	dxcArgs.emplaceBack("-Wundef");
-	dxcArgs.emplaceBack("-Wno-unused-const-variable");
-	dxcArgs.emplaceBack("-Wno-unused-parameter");
-	dxcArgs.emplaceBack("-Wno-unneeded-internal-declaration");
-	dxcArgs.emplaceBack("-HV");
-	dxcArgs.emplaceBack("2021");
-	dxcArgs.emplaceBack("-E");
-	dxcArgs.emplaceBack("main");
-	dxcArgs.emplaceBack("-T");
-	dxcArgs.emplaceBack(profile(shaderType));
+	std::vector<std::wstring> dxcArgs;
+	dxcArgs.push_back(L"-Fo");
+	dxcArgs.push_back(L"-Wall");
+	dxcArgs.push_back(L"-Wextra");
+	dxcArgs.push_back(L"-Wno-conversion");
+	dxcArgs.push_back(L"-Werror");
+	dxcArgs.push_back(L"-Wfatal-errors");
+	dxcArgs.push_back(L"-Wundef");
+	dxcArgs.push_back(L"-Wno-unused-const-variable");
+	dxcArgs.push_back(L"-Wno-unused-parameter");
+	dxcArgs.push_back(L"-Wno-unneeded-internal-declaration");
+	dxcArgs.push_back(L"-HV");
+	dxcArgs.push_back(L"2021");
+	dxcArgs.push_back(L"-E");
+	dxcArgs.push_back(L"main");
+	dxcArgs.push_back(L"-T");
+	dxcArgs.push_back(profile(shaderType));
 
 	if(ANKI_COMPILER_MSVC)
 	{
-		dxcArgs.emplaceBack("-fdiagnostics-format=msvc"); // Make errors clickable in visual studio
+		dxcArgs.push_back(L"-fdiagnostics-format=msvc"); // Make errors clickable in visual studio
 	}
 
 	if(spirv)
 	{
-		dxcArgs.emplaceBack("-spirv");
-		dxcArgs.emplaceBack("-fspv-target-env=vulkan1.1spirv1.4");
-		// dxcArgs.emplaceBack("-fvk-support-nonzero-base-instance"); // Match DX12's behavior, SV_INSTANCEID starts from zero
+		dxcArgs.push_back(L"-spirv");
+		dxcArgs.push_back(L"-fspv-target-env=vulkan1.1spirv1.4");
+		// dxcArgs.push_back(L"-fvk-support-nonzero-base-instance"); // Match DX12's behavior, SV_INSTANCEID starts from zero
 
 		// Shift the bindings in order to identify the registers when doing reflection
 		for(U32 ds = 0; ds < kMaxRegisterSpaces; ++ds)
 		{
-			dxcArgs.emplaceBack("-fvk-b-shift");
-			dxcArgs.emplaceBack(ShaderCompilerString().sprintf("%u", kDxcVkBindingShifts[ds][HlslResourceType::kCbv]));
-			dxcArgs.emplaceBack(ShaderCompilerString().sprintf("%u", ds));
+			dxcArgs.push_back(L"-fvk-b-shift");
+			dxcArgs.push_back(std::to_wstring(kDxcVkBindingShifts[ds][HlslResourceType::kCbv]));
+			dxcArgs.push_back(std::to_wstring(ds));
 
-			dxcArgs.emplaceBack("-fvk-t-shift");
-			dxcArgs.emplaceBack(ShaderCompilerString().sprintf("%u", kDxcVkBindingShifts[ds][HlslResourceType::kSrv]));
-			dxcArgs.emplaceBack(ShaderCompilerString().sprintf("%u", ds));
+			dxcArgs.push_back(L"-fvk-t-shift");
+			dxcArgs.push_back(std::to_wstring(kDxcVkBindingShifts[ds][HlslResourceType::kSrv]));
+			dxcArgs.push_back(std::to_wstring(ds));
 
-			dxcArgs.emplaceBack("-fvk-u-shift");
-			dxcArgs.emplaceBack(ShaderCompilerString().sprintf("%u", kDxcVkBindingShifts[ds][HlslResourceType::kUav]));
-			dxcArgs.emplaceBack(ShaderCompilerString().sprintf("%u", ds));
+			dxcArgs.push_back(L"-fvk-u-shift");
+			dxcArgs.push_back(std::to_wstring(kDxcVkBindingShifts[ds][HlslResourceType::kUav]));
+			dxcArgs.push_back(std::to_wstring(ds));
 
-			dxcArgs.emplaceBack("-fvk-s-shift");
-			dxcArgs.emplaceBack(ShaderCompilerString().sprintf("%u", kDxcVkBindingShifts[ds][HlslResourceType::kSampler]));
-			dxcArgs.emplaceBack(ShaderCompilerString().sprintf("%u", ds));
+			dxcArgs.push_back(L"-fvk-s-shift");
+			dxcArgs.push_back(std::to_wstring(kDxcVkBindingShifts[ds][HlslResourceType::kSampler]));
+			dxcArgs.push_back(std::to_wstring(ds));
 		}
 	}
 	else
 	{
-		dxcArgs.emplaceBack("-Wno-ignored-attributes"); // TODO remove that at some point
-		dxcArgs.emplaceBack("-Wno-inline-asm"); // Workaround a DXC bug
+		dxcArgs.push_back(L"-Wno-ignored-attributes"); // TODO remove that at some point
+		dxcArgs.push_back(L"-Wno-inline-asm"); // Workaround a DXC bug
 	}
 
 	if(debugInfo)
 	{
-		dxcArgs.emplaceBack("-Zi");
+		dxcArgs.push_back(L"-Zi");
 	}
 
-	dxcArgs.emplaceBack(hlslFilename);
-
 	if(compileWith16bitTypes)
 	{
-		dxcArgs.emplaceBack("-enable-16bit-types");
+		dxcArgs.push_back(L"-enable-16bit-types");
 	}
 
 	for(CString extraArg : compilerArgs)
 	{
-		dxcArgs.emplaceBack(extraArg);
+		WChar wstr[128];
+		extraArg.toWideChars(wstr, 128);
+		dxcArgs.push_back(wstr);
+	}
+
+	std::vector<const WChar*> dxcArgsRaw;
+	dxcArgsRaw.reserve(dxcArgs.size());
+	for(const auto& x : dxcArgs)
+	{
+		dxcArgsRaw.push_back(x.c_str());
+	}
+
+	// Compile
+	CComPtr<IDxcCompiler3> dxcCompiler;
+	ANKI_DXC_CHECK(g_DxcCreateInstance(CLSID_DxcCompiler, IID_PPV_ARGS(&dxcCompiler)));
+
+	const DxcBuffer buff = {src.getBegin(), src.getLength(), 0};
+	CComPtr<IDxcResult> pResults;
+	ANKI_DXC_CHECK(dxcCompiler->Compile(&buff, dxcArgsRaw.data(), U32(dxcArgsRaw.size()), nullptr, IID_PPV_ARGS(&pResults)));
+
+	CComPtr<IDxcBlobUtf8> pErrors = nullptr;
+	ANKI_DXC_CHECK(pResults->GetOutput(DXC_OUT_ERRORS, IID_PPV_ARGS(&pErrors), nullptr));
+	if(pErrors != nullptr && pErrors->GetStringLength() != 0)
+	{
+		errorMessage = pErrors->GetStringPointer();
 	}
 
-	ShaderCompilerDynamicArray<CString> dxcArgs2;
-	dxcArgs2.resize(U32(dxcArgs.getSize()));
-	U32 count = 0;
-	for(auto& it : dxcArgs)
+	HRESULT hrStatus;
+	ANKI_DXC_CHECK(pResults->GetStatus(&hrStatus));
+	if(FAILED(hrStatus))
 	{
-		dxcArgs2[count++] = it.cstr();
+		return Error::kFunctionFailed;
 	}
 
-	while(true)
+	CComPtr<IDxcBlob> pShader = nullptr;
+	ANKI_DXC_CHECK(pResults->GetOutput(DXC_OUT_OBJECT, IID_PPV_ARGS(&pShader), nullptr));
+	if(pShader != nullptr)
 	{
-		I32 exitCode;
-		ShaderCompilerString stdOut;
+		bin.resize(U32(pShader->GetBufferSize()));
+		memcpy(bin.getBegin(), pShader->GetBufferPointer(), pShader->GetBufferSize());
+	}
+
+	return Error::kNone;
+}
+
+Error compileHlslToSpirv(CString src, ShaderType shaderType, Bool compileWith16bitTypes, Bool debugInfo, ConstWeakArray<CString> compilerArgs,
+						 ShaderCompilerDynamicArray<U8>& spirv, ShaderCompilerString& errorMessage)
+{
+	return compileHlsl(src, shaderType, compileWith16bitTypes, debugInfo, compilerArgs, true, spirv, errorMessage);
+}
+
+Error compileHlslToDxil(CString src, ShaderType shaderType, Bool compileWith16bitTypes, Bool debugInfo, ConstWeakArray<CString> compilerArgs,
+						ShaderCompilerDynamicArray<U8>& dxil, ShaderCompilerString& errorMessage)
+{
+	return compileHlsl(src, shaderType, compileWith16bitTypes, debugInfo, compilerArgs, false, dxil, errorMessage);
+}
 
 #if ANKI_OS_WINDOWS
-		CString dxcBin = ANKI_SOURCE_DIRECTORY "/ThirdParty/Bin/Windows64/dxc.exe";
-#elif ANKI_OS_LINUX
-		CString dxcBin = ANKI_SOURCE_DIRECTORY "/ThirdParty/Bin/Linux64/dxc";
-#else
-		CString dxcBin = "N/A";
-#endif
+Error doReflectionDxil(ConstWeakArray<U8> dxil, ShaderType type, ShaderReflection& refl, ShaderCompilerString& errorMessage)
+{
+	using Microsoft::WRL::ComPtr;
 
-		// Run once without stdout or stderr. Because if you do the process library will crap out after a while
-		ANKI_CHECK(Process::callProcess(dxcBin, dxcArgs2, nullptr, nullptr, exitCode));
+	// Lazyly load the DXC DLL
+	{
+		LockGuard lock(g_dxcLibMtx);
 
-		if(exitCode != 0)
+		if(g_dxcLib == 0)
 		{
-			// There was an error, run again just to get the stderr
-			String errorMessageTmp;
-			const Error err = Process::callProcess(dxcBin, dxcArgs2, nullptr, &errorMessageTmp, exitCode);
-			(void)err; // Shoudn't throw an error
-			errorMessage = errorMessageTmp;
+			// Init DXC
+			g_dxcLib = LoadLibraryA(ANKI_SOURCE_DIRECTORY "/ThirdParty/Bin/Windows64/dxcompiler.dll");
+			if(g_dxcLib == 0)
+			{
+				ANKI_SHADER_COMPILER_LOGE("dxcompiler.dll missing or wrong architecture");
+				return Error::kFunctionFailed;
+			}
+
+			g_DxcCreateInstance = reinterpret_cast<DxcCreateInstanceProc>(GetProcAddress(g_dxcLib, "DxcCreateInstance"));
+			if(g_DxcCreateInstance == nullptr)
+			{
+				ANKI_SHADER_COMPILER_LOGE("DxcCreateInstance was not found in the dxcompiler.dll");
+				return Error::kFunctionFailed;
+			}
+		}
+	}
+
+	const Bool isLib = (type >= ShaderType::kFirstRayTracing && type <= ShaderType::kLastRayTracing) || type == ShaderType::kWorkGraph;
 
-			ShaderCompilerString args;
-			dxcArgs.join(" ", args);
-			errorMessage += " (";
-			errorMessage += args;
-			errorMessage += ")";
+	ComPtr<IDxcUtils> utils;
+	ANKI_DXC_CHECK(g_DxcCreateInstance(CLSID_DxcUtils, IID_PPV_ARGS(&utils)));
 
-			if(!errorMessage.isEmpty() && errorMessage.find("The process cannot access the file because") != CString::kNpos)
+	ComPtr<ID3D12ShaderReflection> dxRefl;
+	ComPtr<ID3D12LibraryReflection> libRefl;
+	ShaderCompilerDynamicArray<ID3D12FunctionReflection*> funcReflections;
+	D3D12_SHADER_DESC shaderDesc = {};
+
+	if(isLib)
+	{
+		const DxcBuffer buff = {dxil.getBegin(), dxil.getSizeInBytes(), 0};
+		ANKI_DXC_CHECK(utils->CreateReflection(&buff, IID_PPV_ARGS(&libRefl)));
+
+		D3D12_LIBRARY_DESC libDesc = {};
+		libRefl->GetDesc(&libDesc);
+
+		if(libDesc.FunctionCount == 0)
+		{
+			errorMessage.sprintf("Expecting at least 1 in D3D12_LIBRARY_DESC::FunctionCount");
+			return Error::kUserData;
+		}
+
+		funcReflections.resize(libDesc.FunctionCount);
+		for(U32 i = 0; i < libDesc.FunctionCount; ++i)
+		{
+
+			funcReflections[i] = libRefl->GetFunctionByIndex(i);
+		}
+	}
+	else
+	{
+		const DxcBuffer buff = {dxil.getBegin(), dxil.getSizeInBytes(), 0};
+		ANKI_DXC_CHECK(utils->CreateReflection(&buff, IID_PPV_ARGS(&dxRefl)));
+
+		ANKI_DXC_CHECK(dxRefl->GetDesc(&shaderDesc));
+	}
+
+	for(U32 ifunc = 0; ifunc < ((isLib) ? funcReflections.getSize() : 1); ++ifunc)
+	{
+		U32 bindingCount;
+		if(isLib)
+		{
+			D3D12_FUNCTION_DESC funcDesc;
+			ANKI_DXC_CHECK(funcReflections[ifunc]->GetDesc(&funcDesc));
+			bindingCount = funcDesc.BoundResources;
+		}
+		else
+		{
+			bindingCount = shaderDesc.BoundResources;
+		}
+
+		for(U32 i = 0; i < bindingCount; ++i)
+		{
+			D3D12_SHADER_INPUT_BIND_DESC bindDesc;
+			if(isLib)
 			{
-				// DXC might fail to read the HLSL because the antivirus might be having a lock on it. Try again
-				errorMessage.destroy();
-				HighRezTimer::sleep(1.0_ms);
+				ANKI_DXC_CHECK(funcReflections[ifunc]->GetResourceBindingDesc(i, &bindDesc));
 			}
-			else if(errorMessage.isEmpty())
+			else
 			{
-				errorMessage = "Unknown error";
-				return Error::kFunctionFailed;
+				ANKI_DXC_CHECK(dxRefl->GetResourceBindingDesc(i, &bindDesc));
+			}
+
+			ShaderReflectionBinding akBinding;
+
+			akBinding.m_type = DescriptorType::kCount;
+			akBinding.m_arraySize = U16(bindDesc.BindCount);
+			akBinding.m_registerBindingPoint = bindDesc.BindPoint;
+
+			if(bindDesc.Type == D3D_SIT_CBUFFER)
+			{
+				// ConstantBuffer
+
+				if(bindDesc.Space == 3000 && bindDesc.BindPoint == 0)
+				{
+					// It's push/root constants
+
+					ID3D12ShaderReflectionConstantBuffer* cbuffer =
+						(isLib) ? funcReflections[ifunc]->GetConstantBufferByName(bindDesc.Name) : dxRefl->GetConstantBufferByName(bindDesc.Name);
+					D3D12_SHADER_BUFFER_DESC desc;
+					ANKI_DXC_CHECK(cbuffer->GetDesc(&desc));
+					refl.m_descriptor.m_fastConstantsSize = desc.Size;
+
+					continue;
+				}
+
+				akBinding.m_type = DescriptorType::kConstantBuffer;
+			}
+			else if(bindDesc.Type == D3D_SIT_TEXTURE && bindDesc.Dimension != D3D_SRV_DIMENSION_BUFFER)
+			{
+				// Texture2D etc
+				akBinding.m_type = DescriptorType::kSrvTexture;
+			}
+			else if(bindDesc.Type == D3D_SIT_TEXTURE && bindDesc.Dimension == D3D_SRV_DIMENSION_BUFFER)
+			{
+				// Buffer
+				akBinding.m_type = DescriptorType::kSrvTexelBuffer;
+			}
+			else if(bindDesc.Type == D3D_SIT_SAMPLER)
+			{
+				// SamplerState
+				akBinding.m_type = DescriptorType::kSampler;
+			}
+			else if(bindDesc.Type == D3D_SIT_UAV_RWTYPED && bindDesc.Dimension == D3D_SRV_DIMENSION_BUFFER)
+			{
+				// RWBuffer
+				akBinding.m_type = DescriptorType::kUavTexelBuffer;
+			}
+			else if(bindDesc.Type == D3D_SIT_UAV_RWTYPED && bindDesc.Dimension != D3D_SRV_DIMENSION_BUFFER)
+			{
+				// RWTexture2D etc
+				akBinding.m_type = DescriptorType::kUavTexture;
+			}
+			else if(bindDesc.Type == D3D_SIT_BYTEADDRESS)
+			{
+				// ByteAddressBuffer
+				akBinding.m_type = DescriptorType::kSrvByteAddressBuffer;
+				akBinding.m_d3dStructuredBufferStride = sizeof(U32);
+			}
+			else if(bindDesc.Type == D3D_SIT_UAV_RWBYTEADDRESS)
+			{
+				// RWByteAddressBuffer
+				akBinding.m_type = DescriptorType::kUavByteAddressBuffer;
+				akBinding.m_d3dStructuredBufferStride = sizeof(U32);
+			}
+			else if(bindDesc.Type == D3D_SIT_RTACCELERATIONSTRUCTURE)
+			{
+				// RaytracingAccelerationStructure
+				akBinding.m_type = DescriptorType::kAccelerationStructure;
+			}
+			else if(bindDesc.Type == D3D_SIT_STRUCTURED)
+			{
+				// StructuredBuffer
+				akBinding.m_type = DescriptorType::kSrvStructuredBuffer;
+				akBinding.m_d3dStructuredBufferStride = U16(bindDesc.NumSamples);
+			}
+			else if(bindDesc.Type == D3D_SIT_UAV_RWSTRUCTURED)
+			{
+				// RWStructuredBuffer
+				akBinding.m_type = DescriptorType::kUavStructuredBuffer;
+				akBinding.m_d3dStructuredBufferStride = U16(bindDesc.NumSamples);
 			}
 			else
 			{
-				// printf("%s\n", src.cstr());
-				return Error::kFunctionFailed;
+				errorMessage.sprintf("Unrecognized type for binding: %s", bindDesc.Name);
+				return Error::kUserData;
+			}
+
+			Bool skip = false;
+			if(isLib)
+			{
+				// Search if the binding exists because it may repeat
+				for(U32 i = 0; i < refl.m_descriptor.m_bindingCounts[bindDesc.Space]; ++i)
+				{
+					if(refl.m_descriptor.m_bindings[bindDesc.Space][i] == akBinding)
+					{
+						skip = true;
+						break;
+					}
+				}
+			}
+
+			if(!skip)
+			{
+				refl.m_descriptor.m_bindings[bindDesc.Space][refl.m_descriptor.m_bindingCounts[bindDesc.Space]] = akBinding;
+				++refl.m_descriptor.m_bindingCounts[bindDesc.Space];
 			}
 		}
-		else
+	}
+
+	for(U32 i = 0; i < kMaxRegisterSpaces; ++i)
+	{
+		std::sort(refl.m_descriptor.m_bindings[i].getBegin(), refl.m_descriptor.m_bindings[i].getBegin() + refl.m_descriptor.m_bindingCounts[i]);
+	}
+
+	if(type == ShaderType::kVertex)
+	{
+		for(U32 i = 0; i < shaderDesc.InputParameters; ++i)
 		{
-			break;
+			D3D12_SIGNATURE_PARAMETER_DESC in;
+			ANKI_DXC_CHECK(dxRefl->GetInputParameterDesc(i, &in));
+
+			VertexAttributeSemantic a = VertexAttributeSemantic::kCount;
+#	define ANKI_ATTRIB_NAME(x, idx) CString(in.SemanticName) == #    x&& in.SemanticIndex == idx
+			if(ANKI_ATTRIB_NAME(POSITION, 0))
+			{
+				a = VertexAttributeSemantic::kPosition;
+			}
+			else if(ANKI_ATTRIB_NAME(NORMAL, 0))
+			{
+				a = VertexAttributeSemantic::kNormal;
+			}
+			else if(ANKI_ATTRIB_NAME(TEXCOORD, 0))
+			{
+				a = VertexAttributeSemantic::kTexCoord;
+			}
+			else if(ANKI_ATTRIB_NAME(COLOR, 0))
+			{
+				a = VertexAttributeSemantic::kColor;
+			}
+			else if(ANKI_ATTRIB_NAME(MISC, 0))
+			{
+				a = VertexAttributeSemantic::kMisc0;
+			}
+			else if(ANKI_ATTRIB_NAME(MISC, 1))
+			{
+				a = VertexAttributeSemantic::kMisc1;
+			}
+			else if(ANKI_ATTRIB_NAME(MISC, 2))
+			{
+				a = VertexAttributeSemantic::kMisc2;
+			}
+			else if(ANKI_ATTRIB_NAME(MISC, 3))
+			{
+				a = VertexAttributeSemantic::kMisc3;
+			}
+			else if(ANKI_ATTRIB_NAME(SV_VERTEXID, 0) || ANKI_ATTRIB_NAME(SV_INSTANCEID, 0))
+			{
+				// Ignore
+				continue;
+			}
+			else
+			{
+				errorMessage.sprintf("Unexpected attribute name: %s", in.SemanticName);
+				return Error::kUserData;
+			}
+#	undef ANKI_ATTRIB_NAME
+
+			refl.m_vertex.m_vertexAttributeMask |= VertexAttributeSemanticBit(1 << a);
+			refl.m_vertex.m_vkVertexAttributeLocations[a] = U8(i); // Just set something
 		}
 	}
 
-	CleanupFile binFileCleanup(binFilename);
+	if(type == ShaderType::kPixel)
+	{
+		for(U32 i = 0; i < shaderDesc.OutputParameters; ++i)
+		{
+			D3D12_SIGNATURE_PARAMETER_DESC desc;
+			ANKI_DXC_CHECK(dxRefl->GetOutputParameterDesc(i, &desc));
 
-	// Read the spirv back
-	File binFile;
-	ANKI_CHECK(binFile.open(binFilename, FileOpenFlag::kRead));
-	bin.resize(U32(binFile.getSize()));
-	ANKI_CHECK(binFile.read(&bin[0], bin.getSizeInBytes()));
-	binFile.close();
+			if(CString(desc.SemanticName) == "SV_TARGET")
+			{
+				refl.m_pixel.m_colorRenderTargetWritemask.set(desc.SemanticIndex);
+			}
+		}
+	}
 
 	return Error::kNone;
 }
-
-Error compileHlslToSpirv(CString src, ShaderType shaderType, Bool compileWith16bitTypes, Bool debugInfo, ConstWeakArray<CString> compilerArgs,
-						 ShaderCompilerDynamicArray<U8>& spirv, ShaderCompilerString& errorMessage)
-{
-	return compileHlsl(src, shaderType, compileWith16bitTypes, debugInfo, compilerArgs, true, spirv, errorMessage);
-}
-
-Error compileHlslToDxil(CString src, ShaderType shaderType, Bool compileWith16bitTypes, Bool debugInfo, ConstWeakArray<CString> compilerArgs,
-						ShaderCompilerDynamicArray<U8>& dxil, ShaderCompilerString& errorMessage)
-{
-	return compileHlsl(src, shaderType, compileWith16bitTypes, debugInfo, compilerArgs, false, dxil, errorMessage);
-}
+#endif
 
 } // end namespace anki

+ 2 - 0
AnKi/ShaderCompiler/Dxc.h

@@ -27,6 +27,8 @@ Error compileHlslToSpirv(CString src, ShaderType shaderType, Bool compileWith16b
 /// Compile HLSL to DXIL.
 Error compileHlslToDxil(CString src, ShaderType shaderType, Bool compileWith16bitTypes, Bool debugInfo, ConstWeakArray<CString> compilerArgs,
 						ShaderCompilerDynamicArray<U8>& dxil, ShaderCompilerString& errorMessage);
+
+Error doReflectionDxil(ConstWeakArray<U8> dxil, ShaderType type, ShaderReflection& refl, ShaderCompilerString& errorMessage);
 /// @}
 
 } // end namespace anki

+ 2 - 555
AnKi/ShaderCompiler/ShaderCompiler.cpp

@@ -6,28 +6,12 @@
 #include <AnKi/ShaderCompiler/ShaderCompiler.h>
 #include <AnKi/ShaderCompiler/ShaderParser.h>
 #include <AnKi/ShaderCompiler/Dxc.h>
+#include <AnKi/ShaderCompiler/Spirv.h>
 #include <AnKi/Util/Serializer.h>
 #include <AnKi/Util/HashMap.h>
-#include <SpirvCross/spirv_cross.hpp>
-
-#define ANKI_DIXL_REFLECTION (ANKI_OS_WINDOWS)
-
-#if ANKI_DIXL_REFLECTION
-#	include <windows.h>
-#	include <ThirdParty/Dxc/dxcapi.h>
-#	include <ThirdParty/Dxc/d3d12shader.h>
-#	include <wrl.h>
-#	include <AnKi/Util/CleanupWindows.h>
-#endif
 
 namespace anki {
 
-#if ANKI_DIXL_REFLECTION
-static HMODULE g_dxcLib = 0;
-static DxcCreateInstanceProc g_DxcCreateInstance = nullptr;
-static Mutex g_dxcLibMtx;
-#endif
-
 void freeShaderBinary(ShaderBinary*& binary)
 {
 	if(binary == nullptr)
@@ -110,543 +94,6 @@ static Bool spinDials(ShaderCompilerDynamicArray<U32>& dials, ConstWeakArray<Sha
 	return done;
 }
 
-/// Does SPIR-V reflection and re-writes the SPIR-V binary's bindings
-Error doReflectionSpirv(ConstWeakArray<U8> spirv, ShaderType type, ShaderReflection& refl, ShaderCompilerString& errorStr)
-{
-	spirv_cross::Compiler spvc(reinterpret_cast<const U32*>(&spirv[0]), spirv.getSize() / sizeof(U32));
-	spirv_cross::ShaderResources rsrc = spvc.get_shader_resources();
-	spirv_cross::ShaderResources rsrcActive = spvc.get_shader_resources(spvc.get_active_interface_variables());
-
-	auto func = [&](const spirv_cross::SmallVector<spirv_cross::Resource>& resources, const DescriptorType origType) -> Error {
-		for(const spirv_cross::Resource& r : resources)
-		{
-			const U32 id = r.id;
-
-			const U32 set = spvc.get_decoration(id, spv::Decoration::DecorationDescriptorSet);
-			const U32 binding = spvc.get_decoration(id, spv::Decoration::DecorationBinding);
-			if(set >= kMaxRegisterSpaces && set != kDxcVkBindlessRegisterSpace)
-			{
-				errorStr.sprintf("Exceeded set for: %s", r.name.c_str());
-				return Error::kUserData;
-			}
-
-			const spirv_cross::SPIRType& typeInfo = spvc.get_type(r.type_id);
-			U32 arraySize = 1;
-			if(typeInfo.array.size() != 0)
-			{
-				if(typeInfo.array.size() != 1)
-				{
-					errorStr.sprintf("Only 1D arrays are supported: %s", r.name.c_str());
-					return Error::kUserData;
-				}
-
-				if(set == kDxcVkBindlessRegisterSpace && typeInfo.array[0] != 0)
-				{
-					errorStr.sprintf("Only the bindless descriptor set can be an unbound array: %s", r.name.c_str());
-					return Error::kUserData;
-				}
-
-				arraySize = typeInfo.array[0];
-			}
-
-			// Images are special, they might be texel buffers
-			DescriptorType type = origType;
-			if((type == DescriptorType::kSrvTexture || type == DescriptorType::kUavTexture) && typeInfo.image.dim == spv::DimBuffer)
-			{
-				if(typeInfo.image.sampled == 1)
-				{
-					type = DescriptorType::kSrvTexelBuffer;
-				}
-				else
-				{
-					ANKI_ASSERT(typeInfo.image.sampled == 2);
-					type = DescriptorType::kUavTexelBuffer;
-				}
-			}
-
-			if(set == kDxcVkBindlessRegisterSpace)
-			{
-				// Bindless dset
-
-				if(arraySize != 0)
-				{
-					errorStr.sprintf("Unexpected unbound array for bindless: %s", r.name.c_str());
-				}
-
-				if(type != DescriptorType::kSrvTexture)
-				{
-					errorStr.sprintf("Unexpected bindless binding: %s", r.name.c_str());
-					return Error::kUserData;
-				}
-
-				refl.m_descriptor.m_hasVkBindlessDescriptorSet = true;
-			}
-			else
-			{
-				// Regular binding
-
-				// Use the binding to find out if it's a read or write storage buffer, there is no other way
-				if(origType == DescriptorType::kSrvStructuredBuffer
-				   && (binding < kDxcVkBindingShifts[set][HlslResourceType::kSrv]
-					   || binding >= kDxcVkBindingShifts[set][HlslResourceType::kSrv] + 1000))
-				{
-					type = DescriptorType::kUavStructuredBuffer;
-				}
-
-				const HlslResourceType hlslResourceType = descriptorTypeToHlslResourceType(type);
-				if(binding < kDxcVkBindingShifts[set][hlslResourceType] || binding >= kDxcVkBindingShifts[set][hlslResourceType] + 1000)
-				{
-					errorStr.sprintf("Unexpected binding: %s", r.name.c_str());
-					return Error::kUserData;
-				}
-
-				ShaderReflectionBinding akBinding;
-				akBinding.m_registerBindingPoint = binding - kDxcVkBindingShifts[set][hlslResourceType];
-				akBinding.m_arraySize = U16(arraySize);
-				akBinding.m_type = type;
-
-				refl.m_descriptor.m_bindings[set][refl.m_descriptor.m_bindingCounts[set]] = akBinding;
-				++refl.m_descriptor.m_bindingCounts[set];
-			}
-		}
-
-		return Error::kNone;
-	};
-
-	Error err = func(rsrc.uniform_buffers, DescriptorType::kConstantBuffer);
-	if(err)
-	{
-		return err;
-	}
-
-	err = func(rsrc.separate_images, DescriptorType::kSrvTexture); // This also handles texel buffers
-	if(err)
-	{
-		return err;
-	}
-
-	err = func(rsrc.separate_samplers, DescriptorType::kSampler);
-	if(err)
-	{
-		return err;
-	}
-
-	err = func(rsrc.storage_buffers, DescriptorType::kSrvStructuredBuffer);
-	if(err)
-	{
-		return err;
-	}
-
-	err = func(rsrc.storage_images, DescriptorType::kUavTexture);
-	if(err)
-	{
-		return err;
-	}
-
-	err = func(rsrc.acceleration_structures, DescriptorType::kAccelerationStructure);
-	if(err)
-	{
-		return err;
-	}
-
-	for(U32 i = 0; i < kMaxRegisterSpaces; ++i)
-	{
-		std::sort(refl.m_descriptor.m_bindings[i].getBegin(), refl.m_descriptor.m_bindings[i].getBegin() + refl.m_descriptor.m_bindingCounts[i]);
-	}
-
-	// Color attachments
-	if(type == ShaderType::kPixel)
-	{
-		for(const spirv_cross::Resource& r : rsrc.stage_outputs)
-		{
-			const U32 id = r.id;
-			const U32 location = spvc.get_decoration(id, spv::Decoration::DecorationLocation);
-
-			refl.m_pixel.m_colorRenderTargetWritemask.set(location);
-		}
-	}
-
-	// Push consts
-	if(rsrc.push_constant_buffers.size() == 1)
-	{
-		const U32 blockSize = U32(spvc.get_declared_struct_size(spvc.get_type(rsrc.push_constant_buffers[0].base_type_id)));
-		if(blockSize == 0 || (blockSize % 16) != 0 || blockSize > kMaxFastConstantsSize)
-		{
-			errorStr.sprintf("Incorrect push constants size");
-			return Error::kUserData;
-		}
-
-		refl.m_descriptor.m_fastConstantsSize = blockSize;
-	}
-
-	// Attribs
-	if(type == ShaderType::kVertex)
-	{
-		for(const spirv_cross::Resource& r : rsrcActive.stage_inputs)
-		{
-			VertexAttributeSemantic a = VertexAttributeSemantic::kCount;
-#define ANKI_ATTRIB_NAME(x) "in.var." #x
-			if(r.name == ANKI_ATTRIB_NAME(POSITION))
-			{
-				a = VertexAttributeSemantic::kPosition;
-			}
-			else if(r.name == ANKI_ATTRIB_NAME(NORMAL))
-			{
-				a = VertexAttributeSemantic::kNormal;
-			}
-			else if(r.name == ANKI_ATTRIB_NAME(TEXCOORD0) || r.name == ANKI_ATTRIB_NAME(TEXCOORD))
-			{
-				a = VertexAttributeSemantic::kTexCoord;
-			}
-			else if(r.name == ANKI_ATTRIB_NAME(COLOR))
-			{
-				a = VertexAttributeSemantic::kColor;
-			}
-			else if(r.name == ANKI_ATTRIB_NAME(MISC0) || r.name == ANKI_ATTRIB_NAME(MISC))
-			{
-				a = VertexAttributeSemantic::kMisc0;
-			}
-			else if(r.name == ANKI_ATTRIB_NAME(MISC1))
-			{
-				a = VertexAttributeSemantic::kMisc1;
-			}
-			else if(r.name == ANKI_ATTRIB_NAME(MISC2))
-			{
-				a = VertexAttributeSemantic::kMisc2;
-			}
-			else if(r.name == ANKI_ATTRIB_NAME(MISC3))
-			{
-				a = VertexAttributeSemantic::kMisc3;
-			}
-			else
-			{
-				errorStr.sprintf("Unexpected attribute name: %s", r.name.c_str());
-				return Error::kUserData;
-			}
-#undef ANKI_ATTRIB_NAME
-
-			refl.m_vertex.m_vertexAttributeMask |= VertexAttributeSemanticBit(1 << a);
-
-			const U32 id = r.id;
-			const U32 location = spvc.get_decoration(id, spv::Decoration::DecorationLocation);
-			if(location > kMaxU8)
-			{
-				errorStr.sprintf("Too high location value for attribute: %s", r.name.c_str());
-				return Error::kUserData;
-			}
-
-			refl.m_vertex.m_vkVertexAttributeLocations[a] = U8(location);
-		}
-	}
-
-	// Discards?
-	if(type == ShaderType::kPixel)
-	{
-		visitSpirv(ConstWeakArray<U32>(reinterpret_cast<const U32*>(&spirv[0]), spirv.getSize() / sizeof(U32)),
-				   [&](U32 cmd, [[maybe_unused]] ConstWeakArray<U32> instructions) {
-					   if(cmd == spv::OpKill)
-					   {
-						   refl.m_pixel.m_discards = true;
-					   }
-				   });
-	}
-
-	return Error::kNone;
-}
-
-#if ANKI_DIXL_REFLECTION
-
-#	define ANKI_REFL_CHECK(x) \
-		do \
-		{ \
-			HRESULT rez; \
-			if((rez = (x)) < 0) [[unlikely]] \
-			{ \
-				errorStr.sprintf("DXC function failed (HRESULT: %d): %s", rez, #x); \
-				return Error::kFunctionFailed; \
-			} \
-		} while(0)
-
-Error doReflectionDxil(ConstWeakArray<U8> dxil, ShaderType type, ShaderReflection& refl, ShaderCompilerString& errorStr)
-{
-	using Microsoft::WRL::ComPtr;
-
-	// Lazyly load the DXC DLL
-	{
-		LockGuard lock(g_dxcLibMtx);
-
-		if(g_dxcLib == 0)
-		{
-			// Init DXC
-			g_dxcLib = LoadLibraryA(ANKI_SOURCE_DIRECTORY "/ThirdParty/Bin/Windows64/dxcompiler.dll");
-			if(g_dxcLib == 0)
-			{
-				ANKI_SHADER_COMPILER_LOGE("dxcompiler.dll missing or wrong architecture");
-				return Error::kFunctionFailed;
-			}
-
-			g_DxcCreateInstance = reinterpret_cast<DxcCreateInstanceProc>(GetProcAddress(g_dxcLib, "DxcCreateInstance"));
-			if(g_DxcCreateInstance == nullptr)
-			{
-				ANKI_SHADER_COMPILER_LOGE("DxcCreateInstance was not found in the dxcompiler.dll");
-				return Error::kFunctionFailed;
-			}
-		}
-	}
-
-	const Bool isLib = (type >= ShaderType::kFirstRayTracing && type <= ShaderType::kLastRayTracing) || type == ShaderType::kWorkGraph;
-
-	ComPtr<IDxcUtils> utils;
-	ANKI_REFL_CHECK(g_DxcCreateInstance(CLSID_DxcUtils, IID_PPV_ARGS(&utils)));
-
-	ComPtr<ID3D12ShaderReflection> dxRefl;
-	ComPtr<ID3D12LibraryReflection> libRefl;
-	ShaderCompilerDynamicArray<ID3D12FunctionReflection*> funcReflections;
-	D3D12_SHADER_DESC shaderDesc = {};
-
-	if(isLib)
-	{
-		const DxcBuffer buff = {dxil.getBegin(), dxil.getSizeInBytes(), 0};
-		ANKI_REFL_CHECK(utils->CreateReflection(&buff, IID_PPV_ARGS(&libRefl)));
-
-		D3D12_LIBRARY_DESC libDesc = {};
-		libRefl->GetDesc(&libDesc);
-
-		if(libDesc.FunctionCount == 0)
-		{
-			errorStr.sprintf("Expecting at least 1 in D3D12_LIBRARY_DESC::FunctionCount");
-			return Error::kUserData;
-		}
-
-		funcReflections.resize(libDesc.FunctionCount);
-		for(U32 i = 0; i < libDesc.FunctionCount; ++i)
-		{
-
-			funcReflections[i] = libRefl->GetFunctionByIndex(i);
-		}
-	}
-	else
-	{
-		const DxcBuffer buff = {dxil.getBegin(), dxil.getSizeInBytes(), 0};
-		ANKI_REFL_CHECK(utils->CreateReflection(&buff, IID_PPV_ARGS(&dxRefl)));
-
-		ANKI_REFL_CHECK(dxRefl->GetDesc(&shaderDesc));
-	}
-
-	for(U32 ifunc = 0; ifunc < ((isLib) ? funcReflections.getSize() : 1); ++ifunc)
-	{
-		U32 bindingCount;
-		if(isLib)
-		{
-			D3D12_FUNCTION_DESC funcDesc;
-			ANKI_REFL_CHECK(funcReflections[ifunc]->GetDesc(&funcDesc));
-			bindingCount = funcDesc.BoundResources;
-		}
-		else
-		{
-			bindingCount = shaderDesc.BoundResources;
-		}
-
-		for(U32 i = 0; i < bindingCount; ++i)
-		{
-			D3D12_SHADER_INPUT_BIND_DESC bindDesc;
-			if(isLib)
-			{
-				ANKI_REFL_CHECK(funcReflections[ifunc]->GetResourceBindingDesc(i, &bindDesc));
-			}
-			else
-			{
-				ANKI_REFL_CHECK(dxRefl->GetResourceBindingDesc(i, &bindDesc));
-			}
-
-			ShaderReflectionBinding akBinding;
-
-			akBinding.m_type = DescriptorType::kCount;
-			akBinding.m_arraySize = U16(bindDesc.BindCount);
-			akBinding.m_registerBindingPoint = bindDesc.BindPoint;
-
-			if(bindDesc.Type == D3D_SIT_CBUFFER)
-			{
-				// ConstantBuffer
-
-				if(bindDesc.Space == 3000 && bindDesc.BindPoint == 0)
-				{
-					// It's push/root constants
-
-					ID3D12ShaderReflectionConstantBuffer* cbuffer =
-						(isLib) ? funcReflections[ifunc]->GetConstantBufferByName(bindDesc.Name) : dxRefl->GetConstantBufferByName(bindDesc.Name);
-					D3D12_SHADER_BUFFER_DESC desc;
-					ANKI_REFL_CHECK(cbuffer->GetDesc(&desc));
-					refl.m_descriptor.m_fastConstantsSize = desc.Size;
-
-					continue;
-				}
-
-				akBinding.m_type = DescriptorType::kConstantBuffer;
-			}
-			else if(bindDesc.Type == D3D_SIT_TEXTURE && bindDesc.Dimension != D3D_SRV_DIMENSION_BUFFER)
-			{
-				// Texture2D etc
-				akBinding.m_type = DescriptorType::kSrvTexture;
-			}
-			else if(bindDesc.Type == D3D_SIT_TEXTURE && bindDesc.Dimension == D3D_SRV_DIMENSION_BUFFER)
-			{
-				// Buffer
-				akBinding.m_type = DescriptorType::kSrvTexelBuffer;
-			}
-			else if(bindDesc.Type == D3D_SIT_SAMPLER)
-			{
-				// SamplerState
-				akBinding.m_type = DescriptorType::kSampler;
-			}
-			else if(bindDesc.Type == D3D_SIT_UAV_RWTYPED && bindDesc.Dimension == D3D_SRV_DIMENSION_BUFFER)
-			{
-				// RWBuffer
-				akBinding.m_type = DescriptorType::kUavTexelBuffer;
-			}
-			else if(bindDesc.Type == D3D_SIT_UAV_RWTYPED && bindDesc.Dimension != D3D_SRV_DIMENSION_BUFFER)
-			{
-				// RWTexture2D etc
-				akBinding.m_type = DescriptorType::kUavTexture;
-			}
-			else if(bindDesc.Type == D3D_SIT_BYTEADDRESS)
-			{
-				// ByteAddressBuffer
-				akBinding.m_type = DescriptorType::kSrvByteAddressBuffer;
-				akBinding.m_d3dStructuredBufferStride = sizeof(U32);
-			}
-			else if(bindDesc.Type == D3D_SIT_UAV_RWBYTEADDRESS)
-			{
-				// RWByteAddressBuffer
-				akBinding.m_type = DescriptorType::kUavByteAddressBuffer;
-				akBinding.m_d3dStructuredBufferStride = sizeof(U32);
-			}
-			else if(bindDesc.Type == D3D_SIT_RTACCELERATIONSTRUCTURE)
-			{
-				// RaytracingAccelerationStructure
-				akBinding.m_type = DescriptorType::kAccelerationStructure;
-			}
-			else if(bindDesc.Type == D3D_SIT_STRUCTURED)
-			{
-				// StructuredBuffer
-				akBinding.m_type = DescriptorType::kSrvStructuredBuffer;
-				akBinding.m_d3dStructuredBufferStride = U16(bindDesc.NumSamples);
-			}
-			else if(bindDesc.Type == D3D_SIT_UAV_RWSTRUCTURED)
-			{
-				// RWStructuredBuffer
-				akBinding.m_type = DescriptorType::kUavStructuredBuffer;
-				akBinding.m_d3dStructuredBufferStride = U16(bindDesc.NumSamples);
-			}
-			else
-			{
-				errorStr.sprintf("Unrecognized type for binding: %s", bindDesc.Name);
-				return Error::kUserData;
-			}
-
-			Bool skip = false;
-			if(isLib)
-			{
-				// Search if the binding exists because it may repeat
-				for(U32 i = 0; i < refl.m_descriptor.m_bindingCounts[bindDesc.Space]; ++i)
-				{
-					if(refl.m_descriptor.m_bindings[bindDesc.Space][i] == akBinding)
-					{
-						skip = true;
-						break;
-					}
-				}
-			}
-
-			if(!skip)
-			{
-				refl.m_descriptor.m_bindings[bindDesc.Space][refl.m_descriptor.m_bindingCounts[bindDesc.Space]] = akBinding;
-				++refl.m_descriptor.m_bindingCounts[bindDesc.Space];
-			}
-		}
-	}
-
-	for(U32 i = 0; i < kMaxRegisterSpaces; ++i)
-	{
-		std::sort(refl.m_descriptor.m_bindings[i].getBegin(), refl.m_descriptor.m_bindings[i].getBegin() + refl.m_descriptor.m_bindingCounts[i]);
-	}
-
-	if(type == ShaderType::kVertex)
-	{
-		for(U32 i = 0; i < shaderDesc.InputParameters; ++i)
-		{
-			D3D12_SIGNATURE_PARAMETER_DESC in;
-			ANKI_REFL_CHECK(dxRefl->GetInputParameterDesc(i, &in));
-
-			VertexAttributeSemantic a = VertexAttributeSemantic::kCount;
-#	define ANKI_ATTRIB_NAME(x, idx) CString(in.SemanticName) == #    x&& in.SemanticIndex == idx
-			if(ANKI_ATTRIB_NAME(POSITION, 0))
-			{
-				a = VertexAttributeSemantic::kPosition;
-			}
-			else if(ANKI_ATTRIB_NAME(NORMAL, 0))
-			{
-				a = VertexAttributeSemantic::kNormal;
-			}
-			else if(ANKI_ATTRIB_NAME(TEXCOORD, 0))
-			{
-				a = VertexAttributeSemantic::kTexCoord;
-			}
-			else if(ANKI_ATTRIB_NAME(COLOR, 0))
-			{
-				a = VertexAttributeSemantic::kColor;
-			}
-			else if(ANKI_ATTRIB_NAME(MISC, 0))
-			{
-				a = VertexAttributeSemantic::kMisc0;
-			}
-			else if(ANKI_ATTRIB_NAME(MISC, 1))
-			{
-				a = VertexAttributeSemantic::kMisc1;
-			}
-			else if(ANKI_ATTRIB_NAME(MISC, 2))
-			{
-				a = VertexAttributeSemantic::kMisc2;
-			}
-			else if(ANKI_ATTRIB_NAME(MISC, 3))
-			{
-				a = VertexAttributeSemantic::kMisc3;
-			}
-			else if(ANKI_ATTRIB_NAME(SV_VERTEXID, 0) || ANKI_ATTRIB_NAME(SV_INSTANCEID, 0))
-			{
-				// Ignore
-				continue;
-			}
-			else
-			{
-				errorStr.sprintf("Unexpected attribute name: %s", in.SemanticName);
-				return Error::kUserData;
-			}
-#	undef ANKI_ATTRIB_NAME
-
-			refl.m_vertex.m_vertexAttributeMask |= VertexAttributeSemanticBit(1 << a);
-			refl.m_vertex.m_vkVertexAttributeLocations[a] = U8(i); // Just set something
-		}
-	}
-
-	if(type == ShaderType::kPixel)
-	{
-		for(U32 i = 0; i < shaderDesc.OutputParameters; ++i)
-		{
-			D3D12_SIGNATURE_PARAMETER_DESC desc;
-			ANKI_REFL_CHECK(dxRefl->GetOutputParameterDesc(i, &desc));
-
-			if(CString(desc.SemanticName) == "SV_TARGET")
-			{
-				refl.m_pixel.m_colorRenderTargetWritemask.set(desc.SemanticIndex);
-			}
-		}
-	}
-
-	return Error::kNone;
-}
-#endif // #if ANKI_DIXL_REFLECTION
-
 static void compileVariantAsync(const ShaderParser& parser, Bool spirv, Bool debugInfo, ShaderBinaryMutation& mutation,
 								ShaderCompilerDynamicArray<ShaderBinaryVariant>& variants,
 								ShaderCompilerDynamicArray<ShaderBinaryCodeBlock>& codeBlocks, ShaderCompilerDynamicArray<U64>& sourceCodeHashes,
@@ -769,7 +216,7 @@ static void compileVariantAsync(const ShaderParser& parser, Bool spirv, Bool deb
 				}
 				else
 				{
-#if ANKI_DIXL_REFLECTION
+#if ANKI_OS_WINDOWS
 					err = doReflectionDxil(il, shaderType, refl, compilerErrorLog);
 #else
 					ANKI_SHADER_COMPILER_LOGE("Can't generate shader compilation on non-windows platforms");

+ 0 - 3
AnKi/ShaderCompiler/ShaderCompiler.h

@@ -46,9 +46,6 @@ Error compileShaderProgram(CString fname, Bool spirv, Bool debugInfo, ShaderComp
 
 /// Free the binary created ONLY by compileShaderProgram.
 void freeShaderBinary(ShaderBinary*& binary);
-
-Error doReflectionDxil(ConstWeakArray<U8> dxil, ShaderType type, ShaderReflection& refl, ShaderCompilerString& errorStr);
-Error doReflectionSpirv(ConstWeakArray<U8> spirv, ShaderType type, ShaderReflection& refl, ShaderCompilerString& errorStr);
 /// @}
 
 } // end namespace anki

+ 0 - 1
AnKi/ShaderCompiler/ShaderProgramCompiler.cpp

@@ -1 +0,0 @@
-

+ 0 - 1
AnKi/ShaderCompiler/ShaderProgramCompiler.h

@@ -1 +0,0 @@
-

+ 0 - 1
AnKi/ShaderCompiler/ShaderProgramParser.cpp

@@ -1 +0,0 @@
-

+ 0 - 1
AnKi/ShaderCompiler/ShaderProgramParser.h

@@ -1 +0,0 @@
-

+ 255 - 0
AnKi/ShaderCompiler/Spirv.cpp

@@ -0,0 +1,255 @@
+// Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#include <AnKi/ShaderCompiler/Spirv.h>
+#include <AnKi/ShaderCompiler/Dxc.h>
+#include <SpirvCross/spirv_cross.hpp>
+
+namespace anki {
+
+Error doReflectionSpirv(ConstWeakArray<U8> spirv, ShaderType type, ShaderReflection& refl, ShaderCompilerString& errorStr)
+{
+	spirv_cross::Compiler spvc(reinterpret_cast<const U32*>(&spirv[0]), spirv.getSize() / sizeof(U32));
+	spirv_cross::ShaderResources rsrc = spvc.get_shader_resources();
+	spirv_cross::ShaderResources rsrcActive = spvc.get_shader_resources(spvc.get_active_interface_variables());
+
+	auto func = [&](const spirv_cross::SmallVector<spirv_cross::Resource>& resources, const DescriptorType origType) -> Error {
+		for(const spirv_cross::Resource& r : resources)
+		{
+			const U32 id = r.id;
+
+			const U32 set = spvc.get_decoration(id, spv::Decoration::DecorationDescriptorSet);
+			const U32 binding = spvc.get_decoration(id, spv::Decoration::DecorationBinding);
+			if(set >= kMaxRegisterSpaces && set != kDxcVkBindlessRegisterSpace)
+			{
+				errorStr.sprintf("Exceeded set for: %s", r.name.c_str());
+				return Error::kUserData;
+			}
+
+			const spirv_cross::SPIRType& typeInfo = spvc.get_type(r.type_id);
+			U32 arraySize = 1;
+			if(typeInfo.array.size() != 0)
+			{
+				if(typeInfo.array.size() != 1)
+				{
+					errorStr.sprintf("Only 1D arrays are supported: %s", r.name.c_str());
+					return Error::kUserData;
+				}
+
+				if(set == kDxcVkBindlessRegisterSpace && typeInfo.array[0] != 0)
+				{
+					errorStr.sprintf("Only the bindless descriptor set can be an unbound array: %s", r.name.c_str());
+					return Error::kUserData;
+				}
+
+				arraySize = typeInfo.array[0];
+			}
+
+			// Images are special, they might be texel buffers
+			DescriptorType type = origType;
+			if((type == DescriptorType::kSrvTexture || type == DescriptorType::kUavTexture) && typeInfo.image.dim == spv::DimBuffer)
+			{
+				if(typeInfo.image.sampled == 1)
+				{
+					type = DescriptorType::kSrvTexelBuffer;
+				}
+				else
+				{
+					ANKI_ASSERT(typeInfo.image.sampled == 2);
+					type = DescriptorType::kUavTexelBuffer;
+				}
+			}
+
+			if(set == kDxcVkBindlessRegisterSpace)
+			{
+				// Bindless dset
+
+				if(arraySize != 0)
+				{
+					errorStr.sprintf("Unexpected unbound array for bindless: %s", r.name.c_str());
+				}
+
+				if(type != DescriptorType::kSrvTexture)
+				{
+					errorStr.sprintf("Unexpected bindless binding: %s", r.name.c_str());
+					return Error::kUserData;
+				}
+
+				refl.m_descriptor.m_hasVkBindlessDescriptorSet = true;
+			}
+			else
+			{
+				// Regular binding
+
+				// Use the binding to find out if it's a read or write storage buffer, there is no other way
+				if(origType == DescriptorType::kSrvStructuredBuffer
+				   && (binding < kDxcVkBindingShifts[set][HlslResourceType::kSrv]
+					   || binding >= kDxcVkBindingShifts[set][HlslResourceType::kSrv] + 1000))
+				{
+					type = DescriptorType::kUavStructuredBuffer;
+				}
+
+				const HlslResourceType hlslResourceType = descriptorTypeToHlslResourceType(type);
+				if(binding < kDxcVkBindingShifts[set][hlslResourceType] || binding >= kDxcVkBindingShifts[set][hlslResourceType] + 1000)
+				{
+					errorStr.sprintf("Unexpected binding: %s", r.name.c_str());
+					return Error::kUserData;
+				}
+
+				ShaderReflectionBinding akBinding;
+				akBinding.m_registerBindingPoint = binding - kDxcVkBindingShifts[set][hlslResourceType];
+				akBinding.m_arraySize = U16(arraySize);
+				akBinding.m_type = type;
+
+				refl.m_descriptor.m_bindings[set][refl.m_descriptor.m_bindingCounts[set]] = akBinding;
+				++refl.m_descriptor.m_bindingCounts[set];
+			}
+		}
+
+		return Error::kNone;
+	};
+
+	Error err = func(rsrc.uniform_buffers, DescriptorType::kConstantBuffer);
+	if(err)
+	{
+		return err;
+	}
+
+	err = func(rsrc.separate_images, DescriptorType::kSrvTexture); // This also handles texel buffers
+	if(err)
+	{
+		return err;
+	}
+
+	err = func(rsrc.separate_samplers, DescriptorType::kSampler);
+	if(err)
+	{
+		return err;
+	}
+
+	err = func(rsrc.storage_buffers, DescriptorType::kSrvStructuredBuffer);
+	if(err)
+	{
+		return err;
+	}
+
+	err = func(rsrc.storage_images, DescriptorType::kUavTexture);
+	if(err)
+	{
+		return err;
+	}
+
+	err = func(rsrc.acceleration_structures, DescriptorType::kAccelerationStructure);
+	if(err)
+	{
+		return err;
+	}
+
+	for(U32 i = 0; i < kMaxRegisterSpaces; ++i)
+	{
+		std::sort(refl.m_descriptor.m_bindings[i].getBegin(), refl.m_descriptor.m_bindings[i].getBegin() + refl.m_descriptor.m_bindingCounts[i]);
+	}
+
+	// Color attachments
+	if(type == ShaderType::kPixel)
+	{
+		for(const spirv_cross::Resource& r : rsrc.stage_outputs)
+		{
+			const U32 id = r.id;
+			const U32 location = spvc.get_decoration(id, spv::Decoration::DecorationLocation);
+
+			refl.m_pixel.m_colorRenderTargetWritemask.set(location);
+		}
+	}
+
+	// Push consts
+	if(rsrc.push_constant_buffers.size() == 1)
+	{
+		const U32 blockSize = U32(spvc.get_declared_struct_size(spvc.get_type(rsrc.push_constant_buffers[0].base_type_id)));
+		if(blockSize == 0 || (blockSize % 16) != 0 || blockSize > kMaxFastConstantsSize)
+		{
+			errorStr.sprintf("Incorrect push constants size");
+			return Error::kUserData;
+		}
+
+		refl.m_descriptor.m_fastConstantsSize = blockSize;
+	}
+
+	// Attribs
+	if(type == ShaderType::kVertex)
+	{
+		for(const spirv_cross::Resource& r : rsrcActive.stage_inputs)
+		{
+			VertexAttributeSemantic a = VertexAttributeSemantic::kCount;
+#define ANKI_ATTRIB_NAME(x) "in.var." #x
+			if(r.name == ANKI_ATTRIB_NAME(POSITION))
+			{
+				a = VertexAttributeSemantic::kPosition;
+			}
+			else if(r.name == ANKI_ATTRIB_NAME(NORMAL))
+			{
+				a = VertexAttributeSemantic::kNormal;
+			}
+			else if(r.name == ANKI_ATTRIB_NAME(TEXCOORD0) || r.name == ANKI_ATTRIB_NAME(TEXCOORD))
+			{
+				a = VertexAttributeSemantic::kTexCoord;
+			}
+			else if(r.name == ANKI_ATTRIB_NAME(COLOR))
+			{
+				a = VertexAttributeSemantic::kColor;
+			}
+			else if(r.name == ANKI_ATTRIB_NAME(MISC0) || r.name == ANKI_ATTRIB_NAME(MISC))
+			{
+				a = VertexAttributeSemantic::kMisc0;
+			}
+			else if(r.name == ANKI_ATTRIB_NAME(MISC1))
+			{
+				a = VertexAttributeSemantic::kMisc1;
+			}
+			else if(r.name == ANKI_ATTRIB_NAME(MISC2))
+			{
+				a = VertexAttributeSemantic::kMisc2;
+			}
+			else if(r.name == ANKI_ATTRIB_NAME(MISC3))
+			{
+				a = VertexAttributeSemantic::kMisc3;
+			}
+			else
+			{
+				errorStr.sprintf("Unexpected attribute name: %s", r.name.c_str());
+				return Error::kUserData;
+			}
+#undef ANKI_ATTRIB_NAME
+
+			refl.m_vertex.m_vertexAttributeMask |= VertexAttributeSemanticBit(1 << a);
+
+			const U32 id = r.id;
+			const U32 location = spvc.get_decoration(id, spv::Decoration::DecorationLocation);
+			if(location > kMaxU8)
+			{
+				errorStr.sprintf("Too high location value for attribute: %s", r.name.c_str());
+				return Error::kUserData;
+			}
+
+			refl.m_vertex.m_vkVertexAttributeLocations[a] = U8(location);
+		}
+	}
+
+	// Discards?
+	if(type == ShaderType::kPixel)
+	{
+		visitSpirv(ConstWeakArray<U32>(reinterpret_cast<const U32*>(&spirv[0]), spirv.getSize() / sizeof(U32)),
+				   [&](U32 cmd, [[maybe_unused]] ConstWeakArray<U32> instructions) {
+					   if(cmd == spv::OpKill)
+					   {
+						   refl.m_pixel.m_discards = true;
+					   }
+				   });
+	}
+
+	return Error::kNone;
+}
+
+} // end namespace anki

+ 20 - 0
AnKi/ShaderCompiler/Spirv.h

@@ -0,0 +1,20 @@
+// Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#pragma once
+
+#include <AnKi/ShaderCompiler/Common.h>
+#include <AnKi/Util/String.h>
+#include <AnKi/Util/WeakArray.h>
+
+namespace anki {
+
+/// @addtogroup shader_compiler
+/// @{
+
+Error doReflectionSpirv(ConstWeakArray<U8> spirv, ShaderType type, ShaderReflection& refl, ShaderCompilerString& errorStr);
+/// @}
+
+} // end namespace anki

BIN
ThirdParty/Bin/Linux64/dxc.bin


BIN
ThirdParty/Bin/Windows64/dxc.exe


BIN
ThirdParty/Bin/Windows64/dxil.dll


+ 1039 - 0
ThirdParty/Dxc/WinAdapter.h

@@ -0,0 +1,1039 @@
+//===- WinAdapter.h - Windows Adapter for non-Windows platforms -*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines Windows-specific types, macros, and SAL annotations used
+// in the codebase for non-Windows platforms.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_WIN_ADAPTER_H
+#define LLVM_SUPPORT_WIN_ADAPTER_H
+
+#ifndef _WIN32
+
+#ifdef __cplusplus
+#include <atomic>
+#include <cassert>
+#include <climits>
+#include <cstring>
+#include <cwchar>
+#include <fstream>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string>
+#include <typeindex>
+#include <typeinfo>
+#include <vector>
+#endif // __cplusplus
+
+#define COM_NO_WINDOWS_H // needed to inform d3d headers that this isn't windows
+
+//===----------------------------------------------------------------------===//
+//
+//                             Begin: Macro Definitions
+//
+//===----------------------------------------------------------------------===//
+#define C_ASSERT(expr) static_assert((expr), "")
+#define ATLASSERT assert
+
+#define CoTaskMemAlloc malloc
+#define CoTaskMemFree free
+
+#define ARRAYSIZE(array) (sizeof(array) / sizeof(array[0]))
+
+#define _countof(a) (sizeof(a) / sizeof(*(a)))
+
+// If it is GCC, there is no UUID support and we must emulate it.
+#ifndef __clang__
+#define __EMULATE_UUID 1
+#endif // __clang__
+
+#ifdef __EMULATE_UUID
+#define __declspec(x)
+#endif // __EMULATE_UUID
+
+#define DECLSPEC_SELECTANY
+
+#ifdef __EMULATE_UUID
+#define uuid(id)
+#endif // __EMULATE_UUID
+
+#define STDMETHODCALLTYPE
+#define STDMETHODIMP_(type) type STDMETHODCALLTYPE
+#define STDMETHODIMP STDMETHODIMP_(HRESULT)
+#define STDMETHOD_(type, name) virtual STDMETHODIMP_(type) name
+#define STDMETHOD(name) STDMETHOD_(HRESULT, name)
+#define EXTERN_C extern "C"
+
+#define UNREFERENCED_PARAMETER(P) (void)(P)
+
+#define RtlEqualMemory(Destination, Source, Length)                            \
+  (!memcmp((Destination), (Source), (Length)))
+#define RtlMoveMemory(Destination, Source, Length)                             \
+  memmove((Destination), (Source), (Length))
+#define RtlCopyMemory(Destination, Source, Length)                             \
+  memcpy((Destination), (Source), (Length))
+#define RtlFillMemory(Destination, Length, Fill)                               \
+  memset((Destination), (Fill), (Length))
+#define RtlZeroMemory(Destination, Length) memset((Destination), 0, (Length))
+#define MoveMemory RtlMoveMemory
+#define CopyMemory RtlCopyMemory
+#define FillMemory RtlFillMemory
+#define ZeroMemory RtlZeroMemory
+
+#define FALSE 0
+#define TRUE 1
+
+// We ignore the code page completely on Linux.
+#define GetConsoleOutputCP() 0
+
+#define _HRESULT_TYPEDEF_(_sc) ((HRESULT)_sc)
+#define DISP_E_BADINDEX _HRESULT_TYPEDEF_(0x8002000BL)
+#define REGDB_E_CLASSNOTREG _HRESULT_TYPEDEF_(0x80040154L)
+
+// This is an unsafe conversion. If needed, we can later implement a safe
+// conversion that throws exceptions for overflow cases.
+#define UIntToInt(uint_arg, int_ptr_arg) *int_ptr_arg = uint_arg
+
+#define INVALID_HANDLE_VALUE ((HANDLE)(LONG_PTR)-1)
+
+// Use errno to implement {Get|Set}LastError
+#define GetLastError() errno
+#define SetLastError(ERR) errno = ERR
+
+// Map these errors to equivalent errnos.
+#define ERROR_SUCCESS 0L
+#define ERROR_ARITHMETIC_OVERFLOW EOVERFLOW
+#define ERROR_FILE_NOT_FOUND ENOENT
+#define ERROR_FUNCTION_NOT_CALLED ENOSYS
+#define ERROR_IO_DEVICE EIO
+#define ERROR_INSUFFICIENT_BUFFER ENOBUFS
+#define ERROR_INVALID_HANDLE EBADF
+#define ERROR_INVALID_PARAMETER EINVAL
+#define ERROR_OUT_OF_STRUCTURES ENOMEM
+#define ERROR_NOT_CAPABLE EPERM
+#define ERROR_NOT_FOUND ENOTSUP
+#define ERROR_UNHANDLED_EXCEPTION EBADF
+#define ERROR_BROKEN_PIPE EPIPE
+
+// Used by HRESULT <--> WIN32 error code conversion
+#define SEVERITY_ERROR 1
+#define FACILITY_WIN32 7
+#define HRESULT_CODE(hr) ((hr) & 0xFFFF)
+#define MAKE_HRESULT(severity, facility, code)                                 \
+  ((HRESULT)(((unsigned long)(severity) << 31) |                               \
+             ((unsigned long)(facility) << 16) | ((unsigned long)(code))))
+
+#define FILE_TYPE_UNKNOWN 0x0000
+#define FILE_TYPE_DISK 0x0001
+#define FILE_TYPE_CHAR 0x0002
+#define FILE_TYPE_PIPE 0x0003
+#define FILE_TYPE_REMOTE 0x8000
+
+#define FILE_ATTRIBUTE_NORMAL 0x00000080
+#define FILE_ATTRIBUTE_DIRECTORY 0x00000010
+#define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
+
+#define STDOUT_FILENO 1
+#define STDERR_FILENO 2
+
+// STGTY ENUMS
+#define STGTY_STORAGE 1
+#define STGTY_STREAM 2
+#define STGTY_LOCKBYTES 3
+#define STGTY_PROPERTY 4
+
+// Storage errors
+#define STG_E_INVALIDFUNCTION 1L
+#define STG_E_ACCESSDENIED 2L
+
+#define STREAM_SEEK_SET 0
+#define STREAM_SEEK_CUR 1
+#define STREAM_SEEK_END 2
+
+#define HEAP_NO_SERIALIZE 0x1
+#define HEAP_ZERO_MEMORY 0x8
+
+#define MB_ERR_INVALID_CHARS 0x00000008 // error for invalid chars
+
+// File IO
+
+#define CREATE_ALWAYS 2
+#define CREATE_NEW 1
+#define OPEN_ALWAYS 4
+#define OPEN_EXISTING 3
+#define TRUNCATE_EXISTING 5
+
+#define FILE_SHARE_DELETE 0x00000004
+#define FILE_SHARE_READ 0x00000001
+#define FILE_SHARE_WRITE 0x00000002
+
+#define GENERIC_READ 0x80000000
+#define GENERIC_WRITE 0x40000000
+
+#define _atoi64 atoll
+#define sprintf_s snprintf
+#define _strdup strdup
+#define _strnicmp strnicmp
+
+#define vsnprintf_s vsnprintf
+#define strcat_s strcat
+#define strcpy_s(dst, n, src) strncpy(dst, src, n)
+#define _vscwprintf vwprintf
+#define vswprintf_s vswprintf
+#define swprintf_s swprintf
+
+#define StringCchCopyW(dst, n, src) wcsncpy(dst, src, n)
+
+#define OutputDebugStringW(msg) fputws(msg, stderr)
+
+#define OutputDebugStringA(msg) fputs(msg, stderr)
+#define OutputDebugFormatA(...) fprintf(stderr, __VA_ARGS__)
+
+// Event Tracing for Windows (ETW) provides application programmers the ability
+// to start and stop event tracing sessions, instrument an application to
+// provide trace events, and consume trace events.
+#define DxcEtw_DXCompilerCreateInstance_Start()
+#define DxcEtw_DXCompilerCreateInstance_Stop(hr)
+#define DxcEtw_DXCompilerCompile_Start()
+#define DxcEtw_DXCompilerCompile_Stop(hr)
+#define DxcEtw_DXCompilerDisassemble_Start()
+#define DxcEtw_DXCompilerDisassemble_Stop(hr)
+#define DxcEtw_DXCompilerPreprocess_Start()
+#define DxcEtw_DXCompilerPreprocess_Stop(hr)
+#define DxcEtw_DxcValidation_Start()
+#define DxcEtw_DxcValidation_Stop(hr)
+
+#define UInt32Add UIntAdd
+#define Int32ToUInt32 IntToUInt
+
+//===--------------------- HRESULT Related Macros -------------------------===//
+
+#define S_OK ((HRESULT)0L)
+#define S_FALSE ((HRESULT)1L)
+
+#define E_ABORT (HRESULT)0x80004004
+#define E_ACCESSDENIED (HRESULT)0x80070005
+#define E_BOUNDS (HRESULT)0x8000000B
+#define E_FAIL (HRESULT)0x80004005
+#define E_HANDLE (HRESULT)0x80070006
+#define E_INVALIDARG (HRESULT)0x80070057
+#define E_NOINTERFACE (HRESULT)0x80004002
+#define E_NOTIMPL (HRESULT)0x80004001
+#define E_NOT_VALID_STATE (HRESULT)0x8007139F
+#define E_OUTOFMEMORY (HRESULT)0x8007000E
+#define E_POINTER (HRESULT)0x80004003
+#define E_UNEXPECTED (HRESULT)0x8000FFFF
+
+#define SUCCEEDED(hr) (((HRESULT)(hr)) >= 0)
+#define FAILED(hr) (((HRESULT)(hr)) < 0)
+#define DXC_FAILED(hr) (((HRESULT)(hr)) < 0)
+
+#define HRESULT_FROM_WIN32(x)                                                  \
+  (HRESULT)(x) <= 0 ? (HRESULT)(x)                                             \
+                    : (HRESULT)(((x) & 0x0000FFFF) | (7 << 16) | 0x80000000)
+
+//===----------------------------------------------------------------------===//
+//
+//                         Begin: Disable SAL Annotations
+//
+//===----------------------------------------------------------------------===//
+#define _In_
+#define _In_z_
+#define _In_opt_
+#define _In_opt_count_(size)
+#define _In_opt_z_
+#define _In_count_(size)
+#define _In_bytecount_(size)
+
+#define _Out_
+#define _Out_opt_
+#define _Outptr_
+#define _Outptr_opt_
+#define _Outptr_result_z_
+#define _Outptr_opt_result_z_
+#define _Outptr_result_maybenull_
+#define _Outptr_result_nullonfailure_
+#define _Outptr_result_buffer_maybenull_(ptr)
+#define _Outptr_result_buffer_(ptr)
+
+#define _COM_Outptr_
+#define _COM_Outptr_opt_
+#define _COM_Outptr_result_maybenull_
+#define _COM_Outptr_opt_result_maybenull_
+
+#define THIS_
+#define THIS
+#define PURE = 0
+
+#define _Maybenull_
+
+#define __debugbreak()
+
+// GCC produces erros on calling convention attributes.
+#ifdef __GNUC__
+#define __cdecl
+#define __CRTDECL
+#define __stdcall
+#define __vectorcall
+#define __thiscall
+#define __fastcall
+#define __clrcall
+#endif // __GNUC__
+
+//===----------------------------------------------------------------------===//
+//
+//                             Begin: Type Definitions
+//
+//===----------------------------------------------------------------------===//
+
+#ifdef __cplusplus
+
+typedef unsigned char BYTE, UINT8;
+typedef unsigned char *LPBYTE;
+
+typedef BYTE BOOLEAN;
+typedef BOOLEAN *PBOOLEAN;
+
+typedef bool BOOL;
+typedef BOOL *LPBOOL;
+
+typedef int INT;
+typedef long LONG;
+typedef unsigned int UINT;
+typedef unsigned long ULONG;
+typedef long long LONGLONG;
+typedef long long LONG_PTR;
+typedef unsigned long long ULONG_PTR;
+typedef unsigned long long ULONGLONG;
+
+typedef uint16_t WORD;
+typedef uint32_t DWORD;
+typedef DWORD *LPDWORD;
+
+typedef uint32_t UINT32;
+typedef uint64_t UINT64;
+
+typedef signed char INT8, *PINT8;
+typedef signed int INT32, *PINT32;
+
+typedef size_t SIZE_T;
+typedef const char *LPCSTR;
+typedef const char *PCSTR;
+
+typedef int errno_t;
+
+typedef wchar_t WCHAR;
+typedef wchar_t *LPWSTR;
+typedef wchar_t *PWCHAR;
+typedef const wchar_t *LPCWSTR;
+typedef const wchar_t *PCWSTR;
+
+typedef WCHAR OLECHAR;
+typedef OLECHAR *BSTR;
+typedef OLECHAR *LPOLESTR;
+typedef char *LPSTR;
+
+typedef void *LPVOID;
+typedef const void *LPCVOID;
+
+typedef std::nullptr_t nullptr_t;
+
+typedef signed int HRESULT;
+
+//===--------------------- Handle Types -----------------------------------===//
+
+typedef void *HANDLE;
+typedef void *RPC_IF_HANDLE;
+
+#define DECLARE_HANDLE(name)                                                   \
+  struct name##__ {                                                            \
+    int unused;                                                                \
+  };                                                                           \
+  typedef struct name##__ *name
+DECLARE_HANDLE(HINSTANCE);
+
+typedef void *HMODULE;
+
+#define STD_INPUT_HANDLE ((DWORD)-10)
+#define STD_OUTPUT_HANDLE ((DWORD)-11)
+#define STD_ERROR_HANDLE ((DWORD)-12)
+
+//===--------------------- ID Types and Macros for COM --------------------===//
+
+#ifdef __EMULATE_UUID
+struct GUID
+#else  // __EMULATE_UUID
+// These specific definitions are required by clang -fms-extensions.
+typedef struct _GUID
+#endif // __EMULATE_UUID
+{
+  uint32_t Data1;
+  uint16_t Data2;
+  uint16_t Data3;
+  uint8_t Data4[8];
+}
+#ifdef __EMULATE_UUID
+;
+#else  // __EMULATE_UUID
+GUID;
+#endif // __EMULATE_UUID
+typedef GUID CLSID;
+typedef const GUID &REFGUID;
+typedef const GUID &REFCLSID;
+
+typedef GUID IID;
+typedef IID *LPIID;
+typedef const IID &REFIID;
+inline bool IsEqualGUID(REFGUID rguid1, REFGUID rguid2) {
+  // Optimization:
+  if (&rguid1 == &rguid2)
+    return true;
+
+  return !memcmp(&rguid1, &rguid2, sizeof(GUID));
+}
+
+inline bool operator==(REFGUID guidOne, REFGUID guidOther) {
+  return !!IsEqualGUID(guidOne, guidOther);
+}
+
+inline bool operator!=(REFGUID guidOne, REFGUID guidOther) {
+  return !(guidOne == guidOther);
+}
+
+inline bool IsEqualIID(REFIID riid1, REFIID riid2) {
+  return IsEqualGUID(riid1, riid2);
+}
+
+inline bool IsEqualCLSID(REFCLSID rclsid1, REFCLSID rclsid2) {
+  return IsEqualGUID(rclsid1, rclsid2);
+}
+
+//===--------------------- Struct Types -----------------------------------===//
+
+typedef struct _FILETIME {
+  DWORD dwLowDateTime;
+  DWORD dwHighDateTime;
+} FILETIME, *PFILETIME, *LPFILETIME;
+
+typedef struct _BY_HANDLE_FILE_INFORMATION {
+  DWORD dwFileAttributes;
+  FILETIME ftCreationTime;
+  FILETIME ftLastAccessTime;
+  FILETIME ftLastWriteTime;
+  DWORD dwVolumeSerialNumber;
+  DWORD nFileSizeHigh;
+  DWORD nFileSizeLow;
+  DWORD nNumberOfLinks;
+  DWORD nFileIndexHigh;
+  DWORD nFileIndexLow;
+} BY_HANDLE_FILE_INFORMATION, *PBY_HANDLE_FILE_INFORMATION,
+    *LPBY_HANDLE_FILE_INFORMATION;
+
+typedef struct _WIN32_FIND_DATAW {
+  DWORD dwFileAttributes;
+  FILETIME ftCreationTime;
+  FILETIME ftLastAccessTime;
+  FILETIME ftLastWriteTime;
+  DWORD nFileSizeHigh;
+  DWORD nFileSizeLow;
+  DWORD dwReserved0;
+  DWORD dwReserved1;
+  WCHAR cFileName[260];
+  WCHAR cAlternateFileName[14];
+} WIN32_FIND_DATAW, *PWIN32_FIND_DATAW, *LPWIN32_FIND_DATAW;
+
+typedef union _LARGE_INTEGER {
+  struct {
+    DWORD LowPart;
+    DWORD HighPart;
+  } u;
+  LONGLONG QuadPart;
+} LARGE_INTEGER;
+
+typedef LARGE_INTEGER *PLARGE_INTEGER;
+
+typedef union _ULARGE_INTEGER {
+  struct {
+    DWORD LowPart;
+    DWORD HighPart;
+  } u;
+  ULONGLONG QuadPart;
+} ULARGE_INTEGER;
+
+typedef ULARGE_INTEGER *PULARGE_INTEGER;
+
+typedef struct tagSTATSTG {
+  LPOLESTR pwcsName;
+  DWORD type;
+  ULARGE_INTEGER cbSize;
+  FILETIME mtime;
+  FILETIME ctime;
+  FILETIME atime;
+  DWORD grfMode;
+  DWORD grfLocksSupported;
+  CLSID clsid;
+  DWORD grfStateBits;
+  DWORD reserved;
+} STATSTG;
+
+enum tagSTATFLAG {
+  STATFLAG_DEFAULT = 0,
+  STATFLAG_NONAME = 1,
+  STATFLAG_NOOPEN = 2
+};
+
+//===--------------------- UUID Related Macros ----------------------------===//
+
+#ifdef __EMULATE_UUID
+
+// The following macros are defined to facilitate the lack of 'uuid' on Linux.
+
+constexpr uint8_t nybble_from_hex(char c) {
+  return ((c >= '0' && c <= '9')
+              ? (c - '0')
+              : ((c >= 'a' && c <= 'f')
+                     ? (c - 'a' + 10)
+                     : ((c >= 'A' && c <= 'F') ? (c - 'A' + 10)
+                                               : /* Should be an error */ -1)));
+}
+
+constexpr uint8_t byte_from_hex(char c1, char c2) {
+  return nybble_from_hex(c1) << 4 | nybble_from_hex(c2);
+}
+
+constexpr uint8_t byte_from_hexstr(const char str[2]) {
+  return nybble_from_hex(str[0]) << 4 | nybble_from_hex(str[1]);
+}
+
+constexpr GUID guid_from_string(const char str[37]) {
+  return GUID{static_cast<uint32_t>(byte_from_hexstr(str)) << 24 |
+                  static_cast<uint32_t>(byte_from_hexstr(str + 2)) << 16 |
+                  static_cast<uint32_t>(byte_from_hexstr(str + 4)) << 8 |
+                  byte_from_hexstr(str + 6),
+              static_cast<uint16_t>(
+                  static_cast<uint16_t>(byte_from_hexstr(str + 9)) << 8 |
+                  byte_from_hexstr(str + 11)),
+              static_cast<uint16_t>(
+                  static_cast<uint16_t>(byte_from_hexstr(str + 14)) << 8 |
+                  byte_from_hexstr(str + 16)),
+              {byte_from_hexstr(str + 19), byte_from_hexstr(str + 21),
+               byte_from_hexstr(str + 24), byte_from_hexstr(str + 26),
+               byte_from_hexstr(str + 28), byte_from_hexstr(str + 30),
+               byte_from_hexstr(str + 32), byte_from_hexstr(str + 34)}};
+}
+
+template <typename interface> inline GUID __emulated_uuidof();
+
+#define CROSS_PLATFORM_UUIDOF(interface, spec)                                 \
+  struct interface;                                                            \
+  template <> inline GUID __emulated_uuidof<interface>() {                     \
+    static const IID _IID = guid_from_string(spec);                            \
+    return _IID;                                                               \
+  }
+
+#define __uuidof(T) __emulated_uuidof<typename std::decay<T>::type>()
+
+#define IID_PPV_ARGS(ppType)                                                   \
+  __uuidof(decltype(**(ppType))), reinterpret_cast<void **>(ppType)
+
+#else // __EMULATE_UUID
+
+#ifndef CROSS_PLATFORM_UUIDOF
+// Warning: This macro exists in dxcapi.h as well
+#define CROSS_PLATFORM_UUIDOF(interface, spec)                                 \
+  struct __declspec(uuid(spec)) interface;
+#endif
+
+template <typename T> inline void **IID_PPV_ARGS_Helper(T **pp) {
+  return reinterpret_cast<void **>(pp);
+}
+#define IID_PPV_ARGS(ppType) __uuidof(**(ppType)), IID_PPV_ARGS_Helper(ppType)
+
+#endif // __EMULATE_UUID
+
+// Needed for d3d headers, but fail to create actual interfaces
+#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8)           \
+  const GUID name = {l, w1, w2, {b1, b2, b3, b4, b5, b6, b7, b8}}
+#define DECLSPEC_UUID(x)
+#define MIDL_INTERFACE(x) struct DECLSPEC_UUID(x)
+#define DECLARE_INTERFACE(iface) struct iface
+#define DECLARE_INTERFACE_(iface, parent) DECLARE_INTERFACE(iface) : parent
+
+//===--------------------- COM Interfaces ---------------------------------===//
+
+CROSS_PLATFORM_UUIDOF(IUnknown, "00000000-0000-0000-C000-000000000046")
+struct IUnknown {
+  IUnknown(){};
+  virtual HRESULT QueryInterface(REFIID riid, void **ppvObject) = 0;
+  virtual ULONG AddRef() = 0;
+  virtual ULONG Release() = 0;
+  template <class Q> HRESULT QueryInterface(Q **pp) {
+    return QueryInterface(__uuidof(Q), (void **)pp);
+  }
+};
+
+CROSS_PLATFORM_UUIDOF(INoMarshal, "ECC8691B-C1DB-4DC0-855E-65F6C551AF49")
+struct INoMarshal : public IUnknown {};
+
+CROSS_PLATFORM_UUIDOF(IMalloc, "00000002-0000-0000-C000-000000000046")
+struct IMalloc : public IUnknown {
+  virtual void *Alloc(SIZE_T size) = 0;
+  virtual void *Realloc(void *ptr, SIZE_T size) = 0;
+  virtual void Free(void *ptr) = 0;
+  virtual SIZE_T GetSize(void *pv) = 0;
+  virtual int DidAlloc(void *pv) = 0;
+  virtual void HeapMinimize(void) = 0;
+};
+
+CROSS_PLATFORM_UUIDOF(ISequentialStream, "0C733A30-2A1C-11CE-ADE5-00AA0044773D")
+struct ISequentialStream : public IUnknown {
+  virtual HRESULT Read(void *pv, ULONG cb, ULONG *pcbRead) = 0;
+  virtual HRESULT Write(const void *pv, ULONG cb, ULONG *pcbWritten) = 0;
+};
+
+CROSS_PLATFORM_UUIDOF(IStream, "0000000c-0000-0000-C000-000000000046")
+struct IStream : public ISequentialStream {
+  virtual HRESULT Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin,
+                       ULARGE_INTEGER *plibNewPosition) = 0;
+  virtual HRESULT SetSize(ULARGE_INTEGER libNewSize) = 0;
+  virtual HRESULT CopyTo(IStream *pstm, ULARGE_INTEGER cb,
+                         ULARGE_INTEGER *pcbRead,
+                         ULARGE_INTEGER *pcbWritten) = 0;
+
+  virtual HRESULT Commit(DWORD grfCommitFlags) = 0;
+
+  virtual HRESULT Revert(void) = 0;
+
+  virtual HRESULT LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb,
+                             DWORD dwLockType) = 0;
+
+  virtual HRESULT UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb,
+                               DWORD dwLockType) = 0;
+
+  virtual HRESULT Stat(STATSTG *pstatstg, DWORD grfStatFlag) = 0;
+
+  virtual HRESULT Clone(IStream **ppstm) = 0;
+};
+
+// These don't need stub implementations as they come from the DirectX Headers
+// They still need the __uuidof() though
+CROSS_PLATFORM_UUIDOF(ID3D12LibraryReflection,
+                      "8E349D19-54DB-4A56-9DC9-119D87BDB804")
+CROSS_PLATFORM_UUIDOF(ID3D12ShaderReflection,
+                      "5A58797D-A72C-478D-8BA2-EFC6B0EFE88E")
+
+//===--------------------- COM Pointer Types ------------------------------===//
+
+class CAllocator {
+public:
+  static void *Reallocate(void *p, size_t nBytes) throw();
+  static void *Allocate(size_t nBytes) throw();
+  static void Free(void *p) throw();
+};
+
+template <class T> class CComPtrBase {
+protected:
+  CComPtrBase() throw() { p = nullptr; }
+  CComPtrBase(T *lp) throw() {
+    p = lp;
+    if (p != nullptr)
+      p->AddRef();
+  }
+  void Swap(CComPtrBase &other) {
+    T *pTemp = p;
+    p = other.p;
+    other.p = pTemp;
+  }
+
+public:
+  ~CComPtrBase() throw() {
+    if (p) {
+      p->Release();
+      p = nullptr;
+    }
+  }
+  operator T *() const throw() { return p; }
+  T &operator*() const { return *p; }
+  T *operator->() const { return p; }
+  T **operator&() throw() {
+    assert(p == nullptr);
+    return &p;
+  }
+  bool operator!() const throw() { return (p == nullptr); }
+  bool operator<(T *pT) const throw() { return p < pT; }
+  bool operator!=(T *pT) const { return !operator==(pT); }
+  bool operator==(T *pT) const throw() { return p == pT; }
+
+  // Release the interface and set to nullptr
+  void Release() throw() {
+    T *pTemp = p;
+    if (pTemp) {
+      p = nullptr;
+      pTemp->Release();
+    }
+  }
+
+  // Attach to an existing interface (does not AddRef)
+  void Attach(T *p2) throw() {
+    if (p) {
+      ULONG ref = p->Release();
+      (void)(ref);
+      // Attaching to the same object only works if duplicate references are
+      // being coalesced.  Otherwise re-attaching will cause the pointer to be
+      // released and may cause a crash on a subsequent dereference.
+      assert(ref != 0 || p2 != p);
+    }
+    p = p2;
+  }
+
+  // Detach the interface (does not Release)
+  T *Detach() throw() {
+    T *pt = p;
+    p = nullptr;
+    return pt;
+  }
+
+  HRESULT CopyTo(T **ppT) throw() {
+    assert(ppT != nullptr);
+    if (ppT == nullptr)
+      return E_POINTER;
+    *ppT = p;
+    if (p)
+      p->AddRef();
+    return S_OK;
+  }
+
+  template <class Q> HRESULT QueryInterface(Q **pp) const throw() {
+    assert(pp != nullptr);
+    return p->QueryInterface(__uuidof(Q), (void **)pp);
+  }
+
+  T *p;
+};
+
+template <class T> class CComPtr : public CComPtrBase<T> {
+public:
+  CComPtr() throw() {}
+  CComPtr(T *lp) throw() : CComPtrBase<T>(lp) {}
+  CComPtr(const CComPtr<T> &lp) throw() : CComPtrBase<T>(lp.p) {}
+  T *operator=(T *lp) throw() {
+    if (*this != lp) {
+      CComPtr(lp).Swap(*this);
+    }
+    return *this;
+  }
+
+  inline bool IsEqualObject(IUnknown *pOther) throw() {
+    if (this->p == nullptr && pOther == nullptr)
+      return true; // They are both NULL objects
+
+    if (this->p == nullptr || pOther == nullptr)
+      return false; // One is NULL the other is not
+
+    CComPtr<IUnknown> punk1;
+    CComPtr<IUnknown> punk2;
+    this->p->QueryInterface(__uuidof(IUnknown), (void **)&punk1);
+    pOther->QueryInterface(__uuidof(IUnknown), (void **)&punk2);
+    return punk1 == punk2;
+  }
+
+  void ComPtrAssign(IUnknown **pp, IUnknown *lp, REFIID riid) {
+    IUnknown *pTemp = *pp; // takes ownership
+    if (lp == nullptr || FAILED(lp->QueryInterface(riid, (void **)pp)))
+      *pp = nullptr;
+    if (pTemp)
+      pTemp->Release();
+  }
+
+  template <typename Q> T *operator=(const CComPtr<Q> &lp) throw() {
+    if (!this->IsEqualObject(lp)) {
+      ComPtrAssign((IUnknown **)&this->p, lp, __uuidof(T));
+    }
+    return *this;
+  }
+
+  // NOTE: This conversion constructor is not part of the official CComPtr spec;
+  // however, it is needed to convert CComPtr<Q> to CComPtr<T> where T derives
+  // from Q on Clang. MSVC compiles this conversion as first a call to
+  // CComPtr<Q>::operator T*, followed by CComPtr<T>(T*), but Clang fails to
+  // compile with error: no viable conversion from 'CComPtr<Q>' to 'CComPtr<T>'.
+  template <typename Q>
+  CComPtr(const CComPtr<Q> &lp) throw() : CComPtrBase<T>(lp.p) {}
+
+  T *operator=(const CComPtr<T> &lp) throw() {
+    if (*this != lp) {
+      CComPtr(lp).Swap(*this);
+    }
+    return *this;
+  }
+
+  CComPtr(CComPtr<T> &&lp) throw() : CComPtrBase<T>() { lp.Swap(*this); }
+
+  T *operator=(CComPtr<T> &&lp) throw() {
+    if (*this != lp) {
+      CComPtr(static_cast<CComPtr &&>(lp)).Swap(*this);
+    }
+    return *this;
+  }
+};
+
+template <class T> class CSimpleArray : public std::vector<T> {
+public:
+  bool Add(const T &t) {
+    this->push_back(t);
+    return true;
+  }
+  int GetSize() { return this->size(); }
+  T *GetData() { return this->data(); }
+  void RemoveAll() { this->clear(); }
+};
+
+template <class T, class Allocator = CAllocator> class CHeapPtrBase {
+protected:
+  CHeapPtrBase() throw() : m_pData(NULL) {}
+  CHeapPtrBase(CHeapPtrBase<T, Allocator> &p) throw() {
+    m_pData = p.Detach(); // Transfer ownership
+  }
+  explicit CHeapPtrBase(T *pData) throw() : m_pData(pData) {}
+
+public:
+  ~CHeapPtrBase() throw() { Free(); }
+
+protected:
+  CHeapPtrBase<T, Allocator> &operator=(CHeapPtrBase<T, Allocator> &p) throw() {
+    if (m_pData != p.m_pData)
+      Attach(p.Detach()); // Transfer ownership
+    return *this;
+  }
+
+public:
+  operator T *() const throw() { return m_pData; }
+  T *operator->() const throw() {
+    assert(m_pData != NULL);
+    return m_pData;
+  }
+
+  T **operator&() throw() {
+    assert(m_pData == NULL);
+    return &m_pData;
+  }
+
+  // Allocate a buffer with the given number of bytes
+  bool AllocateBytes(size_t nBytes) throw() {
+    assert(m_pData == NULL);
+    m_pData = static_cast<T *>(Allocator::Allocate(nBytes * sizeof(char)));
+    if (m_pData == NULL)
+      return false;
+
+    return true;
+  }
+
+  // Attach to an existing pointer (takes ownership)
+  void Attach(T *pData) throw() {
+    Allocator::Free(m_pData);
+    m_pData = pData;
+  }
+
+  // Detach the pointer (releases ownership)
+  T *Detach() throw() {
+    T *pTemp = m_pData;
+    m_pData = NULL;
+    return pTemp;
+  }
+
+  // Free the memory pointed to, and set the pointer to NULL
+  void Free() throw() {
+    Allocator::Free(m_pData);
+    m_pData = NULL;
+  }
+
+  // Reallocate the buffer to hold a given number of bytes
+  bool ReallocateBytes(size_t nBytes) throw() {
+    T *pNew;
+    pNew =
+        static_cast<T *>(Allocator::Reallocate(m_pData, nBytes * sizeof(char)));
+    if (pNew == NULL)
+      return false;
+    m_pData = pNew;
+
+    return true;
+  }
+
+public:
+  T *m_pData;
+};
+
+template <typename T, class Allocator = CAllocator>
+class CHeapPtr : public CHeapPtrBase<T, Allocator> {
+public:
+  CHeapPtr() throw() {}
+  CHeapPtr(CHeapPtr<T, Allocator> &p) throw() : CHeapPtrBase<T, Allocator>(p) {}
+  explicit CHeapPtr(T *p) throw() : CHeapPtrBase<T, Allocator>(p) {}
+  CHeapPtr<T> &operator=(CHeapPtr<T, Allocator> &p) throw() {
+    CHeapPtrBase<T, Allocator>::operator=(p);
+    return *this;
+  }
+
+  // Allocate a buffer with the given number of elements
+  bool Allocate(size_t nElements = 1) throw() {
+    size_t nBytes = nElements * sizeof(T);
+    return this->AllocateBytes(nBytes);
+  }
+
+  // Reallocate the buffer to hold a given number of elements
+  bool Reallocate(size_t nElements) throw() {
+    size_t nBytes = nElements * sizeof(T);
+    return this->ReallocateBytes(nBytes);
+  }
+};
+
+#define CComHeapPtr CHeapPtr
+
+//===--------------------------- BSTR Allocation --------------------------===//
+
+void SysFreeString(BSTR bstrString);
+// Allocate string with length prefix
+BSTR SysAllocStringLen(const OLECHAR *strIn, UINT ui);
+
+//===--------------------------- BSTR Length ------------------------------===//
+unsigned int SysStringLen(const BSTR bstrString);
+
+//===--------------------- UTF-8 Related Types ----------------------------===//
+
+// Code Page
+#define CP_ACP 0
+#define CP_UTF8 65001 // UTF-8 translation.
+
+// RAII style mechanism for setting/unsetting a locale for the specified Windows
+// codepage
+class ScopedLocale {
+  const char *m_prevLocale;
+
+public:
+  explicit ScopedLocale(uint32_t codePage)
+      : m_prevLocale(setlocale(LC_ALL, nullptr)) {
+    assert((codePage == CP_UTF8) &&
+           "Support for Linux only handles UTF8 code pages");
+    setlocale(LC_ALL, "en_US.UTF-8");
+  }
+  ~ScopedLocale() {
+    if (m_prevLocale != nullptr) {
+      setlocale(LC_ALL, m_prevLocale);
+    }
+  }
+};
+
+// The t_nBufferLength parameter is part of the published interface, but not
+// used here.
+template <int t_nBufferLength = 128> class CW2AEX {
+public:
+  CW2AEX(LPCWSTR psz) {
+    ScopedLocale locale(CP_UTF8);
+
+    if (!psz) {
+      m_psz = NULL;
+      return;
+    }
+
+    int len = (wcslen(psz) + 1) * 4;
+    m_psz = new char[len];
+    std::wcstombs(m_psz, psz, len);
+  }
+
+  ~CW2AEX() { delete[] m_psz; }
+
+  operator LPSTR() const { return m_psz; }
+
+  char *m_psz;
+};
+typedef CW2AEX<> CW2A;
+
+// The t_nBufferLength parameter is part of the published interface, but not
+// used here.
+template <int t_nBufferLength = 128> class CA2WEX {
+public:
+  CA2WEX(LPCSTR psz) {
+    ScopedLocale locale(CP_UTF8);
+
+    if (!psz) {
+      m_psz = NULL;
+      return;
+    }
+
+    int len = strlen(psz) + 1;
+    m_psz = new wchar_t[len];
+    std::mbstowcs(m_psz, psz, len);
+  }
+
+  ~CA2WEX() { delete[] m_psz; }
+
+  operator LPWSTR() const { return m_psz; }
+
+  wchar_t *m_psz;
+};
+
+typedef CA2WEX<> CA2W;
+
+//===--------- File IO Related Types ----------------===//
+
+class CHandle {
+public:
+  CHandle(HANDLE h);
+  ~CHandle();
+  operator HANDLE() const throw();
+
+private:
+  HANDLE m_h;
+};
+
+/////////////////////////////////////////////////////////////////////////////
+// CComBSTR
+
+class CComBSTR {
+public:
+  BSTR m_str;
+  CComBSTR() : m_str(nullptr){};
+  CComBSTR(int nSize, LPCWSTR sz);
+  ~CComBSTR() throw() { SysFreeString(m_str); }
+  unsigned int Length() const throw() { return SysStringLen(m_str); }
+  operator BSTR() const throw() { return m_str; }
+
+  bool operator==(const CComBSTR &bstrSrc) const throw();
+
+  BSTR *operator&() throw() { return &m_str; }
+
+  BSTR Detach() throw() {
+    BSTR s = m_str;
+    m_str = NULL;
+    return s;
+  }
+
+  void Empty() throw() {
+    SysFreeString(m_str);
+    m_str = NULL;
+  }
+};
+
+//===--------- Convert argv to wchar ----------------===//
+class WArgV {
+  std::vector<std::wstring> WStringVector;
+  std::vector<const wchar_t *> WCharPtrVector;
+
+public:
+  WArgV(int argc, const char **argv);
+  const wchar_t **argv() { return WCharPtrVector.data(); }
+};
+
+#endif // __cplusplus
+
+#endif // _WIN32
+
+#endif // LLVM_SUPPORT_WIN_ADAPTER_H

BIN
ThirdParty/Dxc/dxc


BIN
ThirdParty/Dxc/dxc.exe


+ 0 - 0
ThirdParty/Bin/Linux64/dxc → ThirdParty/Dxc/dxc.sh


BIN
ThirdParty/Bin/Windows64/dxcompiler.dll → ThirdParty/Dxc/dxcompiler.dll


BIN
ThirdParty/Dxc/dxcompiler.lib


BIN
ThirdParty/Dxc/dxil.dll


BIN
ThirdParty/Bin/Linux64/libdxcompiler.so → ThirdParty/Dxc/libdxcompiler.so


BIN
ThirdParty/Dxc/libdxil.so