// 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