// Copyright Epic Games, Inc. All Rights Reserved. #include "VulkanShaderFormat.h" #include "VulkanCommon.h" #include "Modules/ModuleInterface.h" #include "Modules/ModuleManager.h" #include "Interfaces/IShaderFormat.h" #include "Interfaces/IShaderFormatModule.h" #include "hlslcc.h" #include "ShaderCore.h" #include "ShaderCompilerCore.h" #include "DXCWrapper.h" #include "ShaderConductorContext.h" #include "RHIShaderFormatDefinitions.inl" class FShaderFormatVulkan : public IShaderFormat { enum { UE_SHADER_VULKAN_ES3_1_VER = 37, UE_SHADER_VULKAN_SM5_VER = 37, UE_SHADER_VULKAN_SM6_VER = 37, }; int32 InternalGetVersion(FName Format) const { if (Format == NAME_VULKAN_SM6) { return UE_SHADER_VULKAN_SM6_VER; } else if (Format == NAME_VULKAN_SM5 || Format == NAME_VULKAN_SM5_ANDROID) { return UE_SHADER_VULKAN_SM5_VER; } else if (Format == NAME_VULKAN_ES3_1_ANDROID || Format == NAME_VULKAN_ES3_1) { return UE_SHADER_VULKAN_ES3_1_VER; } check(0); return -1; } uint32 ShaderConductorVersionHash; public: FShaderFormatVulkan(uint32 InShaderConductorVersionHash) : ShaderConductorVersionHash(InShaderConductorVersionHash) { } virtual uint32 GetVersion(FName Format) const override { uint32 Version = HashCombine(GetTypeHash(HLSLCC_VersionMajor), GetTypeHash(HLSLCC_VersionMinor)); Version = HashCombine(Version, GetTypeHash(InternalGetVersion(Format))); Version = HashCombine(Version, GetTypeHash(ShaderConductorVersionHash)); #if VULKAN_ENABLE_BINDING_DEBUG_NAMES Version = HashCombine(Version, 0xFC0848E2); #endif #if UE_VULKAN_SHADER_COMPILER_ALLOW_DEAD_CODE_REMOVAL Version = HashCombine(Version, 0x75E2FE85); #endif // UE_VULKAN_SHADER_COMPILER_ALLOW_DEAD_CODE_REMOVAL return Version; } virtual void GetSupportedFormats(TArray& OutFormats) const { OutFormats.Add(NAME_VULKAN_SM5); OutFormats.Add(NAME_VULKAN_ES3_1_ANDROID); OutFormats.Add(NAME_VULKAN_ES3_1); OutFormats.Add(NAME_VULKAN_SM5_ANDROID); OutFormats.Add(NAME_VULKAN_SM6); } virtual void CompileShader(FName Format, const struct FShaderCompilerInput& Input, struct FShaderCompilerOutput& Output,const FString& WorkingDirectory) const { check(InternalGetVersion(Format) >= 0); if (Format == NAME_VULKAN_ES3_1) { DoCompileVulkanShader(Input, Output, WorkingDirectory, EVulkanShaderVersion::ES3_1); } else if (Format == NAME_VULKAN_ES3_1_ANDROID) { DoCompileVulkanShader(Input, Output, WorkingDirectory, EVulkanShaderVersion::ES3_1_ANDROID); } else if (Format == NAME_VULKAN_SM5_ANDROID) { DoCompileVulkanShader(Input, Output, WorkingDirectory, EVulkanShaderVersion::SM5_ANDROID); } else if (Format == NAME_VULKAN_SM5) { DoCompileVulkanShader(Input, Output, WorkingDirectory, EVulkanShaderVersion::SM5); } else if (Format == NAME_VULKAN_SM6) { DoCompileVulkanShader(Input, Output, WorkingDirectory, EVulkanShaderVersion::SM6); } } virtual const TCHAR* GetPlatformIncludeDirectory() const { return TEXT("Vulkan"); } virtual bool UsesHLSLcc(const struct FShaderCompilerInput& Input) const override { return !Input.Environment.CompilerFlags.Contains(CFLAG_ForceDXC); } }; /** * Module for Vulkan shaders */ static IShaderFormat* Singleton = nullptr; class FVulkanShaderFormatModule : public IShaderFormatModule, public FShaderConductorModuleWrapper { public: virtual ~FVulkanShaderFormatModule() { delete Singleton; Singleton = nullptr; } virtual IShaderFormat* GetShaderFormat() { if (!Singleton) { Singleton = new FShaderFormatVulkan(FShaderConductorModuleWrapper::GetModuleVersionHash()); } return Singleton; } virtual void ShutdownModule() override { CrossCompiler::FShaderConductorContext::Shutdown(); } }; IMPLEMENT_MODULE( FVulkanShaderFormatModule, VulkanShaderFormat);