//********************************** Banshee Engine (www.banshee3d.com) **************************************************// //**************** Copyright (c) 2016 Marko Pintera (marko.pintera@gmail.com). All rights reserved. **********************// #pragma once #include "BsSLPrerequisites.h" #include "Material/BsShader.h" #include "RenderAPI/BsGpuProgram.h" #include "RenderAPI/BsRasterizerState.h" #include "RenderAPI/BsDepthStencilState.h" #include "RenderAPI/BsBlendState.h" extern "C" { #include "BsASTFX.h" } namespace bs { /** @addtogroup BansheeSL * @{ */ /** Contains the results of compilation returned from the BSLFXCompiler. */ struct BSLFXCompileResult { SPtr shader; /**< Resulting shader if compilation was successful. Null if error occurred. */ String errorMessage; /**< Error message if compilation failed. */ int errorLine = 0; /**< Line of the error if one occurred. */ int errorColumn = 0; /**< Column of the error if one occurred. */ String errorFile; /**< File in which the error occurred. Empty if root file. */ }; /** Transforms a source file written in BSL FX syntax into a Shader object. */ class BSLFXCompiler { /** Possible types of code blocks within a shader. */ enum class CodeBlockType { Vertex, Fragment, Geometry, Hull, Domain, Compute, Common }; /** Temporary data describing a pass during parsing. */ struct PassData { BLEND_STATE_DESC blendDesc; RASTERIZER_STATE_DESC rasterizerDesc; DEPTH_STENCIL_STATE_DESC depthStencilDesc; UINT32 stencilRefValue = 0; UINT32 seqIdx = 0; bool blendIsDefault = true; bool rasterizerIsDefault = true; bool depthStencilIsDefault = true; String code; // Parsed code block String vertexCode; String fragmentCode; String geometryCode; String hullCode; String domainCode; String computeCode; }; /** Information describing a technique, without the actual contents. */ struct TechniqueMetaData { String name; Vector includes; bool isMixin; String language; StringID renderer = RendererAny; Vector tags; }; /** Temporary data for describing a technique during parsing. */ struct TechniqueData { TechniqueMetaData metaData; Vector passes; }; public: /** Transforms a source file written in BSL FX syntax into a Shader object. */ static BSLFXCompileResult compile(const String& name, const String& source, const UnorderedMap& defines); private: /** Converts the provided source into an abstract syntax tree using the lexer & parser for BSL FX syntax. */ static void parseFX(ParseState* parseState, const char* source); /** Parses the technique node and outputs the relevant meta-data. */ static TechniqueMetaData parseTechniqueMetaData(ASTFXNode* technique); /** Converts FX renderer name into an in-engine renderer identifier. */ static StringID parseRenderer(const String& name); /** Maps FX queue sort type enum into in-engine queue sort type mode. */ static QueueSortType parseSortType(CullAndSortModeValue sortType); /** Maps FX comparison function enum into in-engine compare function. */ static CompareFunction parseCompFunc(CompFuncValue compFunc); /** Maps FX operation to in-engine blend factor. */ static BlendFactor parseBlendFactor(OpValue factor); /** Maps FX blend operation to in-engine blend operation. */ static BlendOperation parseBlendOp(BlendOpValue op); /** Maps FX operation to in-engine stencil operation. */ static StencilOperation parseStencilOp(OpValue op); /** Maps FX cull mode enum to in-engine cull mode. */ static CullingMode parseCullMode(CullAndSortModeValue cm); /** Maps FX fill mode enum to in-engine fill mode. */ static PolygonMode parseFillMode(FillModeValue fm); /** * Populates the front facing operation portion of the depth-stencil state descriptor from the provided stencil-op * AST node. */ static void parseStencilFront(DEPTH_STENCIL_STATE_DESC& desc, ASTFXNode* stencilOpNode); /** * Populates the back backing operation portion of the depth-stencil state descriptor from the provided stencil-op * AST node. */ static void parseStencilBack(DEPTH_STENCIL_STATE_DESC& desc, ASTFXNode* stencilOpNode); /** Populates the color (RGB) portion of the blend state descriptor from the provided blend definition AST node. */ static void parseColorBlendDef(RENDER_TARGET_BLEND_STATE_DESC& desc, ASTFXNode* blendDefNode); /** Populates the alpha portion of the blend state descriptor from the provided blend definition AST node. */ static void parseAlphaBlendDef(RENDER_TARGET_BLEND_STATE_DESC& desc, ASTFXNode* blendDefNode); /** * Populates blend state descriptor for a single render target from the provided AST node. Which target gets * updated depends on the index set in the AST node. */ static void parseRenderTargetBlendState(BLEND_STATE_DESC& desc, ASTFXNode* targetNode); /** * Parses the blend state AST node and populates the pass' blend state descriptor. Returns false if the descriptor * wasn't modified. */ static bool parseBlendState(PassData& passData, ASTFXNode* blendNode); /** * Parses the rasterizer state AST node and populates the pass' rasterizer state descriptor. Returns false if the * descriptor wasn't modified. */ static bool parseRasterizerState(PassData& passData, ASTFXNode* rasterNode); /** * Parses the depth state AST node and populates the pass' depth-stencil state descriptor. Returns false if the * descriptor wasn't modified. */ static bool parseDepthState(PassData& passData, ASTFXNode* depthNode); /** * Parses the stencil state AST node and populates the pass' depth-stencil state descriptor. Returns false if the * descriptor wasn't modified. */ static bool parseStencilState(PassData& passData, ASTFXNode* stencilNode); /** * Parses a code AST node and outputs the result in one of the streams within the provided pass data. * * @param[in] codeNode AST node to parse * @param[in] codeBlocks GPU program source code. * @param[in] passData Pass data containing temporary pass data, including the code streams that the code * block code will be written to. */ static void parseCodeBlock(ASTFXNode* codeNode, const Vector& codeBlocks, PassData& passData); /** * Parses the pass AST node and populates the provided @passData with all relevant pass parameters. * * @param[in] passNode Node to parse. * @param[in] codeBlocks GPU program source code. * @param[out] passData Will contain pass data after parsing. */ static void parsePass(ASTFXNode* passNode, const Vector& codeBlocks, PassData& passData); /** * Parses the technique AST node and generates a single technique object. * * @param[in] techniqueNode Node to parse. * @param[in] codeBlocks GPU program source code. * @param[out] techniqueData Will contain technique data after parsing. */ static void parseTechnique(ASTFXNode* techniqueNode, const Vector& codeBlocks, TechniqueData& techniqueData); /** * Parser the options AST node that contains global shader options. * * @param[in] optionsNode Node to parse. * @param[in] shaderDesc Descriptor to apply the found options to. */ static void parseOptions(ASTFXNode* optionsNode, SHADER_DESC& shaderDesc); /** * Parses the AST node hierarchy and generates a shader object. * * @param[in] name Optional name for the shader. * @param[in, out] parseState Parser state object that has previously been initialized with the AST using * parseFX(). * @param codeBlocks GPU program source code. * @return A result object containing the shader if successful, or error message if not. */ static BSLFXCompileResult parseShader(const String& name, ParseState* parseState, Vector& codeBlocks); /** * Converts a null-terminated string into a standard string, and eliminates quotes that are assumed to be at the * first and last index. */ static String removeQuotes(const char* input); }; /** @} */ }