Add custom shader compiler for Xbox Scarlett

This commit is contained in:
Wojtek Figat
2025-11-18 12:07:39 +01:00
parent 7a9c58003d
commit 329ebb6482
10 changed files with 112 additions and 85 deletions

View File

@@ -15,26 +15,32 @@
#include "Editor/ProjectInfo.h" #include "Editor/ProjectInfo.h"
#include "Editor/Utilities/EditorUtilities.h" #include "Editor/Utilities/EditorUtilities.h"
GDKPlatformTools::GDKPlatformTools() String GetGDK()
{ {
// Find GDK String gdk;
Platform::GetEnvironmentVariable(TEXT("GameDKLatest"), _gdkPath); Platform::GetEnvironmentVariable(TEXT("GameDKLatest"), gdk);
if (_gdkPath.IsEmpty() || !FileSystem::DirectoryExists(_gdkPath)) if (gdk.IsEmpty() || !FileSystem::DirectoryExists(gdk))
{ {
_gdkPath.Clear(); gdk.Clear();
Platform::GetEnvironmentVariable(TEXT("GRDKLatest"), _gdkPath); Platform::GetEnvironmentVariable(TEXT("GRDKLatest"), gdk);
if (_gdkPath.IsEmpty() || !FileSystem::DirectoryExists(_gdkPath)) if (gdk.IsEmpty() || !FileSystem::DirectoryExists(gdk))
{ {
_gdkPath.Clear(); gdk.Clear();
} }
else else
{ {
if (_gdkPath.EndsWith(TEXT("GRDK\\"))) if (gdk.EndsWith(TEXT("GRDK\\")))
_gdkPath.Remove(_gdkPath.Length() - 6); gdk.Remove(gdk.Length() - 6);
else if (_gdkPath.EndsWith(TEXT("GRDK"))) else if (gdk.EndsWith(TEXT("GRDK")))
_gdkPath.Remove(_gdkPath.Length() - 5); gdk.Remove(gdk.Length() - 5);
} }
} }
return gdk;
}
GDKPlatformTools::GDKPlatformTools()
{
_gdkPath = GetGDK();
} }
DotNetAOTModes GDKPlatformTools::UseAOT() const DotNetAOTModes GDKPlatformTools::UseAOT() const

View File

