// Copyright (c) Wojciech Figat. All rights reserved.
#pragma once
#if COMPILE_WITH_SHADER_COMPILER
#include "ShaderCompilationContext.h"
#include "Parser/ShaderMeta.h"
#include "Engine/Graphics/Shaders/GPUShaderProgram.h"
#include "Engine/Graphics/Shaders/GPUVertexLayout.h"
///
/// Base class for the objects that can compile shaders source code.
///
class ShaderCompiler
{
public:
struct ShaderResourceBuffer
{
byte Slot;
bool IsUsed;
uint32 Size;
};
private:
ShaderProfile _profile;
PlatformType _platform;
Array _funcNameDefineBuffer;
protected:
ShaderCompilationContext* _context = nullptr;
Array _globalMacros;
Array _macros;
Array _constantBuffers;
public:
///
/// Initializes a new instance of the class.
///
/// The profile.
/// The platform.
ShaderCompiler(ShaderProfile profile, PlatformType platform = (PlatformType)0)
: _profile(profile)
, _platform(platform)
{
}
///
/// Finalizes an instance of the class.
///
virtual ~ShaderCompiler() = default;
public:
///
/// Gets shader profile supported by this compiler.
///
FORCE_INLINE ShaderProfile GetProfile() const
{
return _profile;
}
///
/// Gets target platform supported by this compiler. Returns invalid value of '0' if any platform works.
///
FORCE_INLINE PlatformType GetPlatform() const
{
return _platform;
}
///
/// Performs the shader compilation.
///
/// The compilation context.
/// True if failed, otherwise false.
bool Compile(ShaderCompilationContext* context);
///
/// Gets the included file source code. Handles system includes and absolute includes. Method is thread-safe.
///
/// The compilation context.
/// The source file that is being compiled.
/// The included file name (absolute or relative).
/// The output source code of the file (null-terminated), null if failed to load.
/// The output source code length of the file (characters count), 0 if failed to load.
/// True if failed, otherwise false.
static bool GetIncludedFileSource(ShaderCompilationContext* context, const char* sourceFile, const char* includedFile, const char*& source, int32& sourceLength);
///
/// Clears the cache used by the shader includes.
///
static void DisposeIncludedFilesCache();
protected:
// Input elements read from reflection after shader compilation. Rough approx or attributes without exact format nor bind slot (only semantics and value dimensions match).
struct AdditionalDataVS
{
GPUVertexLayout::Elements Inputs;
};
typedef bool (*WritePermutationData)(ShaderCompilationContext*, ShaderFunctionMeta&, int32, const Array&, void*);
virtual bool CompileShader(ShaderFunctionMeta& meta, WritePermutationData customDataWrite = nullptr) = 0;
bool CompileShaders();
virtual bool OnCompileBegin();
virtual bool OnCompileEnd();
static bool WriteShaderFunctionBegin(ShaderCompilationContext* context, ShaderFunctionMeta& meta);
static bool WriteShaderFunctionPermutation(ShaderCompilationContext* context, ShaderFunctionMeta& meta, int32 permutationIndex, const ShaderBindings& bindings, const void* header, int32 headerSize, const void* cache, int32 cacheSize);
static bool WriteShaderFunctionPermutation(ShaderCompilationContext* context, ShaderFunctionMeta& meta, int32 permutationIndex, const ShaderBindings& bindings, const void* cache, int32 cacheSize);
static bool WriteShaderFunctionEnd(ShaderCompilationContext* context, ShaderFunctionMeta& meta);
static bool WriteCustomDataVS(ShaderCompilationContext* context, ShaderFunctionMeta& meta, int32 permutationIndex, const Array& macros, void* additionalData);
static bool WriteCustomDataHS(ShaderCompilationContext* context, ShaderFunctionMeta& meta, int32 permutationIndex, const Array& macros, void* additionalData);
void GetDefineForFunction(ShaderFunctionMeta& meta, Array& macros);
static VertexElement::Types ParseVertexElementType(StringAnsiView semantic, uint32 index = 0);
};
#endif