| 1 | /*
|
| 2 | * Xsc.h
|
| 3 | *
|
| 4 | * This file is part of the XShaderCompiler project (Copyright (c) 2014-2017 by Lukas Hermanns)
|
| 5 | * See "LICENSE.txt" for license information.
|
| 6 | */
|
| 7 |
|
| 8 | #ifndef XSC_XSC_H
|
| 9 | #define XSC_XSC_H
|
| 10 |
|
| 11 |
|
| 12 | #include "Export.h"
|
| 13 | #include "Log.h"
|
| 14 | #include "IncludeHandler.h"
|
| 15 | #include "Targets.h"
|
| 16 | #include "Version.h"
|
| 17 | #include "Reflection.h"
|
| 18 |
|
| 19 | #include <string>
|
| 20 | #include <vector>
|
| 21 | #include <map>
|
| 22 | #include <istream>
|
| 23 | #include <ostream>
|
| 24 | #include <memory>
|
| 25 |
|
| 26 |
|
| 27 | /**
|
| 28 | \mainpage
|
| 29 | Welcome to the XShaderCompiler, Version 0.10 Alpha
|
| 30 |
|
| 31 | Here is a quick start example:
|
| 32 | \code
|
| 33 | #include <Xsc/Xsc.h>
|
| 34 | #include <fstream>
|
| 35 |
|
| 36 | int main()
|
| 37 | {
|
| 38 | // Open input and output streams
|
| 39 | auto inputStream = std::make_shared<std::ifstream>("Example.hlsl");
|
| 40 | std::ofstream outputStream("Example.VS.vert");
|
| 41 |
|
| 42 | // Initialize shader input descriptor structure
|
| 43 | Xsc::ShaderInput inputDesc;
|
| 44 | {
|
| 45 | inputDesc.sourceCode = inputStream;
|
| 46 | inputDesc.shaderVersion = Xsc::InputShaderVersion::HLSL5;
|
| 47 | inputDesc.entryPoint = "VS";
|
| 48 | inputDesc.shaderTarget = Xsc::ShaderTarget::VertexShader;
|
| 49 | }
|
| 50 |
|
| 51 | // Initialize shader output descriptor structure
|
| 52 | Xsc::ShaderOutput outputDesc;
|
| 53 | {
|
| 54 | outputDesc.sourceCode = &outputStream;
|
| 55 | outputDesc.shaderVersion = Xsc::OutputShaderVersion::GLSL330;
|
| 56 | }
|
| 57 |
|
| 58 | // Compile HLSL code into GLSL
|
| 59 | Xsc::StdLog log;
|
| 60 | bool result = Xsc::CompileShader(inputDesc, outputDesc, &log);
|
| 61 |
|
| 62 | // Show compilation status
|
| 63 | if (result)
|
| 64 | std::cout << "Compilation successful" << std::endl;
|
| 65 | else
|
| 66 | std::cerr << "Compilation failed" << std::endl;
|
| 67 |
|
| 68 | return 0;
|
| 69 | }
|
| 70 | \endcode
|
| 71 | */
|
| 72 |
|
| 73 |
|
| 74 | //! Main XShaderCompiler namespace
|
| 75 | namespace Xsc
|
| 76 | {
|
| 77 |
|
| 78 |
|
| 79 | /* ===== Public structures ===== */
|
| 80 |
|
| 81 | //! Compiler warning flags.
|
| 82 | struct Warnings
|
| 83 | {
|
| 84 | enum : unsigned int
|
| 85 | {
|
| 86 | Basic = (1 << 0), //!< Warning for basic issues (control path, disabled code etc.).
|
| 87 | Syntax = (1 << 1), //!< Warning for syntactic issues.
|
| 88 | PreProcessor = (1 << 2), //!< Warning for pre-processor issues.
|
| 89 | UnusedVariables = (1 << 3), //!< Warning for unused variables.
|
| 90 | EmptyStatementBody = (1 << 4), //!< Warning for statements with empty body.
|
| 91 | ImplicitTypeConversions = (1 << 5), //!< Warning for specific implicit type conversions.
|
| 92 | DeclarationShadowing = (1 << 6), //!< Warning for declarations that shadow a previous local (e.g. for-loops or variables in class hierarchy).
|
| 93 | UnlocatedObjects = (1 << 7), //!< Warning for optional objects that where not found.
|
| 94 | RequiredExtensions = (1 << 8), //!< Warning for required extensions in the output code.
|
| 95 | CodeReflection = (1 << 9), //!< Warning for issues during code reflection.
|
| 96 | IndexBoundary = (1 << 10), //!< Warning for index boundary violations.
|
| 97 |
|
| 98 | All = (~0u), //!< All warnings.
|
| 99 | };
|
| 100 | };
|
| 101 |
|
| 102 | /**
|
| 103 | \brief Language extension flags.
|
| 104 | \remakrs This is only supported, if the compiler was build with the 'XSC_ENABLE_LANGUAGE_EXT' macro.
|
| 105 | */
|
| 106 | struct Extensions
|
| 107 | {
|
| 108 | enum : unsigned int
|
| 109 | {
|
| 110 | LayoutAttribute = (1 << 0), //!< Enables the 'layout' attribute extension (e.g. "[layout(rgba8)]").
|
| 111 | SpaceAttribute = (1 << 1), //!< Enables the 'space' attribute extension for a stronger type system (e.g. "[space(OBJECT, MODEL)]").
|
| 112 |
|
| 113 | All = (~0u) //!< All extensions.
|
| 114 | };
|
| 115 | };
|
| 116 |
|
| 117 | //! Formatting descriptor structure for the output shader.
|
| 118 | struct Formatting
|
| 119 | {
|
| 120 | //! If true, scopes are always written in braces. By default false.
|
| 121 | bool alwaysBracedScopes = false;
|
| 122 |
|
| 123 | //! If true, blank lines are allowed. By default true.
|
| 124 | bool blanks = true;
|
| 125 |
|
| 126 | //! If true, wrapper functions for special intrinsics are written in a compact formatting (i.e. all in one line). By default false.
|
| 127 | bool compactWrappers = false;
|
| 128 |
|
| 129 | //! Indentation string for code generation. By default std::string(4, ' ').
|
| 130 | std::string indent = " " ;
|
| 131 |
|
| 132 | //! If true, line marks are allowed. By default false.
|
| 133 | bool lineMarks = false;
|
| 134 |
|
| 135 | //! If true, auto-formatting of line separation is allowed. By default true.
|
| 136 | bool lineSeparation = true;
|
| 137 |
|
| 138 | //! If true, the '{'-braces for an open scope gets its own line. If false, braces are written like in Java coding conventions. By default true.
|
| 139 | bool newLineOpenScope = true;
|
| 140 | };
|
| 141 |
|
| 142 | //! Structure for additional translation options.
|
| 143 | struct Options
|
| 144 | {
|
| 145 | //! If true, the shader output may contain GLSL extensions, if the target shader version is too low. By default false.
|
| 146 | bool allowExtensions = false;
|
| 147 |
|
| 148 | /**
|
| 149 | \brief If true, binding slots for all buffer types will be generated sequentially, starting with index at 'autoBindingStartSlot'. By default false.
|
| 150 | \remarks This will also enable 'explicitBinding'.
|
| 151 | */
|
| 152 | bool autoBinding = false;
|
| 153 |
|
| 154 | //! Index to start generating binding slots from. Only relevant if 'autoBinding' is enabled. By default 0.
|
| 155 | int autoBindingStartSlot = 0;
|
| 156 |
|
| 157 | //! If true, explicit binding slots are enabled. By default false.
|
| 158 | bool explicitBinding = false;
|
| 159 |
|
| 160 | //! If true, generate 'location' layout qualifiers for fragment program outputs. This can also be enabled by setting
|
| 161 | //! 'explicitBinding' to true.
|
| 162 | bool fragmentLocations = false;
|
| 163 |
|
| 164 | //! If true, code obfuscation is performed. By default false.
|
| 165 | bool obfuscate = false;
|
| 166 |
|
| 167 | //! If true, little code optimizations are performed. By default false.
|
| 168 | bool optimize = false;
|
| 169 |
|
| 170 | //TODO: maybe merge this option with "optimize" (preferWrappers == !optimize)
|
| 171 | //! If true, intrinsics are prefered to be implemented as wrappers (instead of inlining). By default false.
|
| 172 | bool preferWrappers = false;
|
| 173 |
|
| 174 | //! If true, only the preprocessed source code will be written out. By default false.
|
| 175 | bool preprocessOnly = false;
|
| 176 |
|
| 177 | //! If true, commentaries are preserved for each statement. By default false.
|
| 178 | bool = false;
|
| 179 |
|
| 180 | //! If true, matrices have row-major alignment. Otherwise the matrices have column-major alignment. By default false.
|
| 181 | bool rowMajorAlignment = false;
|
| 182 |
|
| 183 | //! If true, generated GLSL code will contain separate sampler and texture objects when supported. By default true.
|
| 184 | bool separateSamplers = true;
|
| 185 |
|
| 186 | //! If true, generated GLSL code will support the 'ARB_separate_shader_objects' extension. By default false.
|
| 187 | bool separateShaders = false;
|
| 188 |
|
| 189 | //! If true, the AST (Abstract Syntax Tree) will be written to the log output. By default false.
|
| 190 | bool showAST = false;
|
| 191 |
|
| 192 | //! If true, the timings of the different compilation processes are written to the log output. By default false.
|
| 193 | bool showTimes = false;
|
| 194 |
|
| 195 | //TODO: remove this option, and determine automatically when unrolling initializers are required!
|
| 196 | //! If true, array initializations will be unrolled. By default false.
|
| 197 | bool unrollArrayInitializers = false;
|
| 198 |
|
| 199 | //! If true, the source code is only validated, but no output code will be generated. By default false.
|
| 200 | bool validateOnly = false;
|
| 201 | };
|
| 202 |
|
| 203 | //! Name mangling descriptor structure for shader input/output variables (also referred to as "varyings"), temporary variables, and reserved keywords.
|
| 204 | struct NameMangling
|
| 205 | {
|
| 206 | /**
|
| 207 | \brief Name mangling prefix for shader input variables. By default "xsv_".
|
| 208 | \remarks This can also be empty or equal to "outputPrefix".
|
| 209 | */
|
| 210 | std::string inputPrefix = "xsv_" ;
|
| 211 |
|
| 212 | /**
|
| 213 | \brief Name mangling prefix for shader output variables. By default "xsv_".
|
| 214 | \remarks This can also be empty or equal to "inputPrefix".
|
| 215 | */
|
| 216 | std::string outputPrefix = "xsv_" ;
|
| 217 |
|
| 218 | /**
|
| 219 | \brief Name mangling prefix for reserved words (such as "texture", "main", "sin" etc.). By default "xsr_".
|
| 220 | \remarks This must not be equal to any of the other prefixes and it must not be empty.
|
| 221 | */
|
| 222 | std::string reservedWordPrefix = "xsr_" ;
|
| 223 |
|
| 224 | /**
|
| 225 | \brief Name mangling prefix for temporary variables. By default "xst_".
|
| 226 | \remarks This must not be equal to any of the other prefixes and it must not be empty.
|
| 227 | */
|
| 228 | std::string temporaryPrefix = "xst_" ;
|
| 229 |
|
| 230 | /**
|
| 231 | \brief Name mangling prefix for namespaces like structures or classes. By default "xsn_".
|
| 232 | \remarks This can also be empty, but if it's not empty it must not be equal to any of the other prefixes.
|
| 233 | */
|
| 234 | std::string namespacePrefix = "xsn_" ;
|
| 235 |
|
| 236 | /**
|
| 237 | If true, shader input/output variables are always renamed to their semantics,
|
| 238 | even for vertex input and fragment output. Otherwise, their original identifiers are used. By default false.
|
| 239 | */
|
| 240 | bool useAlwaysSemantics = false;
|
| 241 |
|
| 242 | /**
|
| 243 | \brief If true, the data fields of a 'buffer'-objects is renamed rather than the outer identifier. By default false.
|
| 244 | \remarks This can be useful for external diagnostic tools, to access the original identifier.
|
| 245 | */
|
| 246 | bool renameBufferFields = false;
|
| 247 | };
|
| 248 |
|
| 249 | //! Shader input descriptor structure.
|
| 250 | struct ShaderInput
|
| 251 | {
|
| 252 | //! Specifies the filename of the input shader code. This is an optional attribute, and only a hint to the compiler.
|
| 253 | std::string filename;
|
| 254 |
|
| 255 | //! Specifies the input source code stream.
|
| 256 | std::shared_ptr<std::istream> sourceCode;
|
| 257 |
|
| 258 | //! Specifies the input shader version (e.g. InputShaderVersion::HLSL5 for "HLSL 5"). By default InputShaderVersion::HLSL5.
|
| 259 | InputShaderVersion shaderVersion = InputShaderVersion::HLSL5;
|
| 260 |
|
| 261 | //! Specifies the target shader (Vertex, Fragment etc.). By default ShaderTarget::Undefined.
|
| 262 | ShaderTarget shaderTarget = ShaderTarget::Undefined;
|
| 263 |
|
| 264 | //! Specifies the HLSL shader entry point. By default "main".
|
| 265 | std::string entryPoint = "main" ;
|
| 266 |
|
| 267 | /**
|
| 268 | \brief Specifies the secondary HLSL shader entry point.
|
| 269 | \remarks This is only used for a Tessellation-Control Shader (alias Hull Shader) entry point,
|
| 270 | when a Tessellation-Control Shader (alias Domain Shader) is the output target.
|
| 271 | This is required to translate all Tessellation-Control attributes (i.e. "partitioning" and "outputtopology")
|
| 272 | to the Tessellation-Evaluation output shader. If this is empty, the default values for these attributes are used.
|
| 273 | */
|
| 274 | std::string secondaryEntryPoint;
|
| 275 |
|
| 276 | /**
|
| 277 | \brief Compiler warning flags. This can be a bitwise OR combination of the "Warnings" enumeration entries. By default 0.
|
| 278 | \see Warnings
|
| 279 | */
|
| 280 | unsigned int warnings = 0;
|
| 281 |
|
| 282 | /**
|
| 283 | \brief Language extension flags. This can be a bitwise OR combination of the "Extensions" enumeration entries. By default 0.
|
| 284 | \remarks This is ignored, if the compiler was not build with the 'XSC_ENABLE_LANGUAGE_EXT' macro.
|
| 285 | \see Extensions
|
| 286 | */
|
| 287 | unsigned int extensions = 0;
|
| 288 |
|
| 289 | /**
|
| 290 | \brief Optional pointer to the implementation of the "IncludeHandler" interface. By default null.
|
| 291 | \remarks If this is null, the default include handler will be used, which will include files with the STL input file streams.
|
| 292 | */
|
| 293 | IncludeHandler* includeHandler = nullptr;
|
| 294 | };
|
| 295 |
|
| 296 | //! Vertex shader semantic (or rather attribute) layout structure.
|
| 297 | struct VertexSemantic
|
| 298 | {
|
| 299 | //! Specifies the shader semantic (or rather attribute).
|
| 300 | std::string semantic;
|
| 301 |
|
| 302 | //! Specifies the binding location.
|
| 303 | int location;
|
| 304 | };
|
| 305 |
|
| 306 | //! Shader output descriptor structure.
|
| 307 | struct ShaderOutput
|
| 308 | {
|
| 309 | //! Specifies the filename of the output shader code. This is an optional attribute, and only a hint to the compiler.
|
| 310 | std::string filename;
|
| 311 |
|
| 312 | //! Specifies the output source code stream. This will contain the output code. This must not be null when passed to the "CompileShader" function!
|
| 313 | std::ostream* sourceCode = nullptr;
|
| 314 |
|
| 315 | //! Specifies the output shader version. By default OutputShaderVersion::GLSL (to auto-detect minimum required version).
|
| 316 | OutputShaderVersion shaderVersion = OutputShaderVersion::GLSL;
|
| 317 |
|
| 318 | //! Optional list of vertex semantic layouts, to bind a vertex attribute (semantic name) to a location index (only used when 'explicitBinding' is true).
|
| 319 | std::vector<VertexSemantic> vertexSemantics;
|
| 320 |
|
| 321 | //! Additional options to configure the code generation.
|
| 322 | Options options;
|
| 323 |
|
| 324 | //! Output code formatting descriptor.
|
| 325 | Formatting formatting;
|
| 326 |
|
| 327 | //! Specifies the options for name mangling.
|
| 328 | NameMangling nameMangling;
|
| 329 | };
|
| 330 |
|
| 331 | //! Descriptor structure for the shader disassembler.
|
| 332 | struct AssemblyDescriptor
|
| 333 | {
|
| 334 | //! Specifies the intermediate language of the assembly input code. Currently only SPIR-V is supported. By default IntermediateLanguage::SPIRV.
|
| 335 | IntermediateLanguage intermediateLanguage = IntermediateLanguage::SPIRV;
|
| 336 |
|
| 337 | //! Specifies the prefix character to be used for ID numbers in the SPIR-V instructions.
|
| 338 | char idPrefixChar = '%';
|
| 339 |
|
| 340 | //! Specifies whether to show the module header or not. By default true.
|
| 341 | bool = true;
|
| 342 |
|
| 343 | //! Specifies whether to show the instruction byte offsets in the disassembly or not. By default true.
|
| 344 | bool showOffsets = true;
|
| 345 |
|
| 346 | //! Specifies whether to indent the instruction operands or not. By default true.
|
| 347 | bool indentOperands = true;
|
| 348 | };
|
| 349 |
|
| 350 |
|
| 351 | /* ===== Public functions ===== */
|
| 352 |
|
| 353 | /**
|
| 354 | \brief Cross compiles the shader code from the specified input stream into the specified output shader code.
|
| 355 | \param[in] inputDesc Input shader code descriptor.
|
| 356 | \param[in] outputDesc Output shader code descriptor.
|
| 357 | \param[in] log Optional pointer to an output log. Inherit from the "Log" class interface. By default null.
|
| 358 | \param[out] reflectionData Optional pointer to a code reflection data structure. By default null.
|
| 359 | \return True if the code has been translated successfully.
|
| 360 | \throw std::invalid_argument If either the input or output streams are null.
|
| 361 | \see ShaderInput
|
| 362 | \see ShaderOutput
|
| 363 | \see Log
|
| 364 | \see ReflectionData
|
| 365 | */
|
| 366 | XSC_EXPORT bool CompileShader(
|
| 367 | const ShaderInput& inputDesc,
|
| 368 | const ShaderOutput& outputDesc,
|
| 369 | Log* log = nullptr,
|
| 370 | Reflection::ReflectionData* reflectionData = nullptr
|
| 371 | );
|
| 372 |
|
| 373 | /**
|
| 374 | \brief Disassembles the SPIR-V binary code into a human readable code.
|
| 375 | \param[in,out] streamIn Specifies the input stream of the SPIR-V binary code.
|
| 376 | \param[in,out] streamOut Specifies the output stream of the human readable code.
|
| 377 | \param[in] formatting Specifies the output formatting.
|
| 378 | \throws std::runtime_error If the disassembling failed.
|
| 379 | \throws std::invalid_argument If 'desc.intermediateLanguage' has an invalid value.
|
| 380 | */
|
| 381 | XSC_EXPORT void DisassembleShader(
|
| 382 | std::istream& streamIn,
|
| 383 | std::ostream& streamOut,
|
| 384 | const AssemblyDescriptor& desc = {}
|
| 385 | );
|
| 386 |
|
| 387 |
|
| 388 | } // /namespace Xsc
|
| 389 |
|
| 390 |
|
| 391 | #endif
|
| 392 |
|
| 393 |
|
| 394 |
|
| 395 | // ================================================================================ |