summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/bgfx/tools/shaderc/shaderc.cpp
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/bgfx/tools/shaderc/shaderc.cpp')
-rw-r--r--3rdparty/bgfx/tools/shaderc/shaderc.cpp1155
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;
}