@@ -526,6 +526,7 @@ bool ProcessShaderBase(CookAssetsStep::AssetCookData& data, ShaderAssetBase* ass
#if PLATFORM_TOOLS_XBOX_SCARLETT #if PLATFORM_TOOLS_XBOX_SCARLETT
case BuildPlatform::XboxScarlett: case BuildPlatform::XboxScarlett:
{ {
options.Platform = PlatformType::XboxScarlett;
const char* platformDefineName = "PLATFORM_XBOX_SCARLETT"; const char* platformDefineName = "PLATFORM_XBOX_SCARLETT";
COMPILE_PROFILE(DirectX_SM6, SHADER_FILE_CHUNK_INTERNAL_D3D_SM6_CACHE); COMPILE_PROFILE(DirectX_SM6, SHADER_FILE_CHUNK_INTERNAL_D3D_SM6_CACHE);
break; break;

View File

@@ -15,7 +15,6 @@ class MemoryWriteStream;
struct FLAXENGINE_API ShaderCompilationOptions struct FLAXENGINE_API ShaderCompilationOptions
{ {
public: public:
/// <summary> /// <summary>
/// Name of the target object (name of the shader or material for better logging readability) /// Name of the target object (name of the shader or material for better logging readability)
/// </summary> /// </summary>
@@ -37,12 +36,16 @@ public:
uint32 SourceLength = 0; uint32 SourceLength = 0;
public: public:
/// <summary> /// <summary>
/// Target shader profile /// Target shader profile
/// </summary> /// </summary>
ShaderProfile Profile = ShaderProfile::Unknown; ShaderProfile Profile = ShaderProfile::Unknown;
/// <summary>
/// Target platform, set to invalid value of 0 if not used (platform-independent compilation).
/// </summary>
PlatformType Platform = (PlatformType)0;
/// <summary> /// <summary>
/// Disables shaders compiler optimizations. Can be used to debug shaders on a target platform or to speed up the shaders compilation time. /// Disables shaders compiler optimizations. Can be used to debug shaders on a target platform or to speed up the shaders compilation time.
/// </summary> /// </summary>
@@ -64,7 +67,6 @@ public:
Array<ShaderMacro> Macros; Array<ShaderMacro> Macros;
public: public:
/// <summary> /// <summary>
/// Output stream to write compiled shader cache to /// Output stream to write compiled shader cache to
/// </summary> /// </summary>

View File

@@ -196,7 +196,7 @@ bool ShaderCompilerD3D::CompileShader(ShaderFunctionMeta& meta, WritePermutation
default: default:
return true; return true;
} }
if (_profile == ShaderProfile::DirectX_SM5) if (GetProfile() == ShaderProfile::DirectX_SM5)
{ {
profileName += "_5_0"; profileName += "_5_0";
} }

View File

@@ -59,7 +59,8 @@ public:
*ppIncludeSource = nullptr; *ppIncludeSource = nullptr;
const char* source; const char* source;
int32 sourceLength; int32 sourceLength;
const StringAnsi filename(pFilename); StringAnsi filename(pFilename);
filename.Replace('\\', '/');
if (ShaderCompiler::GetIncludedFileSource(_context, "", filename.Get(), source, sourceLength)) if (ShaderCompiler::GetIncludedFileSource(_context, "", filename.Get(), source, sourceLength))
return E_FAIL; return E_FAIL;
IDxcBlobEncoding* textBlob; IDxcBlobEncoding* textBlob;
@@ -70,25 +71,25 @@ public:
} }
}; };
ShaderCompilerDX::ShaderCompilerDX(ShaderProfile profile) ShaderCompilerDX::ShaderCompilerDX(ShaderProfile profile, PlatformType platform, void* dxcCreateInstanceProc)
: ShaderCompiler(profile) : ShaderCompiler(profile, platform)
{ {
IDxcCompiler3* compiler = nullptr; IDxcCompiler3* compiler = nullptr;
IDxcLibrary* library = nullptr; IDxcLibrary* library = nullptr;
IDxcContainerReflection* containerReflection = nullptr; IDxcContainerReflection* containerReflection = nullptr;
if (FAILED(DxcCreateInstance(CLSID_DxcCompiler, __uuidof(compiler), reinterpret_cast<void**>(&compiler))) || DxcCreateInstanceProc createInstance = dxcCreateInstanceProc ? (DxcCreateInstanceProc)dxcCreateInstanceProc : &DxcCreateInstance;
FAILED(DxcCreateInstance(CLSID_DxcLibrary, __uuidof(library), reinterpret_cast<void**>(&library))) || if (FAILED(createInstance(CLSID_DxcCompiler, __uuidof(compiler), reinterpret_cast<void**>(&compiler))) ||
FAILED(DxcCreateInstance(CLSID_DxcContainerReflection, __uuidof(containerReflection), reinterpret_cast<void**>(&containerReflection)))) FAILED(createInstance(CLSID_DxcLibrary, __uuidof(library), reinterpret_cast<void**>(&library))) ||
FAILED(createInstance(CLSID_DxcContainerReflection, __uuidof(containerReflection), reinterpret_cast<void**>(&containerReflection))))
{ {
LOG(Error, "DxcCreateInstance failed"); LOG(Error, "DxcCreateInstance failed");
} }
_compiler = compiler; _compiler = compiler;
_library = library; _library = library;
_containerReflection = containerReflection; _containerReflection = containerReflection;
static bool PrintVersion = true; static HashSet<void*> PrintVersions;
if (PrintVersion) if (PrintVersions.Add(createInstance))
{ {
PrintVersion = false;
IDxcVersionInfo* version = nullptr; IDxcVersionInfo* version = nullptr;
if (compiler && SUCCEEDED(compiler->QueryInterface(__uuidof(version), reinterpret_cast<void**>(&version)))) if (compiler && SUCCEEDED(compiler->QueryInterface(__uuidof(version), reinterpret_cast<void**>(&version))))
{ {
@@ -221,6 +222,7 @@ bool ShaderCompilerDX::CompileShader(ShaderFunctionMeta& meta, WritePermutationD
argsFull.Add(TEXT("-D")); argsFull.Add(TEXT("-D"));
argsFull.Add(*d); argsFull.Add(*d);
} }
GetArgs(argsFull);
// Compile // Compile
ComPtr<IDxcResult> results; ComPtr<IDxcResult> results;

View File

@@ -22,7 +22,9 @@ public:
/// Initializes a new instance of the <see cref="ShaderCompilerDX"/> class. /// Initializes a new instance of the <see cref="ShaderCompilerDX"/> class.
/// </summary> /// </summary>
/// <param name="profile">The profile.</param> /// <param name="profile">The profile.</param>
ShaderCompilerDX(ShaderProfile profile); /// <param name="platform">The platform.</param>
/// <param name="dxcCreateInstanceProc">The custom DXC Compiler factory function.</param>
ShaderCompilerDX(ShaderProfile profile, PlatformType platform = (PlatformType)0, void* dxcCreateInstanceProc = nullptr);
/// <summary> /// <summary>
/// Finalizes an instance of the <see cref="ShaderCompilerDX"/> class. /// Finalizes an instance of the <see cref="ShaderCompilerDX"/> class.
@@ -30,6 +32,10 @@ public:
~ShaderCompilerDX(); ~ShaderCompilerDX();
protected: protected:
virtual void GetArgs(Array<const Char*, InlinedAllocation<250>> args)
{
}
// [ShaderCompiler] // [ShaderCompiler]
bool CompileShader(ShaderFunctionMeta& meta, WritePermutationData customDataWrite = nullptr) override; bool CompileShader(ShaderFunctionMeta& meta, WritePermutationData customDataWrite = nullptr) override;
bool OnCompileBegin() override; bool OnCompileBegin() override;

View File

@@ -23,10 +23,11 @@ public:
}; };
private: private:
ShaderProfile _profile;
PlatformType _platform;
Array<char> _funcNameDefineBuffer; Array<char> _funcNameDefineBuffer;
protected: protected:
ShaderProfile _profile;
ShaderCompilationContext* _context = nullptr; ShaderCompilationContext* _context = nullptr;
Array<ShaderMacro> _globalMacros; Array<ShaderMacro> _globalMacros;
Array<ShaderMacro> _macros; Array<ShaderMacro> _macros;
@@ -37,8 +38,10 @@ public:
/// Initializes a new instance of the <see cref="ShaderCompiler"/> class. /// Initializes a new instance of the <see cref="ShaderCompiler"/> class.
/// </summary> /// </summary>
/// <param name="profile">The profile.</param> /// <param name="profile">The profile.</param>
ShaderCompiler(ShaderProfile profile) /// <param name="platform">The platform.</param>
ShaderCompiler(ShaderProfile profile, PlatformType platform = (PlatformType)0)
: _profile(profile) : _profile(profile)
, _platform(platform)
{ {
} }
@@ -51,12 +54,19 @@ public:
/// <summary> /// <summary>
/// Gets shader profile supported by this compiler. /// Gets shader profile supported by this compiler.
/// </summary> /// </summary>
/// <returns>The shader profile.</returns>
FORCE_INLINE ShaderProfile GetProfile() const FORCE_INLINE ShaderProfile GetProfile() const
{ {
return _profile; return _profile;
} }
/// <summary>
/// Gets target platform supported by this compiler. Returns invalid value of '0' if any platform works.
/// </summary>
FORCE_INLINE PlatformType GetPlatform() const
{
return _platform;
}
/// <summary> /// <summary>
/// Performs the shader compilation. /// Performs the shader compilation.
/// </summary> /// </summary>

View File

@@ -63,6 +63,8 @@ public class ShadersCompilation : EngineModule
options.PrivateDependencies.Add("ShaderCompilerPS4"); options.PrivateDependencies.Add("ShaderCompilerPS4");
if (Sdk.HasValid("PS5Sdk")) if (Sdk.HasValid("PS5Sdk"))
options.PrivateDependencies.Add("ShaderCompilerPS5"); options.PrivateDependencies.Add("ShaderCompilerPS5");
if (Flax.Build.Platform.GetPlatform(TargetPlatform.XboxScarlett, true) != null)
options.PrivateDependencies.Add("ShaderCompilerXboxScarlett");
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@@ -48,6 +48,9 @@
#if COMPILE_WITH_PS5_SHADER_COMPILER #if COMPILE_WITH_PS5_SHADER_COMPILER
#include "Platforms/PS5/Engine/ShaderCompilerPS5/ShaderCompilerPS5.h" #include "Platforms/PS5/Engine/ShaderCompilerPS5/ShaderCompilerPS5.h"
#endif #endif
#if COMPILE_WITH_XBOX_SCARLETT_SHADER_COMPILER
#include "Platforms/XboxScarlett/Engine/ShaderCompilerXboxScarlett/ShaderCompilerXboxScarlett.h"
#endif
namespace ShadersCompilationImpl namespace ShadersCompilationImpl
{ {
@@ -165,20 +168,16 @@ bool ShadersCompilation::Compile(ShaderCompilationOptions& options)
bool result; bool result;
{ {
ShaderCompilationContext context(&options, &meta); ShaderCompilationContext context(&options, &meta);
auto compiler = RequestCompiler(options.Profile, options.Platform);
// Request shaders compiler
auto compiler = RequestCompiler(options.Profile);
if (compiler == nullptr) if (compiler == nullptr)
{ {
LOG(Error, "Shader compiler request failed."); LOG(Error, "Shader compiler request failed.");
return true; return true;
} }
ASSERT(compiler->GetProfile() == options.Profile); ASSERT_LOW_LAYER(compiler->GetProfile() == options.Profile);
// Call compilation process // Call compilation process
result = compiler->Compile(&context); result = compiler->Compile(&context);
// Dismiss compiler
FreeCompiler(compiler); FreeCompiler(compiler);
#if GPU_USE_SHADERS_DEBUG_LAYER #if GPU_USE_SHADERS_DEBUG_LAYER
@@ -210,65 +209,65 @@ bool ShadersCompilation::Compile(ShaderCompilationOptions& options)
return result; return result;
} }
ShaderCompiler* ShadersCompilation::CreateCompiler(ShaderProfile profile) ShaderCompiler* ShadersCompilation::RequestCompiler(ShaderProfile profile, PlatformType platform)
{ {
ShaderCompiler* result = nullptr;
switch (profile)
{
#if COMPILE_WITH_D3D_SHADER_COMPILER
case ShaderProfile::DirectX_SM4:
case ShaderProfile::DirectX_SM5:
result = New<ShaderCompilerD3D>(profile);
break;
#endif
#if COMPILE_WITH_DX_SHADER_COMPILER
case ShaderProfile::DirectX_SM6:
result = New<ShaderCompilerDX>(profile);
break;
#endif
#if COMPILE_WITH_VK_SHADER_COMPILER
case ShaderProfile::Vulkan_SM5:
result = New<ShaderCompilerVulkan>(profile);
break;
#endif
#if COMPILE_WITH_PS4_SHADER_COMPILER
case ShaderProfile::PS4:
result = New<ShaderCompilerPS4>();
break;
#endif
#if COMPILE_WITH_PS5_SHADER_COMPILER
case ShaderProfile::PS5:
result = New<ShaderCompilerPS5>();
break;
#endif
default:
break;
}
ASSERT_LOW_LAYER(result == nullptr || result->GetProfile() == profile);
return result;
}
ShaderCompiler* ShadersCompilation::RequestCompiler(ShaderProfile profile)
{
ShaderCompiler* compiler;
ScopeLock lock(Locker); ScopeLock lock(Locker);
// Try to find ready compiler // Try to find ready compiler
ShaderCompiler* compiler = nullptr;
for (int32 i = 0; i < ReadyCompilers.Count(); i++) for (int32 i = 0; i < ReadyCompilers.Count(); i++)
{ {
compiler = ReadyCompilers[i]; compiler = ReadyCompilers.Get()[i];
if (compiler->GetProfile() == profile) if (compiler->GetProfile() == profile &&
(compiler->GetPlatform() == platform || (int32)compiler->GetPlatform() == 0))
{ {
// Use it
ReadyCompilers.RemoveAt(i); ReadyCompilers.RemoveAt(i);
return compiler; return compiler;
} }
} }
// Create new compiler for a target profile // Create new compiler for a target profile
compiler = CreateCompiler(profile); switch (profile)
{
#if COMPILE_WITH_D3D_SHADER_COMPILER
case ShaderProfile::DirectX_SM4:
case ShaderProfile::DirectX_SM5:
compiler = New<ShaderCompilerD3D>(profile);
break;
#endif
#if COMPILE_WITH_DX_SHADER_COMPILER
case ShaderProfile::DirectX_SM6:
switch (platform)
{
case PlatformType::XboxScarlett:
#if COMPILE_WITH_XBOX_SCARLETT_SHADER_COMPILER
compiler = New<ShaderCompilerXboxScarlett>();
#endif
break;
default:
compiler = New<ShaderCompilerDX>(profile);
break;
}
break;
#endif
#if COMPILE_WITH_VK_SHADER_COMPILER
case ShaderProfile::Vulkan_SM5:
compiler = New<ShaderCompilerVulkan>(profile);
break;
#endif
#if COMPILE_WITH_PS4_SHADER_COMPILER
case ShaderProfile::PS4:
compiler = New<ShaderCompilerPS4>();
break;
#endif
#if COMPILE_WITH_PS5_SHADER_COMPILER
case ShaderProfile::PS5:
compiler = New<ShaderCompilerPS5>();
break;
#endif
default:
break;
}
if (compiler == nullptr) if (compiler == nullptr)
{ {
LOG(Error, "Cannot create Shader Compiler for profile {0}", ::ToString(profile)); LOG(Error, "Cannot create Shader Compiler for profile {0}", ::ToString(profile));
@@ -414,7 +413,8 @@ String ShadersCompilation::ResolveShaderPath(StringView path)
// Skip to the last root start './' but preserve the leading one // Skip to the last root start './' but preserve the leading one
for (int32 i = path.Length() - 2; i >= 2; i--) for (int32 i = path.Length() - 2; i >= 2; i--)
{ {
if (StringUtils::Compare(path.Get() + i, TEXT("./"), 2) == 0) const Char* pos = path.Get() + i;
if (pos[0] == '.' && pos[1] == '/')
{ {
path = path.Substring(i); path = path.Substring(i);
break; break;

View File

@@ -48,9 +48,7 @@ public:
static String CompactShaderPath(StringView path); static String CompactShaderPath(StringView path);
private: private:
static ShaderCompiler* RequestCompiler(ShaderProfile profile, PlatformType platform);
static ShaderCompiler* CreateCompiler(ShaderProfile profile);
static ShaderCompiler* RequestCompiler(ShaderProfile profile);
static void FreeCompiler(ShaderCompiler* compiler); static void FreeCompiler(ShaderCompiler* compiler);
}; };