diff options
Diffstat (limited to '3rdparty/bgfx/tools/shaderc/shaderc.cpp')
-rw-r--r-- | 3rdparty/bgfx/tools/shaderc/shaderc.cpp | 1155 |
1 files changed, 765 insertions, 390 deletions
diff --git a/3rdparty/bgfx/tools/shaderc/shaderc.cpp b/3rdparty/bgfx/tools/shaderc/shaderc.cpp index bc92f90570d..a8c284c14af 100644 --- a/3rdparty/bgfx/tools/shaderc/shaderc.cpp +++ b/3rdparty/bgfx/tools/shaderc/shaderc.cpp @@ -1,6 +1,6 @@ /* - * Copyright 2011-2018 Branimir Karadzic. All rights reserved. - * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause + * Copyright 2011-2022 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE */ #include "shaderc.h" @@ -13,18 +13,114 @@ extern "C" #include <fpp.h> } // extern "C" -#define BGFX_SHADER_BIN_VERSION 6 +#define BGFX_SHADER_BIN_VERSION 11 #define BGFX_CHUNK_MAGIC_CSH BX_MAKEFOURCC('C', 'S', 'H', BGFX_SHADER_BIN_VERSION) #define BGFX_CHUNK_MAGIC_FSH BX_MAKEFOURCC('F', 'S', 'H', BGFX_SHADER_BIN_VERSION) #define BGFX_CHUNK_MAGIC_VSH BX_MAKEFOURCC('V', 'S', 'H', BGFX_SHADER_BIN_VERSION) #define BGFX_SHADERC_VERSION_MAJOR 1 -#define BGFX_SHADERC_VERSION_MINOR 16 +#define BGFX_SHADERC_VERSION_MINOR 18 namespace bgfx { bool g_verbose = false; + struct ShadingLang + { + enum Enum + { + ESSL, + GLSL, + HLSL, + Metal, + PSSL, + SpirV, + + Count + }; + }; + + static const char* s_shadingLangName[] = + { + "OpenGL ES Shading Language / WebGL (ESSL)", + "OpenGL Shading Language (GLSL)", + "High-Level Shading Language (HLSL)", + "Metal Shading Language (MSL)", + "PlayStation Shader Language (PSSL)", + "Standard Portable Intermediate Representation - V (SPIR-V)", + + "Unknown?!" + }; + BX_STATIC_ASSERT(BX_COUNTOF(s_shadingLangName) == ShadingLang::Count+1, "ShadingLang::Enum and s_shadingLangName mismatch"); + + const char* getName(ShadingLang::Enum _lang) + { + return s_shadingLangName[_lang]; + } + + // c - compute + // d - domain + // f - fragment + // g - geometry + // h - hull + // v - vertex + // + // OpenGL #version Features Direct3D Features Shader Model + // 2.1 120 vf 9.0 vf 2.0 + // 3.0 130 + // 3.1 140 + // 3.2 150 vgf + // 3.3 330 10.0 vgf 4.0 + // 4.0 400 vhdgf + // 4.1 410 + // 4.2 420 11.0 vhdgf+c 5.0 + // 4.3 430 vhdgf+c + // 4.4 440 + // + // SPIR-V profile naming convention: + // spirv<SPIR-V version>-<Vulkan version> + // + // SPIR-V version | Vulkan version | shaderc encoding + // 1.0 | 1.0 | 1010 + // 1.3 | 1.1 | 1311 + // 1.4 | 1.1 | 1411 + // 1.5 | 1.2 | 1512 + + struct Profile + { + ShadingLang::Enum lang; + uint32_t id; + const char* name; + }; + + static const Profile s_profiles[] = + { + { ShadingLang::ESSL, 100, "100_es" }, + { ShadingLang::ESSL, 300, "300_es" }, + { ShadingLang::ESSL, 310, "310_es" }, + { ShadingLang::ESSL, 320, "320_es" }, + { ShadingLang::HLSL, 300, "s_3_0" }, + { ShadingLang::HLSL, 400, "s_4_0" }, + { ShadingLang::HLSL, 500, "s_5_0" }, + { ShadingLang::Metal, 1000, "metal" }, + { ShadingLang::PSSL, 1000, "pssl" }, + { ShadingLang::SpirV, 1311, "spirv13-11" }, + { ShadingLang::SpirV, 1411, "spirv14-11" }, + { ShadingLang::SpirV, 1512, "spirv15-12" }, + { ShadingLang::SpirV, 1010, "spirv10-10" }, + { ShadingLang::SpirV, 1010, "spirv" }, + { ShadingLang::GLSL, 120, "120" }, + { ShadingLang::GLSL, 130, "130" }, + { ShadingLang::GLSL, 140, "140" }, + { ShadingLang::GLSL, 150, "150" }, + { ShadingLang::GLSL, 330, "330" }, + { ShadingLang::GLSL, 400, "400" }, + { ShadingLang::GLSL, 410, "410" }, + { ShadingLang::GLSL, 420, "420" }, + { ShadingLang::GLSL, 430, "430" }, + { ShadingLang::GLSL, 440, "440" }, + }; + static const char* s_ARB_shader_texture_lod[] = { "texture2DLod", @@ -87,6 +183,17 @@ namespace bgfx { "gl_VertexID", "gl_InstanceID", + "texture2DLodOffset", + NULL + }; + + // To be use from vertex program require: + // https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_shader_viewport_layer_array.txt + // DX11 11_1 feature level + static const char* s_ARB_shader_viewport_layer_array[] = + { + "gl_ViewportIndex", + "gl_Layer", NULL }; @@ -119,11 +226,13 @@ namespace bgfx "usampler3D", "isamplerCube", "usamplerCube", + "textureSize", NULL }; static const char* s_textureArray[] = { + "sampler2DArray", "texture2DArray", "texture2DArrayLod", "shadow2DArray", @@ -145,6 +254,23 @@ namespace bgfx NULL }; + static const char* s_bitsToEncoders[] = + { + "floatBitsToUint", + "floatBitsToInt", + "intBitsToFloat", + "uintBitsToFloat", + NULL + }; + + static const char* s_unsignedVecs[] = + { + "uvec2", + "uvec3", + "uvec4", + NULL + }; + const char* s_uniformTypeName[] = { "int", "int", @@ -155,7 +281,59 @@ namespace bgfx }; BX_STATIC_ASSERT(BX_COUNTOF(s_uniformTypeName) == UniformType::Count*2); + static const char* s_allowedVertexShaderInputs[] = + { + "a_position", + "a_normal", + "a_tangent", + "a_bitangent", + "a_color0", + "a_color1", + "a_color2", + "a_color3", + "a_indices", + "a_weight", + "a_texcoord0", + "a_texcoord1", + "a_texcoord2", + "a_texcoord3", + "a_texcoord4", + "a_texcoord5", + "a_texcoord6", + "a_texcoord7", + "i_data0", + "i_data1", + "i_data2", + "i_data3", + "i_data4", + NULL + }; + + void fatal(const char* _filePath, uint16_t _line, Fatal::Enum _code, const char* _format, ...) + { + BX_UNUSED(_filePath, _line, _code); + + va_list argList; + va_start(argList, _format); + + bx::vprintf(_format, argList); + + va_end(argList); + + abort(); + } + + void trace(const char* _filePath, uint16_t _line, const char* _format, ...) + { + BX_UNUSED(_filePath, _line); + + va_list argList; + va_start(argList, _format); + bx::vprintf(_format, argList); + + va_end(argList); + } Options::Options() : shaderType(' ') , disasm(false) @@ -251,7 +429,7 @@ namespace bgfx const char* getUniformTypeName(UniformType::Enum _enum) { - uint32_t idx = _enum & ~(BGFX_UNIFORM_FRAGMENTBIT|BGFX_UNIFORM_SAMPLERBIT); + uint32_t idx = _enum & ~(kUniformFragmentBit|kUniformSamplerBit); if (idx < UniformType::Count) { return s_uniformTypeName[idx]; @@ -290,7 +468,7 @@ namespace bgfx len = bx::vsnprintf(out, len, _format, argList); } - len = bx::write(_writer, out, len); + len = bx::write(_writer, out, len, bx::ErrorAssert{}); va_end(argList); @@ -385,15 +563,13 @@ namespace bgfx len = bx::vsnprintf(out, len, _format, argList); } - bx::Error err; - int32_t size = bx::FileWriter::write(out, len, &err); + int32_t size = bx::FileWriter::write(out, len, bx::ErrorAssert{}); va_end(argList); return size; } - std::string m_filePath; bx::StringView m_name; typedef std::vector<uint8_t> Buffer; Buffer m_buffer; @@ -432,7 +608,7 @@ namespace bgfx { m_size = (uint32_t)bx::getSize(&reader); m_data = new char[m_size+1]; - m_size = (uint32_t)bx::read(&reader, m_data, m_size); + m_size = (uint32_t)bx::read(&reader, m_data, m_size, bx::ErrorAssert{}); bx::close(&reader); if (m_data[0] == '\xef' @@ -482,7 +658,7 @@ namespace bgfx } replace[len] = '\0'; - BX_CHECK(len >= bx::strLen(_replace), ""); + BX_ASSERT(len >= bx::strLen(_replace), ""); for (bx::StringView ptr = bx::strFind(_str, _find) ; !ptr.isEmpty() ; ptr = bx::strFind(ptr.getPtr() + len, _find) @@ -500,38 +676,33 @@ namespace bgfx void printCode(const char* _code, int32_t _line, int32_t _start, int32_t _end, int32_t _column) { - fprintf(stderr, "Code:\n---\n"); + bx::printf("Code:\n---\n"); - bx::Error err; - LineReader reader(_code); - for (int32_t line = 1; err.isOk() && line < _end; ++line) + bx::LineReader reader(_code); + for (int32_t line = 1; !reader.isDone() && line < _end; ++line) { - char str[4096]; - int32_t len = bx::read(&reader, str, BX_COUNTOF(str), &err); + bx::StringView strLine = reader.next(); - if (err.isOk() - && line >= _start) + if (line >= _start) { - std::string strLine(str, len); - if (_line == line) { - fprintf(stderr, "\n"); - fprintf(stderr, ">>> %3d: %s", line, strLine.c_str() ); + bx::printf("\n"); + bx::printf(">>> %3d: %.*s\n", line, strLine.getLength(), strLine.getPtr() ); if (-1 != _column) { - fprintf(stderr, ">>> %3d: %*s\n", _column, _column, "^"); + bx::printf(">>> %3d: %*s\n", _column, _column, "^"); } - fprintf(stderr, "\n"); + bx::printf("\n"); } else { - fprintf(stderr, " %3d: %s", line, strLine.c_str() ); + bx::printf(" %3d: %.*s\n", line, strLine.getLength(), strLine.getPtr() ); } } } - fprintf(stderr, "---\n"); + bx::printf("---\n"); } void writeFile(const char* _filePath, const void* _data, int32_t _size) @@ -539,7 +710,7 @@ namespace bgfx bx::FileWriter out; if (bx::open(&out, _filePath) ) { - bx::write(&out, _data, _size); + bx::write(&out, _data, _size, bx::ErrorAssert{}); bx::close(&out); } } @@ -712,7 +883,7 @@ namespace bgfx static void fppError(void* /*_userData*/, char* _format, va_list _vargs) { - vfprintf(stderr, _format, _vargs); + bx::vprintf(_format, _vargs); } char* scratch(const char* _str) @@ -738,27 +909,31 @@ namespace bgfx typedef std::vector<std::string> InOut; - uint32_t parseInOut(InOut& _inout, const char* _str, const char* _eol) + uint32_t parseInOut(InOut& _inout, const bx::StringView& _str) { uint32_t hash = 0; - _str = bx::strLTrimSpace(_str).getPtr(); + bx::StringView str = bx::strLTrimSpace(_str); - if (_str < _eol) + if (!str.isEmpty() ) { - const char* delim; + bx::StringView delim; do { - delim = strpbrk(_str, " ,"); - if (NULL != delim) + delim = bx::strFind(str, ','); + if (delim.isEmpty() ) { - delim = delim > _eol ? _eol : delim; - std::string token; - token.assign(_str, delim-_str); - _inout.push_back(token); - _str = bx::strLTrimSpace(delim + 1).getPtr(); + delim = bx::strFind(str, ' '); + } + + const bx::StringView token(bx::strRTrim(bx::StringView(str.getPtr(), delim.getPtr() ), " ") ); + + if (!token.isEmpty() ) + { + _inout.push_back(std::string(token.getPtr(), token.getTerm() ) ); + str = bx::strLTrimSpace(bx::StringView(delim.getPtr() + 1, str.getTerm() ) ); } } - while (delim < _eol && _str < _eol && NULL != delim); + while (!delim.isEmpty() ); std::sort(_inout.begin(), _inout.end() ); @@ -806,51 +981,33 @@ namespace bgfx return bx::strFind(_filePath, fp.getBaseName() ); } - // c - compute - // d - domain - // f - fragment - // g - geometry - // h - hull - // v - vertex - // - // OpenGL #version Features Direct3D Features Shader Model - // 2.1 120 vf 9.0 vf 2.0 - // 3.0 130 - // 3.1 140 - // 3.2 150 vgf - // 3.3 330 10.0 vgf 4.0 - // 4.0 400 vhdgf - // 4.1 410 - // 4.2 420 11.0 vhdgf+c 5.0 - // 4.3 430 vhdgf+c - // 4.4 440 - void help(const char* _error = NULL) { if (NULL != _error) { - fprintf(stderr, "Error:\n%s\n\n", _error); + bx::printf("Error:\n%s\n\n", _error); } - fprintf(stderr - , "shaderc, bgfx shader compiler tool, version %d.%d.%d.\n" - "Copyright 2011-2018 Branimir Karadzic. All rights reserved.\n" - "License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause\n\n" + bx::printf( + "shaderc, bgfx shader compiler tool, version %d.%d.%d.\n" + "Copyright 2011-2022 Branimir Karadzic. All rights reserved.\n" + "License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE\n\n" , BGFX_SHADERC_VERSION_MAJOR , BGFX_SHADERC_VERSION_MINOR , BGFX_API_VERSION ); - fprintf(stderr - , "Usage: shaderc -f <in> -o <out> --type <v/f> --platform <platform>\n" + bx::printf( + "Usage: shaderc -f <in> -o <out> --type <v/f/c> --platform <platform>\n" "\n" "Options:\n" - " -h, --help Help.\n" - " -v, --version Version information only.\n" - " -f <file path> Input file path.\n" - " -i <include path> Include path (for multiple paths use -i multiple times).\n" - " -o <file path> Output file path.\n" + " -h, --help Display this help and exit.\n" + " -v, --version Output version information and exit.\n" + " -f <file path> Input's file path.\n" + " -i <include path> Include path. (for multiple paths use -i multiple times)\n" + " -o <file path> Output's file path.\n" + " --stdout Output to console.\n" " --bin2c [array name] Generate C header file. If array name is not specified base file name will be used as name.\n" " --depends Generate makefile style depends file.\n" " --platform <platform> Target platform.\n" @@ -858,24 +1015,46 @@ namespace bgfx " asm.js\n" " ios\n" " linux\n" - " nacl\n" + " orbis\n" " osx\n" " windows\n" - " --preprocess Preprocess only.\n" - " --define <defines> Add defines to preprocessor (semicolon separated).\n" - " --raw Do not process shader. No preprocessor, and no glsl-optimizer (GLSL only).\n" - " --type <type> Shader type (vertex, fragment)\n" - " --varyingdef <file path> Path to varying.def.sc file.\n" - " --verbose Verbose.\n" + " -p, --profile <profile> Shader model. Defaults to GLSL.\n" + ); + + { + ShadingLang::Enum lang = ShadingLang::Count; + for (uint32_t ii = 0; ii < BX_COUNTOF(s_profiles); ++ii) + { + const Profile& profile = s_profiles[ii]; + if (lang != profile.lang) + { + lang = profile.lang; + bx::printf("\n"); + bx::printf(" %-20s %s\n", profile.name, getName(profile.lang) ); + } + else + { + bx::printf(" %s\n", profile.name); + } + + } + } + + bx::printf( + " --preprocess Only pre-process.\n" + " --define <defines> Add defines to preprocessor. (Semicolon-separated)\n" + " --raw Do not process shader. No preprocessor, and no glsl-optimizer. (GLSL only)\n" + " --type <type> Shader type. Can be 'vertex', 'fragment, or 'compute'.\n" + " --varyingdef <file path> varying.def.sc's file path.\n" + " --verbose Be verbose.\n" "\n" - "Options (DX9 and DX11 only):\n" + "(DX9 and DX11 only):\n" "\n" " --debug Debug information.\n" " --disasm Disassemble compiled shader.\n" - " -p, --profile <profile> Shader model (f.e. ps_3_0).\n" - " -O <level> Optimization level (0, 1, 2, 3).\n" + " -O <level> Set optimization level. Can be 0 to 3.\n" " --Werror Treat warnings as errors.\n" "\n" @@ -890,58 +1069,41 @@ namespace bgfx return word; } - bool compileShader(const char* _varying, const char* _comment, char* _shader, uint32_t _shaderLen, Options& _options, bx::FileWriter* _writer) + bool compileShader(const char* _varying, const char* _comment, char* _shader, uint32_t _shaderLen, Options& _options, bx::WriterI* _writer) { - uint32_t glsl = 0; - uint32_t essl = 0; - uint32_t hlsl = 0; - uint32_t d3d = 11; - uint32_t metal = 0; - uint32_t pssl = 0; - uint32_t spirv = 0; - const char* profile = _options.profile.c_str(); - if ('\0' != profile[0]) - { - if (0 == bx::strCmp(&profile[1], "s_4_0_level", 11) ) - { - hlsl = 2; - } - else if (0 == bx::strCmp(&profile[1], "s_3", 3) ) - { - hlsl = 3; - d3d = 9; - } - else if (0 == bx::strCmp(&profile[1], "s_4", 3) ) - { - hlsl = 4; - } - else if (0 == bx::strCmp(&profile[1], "s_5", 3) ) - { - hlsl = 5; - } - else if (0 == bx::strCmp(profile, "metal") ) - { - metal = 1; - } - else if (0 == bx::strCmp(profile, "pssl") ) - { - pssl = 1; - } - else if (0 == bx::strCmp(profile, "spirv") ) + uint32_t profile_id = 0; + + const char* profile_opt = _options.profile.c_str(); + if ('\0' != profile_opt[0]) + { + const uint32_t count = BX_COUNTOF(s_profiles); + for (profile_id=0; profile_id<count; profile_id++ ) { - spirv = 1; + if (0 == bx::strCmp(profile_opt, s_profiles[profile_id].name) ) + { + break; + } + else if (s_profiles[profile_id].lang == ShadingLang::HLSL + && 0 == bx::strCmp(&profile_opt[1], s_profiles[profile_id].name) ) + { + // This test is here to allow hlsl profile names e.g: + // cs_4_0, gs_5_0, etc... + // There's no check to ensure that the profile name matches the shader type set via the cli. + // This means that you can pass `hs_5_0` when compiling a fragment shader. + break; + } } - else + + if (profile_id == count) { - bx::fromString(&glsl, profile); + bx::printf("Unknown profile: %s\n", profile_opt); + return false; } } - else - { - essl = 2; - } - Preprocessor preprocessor(_options.inputFilePath.c_str(), 0 != essl); + const Profile *profile = &s_profiles[profile_id]; + + Preprocessor preprocessor(_options.inputFilePath.c_str(), profile->lang != ShadingLang::ESSL); for (size_t ii = 0; ii < _options.includeDirs.size(); ++ii) { @@ -967,7 +1129,6 @@ namespace bgfx preprocessor.setDefaultDefine("BX_PLATFORM_WINDOWS"); preprocessor.setDefaultDefine("BX_PLATFORM_XBOXONE"); -// preprocessor.setDefaultDefine("BGFX_SHADER_LANGUAGE_ESSL"); preprocessor.setDefaultDefine("BGFX_SHADER_LANGUAGE_GLSL"); preprocessor.setDefaultDefine("BGFX_SHADER_LANGUAGE_HLSL"); preprocessor.setDefaultDefine("BGFX_SHADER_LANGUAGE_METAL"); @@ -979,32 +1140,58 @@ namespace bgfx preprocessor.setDefaultDefine("BGFX_SHADER_TYPE_VERTEX"); char glslDefine[128]; - bx::snprintf(glslDefine, BX_COUNTOF(glslDefine) - , "BGFX_SHADER_LANGUAGE_GLSL=%d" - , essl ? 1 : glsl - ); + if (profile->lang == ShadingLang::GLSL + || profile->lang == ShadingLang::ESSL) + { + bx::snprintf(glslDefine, BX_COUNTOF(glslDefine) + , "BGFX_SHADER_LANGUAGE_GLSL=%d" + , profile->id + ); + } + + char hlslDefine[128]; + if (profile->lang == ShadingLang::HLSL) + { + bx::snprintf(hlslDefine, BX_COUNTOF(hlslDefine) + , "BGFX_SHADER_LANGUAGE_HLSL=%d" + , profile->id); + } const char* platform = _options.platform.c_str(); if (0 == bx::strCmpI(platform, "android") ) { preprocessor.setDefine("BX_PLATFORM_ANDROID=1"); - preprocessor.setDefine("BGFX_SHADER_LANGUAGE_GLSL=1"); + if (profile->lang == ShadingLang::SpirV) + { + preprocessor.setDefine("BGFX_SHADER_LANGUAGE_SPIRV=1"); + } + else + { + preprocessor.setDefine(glslDefine); + } } else if (0 == bx::strCmpI(platform, "asm.js") ) { preprocessor.setDefine("BX_PLATFORM_EMSCRIPTEN=1"); - preprocessor.setDefine("BGFX_SHADER_LANGUAGE_GLSL=1"); + preprocessor.setDefine(glslDefine); } else if (0 == bx::strCmpI(platform, "ios") ) { preprocessor.setDefine("BX_PLATFORM_IOS=1"); - preprocessor.setDefine("BGFX_SHADER_LANGUAGE_GLSL=1"); + if (profile->lang == ShadingLang::Metal) + { + preprocessor.setDefine("BGFX_SHADER_LANGUAGE_METAL=1"); + } + else + { + preprocessor.setDefine(glslDefine); + } } else if (0 == bx::strCmpI(platform, "linux") ) { preprocessor.setDefine("BX_PLATFORM_LINUX=1"); - if (0 != spirv) + if (profile->lang == ShadingLang::SpirV) { preprocessor.setDefine("BGFX_SHADER_LANGUAGE_SPIRV=1"); } @@ -1016,17 +1203,35 @@ namespace bgfx else if (0 == bx::strCmpI(platform, "osx") ) { preprocessor.setDefine("BX_PLATFORM_OSX=1"); - preprocessor.setDefine(glslDefine); + if (profile->lang != ShadingLang::Metal) + { + preprocessor.setDefine(glslDefine); + } char temp[256]; - bx::snprintf(temp, sizeof(temp), "BGFX_SHADER_LANGUAGE_METAL=%d", metal); + bx::snprintf( + temp + , sizeof(temp) + , "BGFX_SHADER_LANGUAGE_METAL=%d" + , (profile->lang == ShadingLang::Metal) ? profile->id : 0 + ); preprocessor.setDefine(temp); } else if (0 == bx::strCmpI(platform, "windows") ) { preprocessor.setDefine("BX_PLATFORM_WINDOWS=1"); - char temp[256]; - bx::snprintf(temp, sizeof(temp), "BGFX_SHADER_LANGUAGE_HLSL=%d", hlsl); - preprocessor.setDefine(temp); + if (profile->lang == ShadingLang::HLSL) + { + preprocessor.setDefine(hlslDefine); + } + else if (profile->lang == ShadingLang::GLSL + || profile->lang == ShadingLang::ESSL) + { + preprocessor.setDefine(glslDefine); + } + else if (profile->lang == ShadingLang::SpirV) + { + preprocessor.setDefine("BGFX_SHADER_LANGUAGE_SPIRV=1"); + } } else if (0 == bx::strCmpI(platform, "orbis") ) { @@ -1034,6 +1239,22 @@ namespace bgfx preprocessor.setDefine("BGFX_SHADER_LANGUAGE_PSSL=1"); preprocessor.setDefine("lit=lit_reserved"); } + else + { + if (profile->lang == ShadingLang::HLSL) + { + preprocessor.setDefine(hlslDefine); + } + else if (profile->lang == ShadingLang::GLSL + || profile->lang == ShadingLang::ESSL) + { + preprocessor.setDefine(glslDefine); + } + else if (profile->lang == ShadingLang::SpirV) + { + preprocessor.setDefine("BGFX_SHADER_LANGUAGE_SPIRV=1"); + } + } preprocessor.setDefine("M_PI=3.1415926535897932384626433832795"); @@ -1052,7 +1273,7 @@ namespace bgfx break; default: - fprintf(stderr, "Unknown type: %c?!", _options.shaderType); + bx::printf("Unknown type: %c?!", _options.shaderType); return false; } @@ -1094,9 +1315,15 @@ namespace bgfx || 0 == bx::strCmp(typen, "noperspective", 13) || 0 == bx::strCmp(typen, "centroid", 8) ) { - interpolation = typen; + if ('f' == _options.shaderType + || profile->lang == ShadingLang::GLSL + || profile->lang == ShadingLang::ESSL) + { + interpolation = typen; + usesInterpolationQualifiers = true; + } + typen = nextWord(parse); - usesInterpolationQualifiers = true; } bx::StringView name = nextWord(parse); @@ -1135,7 +1362,8 @@ namespace bgfx var.m_name.assign(name.getPtr(), name.getTerm() ); var.m_semantics.assign(semantics.getPtr(), semantics.getTerm() ); - if (d3d == 9 + if (profile->lang == ShadingLang::HLSL + && profile->id < 400 && var.m_semantics == "BITANGENT") { var.m_semantics = "BINORMAL"; @@ -1159,6 +1387,7 @@ namespace bgfx InOut shaderOutputs; uint32_t inputHash = 0; uint32_t outputHash = 0; + bx::ErrorAssert err; char* data; char* input; @@ -1192,74 +1421,107 @@ namespace bgfx input = const_cast<char*>(bx::strLTrimSpace(data).getPtr() ); while (input[0] == '$') { - const char* str = bx::strLTrimSpace(input+1).getPtr(); + bx::StringView str = bx::strLTrimSpace(input+1); bx::StringView eol = bx::strFindEol(str); bx::StringView nl = bx::strFindNl(eol); input = const_cast<char*>(nl.getPtr() ); if (0 == bx::strCmp(str, "input", 5) ) { - str += 5; + str = bx::StringView(str.getPtr() + 5, str.getTerm() ); bx::StringView comment = bx::strFind(str, "//"); eol = !comment.isEmpty() && comment.getPtr() < eol.getPtr() ? comment.getPtr() : eol; - inputHash = parseInOut(shaderInputs, str, eol.getPtr() ); + inputHash = parseInOut(shaderInputs, bx::StringView(str.getPtr(), eol.getPtr() ) ); } else if (0 == bx::strCmp(str, "output", 6) ) { - str += 6; + str = bx::StringView(str.getPtr() + 6, str.getTerm() ); bx::StringView comment = bx::strFind(str, "//"); eol = !comment.isEmpty() && comment.getPtr() < eol.getPtr() ? comment.getPtr() : eol; - outputHash = parseInOut(shaderOutputs, str, eol.getPtr() ); + outputHash = parseInOut(shaderOutputs, bx::StringView(str.getPtr(), eol.getPtr() ) ); } else if (0 == bx::strCmp(str, "raw", 3) ) { raw = true; - str += 3; + str = bx::StringView(str.getPtr() + 3, str.getTerm() ); } input = const_cast<char*>(bx::strLTrimSpace(input).getPtr() ); } } - if (raw) + bool invalidShaderAttribute = false; + if ('v' == _options.shaderType) + { + for (InOut::const_iterator it = shaderInputs.begin(), itEnd = shaderInputs.end(); it != itEnd; ++it) + { + if (bx::findIdentifierMatch(it->c_str(), s_allowedVertexShaderInputs).isEmpty() ) + { + invalidShaderAttribute = true; + bx::printf( + "Invalid vertex shader input attribute '%s'.\n" + "\n" + "Valid input attributes:\n" + " a_position, a_normal, a_tangent, a_bitangent, a_color0, a_color1, a_color2, a_color3, a_indices, a_weight,\n" + " a_texcoord0, a_texcoord1, a_texcoord2, a_texcoord3, a_texcoord4, a_texcoord5, a_texcoord6, a_texcoord7,\n" + " i_data0, i_data1, i_data2, i_data3, i_data4.\n" + "\n" + , it->c_str() ); + break; + } + } + } + + if (invalidShaderAttribute) + { + } + else if (raw) { if ('f' == _options.shaderType) { - bx::write(_writer, BGFX_CHUNK_MAGIC_FSH); - bx::write(_writer, inputHash); - bx::write(_writer, uint32_t(0) ); + bx::write(_writer, BGFX_CHUNK_MAGIC_FSH, &err); } else if ('v' == _options.shaderType) { - bx::write(_writer, BGFX_CHUNK_MAGIC_VSH); - bx::write(_writer, uint32_t(0) ); - bx::write(_writer, outputHash); + bx::write(_writer, BGFX_CHUNK_MAGIC_VSH, &err); } else { - bx::write(_writer, BGFX_CHUNK_MAGIC_CSH); - bx::write(_writer, uint32_t(0) ); - bx::write(_writer, outputHash); + bx::write(_writer, BGFX_CHUNK_MAGIC_CSH, &err); } - if (0 != glsl) + bx::write(_writer, inputHash, &err); + bx::write(_writer, outputHash, &err); + } + + if (raw) + { + if (profile->lang == ShadingLang::GLSL) { - bx::write(_writer, uint16_t(0) ); + bx::write(_writer, uint16_t(0), &err); uint32_t shaderSize = (uint32_t)bx::strLen(input); - bx::write(_writer, shaderSize); - bx::write(_writer, input, shaderSize); - bx::write(_writer, uint8_t(0) ); + bx::write(_writer, shaderSize, &err); + bx::write(_writer, input, shaderSize, &err); + bx::write(_writer, uint8_t(0), &err); compiled = true; } - else if (0 != pssl) + else if (profile->lang == ShadingLang::Metal) + { + compiled = compileMetalShader(_options, BX_MAKEFOURCC('M', 'T', 'L', 0), input, _writer); + } + else if (profile->lang == ShadingLang::SpirV) + { + compiled = compileSPIRVShader(_options, profile->id, input, _writer); + } + else if (profile->lang == ShadingLang::PSSL) { compiled = compilePSSLShader(_options, 0, input, _writer); } else { - compiled = compileHLSLShader(_options, d3d, input, _writer); + compiled = compileHLSLShader(_options, profile->id, input, _writer); } } else if ('c' == _options.shaderType) // Compute @@ -1267,18 +1529,17 @@ namespace bgfx bx::StringView entry = bx::strFind(input, "void main()"); if (entry.isEmpty() ) { - fprintf(stderr, "Shader entry point 'void main()' is not found.\n"); + bx::printf("Shader entry point 'void main()' is not found.\n"); } else { - if (0 != glsl - || 0 != essl - || 0 != metal) + if (profile->lang == ShadingLang::GLSL + || profile->lang == ShadingLang::ESSL) { } else { - if (0 != pssl) + if (profile->lang != ShadingLang::PSSL) { preprocessor.writef(getPsslPreamble() ); } @@ -1354,7 +1615,12 @@ namespace bgfx { if (_options.preprocessOnly) { - bx::write(_writer, preprocessor.m_preprocessed.c_str(), (int32_t)preprocessor.m_preprocessed.size() ); + bx::write( + _writer + , preprocessor.m_preprocessed.c_str() + , (int32_t)preprocessor.m_preprocessed.size() + , &err + ); return true; } @@ -1362,56 +1628,57 @@ namespace bgfx { std::string code; - bx::write(_writer, BGFX_CHUNK_MAGIC_CSH); - bx::write(_writer, uint32_t(0) ); - bx::write(_writer, outputHash); + bx::write(_writer, BGFX_CHUNK_MAGIC_CSH, &err); + bx::write(_writer, uint32_t(0), &err); + bx::write(_writer, outputHash, &err); - if (0 != glsl - || 0 != essl) + if (profile->lang == ShadingLang::GLSL + || profile->lang == ShadingLang::ESSL) { - if (essl) + if (profile->lang == ShadingLang::ESSL) { bx::stringPrintf(code, "#version 310 es\n"); } else { - bx::stringPrintf(code, "#version %d\n", glsl == 0 ? 430 : glsl); + bx::stringPrintf( + code + , "#version %d\n" + , (profile->lang != ShadingLang::GLSL) ? 430 : profile->id + ); } -#if 1 code += preprocessor.m_preprocessed; - bx::write(_writer, uint16_t(0) ); + bx::write(_writer, uint16_t(0), &err); uint32_t shaderSize = (uint32_t)code.size(); - bx::write(_writer, shaderSize); - bx::write(_writer, code.c_str(), shaderSize); - bx::write(_writer, uint8_t(0) ); + bx::write(_writer, shaderSize, &err); + bx::write(_writer, code.c_str(), shaderSize, &err); + bx::write(_writer, uint8_t(0), &err); compiled = true; -#else - code += _comment; - code += preprocessor.m_preprocessed; - - compiled = compileGLSLShader(cmdLine, essl, code, writer); -#endif // 0 } else { code += _comment; code += preprocessor.m_preprocessed; - if (0 != spirv) + if (profile->lang == ShadingLang::Metal) { - compiled = compileSPIRVShader(_options, 0, code, _writer); + compiled = compileMetalShader(_options, BX_MAKEFOURCC('M', 'T', 'L', 0), code, _writer); } - else if (0 != pssl) + else if (profile->lang == ShadingLang::SpirV) + { + compiled = compileSPIRVShader(_options, profile->id, code, _writer); + } + else if (profile->lang == ShadingLang::PSSL) { compiled = compilePSSLShader(_options, 0, code, _writer); } else { - compiled = compileHLSLShader(_options, d3d, code, _writer); + compiled = compileHLSLShader(_options, profile->id, code, _writer); } } } @@ -1439,15 +1706,14 @@ namespace bgfx bx::StringView entry = bx::strFind(shader, "void main()"); if (entry.isEmpty() ) { - fprintf(stderr, "Shader entry point 'void main()' is not found.\n"); + bx::printf("Shader entry point 'void main()' is not found.\n"); } else { - if (0 != glsl - || 0 != essl - || 0 != metal) + if (profile->lang == ShadingLang::GLSL + || profile->lang == ShadingLang::ESSL) { - if (0 == essl) + if (profile->lang != ShadingLang::ESSL) { // bgfx shadow2D/Proj behave like EXT_shadow_samplers // not as GLSL language 1.2 specs shadow2D/Proj. @@ -1457,6 +1723,32 @@ namespace bgfx ); } + // gl_FragColor and gl_FragData are deprecated for essl > 300 + if (profile->lang == ShadingLang::ESSL + && profile->id >= 300) + { + const bool hasFragColor = !bx::strFind(input, "gl_FragColor").isEmpty(); + bool hasFragData[8] = {}; + uint32_t numFragData = 0; + for (uint32_t ii = 0; ii < BX_COUNTOF(hasFragData); ++ii) + { + char temp[32]; + bx::snprintf(temp, BX_COUNTOF(temp), "gl_FragData[%d]", ii); + hasFragData[ii] = !bx::strFind(input, temp).isEmpty(); + numFragData += hasFragData[ii]; + } + if (hasFragColor) + { + preprocessor.writef("#define gl_FragColor bgfx_FragColor\n"); + preprocessor.writef("out mediump vec4 bgfx_FragColor;\n"); + } + else if (numFragData) + { + preprocessor.writef("#define gl_FragData bgfx_FragData\n"); + preprocessor.writef("out mediump vec4 bgfx_FragData[gl_MaxDrawBuffers];\n"); + } + } + for (InOut::const_iterator it = shaderInputs.begin(), itEnd = shaderInputs.end(); it != itEnd; ++it) { VaryingMap::const_iterator varyingIt = varyingMap.find(*it); @@ -1468,21 +1760,23 @@ namespace bgfx if (0 == bx::strCmp(name, "a_", 2) || 0 == bx::strCmp(name, "i_", 2) ) { - preprocessor.writef("attribute %s %s %s %s;\n" - , var.m_precision.c_str() - , var.m_interpolation.c_str() - , var.m_type.c_str() - , name - ); + preprocessor.writef( + "attribute %s %s %s %s;\n" + , var.m_precision.c_str() + , var.m_interpolation.c_str() + , var.m_type.c_str() + , name + ); } else { - preprocessor.writef("%s varying %s %s %s;\n" - , var.m_interpolation.c_str() - , var.m_precision.c_str() - , var.m_type.c_str() - , name - ); + preprocessor.writef( + "%s varying %s %s %s;\n" + , var.m_interpolation.c_str() + , var.m_precision.c_str() + , var.m_type.c_str() + , name + ); } } } @@ -1503,7 +1797,7 @@ namespace bgfx } else { - if (0 != pssl) + if (profile->lang == ShadingLang::PSSL) { preprocessor.writef(getPsslPreamble() ); } @@ -1526,8 +1820,8 @@ namespace bgfx "#define mat4 float4x4\n" ); - if (hlsl != 0 - && hlsl < 4) + if (profile->lang == ShadingLang::HLSL + && profile->id < 400) { preprocessor.writef( "#define centroid\n" @@ -1548,7 +1842,7 @@ namespace bgfx } const bool hasFragColor = !bx::strFind(input, "gl_FragColor").isEmpty(); - const bool hasFragCoord = !bx::strFind(input, "gl_FragCoord").isEmpty() || hlsl > 3 || hlsl == 2; + const bool hasFragCoord = !bx::strFind(input, "gl_FragCoord").isEmpty() || profile->id >= 400; const bool hasFragDepth = !bx::strFind(input, "gl_FragDepth").isEmpty(); const bool hasFrontFacing = !bx::strFind(input, "gl_FrontFacing").isEmpty(); const bool hasPrimitiveId = !bx::strFind(input, "gl_PrimitiveID").isEmpty(); @@ -1572,10 +1866,10 @@ namespace bgfx // If it has gl_FragData or gl_FragColor, color target at // index 0 exists, otherwise shader is not modifying color // targets. - hasFragData[0] |= hasFragColor || d3d < 11; + hasFragData[0] |= hasFragColor || profile->id < 400; if (!insert.isEmpty() - && d3d < 11 + && profile->id < 400 && !hasFragColor) { insert = strInsert(const_cast<char*>(insert.getPtr()+1), "\ngl_FragColor = bgfx_VoidFrag;\n"); @@ -1609,7 +1903,7 @@ namespace bgfx } } - const uint32_t maxRT = d3d > 9 ? BX_COUNTOF(hasFragData) : 4; + const uint32_t maxRT = profile->id >= 400 ? BX_COUNTOF(hasFragData) : 4; for (uint32_t ii = 0; ii < BX_COUNTOF(hasFragData); ++ii) { @@ -1636,7 +1930,7 @@ namespace bgfx if (hasFrontFacing) { - if (hlsl == 3) + if (profile->id < 400) { preprocessor.writef( " \\\n\t%sfloat __vface : VFACE" @@ -1654,7 +1948,7 @@ namespace bgfx if (hasPrimitiveId) { - if (hlsl > 3) + if (profile->id >= 400) { preprocessor.writef( " \\\n\t%suint gl_PrimitiveID : SV_PrimitiveID" @@ -1663,7 +1957,7 @@ namespace bgfx } else { - fprintf(stderr, "gl_PrimitiveID builtin is not supported by this D3D9 HLSL.\n"); + bx::printf("gl_PrimitiveID builtin is not supported by D3D9 HLSL.\n"); return false; } } @@ -1674,7 +1968,7 @@ namespace bgfx if (hasFrontFacing) { - if (hlsl == 3) + if (profile->id < 400) { preprocessor.writef( "#define gl_FrontFacing (__vface >= 0.0)\n" @@ -1684,8 +1978,10 @@ namespace bgfx } else if ('v' == _options.shaderType) { - const bool hasVertexId = !bx::strFind(input, "gl_VertexID").isEmpty(); - const bool hasInstanceId = !bx::strFind(input, "gl_InstanceID").isEmpty(); + const bool hasVertexId = !bx::strFind(input, "gl_VertexID").isEmpty(); + const bool hasInstanceId = !bx::strFind(input, "gl_InstanceID").isEmpty(); + const bool hasViewportId = !bx::strFind(input, "gl_ViewportIndex").isEmpty(); + const bool hasLayerId = !bx::strFind(input, "gl_Layer").isEmpty(); bx::StringView brace = bx::strFind(bx::StringView(entry.getPtr(), shader.getTerm() ), "{"); if (!brace.isEmpty() ) @@ -1703,6 +1999,7 @@ namespace bgfx "\tvec4 gl_Position : SV_POSITION;\n" "#define gl_Position _varying_.gl_Position\n" ); + for (InOut::const_iterator it = shaderOutputs.begin(), itEnd = shaderOutputs.end(); it != itEnd; ++it) { VaryingMap::const_iterator varyingIt = varyingMap.find(*it); @@ -1723,6 +2020,39 @@ namespace bgfx ); } } + + if (hasViewportId) + { + if (profile->id >= 400) + { + preprocessor.writef( + "\tuint gl_ViewportIndex : SV_ViewportArrayIndex;\n" + "#define gl_ViewportIndex _varying_.gl_ViewportIndex\n" + ); + } + else + { + bx::printf("gl_ViewportIndex builtin is not supported by D3D9 HLSL.\n"); + return false; + } + } + + if (hasLayerId) + { + if (profile->id >= 400) + { + preprocessor.writef( + "\tuint gl_Layer : SV_RenderTargetArrayIndex;\n" + "#define gl_Layer _varying_.gl_Layer\n" + ); + } + else + { + bx::printf("gl_Layer builtin is not supported by D3D9 HLSL.\n"); + return false; + } + } + preprocessor.writef( "};\n" ); @@ -1748,7 +2078,7 @@ namespace bgfx if (hasVertexId) { - if (d3d > 9) + if (profile->id >= 400) { preprocessor.writef( " \\\n\t%suint gl_VertexID : SV_VertexID" @@ -1757,14 +2087,14 @@ namespace bgfx } else { - fprintf(stderr, "gl_VertexID builtin is not supported by this D3D9 HLSL.\n"); + bx::printf("gl_VertexID builtin is not supported by D3D9 HLSL.\n"); return false; } } if (hasInstanceId) { - if (d3d > 9) + if (profile->id >= 400) { preprocessor.writef( " \\\n\t%suint gl_InstanceID : SV_InstanceID" @@ -1773,7 +2103,7 @@ namespace bgfx } else { - fprintf(stderr, "gl_InstanceID builtin is not supported by this D3D9 HLSL.\n"); + bx::printf("gl_InstanceID builtin is not supported by D3D9 HLSL.\n"); return false; } } @@ -1804,21 +2134,6 @@ namespace bgfx "\t} \\\n" ); - if (hlsl != 0 - && hlsl <= 3) - { -// preprocessor.writef( -// "\tgl_Position.xy += u_viewTexel.xy * gl_Position.w; \\\n" -// ); - } - - if (0 != spirv) - { - preprocessor.writef( - "\tgl_Position.y = -gl_Position.y; \\\n" - ); - } - preprocessor.writef( "\treturn _varying_" ); @@ -1827,23 +2142,14 @@ namespace bgfx if (preprocessor.run(input) ) { - //BX_TRACE("Input file: %s", filePath); - //BX_TRACE("Output file: %s", outFilePath); - if (_options.preprocessOnly) { - if (0 != glsl) - { - if (essl != 0) - { - writef(_writer - , "#ifdef GL_ES\n" - "precision highp float;\n" - "#endif // GL_ES\n\n" - ); - } - } - bx::write(_writer, preprocessor.m_preprocessed.c_str(), (int32_t)preprocessor.m_preprocessed.size() ); + bx::write( + _writer + , preprocessor.m_preprocessed.c_str() + , (int32_t)preprocessor.m_preprocessed.size() + , &err + ); return true; } @@ -1853,63 +2159,81 @@ namespace bgfx if ('f' == _options.shaderType) { - bx::write(_writer, BGFX_CHUNK_MAGIC_FSH); - bx::write(_writer, inputHash); - bx::write(_writer, uint32_t(0) ); + bx::write(_writer, BGFX_CHUNK_MAGIC_FSH, &err); + bx::write(_writer, inputHash, &err); + bx::write(_writer, uint32_t(0), &err); } else if ('v' == _options.shaderType) { - bx::write(_writer, BGFX_CHUNK_MAGIC_VSH); - bx::write(_writer, uint32_t(0) ); - bx::write(_writer, outputHash); + bx::write(_writer, BGFX_CHUNK_MAGIC_VSH, &err); + bx::write(_writer, uint32_t(0), &err); + bx::write(_writer, outputHash, &err); } else { - bx::write(_writer, BGFX_CHUNK_MAGIC_CSH); - bx::write(_writer, uint32_t(0) ); - bx::write(_writer, outputHash); + bx::write(_writer, BGFX_CHUNK_MAGIC_CSH, &err); + bx::write(_writer, uint32_t(0), &err); + bx::write(_writer, outputHash, &err); } - if (0 != glsl - || 0 != essl - || 0 != metal) + if (profile->lang == ShadingLang::GLSL + || profile->lang == ShadingLang::ESSL) { - if (!bx::strFind(preprocessor.m_preprocessed.c_str(), "layout(std430").isEmpty() ) + const bx::StringView preprocessedInput(preprocessor.m_preprocessed.c_str() ); + uint32_t glsl_profile = profile->id; + + const bool usesBitsToEncoders = true + && _options.shaderType == 'f' + && !bx::findIdentifierMatch(preprocessedInput, s_bitsToEncoders).isEmpty() + ; + + if (!bx::strFind(preprocessedInput, "layout(std430").isEmpty() + || !bx::strFind(preprocessedInput, "image2D").isEmpty() + || usesBitsToEncoders) { - glsl = 430; + if (profile->lang == ShadingLang::GLSL + && glsl_profile < 430) + { + glsl_profile = 430; + } + else if (glsl_profile < 310) + { + glsl_profile = 310; + } } - if (glsl < 400) + if (glsl_profile < 400) { const bool usesTextureLod = false || !bx::findIdentifierMatch(input, s_ARB_shader_texture_lod).isEmpty() || !bx::findIdentifierMatch(input, s_EXT_shader_texture_lod).isEmpty() ; - const bool usesInstanceID = !bx::findIdentifierMatch(input, "gl_InstanceID").isEmpty(); - const bool usesGpuShader4 = !bx::findIdentifierMatch(input, s_EXT_gpu_shader4).isEmpty(); - const bool usesGpuShader5 = !bx::findIdentifierMatch(input, s_ARB_gpu_shader5).isEmpty(); - const bool usesTexelFetch = !bx::findIdentifierMatch(input, s_texelFetch).isEmpty(); - const bool usesTextureMS = !bx::findIdentifierMatch(input, s_ARB_texture_multisample).isEmpty(); - const bool usesTextureArray = !bx::findIdentifierMatch(input, s_textureArray).isEmpty(); - const bool usesPacking = !bx::findIdentifierMatch(input, s_ARB_shading_language_packing).isEmpty(); - - if (0 == essl) + + const bool usesGpuShader5 = true + && _options.shaderType != 'f' + && !bx::findIdentifierMatch(input, s_ARB_gpu_shader5).isEmpty() + ; + + const bool usesInstanceID = !bx::findIdentifierMatch(input, "gl_InstanceID").isEmpty(); + const bool usesGpuShader4 = !bx::findIdentifierMatch(input, s_EXT_gpu_shader4).isEmpty(); + const bool usesTexelFetch = !bx::findIdentifierMatch(input, s_texelFetch).isEmpty(); + const bool usesTextureMS = !bx::findIdentifierMatch(input, s_ARB_texture_multisample).isEmpty(); + const bool usesTextureArray = !bx::findIdentifierMatch(input, s_textureArray).isEmpty(); + const bool usesPacking = !bx::findIdentifierMatch(input, s_ARB_shading_language_packing).isEmpty(); + const bool usesViewportLayerArray = !bx::findIdentifierMatch(input, s_ARB_shader_viewport_layer_array).isEmpty(); + const bool usesUnsignedVecs = !bx::findIdentifierMatch(preprocessedInput, s_unsignedVecs).isEmpty(); + + if (profile->lang != ShadingLang::ESSL) { - const bool need130 = 120 == glsl && (false + const bool need130 = (120 == glsl_profile && (false || !bx::findIdentifierMatch(input, s_130).isEmpty() || usesInterpolationQualifiers || usesTexelFetch - ); + || usesUnsignedVecs + ) ); - if (0 != metal) - { - bx::stringPrintf(code, "#version 120\n"); - } - else - { - bx::stringPrintf(code, "#version %s\n", need130 ? "130" : _options.profile.c_str()); - glsl = 130; - } + bx::stringPrintf(code, "#version %d\n", need130 ? 130 : glsl_profile); + glsl_profile = 130; if (need130) { @@ -1925,6 +2249,13 @@ namespace bgfx ); } + if (usesViewportLayerArray) + { + bx::stringPrintf(code + , "#extension GL_ARB_shader_viewport_layer_array : enable\n" + ); + } + if (usesGpuShader4) { bx::stringPrintf(code @@ -1981,7 +2312,7 @@ namespace bgfx ); } - if (130 > glsl) + if (130 > glsl_profile) { bx::stringPrintf(code, "#define ivec2 vec2\n" @@ -2009,7 +2340,7 @@ namespace bgfx ); } - if (need130) + if (need130 || (glsl_profile >= 130)) { bx::stringPrintf(code , "#define bgfxShadow2D(_sampler, _coord) vec4_splat(texture(_sampler, _coord))\n" @@ -2020,62 +2351,31 @@ namespace bgfx { bx::stringPrintf(code , "#define bgfxShadow2D shadow2D\n" - "#define bgfxShadow2DProj shadow2DProj\n" + "#define bgfxShadow2DProj shader2DProj\n" ); } } else { - if (usesInterpolationQualifiers) + if ((glsl_profile < 300) && usesUnsignedVecs) + { + glsl_profile = 300; + } + + if (glsl_profile > 100) { - bx::stringPrintf(code, "#version 300 es\n"); + bx::stringPrintf(code, "#version %d es\n", glsl_profile); bx::stringPrintf(code, "#define attribute in\n"); bx::stringPrintf(code, "#define varying %s\n" , 'f' == _options.shaderType ? "in" : "out" ); + bx::stringPrintf(code, "precision highp float;\n"); + bx::stringPrintf(code, "precision highp int;\n"); } - else if (essl == 2) + + if (glsl_profile >= 300) { - code += - "mat2 transpose(mat2 _mtx)\n" - "{\n" - " vec2 v0 = _mtx[0];\n" - " vec2 v1 = _mtx[1];\n" - "\n" - " return mat2(\n" - " vec2(v0.x, v1.x)\n" - " , vec2(v0.y, v1.y)\n" - " );\n" - "}\n" - "\n" - "mat3 transpose(mat3 _mtx)\n" - "{\n" - " vec3 v0 = _mtx[0];\n" - " vec3 v1 = _mtx[1];\n" - " vec3 v2 = _mtx[2];\n" - "\n" - " return mat3(\n" - " vec3(v0.x, v1.x, v2.x)\n" - " , vec3(v0.y, v1.y, v2.y)\n" - " , vec3(v0.z, v1.z, v2.z)\n" - " );\n" - "}\n" - "\n" - "mat4 transpose(mat4 _mtx)\n" - "{\n" - " vec4 v0 = _mtx[0];\n" - " vec4 v1 = _mtx[1];\n" - " vec4 v2 = _mtx[2];\n" - " vec4 v3 = _mtx[3];\n" - "\n" - " return mat4(\n" - " vec4(v0.x, v1.x, v2.x, v3.x)\n" - " , vec4(v0.y, v1.y, v2.y, v3.y)\n" - " , vec4(v0.z, v1.z, v2.z, v3.z)\n" - " , vec4(v0.w, v1.w, v2.w, v3.w)\n" - " );\n" - "}\n" - ; + bx::stringPrintf(code, "precision highp sampler2DArray;\n"); } // Pretend that all extensions are available. @@ -2103,7 +2403,7 @@ namespace bgfx bx::stringPrintf(code, "#extension GL_OES_texture_3D : enable\n"); } - if (!bx::findIdentifierMatch(input, s_EXT_shadow_samplers).isEmpty() ) + if ((glsl_profile < 300) && (!bx::findIdentifierMatch(input, s_EXT_shadow_samplers).isEmpty())) { bx::stringPrintf(code , "#extension GL_EXT_shadow_samplers : enable\n" @@ -2111,6 +2411,13 @@ namespace bgfx "#define shadow2DProj shadow2DProjEXT\n" ); } + else + { + bx::stringPrintf(code + , "#define shadow2D(_sampler, _coord) texture(_sampler, _coord)\n" + "#define shadow2DProj(_sampler, _coord) textureProj(_sampler, _coord)\n" + ); + } if (usesGpuShader5) { @@ -2126,7 +2433,7 @@ namespace bgfx ); } - if (!bx::findIdentifierMatch(input, "gl_FragDepth").isEmpty() ) + if ((glsl_profile < 300) && (!bx::findIdentifierMatch(input, "gl_FragDepth").isEmpty() )) { bx::stringPrintf(code , "#extension GL_EXT_frag_depth : enable\n" @@ -2141,25 +2448,76 @@ namespace bgfx ); } - bx::stringPrintf(code - , "#define ivec2 vec2\n" - "#define ivec3 vec3\n" - "#define ivec4 vec4\n" - ); + if (glsl_profile == 100) + { + code += + "mat2 transpose(mat2 _mtx)\n" + "{\n" + " vec2 v0 = _mtx[0];\n" + " vec2 v1 = _mtx[1];\n" + "\n" + " return mat2(\n" + " vec2(v0.x, v1.x)\n" + " , vec2(v0.y, v1.y)\n" + " );\n" + "}\n" + "\n" + "mat3 transpose(mat3 _mtx)\n" + "{\n" + " vec3 v0 = _mtx[0];\n" + " vec3 v1 = _mtx[1];\n" + " vec3 v2 = _mtx[2];\n" + "\n" + " return mat3(\n" + " vec3(v0.x, v1.x, v2.x)\n" + " , vec3(v0.y, v1.y, v2.y)\n" + " , vec3(v0.z, v1.z, v2.z)\n" + " );\n" + "}\n" + "\n" + "mat4 transpose(mat4 _mtx)\n" + "{\n" + " vec4 v0 = _mtx[0];\n" + " vec4 v1 = _mtx[1];\n" + " vec4 v2 = _mtx[2];\n" + " vec4 v3 = _mtx[3];\n" + "\n" + " return mat4(\n" + " vec4(v0.x, v1.x, v2.x, v3.x)\n" + " , vec4(v0.y, v1.y, v2.y, v3.y)\n" + " , vec4(v0.z, v1.z, v2.z, v3.z)\n" + " , vec4(v0.w, v1.w, v2.w, v3.w)\n" + " );\n" + "}\n" + ; + } } } else { - bx::stringPrintf(code, "#version %d\n", glsl); + bx::stringPrintf(code, "#version %d\n", glsl_profile); + + if (120 < glsl_profile) + { + if (!bx::findIdentifierMatch(input, "gl_FragColor").isEmpty() ) + { + bx::stringPrintf(code + , "out vec4 bgfx_FragColor;\n" + "#define gl_FragColor bgfx_FragColor\n" + ); + } + } bx::stringPrintf(code - , "#define texture2DLod textureLod\n" - "#define texture2DGrad textureGrad\n" - "#define texture2DProjLod textureProjLod\n" - "#define texture2DProjGrad textureProjGrad\n" - "#define textureCubeLod textureLod\n" - "#define textureCubeGrad textureGrad\n" - "#define texture3D texture\n" + , "#define texture2D texture\n" + "#define texture2DLod textureLod\n" + "#define texture2DGrad textureGrad\n" + "#define texture2DProjLod textureProjLod\n" + "#define texture2DProjGrad textureProjGrad\n" + "#define textureCubeLod textureLod\n" + "#define textureCubeGrad textureGrad\n" + "#define texture3D texture\n" + "#define texture2DLodOffset textureLodOffset\n" ); bx::stringPrintf(code, "#define attribute in\n"); @@ -2173,16 +2531,17 @@ namespace bgfx ); } - if (glsl > 400) + if ( (profile->lang == ShadingLang::GLSL && glsl_profile > 400) + || (profile->lang == ShadingLang::ESSL && glsl_profile > 300) ) { code += preprocessor.m_preprocessed; - bx::write(_writer, uint16_t(0) ); + bx::write(_writer, uint16_t(0), &err); uint32_t shaderSize = (uint32_t)code.size(); - bx::write(_writer, shaderSize); - bx::write(_writer, code.c_str(), shaderSize); - bx::write(_writer, uint8_t(0) ); + bx::write(_writer, shaderSize, &err); + bx::write(_writer, code.c_str(), shaderSize, &err); + bx::write(_writer, uint8_t(0), &err); compiled = true; } @@ -2191,7 +2550,12 @@ namespace bgfx code += _comment; code += preprocessor.m_preprocessed; - compiled = compileGLSLShader(_options, metal ? BX_MAKEFOURCC('M', 'T', 'L', 0) : essl, code, _writer); + if (profile->lang == ShadingLang::ESSL) + { + glsl_profile |= 0x80000000; + } + + compiled = compileGLSLShader(_options, glsl_profile, code, _writer); } } else @@ -2199,17 +2563,21 @@ namespace bgfx code += _comment; code += preprocessor.m_preprocessed; - if (0 != spirv) + if (profile->lang == ShadingLang::Metal) + { + compiled = compileMetalShader(_options, BX_MAKEFOURCC('M', 'T', 'L', 0), code, _writer); + } + else if (profile->lang == ShadingLang::SpirV) { - compiled = compileSPIRVShader(_options, 0, code, _writer); + compiled = compileSPIRVShader(_options, profile->id, code, _writer); } - else if (0 != pssl) + else if (profile->lang == ShadingLang::PSSL) { compiled = compilePSSLShader(_options, 0, code, _writer); } else { - compiled = compileHLSLShader(_options, d3d, code, _writer); + compiled = compileHLSLShader(_options, profile->id, code, _writer); } } } @@ -2242,8 +2610,8 @@ namespace bgfx if (cmdLine.hasArg('v', "version") ) { - fprintf(stderr - , "shaderc, bgfx shader compiler tool, version %d.%d.%d.\n" + bx::printf( + "shaderc, bgfx shader compiler tool, version %d.%d.%d.\n" , BGFX_SHADERC_VERSION_MAJOR , BGFX_SHADERC_VERSION_MINOR , BGFX_API_VERSION @@ -2266,10 +2634,11 @@ namespace bgfx return bx::kExitFailure; } + bool consoleOut = cmdLine.hasArg("stdout"); const char* outFilePath = cmdLine.findOption('o'); - if (NULL == outFilePath) + if (NULL == outFilePath && !consoleOut) { - help("Output file name must be specified."); + help("Output file name must be specified or use \"--stdout\" to output to stdout."); return bx::kExitFailure; } @@ -2282,7 +2651,7 @@ namespace bgfx Options options; options.inputFilePath = filePath; - options.outputFilePath = outFilePath; + options.outputFilePath = consoleOut ? "" : outFilePath; options.shaderType = bx::toLower(type[0]); options.disasm = cmdLine.hasArg('\0', "disasm"); @@ -2403,7 +2772,7 @@ namespace bgfx bx::FileReader reader; if (!bx::open(&reader, filePath) ) { - fprintf(stderr, "Unable to open file '%s'.\n", filePath); + bx::printf("Unable to open file '%s'.\n", filePath); } else { @@ -2423,14 +2792,14 @@ namespace bgfx } else { - fprintf(stderr, "ERROR: Failed to parse varying def file: \"%s\" No input/output semantics will be generated in the code!\n", varyingdef); + bx::printf("ERROR: Failed to parse varying def file: \"%s\" No input/output semantics will be generated in the code!\n", varyingdef); } } const size_t padding = 16384; uint32_t size = (uint32_t)bx::getSize(&reader); char* data = new char[size+padding+1]; - size = (uint32_t)bx::read(&reader, data, size); + size = (uint32_t)bx::read(&reader, data, size, bx::ErrorAssert{}); if (data[0] == '\xef' && data[1] == '\xbb' @@ -2448,25 +2817,31 @@ namespace bgfx bx::FileWriter* writer = NULL; - if (!bin2c.isEmpty() ) + if (!consoleOut) { - writer = new Bin2cWriter(bin2c); - } - else - { - writer = new bx::FileWriter; - } + if (!bin2c.isEmpty()) + { + writer = new Bin2cWriter(bin2c); + } + else + { + writer = new bx::FileWriter; + } - if (!bx::open(writer, outFilePath) ) - { - fprintf(stderr, "Unable to open output file '%s'.", outFilePath); - return bx::kExitFailure; + if (!bx::open(writer, outFilePath)) + { + bx::printf("Unable to open output file '%s'.\n", outFilePath); + return bx::kExitFailure; + } } - compiled = compileShader(varying, commandLineComment.c_str(), data, size, options, writer); + compiled = compileShader(varying, commandLineComment.c_str(), data, size, options, consoleOut ? bx::getStdOut() : writer); - bx::close(writer); - delete writer; + if (!consoleOut) + { + bx::close(writer); + delete writer; + } } if (compiled) @@ -2474,9 +2849,9 @@ namespace bgfx return bx::kExitSuccess; } - remove(outFilePath); + bx::remove(outFilePath); - fprintf(stderr, "Failed to build shader.\n"); + bx::printf("Failed to build shader.\n"); return bx::kExitFailure; } |