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.cpp1937
1 files changed, 1066 insertions, 871 deletions
diff --git a/3rdparty/bgfx/tools/shaderc/shaderc.cpp b/3rdparty/bgfx/tools/shaderc/shaderc.cpp
index 57934b5c632..f8d22df4fd1 100644
--- a/3rdparty/bgfx/tools/shaderc/shaderc.cpp
+++ b/3rdparty/bgfx/tools/shaderc/shaderc.cpp
@@ -5,6 +5,7 @@
#include "shaderc.h"
#include <bx/commandline.h>
+#include <bx/filepath.h>
#define MAX_TAGS 256
extern "C"
@@ -12,14 +13,17 @@ extern "C"
#include <fpp.h>
} // extern "C"
+#define BGFX_CHUNK_MAGIC_CSH BX_MAKEFOURCC('C', 'S', 'H', 0x3)
+#define BGFX_CHUNK_MAGIC_FSH BX_MAKEFOURCC('F', 'S', 'H', 0x5)
+#define BGFX_CHUNK_MAGIC_VSH BX_MAKEFOURCC('V', 'S', 'H', 0x5)
+
+#define BGFX_SHADERC_VERSION_MAJOR 1
+#define BGFX_SHADERC_VERSION_MINOR 6
+
namespace bgfx
{
bool g_verbose = false;
- #define BGFX_CHUNK_MAGIC_CSH BX_MAKEFOURCC('C', 'S', 'H', 0x2)
- #define BGFX_CHUNK_MAGIC_FSH BX_MAKEFOURCC('F', 'S', 'H', 0x4)
- #define BGFX_CHUNK_MAGIC_VSH BX_MAKEFOURCC('V', 'S', 'H', 0x4)
-
static const char* s_ARB_shader_texture_lod[] =
{
"texture2DLod",
@@ -78,6 +82,13 @@ namespace bgfx
NULL
};
+ static const char* s_EXT_gpu_shader4[] =
+ {
+ "gl_VertexID",
+ "gl_InstanceID",
+ NULL
+ };
+
static const char* s_ARB_gpu_shader5[] =
{
"bitfieldReverse",
@@ -139,13 +150,84 @@ namespace bgfx
};
BX_STATIC_ASSERT(BX_COUNTOF(s_uniformTypeName) == UniformType::Count*2);
+
+ Options::Options()
+ : shaderType(' ')
+ , disasm(false)
+ , raw(false)
+ , preprocessOnly(false)
+ , depends(false)
+ , debugInformation(false)
+ , avoidFlowControl(false)
+ , noPreshader(false)
+ , partialPrecision(false)
+ , preferFlowControl(false)
+ , backwardsCompatibility(false)
+ , warningsAreErrors(false)
+ , optimize(false)
+ , optimizationLevel(3)
+ {
+ }
+
+ void Options::dump()
+ {
+ BX_TRACE("Options:\n"
+ "\t shaderType: %c\n"
+ "\t platform: %s\n"
+ "\t profile: %s\n"
+ "\t inputFile: %s\n"
+ "\t outputFile: %s\n"
+ "\t disasm: %s\n"
+ "\t raw: %s\n"
+ "\t preprocessOnly: %s\n"
+ "\t depends: %s\n"
+ "\t debugInformation: %s\n"
+ "\t avoidFlowControl: %s\n"
+ "\t noPreshader: %s\n"
+ "\t partialPrecision: %s\n"
+ "\t preferFlowControl: %s\n"
+ "\t backwardsCompatibility: %s\n"
+ "\t warningsAreErrors: %s\n"
+ "\t optimize: %s\n"
+ "\t optimizationLevel: %d\n"
+
+ , shaderType
+ , platform.c_str()
+ , profile.c_str()
+ , inputFilePath.c_str()
+ , outputFilePath.c_str()
+ , disasm ? "true" : "false"
+ , raw ? "true" : "false"
+ , preprocessOnly ? "true" : "false"
+ , depends ? "true" : "false"
+ , debugInformation ? "true" : "false"
+ , avoidFlowControl ? "true" : "false"
+ , noPreshader ? "true" : "false"
+ , partialPrecision ? "true" : "false"
+ , preferFlowControl ? "true" : "false"
+ , backwardsCompatibility ? "true" : "false"
+ , warningsAreErrors ? "true" : "false"
+ , optimize ? "true" : "false"
+ , optimizationLevel
+ );
+
+ for(size_t i=0; i<includeDirs.size(); ++i)
+ BX_TRACE("\t include :%s\n", includeDirs[i].c_str());
+
+ for(size_t i=0; i<defines.size(); ++i)
+ BX_TRACE("\t define :%s\n", defines[i].c_str());
+
+ for(size_t i=0; i<dependencies.size(); ++i)
+ BX_TRACE("\t dependency :%s\n", dependencies[i].c_str());
+ }
+
const char* interpolationDx11(const char* _glsl)
{
- if (0 == strcmp(_glsl, "smooth") )
+ if (0 == bx::strCmp(_glsl, "smooth") )
{
return "linear";
}
- else if (0 == strcmp(_glsl, "flat") )
+ else if (0 == bx::strCmp(_glsl, "flat") )
{
return "nointerpolation";
}
@@ -169,7 +251,7 @@ namespace bgfx
for (uint32_t ii = 0; ii < UniformType::Count*2; ++ii)
{
if (NULL != s_uniformTypeName[ii]
- && 0 == strcmp(_name, s_uniformTypeName[ii]) )
+ && 0 == bx::strCmp(_name, s_uniformTypeName[ii]) )
{
return UniformType::Enum(ii/2);
}
@@ -201,7 +283,7 @@ namespace bgfx
return len;
}
- class Bin2cWriter : public bx::CrtFileWriter
+ class Bin2cWriter : public bx::FileWriter
{
public:
Bin2cWriter(const char* _name)
@@ -213,13 +295,13 @@ namespace bgfx
{
}
- virtual void close() BX_OVERRIDE
+ virtual void close() override
{
generate();
- return bx::CrtFileWriter::close();
+ return bx::FileWriter::close();
}
- virtual int32_t write(const void* _data, int32_t _size, bx::Error*) BX_OVERRIDE
+ virtual int32_t write(const void* _data, int32_t _size, bx::Error*) override
{
const char* data = (const char*)_data;
m_buffer.insert(m_buffer.end(), data, data+_size);
@@ -290,7 +372,7 @@ namespace bgfx
}
bx::Error err;
- int32_t size = bx::CrtFileWriter::write(out, len, &err);
+ int32_t size = bx::FileWriter::write(out, len, &err);
va_end(argList);
@@ -321,7 +403,7 @@ namespace bgfx
File(const char* _filePath)
: m_data(NULL)
{
- bx::CrtFileReader reader;
+ bx::FileReader reader;
if (bx::open(&reader, _filePath) )
{
m_size = (uint32_t)bx::getSize(&reader);
@@ -333,7 +415,7 @@ namespace bgfx
&& m_data[1] == '\xbb'
&& m_data[2] == '\xbf')
{
- memmove(m_data, &m_data[3], m_size-3);
+ bx::memMove(m_data, &m_data[3], m_size-3);
m_size -= 3;
}
@@ -363,26 +445,29 @@ namespace bgfx
char* strInsert(char* _str, const char* _insert)
{
- uint32_t len = bx::strnlen(_insert);
- bx::memMove(&_str[len], _str, bx::strnlen(_str) );
+ uint32_t len = bx::strLen(_insert);
+ bx::memMove(&_str[len], _str, bx::strLen(_str) );
bx::memCopy(_str, _insert, len);
return _str + len;
}
void strReplace(char* _str, const char* _find, const char* _replace)
{
- const int32_t len = bx::strnlen(_find);
+ const int32_t len = bx::strLen(_find);
char* replace = (char*)alloca(len+1);
- bx::strlcpy(replace, _replace, len+1);
- for (int32_t ii = bx::strnlen(replace); ii < len; ++ii)
+ bx::strCopy(replace, len+1, _replace);
+ for (int32_t ii = bx::strLen(replace); ii < len; ++ii)
{
replace[ii] = ' ';
}
replace[len] = '\0';
- BX_CHECK(len >= bx::strnlen(_replace), "");
- for (const char* ptr = bx::strnstr(_str, _find); NULL != ptr; ptr = bx::strnstr(ptr + len, _find) )
+ BX_CHECK(len >= bx::strLen(_replace), "");
+ for (const char* ptr = bx::strFind(_str, _find)
+ ; NULL != ptr
+ ; ptr = bx::strFind(ptr + len, _find)
+ )
{
bx::memCopy(const_cast<char*>(ptr), replace, len);
}
@@ -398,15 +483,22 @@ namespace bgfx
{
fprintf(stderr, "Code:\n---\n");
- LineReader lr(_code);
- for (int32_t line = 1; !lr.isEof() && line < _end; ++line)
+ bx::Error err;
+ LineReader reader(_code);
+ for (int32_t line = 1; err.isOk() && line < _end; ++line)
{
- if (line >= _start)
+ char str[4096];
+ int32_t len = bx::read(&reader, str, BX_COUNTOF(str), &err);
+
+ if (err.isOk()
+ && line >= _start)
{
+ std::string strLine(str, len);
+
if (_line == line)
{
fprintf(stderr, "\n");
- fprintf(stderr, ">>> %3d: %s", line, lr.getLine().c_str() );
+ fprintf(stderr, ">>> %3d: %s", line, strLine.c_str() );
if (-1 != _column)
{
fprintf(stderr, ">>> %3d: %*s\n", _column, _column, "^");
@@ -415,13 +507,9 @@ namespace bgfx
}
else
{
- fprintf(stderr, " %3d: %s", line, lr.getLine().c_str() );
+ fprintf(stderr, " %3d: %s", line, strLine.c_str() );
}
}
- else
- {
- lr.skipLine();
- }
}
fprintf(stderr, "---\n");
@@ -429,7 +517,7 @@ namespace bgfx
void writeFile(const char* _filePath, const void* _data, int32_t _size)
{
- bx::CrtFileWriter out;
+ bx::FileWriter out;
if (bx::open(&out, _filePath) )
{
bx::write(&out, _data, _size);
@@ -517,7 +605,10 @@ namespace bgfx
{
char* start = scratch(_includeDir);
- for (char* split = strchr(start, ';'); NULL != split; split = strchr(start, ';') )
+ for (char* split = const_cast<char*>(bx::strFind(start, ';') )
+ ; NULL != split
+ ; split = const_cast<char*>(bx::strFind(start, ';') )
+ )
{
*split = '\0';
m_tagptr->tag = FPPTAG_INCLUDE_DIR;
@@ -545,7 +636,7 @@ namespace bgfx
m_input = m_default;
m_input += "\n\n";
- int32_t len = bx::strnlen(_input)+1;
+ int32_t len = bx::strLen(_input)+1;
char* temp = new char[len];
bx::eolLF(temp, len, _input);
m_input += temp;
@@ -606,8 +697,8 @@ namespace bgfx
char* scratch(const char* _str)
{
char* result = &m_scratch[m_scratchPos];
- strcpy(result, _str);
- m_scratchPos += (uint32_t)strlen(_str)+1;
+ bx::strCopy(result, uint32_t(sizeof(m_scratch)-m_scratchPos), _str);
+ m_scratchPos += (uint32_t)bx::strLen(_str)+1;
return result;
}
@@ -688,6 +779,15 @@ namespace bgfx
strReplace(_data, find, "bgfx_VoidFrag");
}
+ const char* baseName(const char* _filePath)
+ {
+ bx::FilePath fp(_filePath);
+ char tmp[bx::kMaxFilePath];
+ bx::strCopy(tmp, BX_COUNTOF(tmp), fp.getFileName() );
+ const char* base = bx::strFind(_filePath, tmp);
+ return base;
+ }
+
// c - compute
// d - domain
// f - fragment
@@ -715,9 +815,12 @@ namespace bgfx
}
fprintf(stderr
- , "shaderc, bgfx shader compiler tool\n"
+ , "shaderc, bgfx shader compiler tool, version %d.%d.%d.\n"
"Copyright 2011-2017 Branimir Karadzic. All rights reserved.\n"
"License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause\n\n"
+ , BGFX_SHADERC_VERSION_MAJOR
+ , BGFX_SHADERC_VERSION_MINOR
+ , BGFX_API_VERSION
);
fprintf(stderr
@@ -725,6 +828,8 @@ namespace bgfx
"\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 use -i multiple times).\n"
" -o <file path> Output file path.\n"
@@ -760,47 +865,9 @@ namespace bgfx
);
}
- int compileShader(int _argc, const char* _argv[])
- {
- bx::CommandLine cmdLine(_argc, _argv);
-
- if (cmdLine.hasArg('h', "help") )
- {
- help();
- return EXIT_FAILURE;
- }
-
- g_verbose = cmdLine.hasArg("verbose");
-
- const char* filePath = cmdLine.findOption('f');
- if (NULL == filePath)
- {
- help("Shader file name must be specified.");
- return EXIT_FAILURE;
- }
-
- const char* outFilePath = cmdLine.findOption('o');
- if (NULL == outFilePath)
- {
- help("Output file name must be specified.");
- return EXIT_FAILURE;
- }
-
- const char* type = cmdLine.findOption('\0', "type");
- if (NULL == type)
- {
- help("Must specify shader type.");
- return EXIT_FAILURE;
- }
-
- const char* platform = cmdLine.findOption('\0', "platform");
- if (NULL == platform)
- {
- platform = "";
- }
-
- bool raw = cmdLine.hasArg('\0', "raw");
+ bool compileShader(const char* _varying, char* _shader, uint32_t _shaderLen, Options& _options, bx::FileWriter* _writer)
+ {
uint32_t glsl = 0;
uint32_t essl = 0;
uint32_t hlsl = 0;
@@ -808,35 +875,35 @@ namespace bgfx
uint32_t metal = 0;
uint32_t pssl = 0;
uint32_t spirv = 0;
- const char* profile = cmdLine.findOption('p', "profile");
- if (NULL != profile)
+ const char* profile = _options.profile.c_str();
+ if ('\0' != profile[0])
{
- if (0 == strncmp(&profile[1], "s_4_0_level", 11) )
+ if (0 == bx::strCmp(&profile[1], "s_4_0_level", 11) )
{
hlsl = 2;
}
- else if (0 == strncmp(&profile[1], "s_3", 3) )
+ else if (0 == bx::strCmp(&profile[1], "s_3", 3) )
{
hlsl = 3;
d3d = 9;
}
- else if (0 == strncmp(&profile[1], "s_4", 3) )
+ else if (0 == bx::strCmp(&profile[1], "s_4", 3) )
{
hlsl = 4;
}
- else if (0 == strncmp(&profile[1], "s_5", 3) )
+ else if (0 == bx::strCmp(&profile[1], "s_5", 3) )
{
hlsl = 5;
}
- else if (0 == strcmp(profile, "metal") )
+ else if (0 == bx::strCmp(profile, "metal") )
{
metal = 1;
}
- else if (0 == strcmp(profile, "pssl") )
+ else if (0 == bx::strCmp(profile, "pssl") )
{
pssl = 1;
}
- else if (0 == strcmp(profile, "spirv") )
+ else if (0 == bx::strCmp(profile, "spirv") )
{
spirv = 1;
}
@@ -850,84 +917,24 @@ namespace bgfx
essl = 2;
}
- const char* bin2c = NULL;
- if (cmdLine.hasArg("bin2c") )
- {
- bin2c = cmdLine.findOption("bin2c");
- if (NULL == bin2c)
- {
- bin2c = bx::baseName(outFilePath);
- uint32_t len = (uint32_t)strlen(bin2c);
- char* temp = (char*)alloca(len+1);
- for (char *out = temp; *bin2c != '\0';)
- {
- char ch = *bin2c++;
- if (isalnum(ch) )
- {
- *out++ = ch;
- }
- else
- {
- *out++ = '_';
- }
- }
- temp[len] = '\0';
-
- bin2c = temp;
- }
- }
-
- bool depends = cmdLine.hasArg("depends");
- bool preprocessOnly = cmdLine.hasArg("preprocess");
- const char* includeDir = cmdLine.findOption('i');
-
- BX_TRACE("depends: %d", depends);
- BX_TRACE("preprocessOnly: %d", preprocessOnly);
- BX_TRACE("includeDir: %s", includeDir);
-
- Preprocessor preprocessor(filePath, 0 != essl);
+ Preprocessor preprocessor(_options.inputFilePath.c_str(), 0 != essl);
- for (int ii = 1; NULL != includeDir; ++ii)
- {
- preprocessor.addInclude(includeDir);
- includeDir = cmdLine.findOption(ii, 'i');
- }
-
- std::string dir;
- {
- const char* base = bx::baseName(filePath);
+ for(size_t i=0; i<_options.includeDirs.size(); ++i)
+ preprocessor.addInclude(_options.includeDirs[i].c_str());
- if (base != filePath)
- {
- dir.assign(filePath, base-filePath);
- preprocessor.addInclude(dir.c_str() );
- }
- }
+ for(size_t i=0; i<_options.defines.size(); ++i)
+ preprocessor.setDefine(_options.defines[i].c_str());
- const char* defines = cmdLine.findOption("define");
- while (NULL != defines
- && '\0' != *defines)
- {
- defines = bx::strws(defines);
- const char* eol = strchr(defines, ';');
- if (NULL == eol)
- {
- eol = defines + strlen(defines);
- }
- std::string define(defines, eol);
- preprocessor.setDefine(define.c_str() );
- defines = ';' == *eol ? eol+1 : eol;
- }
+ for(size_t i=0; i<_options.dependencies.size(); ++i)
+ preprocessor.addDependency(_options.dependencies[i].c_str());
preprocessor.setDefaultDefine("BX_PLATFORM_ANDROID");
preprocessor.setDefaultDefine("BX_PLATFORM_EMSCRIPTEN");
preprocessor.setDefaultDefine("BX_PLATFORM_IOS");
preprocessor.setDefaultDefine("BX_PLATFORM_LINUX");
- preprocessor.setDefaultDefine("BX_PLATFORM_NACL");
preprocessor.setDefaultDefine("BX_PLATFORM_OSX");
preprocessor.setDefaultDefine("BX_PLATFORM_PS4");
preprocessor.setDefaultDefine("BX_PLATFORM_WINDOWS");
- preprocessor.setDefaultDefine("BX_PLATFORM_XBOX360");
preprocessor.setDefaultDefine("BX_PLATFORM_XBOXONE");
// preprocessor.setDefaultDefine("BGFX_SHADER_LANGUAGE_ESSL");
@@ -947,22 +954,24 @@ namespace bgfx
, essl ? 1 : glsl
);
- if (0 == bx::strincmp(platform, "android") )
+ 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");
}
- else if (0 == bx::strincmp(platform, "asm.js") )
+ else if (0 == bx::strCmpI(platform, "asm.js") )
{
preprocessor.setDefine("BX_PLATFORM_EMSCRIPTEN=1");
preprocessor.setDefine("BGFX_SHADER_LANGUAGE_GLSL=1");
}
- else if (0 == bx::strincmp(platform, "ios") )
+ else if (0 == bx::strCmpI(platform, "ios") )
{
preprocessor.setDefine("BX_PLATFORM_IOS=1");
preprocessor.setDefine("BGFX_SHADER_LANGUAGE_GLSL=1");
}
- else if (0 == bx::strincmp(platform, "linux") )
+ else if (0 == bx::strCmpI(platform, "linux") )
{
preprocessor.setDefine("BX_PLATFORM_LINUX=1");
if (0 != spirv)
@@ -974,12 +983,7 @@ namespace bgfx
preprocessor.setDefine(glslDefine);
}
}
- else if (0 == bx::strincmp(platform, "nacl") )
- {
- preprocessor.setDefine("BX_PLATFORM_NACL=1");
- preprocessor.setDefine("BGFX_SHADER_LANGUAGE_GLSL=1");
- }
- else if (0 == bx::strincmp(platform, "osx") )
+ else if (0 == bx::strCmpI(platform, "osx") )
{
preprocessor.setDefine("BX_PLATFORM_OSX=1");
preprocessor.setDefine(glslDefine);
@@ -987,19 +991,14 @@ namespace bgfx
bx::snprintf(temp, sizeof(temp), "BGFX_SHADER_LANGUAGE_METAL=%d", metal);
preprocessor.setDefine(temp);
}
- else if (0 == bx::strincmp(platform, "windows") )
+ 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);
}
- else if (0 == bx::strincmp(platform, "xbox360") )
- {
- preprocessor.setDefine("BX_PLATFORM_XBOX360=1");
- preprocessor.setDefine("BGFX_SHADER_LANGUAGE_HLSL=3");
- }
- else if (0 == bx::strincmp(platform, "orbis") )
+ else if (0 == bx::strCmpI(platform, "orbis") )
{
preprocessor.setDefine("BX_PLATFORM_PS4=1");
preprocessor.setDefine("BGFX_SHADER_LANGUAGE_PSSL=1");
@@ -1008,8 +1007,7 @@ namespace bgfx
preprocessor.setDefine("M_PI=3.1415926535897932384626433832795");
- char shaderType = bx::toLower(type[0]);
- switch (shaderType)
+ switch (_options.shaderType)
{
case 'c':
preprocessor.setDefine("BGFX_SHADER_TYPE_COMPUTE=1");
@@ -1024,836 +1022,774 @@ namespace bgfx
break;
default:
- fprintf(stderr, "Unknown type: %s?!", type);
- return EXIT_FAILURE;
+ fprintf(stderr, "Unknown type: %c?!", _options.shaderType);
+ return false;
}
bool compiled = false;
- bx::CrtFileReader reader;
- if (!bx::open(&reader, filePath) )
- {
- fprintf(stderr, "Unable to open file '%s'.\n", filePath);
- }
- else
- {
- VaryingMap varyingMap;
+ VaryingMap varyingMap;
+ const char* parse = _varying;
- std::string defaultVarying = dir + "varying.def.sc";
- const char* varyingdef = cmdLine.findOption("varyingdef", defaultVarying.c_str() );
- File attribdef(varyingdef);
- const char* parse = attribdef.getData();
- if (NULL != parse
+ while (NULL != parse
&& *parse != '\0')
+ {
+ parse = bx::strws(parse);
+ const char* eol = bx::strFind(parse, ';');
+ if (NULL == eol)
{
- preprocessor.addDependency(varyingdef);
- }
- else
- {
- fprintf(stderr, "ERROR: Failed to parse varying def file: \"%s\" No input/output semantics will be generated in the code!\n", varyingdef);
+ eol = bx::streol(parse);
}
- while (NULL != parse
- && *parse != '\0')
+ if (NULL != eol)
{
- parse = bx::strws(parse);
- const char* eol = strchr(parse, ';');
- if (NULL == eol)
+ const char* precision = NULL;
+ const char* interpolation = NULL;
+ const char* typen = parse;
+
+ if (0 == bx::strCmp(typen, "lowp", 4)
+ || 0 == bx::strCmp(typen, "mediump", 7)
+ || 0 == bx::strCmp(typen, "highp", 5) )
{
- eol = bx::streol(parse);
+ precision = typen;
+ typen = parse = bx::strws(bx::strword(parse) );
}
- if (NULL != eol)
+ if (0 == bx::strCmp(typen, "flat", 4)
+ || 0 == bx::strCmp(typen, "smooth", 6)
+ || 0 == bx::strCmp(typen, "noperspective", 13)
+ || 0 == bx::strCmp(typen, "centroid", 8) )
{
- const char* precision = NULL;
- const char* interpolation = NULL;
- const char* typen = parse;
+ interpolation = typen;
+ typen = parse = bx::strws(bx::strword(parse) );
+ }
- if (0 == strncmp(typen, "lowp", 4)
- || 0 == strncmp(typen, "mediump", 7)
- || 0 == strncmp(typen, "highp", 5) )
+ const char* name = parse = bx::strws(bx::strword(parse) );
+ const char* column = parse = bx::strws(bx::strword(parse) );
+ const char* semantics = parse = bx::strws( (*parse == ':' ? ++parse : parse) );
+ const char* assign = parse = bx::strws(bx::strword(parse) );
+ const char* init = parse = bx::strws( (*parse == '=' ? ++parse : parse) );
+
+ if (typen < eol
+ && name < eol
+ && column < eol
+ && ':' == *column
+ && semantics < eol)
+ {
+ Varying var;
+ if (NULL != precision)
{
- precision = typen;
- typen = parse = bx::strws(bx::strword(parse) );
+ var.m_precision.assign(precision, bx::strword(precision)-precision);
}
- if (0 == strncmp(typen, "flat", 4)
- || 0 == strncmp(typen, "smooth", 6)
- || 0 == strncmp(typen, "noperspective", 13)
- || 0 == strncmp(typen, "centroid", 8) )
+ if (NULL != interpolation)
{
- interpolation = typen;
- typen = parse = bx::strws(bx::strword(parse) );
+ var.m_interpolation.assign(interpolation, bx::strword(interpolation)-interpolation);
}
- const char* name = parse = bx::strws(bx::strword(parse) );
- const char* column = parse = bx::strws(bx::strword(parse) );
- const char* semantics = parse = bx::strws( (*parse == ':' ? ++parse : parse) );
- const char* assign = parse = bx::strws(bx::strword(parse) );
- const char* init = parse = bx::strws( (*parse == '=' ? ++parse : parse) );
-
- if (typen < eol
- && name < eol
- && column < eol
- && ':' == *column
- && semantics < eol)
- {
- Varying var;
- if (NULL != precision)
- {
- var.m_precision.assign(precision, bx::strword(precision)-precision);
- }
-
- if (NULL != interpolation)
- {
- var.m_interpolation.assign(interpolation, bx::strword(interpolation)-interpolation);
- }
-
- var.m_type.assign(typen, bx::strword(typen)-typen);
- var.m_name.assign(name, bx::strword(name)-name);
- var.m_semantics.assign(semantics, bx::strword(semantics)-semantics);
-
- if (d3d == 9
- && var.m_semantics == "BITANGENT")
- {
- var.m_semantics = "BINORMAL";
- }
+ var.m_type.assign(typen, bx::strword(typen)-typen);
+ var.m_name.assign(name, bx::strword(name)-name);
+ var.m_semantics.assign(semantics, bx::strword(semantics)-semantics);
- if (assign < eol
- && '=' == *assign
- && init < eol)
- {
- var.m_init.assign(init, eol-init);
- }
+ if (d3d == 9
+ && var.m_semantics == "BITANGENT")
+ {
+ var.m_semantics = "BINORMAL";
+ }
- varyingMap.insert(std::make_pair(var.m_name, var) );
+ if (assign < eol
+ && '=' == *assign
+ && init < eol)
+ {
+ var.m_init.assign(init, eol-init);
}
- parse = bx::strws(bx::strnl(eol) );
+ varyingMap.insert(std::make_pair(var.m_name, var) );
}
- }
- InOut shaderInputs;
- InOut shaderOutputs;
- uint32_t inputHash = 0;
- uint32_t outputHash = 0;
-
- char* data;
- char* input;
- {
- const size_t padding = 4096;
- uint32_t size = (uint32_t)bx::getSize(&reader);
- data = new char[size+padding+1];
- size = (uint32_t)bx::read(&reader, data, size);
-
- if (data[0] == '\xef'
- && data[1] == '\xbb'
- && data[2] == '\xbf')
- {
- memmove(data, &data[3], size-3);
- size -= 3;
- }
+ parse = bx::strws(bx::strnl(eol) );
+ }
+ }
- // Compiler generates "error X3000: syntax error: unexpected end of file"
- // if input doesn't have empty line at EOF.
- data[size] = '\n';
- memset(&data[size+1], 0, padding);
- bx::close(&reader);
+ bool raw = _options.raw;
- if (!raw)
- {
- // To avoid commented code being recognized as used feature,
- // first preprocess pass is used to strip all comments before
- // substituting code.
- preprocessor.run(data);
- delete [] data;
-
- size = (uint32_t)preprocessor.m_preprocessed.size();
- data = new char[size+padding+1];
- memcpy(data, preprocessor.m_preprocessed.c_str(), size);
- memset(&data[size], 0, padding+1);
- }
+ InOut shaderInputs;
+ InOut shaderOutputs;
+ uint32_t inputHash = 0;
+ uint32_t outputHash = 0;
- strNormalizeEol(data);
+ char* data;
+ char* input;
+ {
+ data = _shader;
+ uint32_t size = _shaderLen;
- input = const_cast<char*>(bx::strws(data) );
- while (input[0] == '$')
- {
- const char* str = bx::strws(input+1);
- const char* eol = bx::streol(str);
- const char* nl = bx::strnl(eol);
- input = const_cast<char*>(nl);
+ const size_t padding = 4096;
- if (0 == strncmp(str, "input", 5) )
- {
- str += 5;
- const char* comment = strstr(str, "//");
- eol = NULL != comment && comment < eol ? comment : eol;
- inputHash = parseInOut(shaderInputs, str, eol);
- }
- else if (0 == strncmp(str, "output", 6) )
- {
- str += 6;
- const char* comment = strstr(str, "//");
- eol = NULL != comment && comment < eol ? comment : eol;
- outputHash = parseInOut(shaderOutputs, str, eol);
- }
- else if (0 == strncmp(str, "raw", 3) )
- {
- raw = true;
- str += 3;
- }
+ if (!raw)
+ {
+ // To avoid commented code being recognized as used feature,
+ // first preprocess pass is used to strip all comments before
+ // substituting code.
+ preprocessor.run(data);
+ delete [] data;
- input = const_cast<char*>(bx::strws(input) );
- }
+ size = (uint32_t)preprocessor.m_preprocessed.size();
+ data = new char[size+padding+1];
+ bx::memCopy(data, preprocessor.m_preprocessed.c_str(), size);
+ bx::memSet(&data[size], 0, padding+1);
}
- if (raw)
+ strNormalizeEol(data);
+
+ input = const_cast<char*>(bx::strws(data) );
+ while (input[0] == '$')
{
- bx::CrtFileWriter* writer = NULL;
+ const char* str = bx::strws(input+1);
+ const char* eol = bx::streol(str);
+ const char* nl = bx::strnl(eol);
+ input = const_cast<char*>(nl);
- if (NULL != bin2c)
+ if (0 == bx::strCmp(str, "input", 5) )
{
- writer = new Bin2cWriter(bin2c);
+ str += 5;
+ const char* comment = bx::strFind(str, "//");
+ eol = NULL != comment && comment < eol ? comment : eol;
+ inputHash = parseInOut(shaderInputs, str, eol);
}
- else
+ else if (0 == bx::strCmp(str, "output", 6) )
{
- writer = new bx::CrtFileWriter;
+ str += 6;
+ const char* comment = bx::strFind(str, "//");
+ eol = NULL != comment && comment < eol ? comment : eol;
+ outputHash = parseInOut(shaderOutputs, str, eol);
}
-
- if (!bx::open(writer, outFilePath) )
+ else if (0 == bx::strCmp(str, "raw", 3) )
{
- fprintf(stderr, "Unable to open output file '%s'.", outFilePath);
- return EXIT_FAILURE;
+ raw = true;
+ str += 3;
}
- if ('f' == shaderType)
- {
- bx::write(writer, BGFX_CHUNK_MAGIC_FSH);
- bx::write(writer, inputHash);
- }
- else if ('v' == shaderType)
- {
- bx::write(writer, BGFX_CHUNK_MAGIC_VSH);
- bx::write(writer, outputHash);
- }
- else
- {
- bx::write(writer, BGFX_CHUNK_MAGIC_CSH);
- bx::write(writer, outputHash);
- }
+ input = const_cast<char*>(bx::strws(input) );
+ }
+ }
- if (0 != glsl)
- {
- bx::write(writer, uint16_t(0) );
+ if (raw)
+ {
+ if ('f' == _options.shaderType)
+ {
+ bx::write(_writer, BGFX_CHUNK_MAGIC_FSH);
+ bx::write(_writer, inputHash);
+ }
+ else if ('v' == _options.shaderType)
+ {
+ bx::write(_writer, BGFX_CHUNK_MAGIC_VSH);
+ bx::write(_writer, outputHash);
+ }
+ else
+ {
+ bx::write(_writer, BGFX_CHUNK_MAGIC_CSH);
+ bx::write(_writer, outputHash);
+ }
- uint32_t shaderSize = (uint32_t)strlen(input);
- bx::write(writer, shaderSize);
- bx::write(writer, input, shaderSize);
- bx::write(writer, uint8_t(0) );
+ if (0 != glsl)
+ {
+ bx::write(_writer, uint16_t(0) );
- compiled = true;
- }
- else if (0 != pssl)
- {
- compiled = compilePSSLShader(cmdLine, 0, input, writer);
- }
- else
- {
- compiled = compileHLSLShader(cmdLine, d3d, input, writer);
- }
+ uint32_t shaderSize = (uint32_t)bx::strLen(input);
+ bx::write(_writer, shaderSize);
+ bx::write(_writer, input, shaderSize);
+ bx::write(_writer, uint8_t(0) );
- bx::close(writer);
- delete writer;
+ compiled = true;
}
- else if ('c' == shaderType) // Compute
+ else if (0 != pssl)
+ {
+ compiled = compilePSSLShader(_options, 0, input, _writer);
+ }
+ else
{
- char* entry = strstr(input, "void main()");
- if (NULL == entry)
+ compiled = compileHLSLShader(_options, d3d, input, _writer);
+ }
+ }
+ else if ('c' == _options.shaderType) // Compute
+ {
+ char* entry = const_cast<char*>(bx::strFind(input, "void main()") );
+ if (NULL == entry)
+ {
+ fprintf(stderr, "Shader entry point 'void main()' is not found.\n");
+ }
+ else
+ {
+ if (0 != glsl
+ || 0 != essl
+ || 0 != metal)
{
- fprintf(stderr, "Shader entry point 'void main()' is not found.\n");
}
else
{
- if (0 != glsl
- || 0 != essl
- || 0 != metal)
+ preprocessor.writef(
+ "#define lowp\n"
+ "#define mediump\n"
+ "#define highp\n"
+ "#define ivec2 int2\n"
+ "#define ivec3 int3\n"
+ "#define ivec4 int4\n"
+ "#define uvec2 uint2\n"
+ "#define uvec3 uint3\n"
+ "#define uvec4 uint4\n"
+ "#define vec2 float2\n"
+ "#define vec3 float3\n"
+ "#define vec4 float4\n"
+ "#define mat2 float2x2\n"
+ "#define mat3 float3x3\n"
+ "#define mat4 float4x4\n"
+ );
+
+ entry[4] = '_';
+
+ preprocessor.writef("#define void_main()");
+ preprocessor.writef(" \\\n\tvoid main(");
+
+ uint32_t arg = 0;
+
+ const bool hasLocalInvocationID = NULL != bx::strFind(input, "gl_LocalInvocationID");
+ const bool hasLocalInvocationIndex = NULL != bx::strFind(input, "gl_LocalInvocationIndex");
+ const bool hasGlobalInvocationID = NULL != bx::strFind(input, "gl_GlobalInvocationID");
+ const bool hasWorkGroupID = NULL != bx::strFind(input, "gl_WorkGroupID");
+
+ if (hasLocalInvocationID)
{
+ preprocessor.writef(
+ " \\\n\t%sint3 gl_LocalInvocationID : SV_GroupThreadID"
+ , arg++ > 0 ? ", " : " "
+ );
}
- else
+
+ if (hasLocalInvocationIndex)
{
preprocessor.writef(
- "#define lowp\n"
- "#define mediump\n"
- "#define highp\n"
- "#define ivec2 int2\n"
- "#define ivec3 int3\n"
- "#define ivec4 int4\n"
- "#define uvec2 uint2\n"
- "#define uvec3 uint3\n"
- "#define uvec4 uint4\n"
- "#define vec2 float2\n"
- "#define vec3 float3\n"
- "#define vec4 float4\n"
- "#define mat2 float2x2\n"
- "#define mat3 float3x3\n"
- "#define mat4 float4x4\n"
+ " \\\n\t%sint gl_LocalInvocationIndex : SV_GroupIndex"
+ , arg++ > 0 ? ", " : " "
);
+ }
- entry[4] = '_';
-
- preprocessor.writef("#define void_main()");
- preprocessor.writef(" \\\n\tvoid main(");
-
- uint32_t arg = 0;
-
- const bool hasLocalInvocationID = NULL != strstr(input, "gl_LocalInvocationID");
- const bool hasLocalInvocationIndex = NULL != strstr(input, "gl_LocalInvocationIndex");
- const bool hasGlobalInvocationID = NULL != strstr(input, "gl_GlobalInvocationID");
- const bool hasWorkGroupID = NULL != strstr(input, "gl_WorkGroupID");
-
- if (hasLocalInvocationID)
- {
- preprocessor.writef(
- " \\\n\t%sint3 gl_LocalInvocationID : SV_GroupThreadID"
- , arg++ > 0 ? ", " : " "
- );
- }
-
- if (hasLocalInvocationIndex)
- {
- preprocessor.writef(
- " \\\n\t%sint gl_LocalInvocationIndex : SV_GroupIndex"
- , arg++ > 0 ? ", " : " "
- );
- }
-
- if (hasGlobalInvocationID)
- {
- preprocessor.writef(
- " \\\n\t%sint3 gl_GlobalInvocationID : SV_DispatchThreadID"
- , arg++ > 0 ? ", " : " "
- );
- }
-
- if (hasWorkGroupID)
- {
- preprocessor.writef(
- " \\\n\t%sint3 gl_WorkGroupID : SV_GroupID"
- , arg++ > 0 ? ", " : " "
- );
- }
-
+ if (hasGlobalInvocationID)
+ {
preprocessor.writef(
- " \\\n\t)\n"
+ " \\\n\t%sint3 gl_GlobalInvocationID : SV_DispatchThreadID"
+ , arg++ > 0 ? ", " : " "
);
}
- if (preprocessor.run(input) )
+ if (hasWorkGroupID)
{
- BX_TRACE("Input file: %s", filePath);
- BX_TRACE("Output file: %s", outFilePath);
+ preprocessor.writef(
+ " \\\n\t%sint3 gl_WorkGroupID : SV_GroupID"
+ , arg++ > 0 ? ", " : " "
+ );
+ }
- if (preprocessOnly)
- {
- bx::CrtFileWriter writer;
+ preprocessor.writef(
+ " \\\n\t)\n"
+ );
+ }
- if (!bx::open(&writer, outFilePath) )
- {
- fprintf(stderr, "Unable to open output file '%s'.", outFilePath);
- return EXIT_FAILURE;
- }
+ if (preprocessor.run(input) )
+ {
+ //BX_TRACE("Input file: %s", filePath);
+ //BX_TRACE("Output file: %s", outFilePath);
- bx::write(&writer, preprocessor.m_preprocessed.c_str(), (int32_t)preprocessor.m_preprocessed.size() );
- bx::close(&writer);
+ if (_options.preprocessOnly)
+ {
+ bx::write(_writer, preprocessor.m_preprocessed.c_str(), (int32_t)preprocessor.m_preprocessed.size() );
- return EXIT_SUCCESS;
- }
+ return true;
+ }
+ {
+ bx::write(_writer, BGFX_CHUNK_MAGIC_CSH);
+ bx::write(_writer, outputHash);
+
+ if (0 != glsl
+ || 0 != essl)
{
- bx::CrtFileWriter* writer = NULL;
+ std::string code;
- if (NULL != bin2c)
+ if (essl)
{
- writer = new Bin2cWriter(bin2c);
+ bx::stringPrintf(code, "#version 310 es\n");
}
else
{
- writer = new bx::CrtFileWriter;
+ bx::stringPrintf(code, "#version %d\n", glsl == 0 ? 430 : glsl);
}
- if (!bx::open(writer, outFilePath) )
- {
- fprintf(stderr, "Unable to open output file '%s'.", outFilePath);
- return EXIT_FAILURE;
- }
-
- bx::write(writer, BGFX_CHUNK_MAGIC_CSH);
- bx::write(writer, outputHash);
+ code += preprocessor.m_preprocessed;
+#if 1
+ bx::write(_writer, uint16_t(0) );
- if (0 != glsl
- || 0 != essl)
- {
- std::string code;
+ uint32_t shaderSize = (uint32_t)code.size();
+ bx::write(_writer, shaderSize);
+ bx::write(_writer, code.c_str(), shaderSize);
+ bx::write(_writer, uint8_t(0) );
- if (essl)
- {
- bx::stringPrintf(code, "#version 310 es\n");
- }
- else
- {
- bx::stringPrintf(code, "#version %d\n", glsl == 0 ? 430 : glsl);
- }
-
- code += preprocessor.m_preprocessed;
- #if 1
- bx::write(writer, uint16_t(0) );
-
- uint32_t shaderSize = (uint32_t)code.size();
- bx::write(writer, shaderSize);
- bx::write(writer, code.c_str(), shaderSize);
- bx::write(writer, uint8_t(0) );
+ compiled = true;
+#else
+ compiled = compileGLSLShader(cmdLine, essl, code, writer);
+#endif // 0
+ }
+ else if (0 != spirv)
+ {
+ compiled = compileSPIRVShader(_options, 0, preprocessor.m_preprocessed, _writer);
+ }
+ else if (0 != pssl)
+ {
+ compiled = compilePSSLShader(_options, 0, preprocessor.m_preprocessed, _writer);
+ }
+ else
+ {
+ compiled = compileHLSLShader(_options, d3d, preprocessor.m_preprocessed, _writer);
+ }
+ }
- compiled = true;
- #else
- compiled = compileGLSLShader(cmdLine, essl, code, writer);
- #endif // 0
- }
- else if (0 != spirv)
+ if (compiled)
+ {
+ if (_options.depends)
+ {
+ std::string ofp = _options.outputFilePath;
+ ofp += ".d";
+ bx::FileWriter writer;
+ if (bx::open(&writer, ofp.c_str() ) )
{
- compiled = compileSPIRVShader(cmdLine, 0, preprocessor.m_preprocessed, writer);
+ writef(&writer, "%s : %s\n", _options.outputFilePath.c_str(), preprocessor.m_depends.c_str() );
+ bx::close(&writer);
}
- else if (0 != pssl)
+ }
+ }
+ }
+ }
+ }
+ else // Vertex/Fragment
+ {
+ char* entry = const_cast<char*>(bx::strFind(input, "void main()") );
+ if (NULL == entry)
+ {
+ fprintf(stderr, "Shader entry point 'void main()' is not found.\n");
+ }
+ else
+ {
+ if (0 != glsl
+ || 0 != essl
+ || 0 != metal)
+ {
+ if (0 == essl)
+ {
+ // bgfx shadow2D/Proj behave like EXT_shadow_samplers
+ // not as GLSL language 1.2 specs shadow2D/Proj.
+ preprocessor.writef(
+ "#define shadow2D(_sampler, _coord) bgfxShadow2D(_sampler, _coord).x\n"
+ "#define shadow2DProj(_sampler, _coord) bgfxShadow2DProj(_sampler, _coord).x\n"
+ );
+ }
+
+ for (InOut::const_iterator it = shaderInputs.begin(), itEnd = shaderInputs.end(); it != itEnd; ++it)
+ {
+ VaryingMap::const_iterator varyingIt = varyingMap.find(*it);
+ if (varyingIt != varyingMap.end() )
+ {
+ const Varying& var = varyingIt->second;
+ const char* name = var.m_name.c_str();
+
+ if (0 == bx::strCmp(name, "a_", 2)
+ || 0 == bx::strCmp(name, "i_", 2) )
{
- compiled = compilePSSLShader(cmdLine, 0, preprocessor.m_preprocessed, writer);
+ 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
{
- compiled = compileHLSLShader(cmdLine, d3d, preprocessor.m_preprocessed, writer);
+ preprocessor.writef("%s varying %s %s %s;\n"
+ , var.m_interpolation.c_str()
+ , var.m_precision.c_str()
+ , var.m_type.c_str()
+ , name
+ );
}
-
- bx::close(writer);
- delete writer;
}
+ }
- if (compiled)
+ for (InOut::const_iterator it = shaderOutputs.begin(), itEnd = shaderOutputs.end(); it != itEnd; ++it)
+ {
+ VaryingMap::const_iterator varyingIt = varyingMap.find(*it);
+ if (varyingIt != varyingMap.end() )
{
- if (depends)
- {
- std::string ofp = outFilePath;
- ofp += ".d";
- bx::CrtFileWriter writer;
- if (bx::open(&writer, ofp.c_str() ) )
- {
- writef(&writer, "%s : %s\n", outFilePath, preprocessor.m_depends.c_str() );
- bx::close(&writer);
- }
- }
+ const Varying& var = varyingIt->second;
+ preprocessor.writef("%s varying %s %s;\n"
+ , var.m_interpolation.c_str()
+ , var.m_type.c_str()
+ , var.m_name.c_str()
+ );
}
}
}
- }
- else // Vertex/Fragment
- {
- char* entry = strstr(input, "void main()");
- if (NULL == entry)
- {
- fprintf(stderr, "Shader entry point 'void main()' is not found.\n");
- }
else
{
- if (0 != glsl
- || 0 != essl
- || 0 != metal)
+ preprocessor.writef(
+ "#define lowp\n"
+ "#define mediump\n"
+ "#define highp\n"
+ "#define ivec2 int2\n"
+ "#define ivec3 int3\n"
+ "#define ivec4 int4\n"
+ "#define uvec2 uint2\n"
+ "#define uvec3 uint3\n"
+ "#define uvec4 uint4\n"
+ "#define vec2 float2\n"
+ "#define vec3 float3\n"
+ "#define vec4 float4\n"
+ "#define mat2 float2x2\n"
+ "#define mat3 float3x3\n"
+ "#define mat4 float4x4\n"
+ );
+
+ if (hlsl != 0
+ && hlsl < 4)
{
- if (0 == essl)
+ preprocessor.writef(
+ "#define centroid\n"
+ "#define flat\n"
+ "#define noperspective\n"
+ "#define smooth\n"
+ );
+ }
+
+ entry[4] = '_';
+
+ if ('f' == _options.shaderType)
+ {
+ const char* insert = bx::strFind(entry, "{");
+ if (NULL != insert)
{
- // bgfx shadow2D/Proj behave like EXT_shadow_samplers
- // not as GLSL language 1.2 specs shadow2D/Proj.
- preprocessor.writef(
- "#define shadow2D(_sampler, _coord) bgfxShadow2D(_sampler, _coord).x\n"
- "#define shadow2DProj(_sampler, _coord) bgfxShadow2DProj(_sampler, _coord).x\n"
- );
+ insert = strInsert(const_cast<char*>(insert+1), "\nvec4 bgfx_VoidFrag = vec4_splat(0.0);\n");
}
- for (InOut::const_iterator it = shaderInputs.begin(), itEnd = shaderInputs.end(); it != itEnd; ++it)
+ const bool hasFragColor = NULL != bx::strFind(input, "gl_FragColor");
+ const bool hasFragCoord = NULL != bx::strFind(input, "gl_FragCoord") || hlsl > 3 || hlsl == 2;
+ const bool hasFragDepth = NULL != bx::strFind(input, "gl_FragDepth");
+ const bool hasFrontFacing = NULL != bx::strFind(input, "gl_FrontFacing");
+ const bool hasPrimitiveId = NULL != bx::strFind(input, "gl_PrimitiveID");
+
+ bool hasFragData[8] = {};
+ uint32_t numFragData = 0;
+ for (uint32_t ii = 0; ii < BX_COUNTOF(hasFragData); ++ii)
{
- VaryingMap::const_iterator varyingIt = varyingMap.find(*it);
- if (varyingIt != varyingMap.end() )
- {
- const Varying& var = varyingIt->second;
- const char* name = var.m_name.c_str();
+ char temp[32];
+ bx::snprintf(temp, BX_COUNTOF(temp), "gl_FragData[%d]", ii);
+ hasFragData[ii] = NULL != bx::strFind(input, temp);
+ numFragData += hasFragData[ii];
+ }
- if (0 == strncmp(name, "a_", 2)
- || 0 == strncmp(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
- );
- }
- 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
- );
- }
+ if (0 == numFragData)
+ {
+ // GL errors when both gl_FragColor and gl_FragData is used.
+ // This will trigger the same error with HLSL compiler too.
+ preprocessor.writef("#define gl_FragColor gl_FragData_0_\n");
+
+ // 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;
+
+ if (NULL != insert
+ && d3d < 11
+ && !hasFragColor)
+ {
+ insert = strInsert(const_cast<char*>(insert+1), "\ngl_FragColor = bgfx_VoidFrag;\n");
}
}
- for (InOut::const_iterator it = shaderOutputs.begin(), itEnd = shaderOutputs.end(); it != itEnd; ++it)
+ preprocessor.writef("#define void_main()");
+ preprocessor.writef(" \\\n\tvoid main(");
+
+ uint32_t arg = 0;
+
+ if (hasFragCoord)
+ {
+ preprocessor.writef(" \\\n\tvec4 gl_FragCoord : SV_POSITION");
+ ++arg;
+ }
+
+ for (InOut::const_iterator it = shaderInputs.begin(), itEnd = shaderInputs.end(); it != itEnd; ++it)
{
VaryingMap::const_iterator varyingIt = varyingMap.find(*it);
if (varyingIt != varyingMap.end() )
{
const Varying& var = varyingIt->second;
- preprocessor.writef("%s varying %s %s;\n"
- , var.m_interpolation.c_str()
+ preprocessor.writef(" \\\n\t%s%s %s %s : %s"
+ , arg++ > 0 ? ", " : " "
+ , interpolationDx11(var.m_interpolation.c_str() )
, var.m_type.c_str()
, var.m_name.c_str()
+ , var.m_semantics.c_str()
);
}
}
- }
- else
- {
- preprocessor.writef(
- "#define lowp\n"
- "#define mediump\n"
- "#define highp\n"
- "#define ivec2 int2\n"
- "#define ivec3 int3\n"
- "#define ivec4 int4\n"
- "#define uvec2 uint2\n"
- "#define uvec3 uint3\n"
- "#define uvec4 uint4\n"
- "#define vec2 float2\n"
- "#define vec3 float3\n"
- "#define vec4 float4\n"
- "#define mat2 float2x2\n"
- "#define mat3 float3x3\n"
- "#define mat4 float4x4\n"
- );
- if (hlsl != 0
- && hlsl < 4)
+ const uint32_t maxRT = d3d > 9 ? BX_COUNTOF(hasFragData) : 4;
+
+ for (uint32_t ii = 0; ii < BX_COUNTOF(hasFragData); ++ii)
+ {
+ if (ii < maxRT)
+ {
+ if (hasFragData[ii])
+ {
+ addFragData(preprocessor, input, ii, arg++ > 0);
+ }
+ }
+ else
+ {
+ voidFragData(input, ii);
+ }
+ }
+
+ if (hasFragDepth)
{
preprocessor.writef(
- "#define centroid\n"
- "#define flat\n"
- "#define noperspective\n"
- "#define smooth\n"
+ " \\\n\t%sout float gl_FragDepth : SV_DEPTH"
+ , arg++ > 0 ? ", " : " "
);
}
- entry[4] = '_';
+ if (hasFrontFacing
+ && hlsl >= 3)
+ {
+ preprocessor.writef(
+ " \\\n\t%sfloat __vface : VFACE"
+ , arg++ > 0 ? ", " : " "
+ );
+ }
- if ('f' == shaderType)
+ if (hasPrimitiveId)
{
- const char* insert = strstr(entry, "{");
- if (NULL != insert)
+ if (d3d > 9)
{
- insert = strInsert(const_cast<char*>(insert+1), "\nvec4 bgfx_VoidFrag = vec4_splat(0.0);\n");
+ preprocessor.writef(
+ " \\\n\t%suint gl_PrimitiveID : SV_PrimitiveID"
+ , arg++ > 0 ? ", " : " "
+ );
}
-
- const bool hasFragColor = NULL != strstr(input, "gl_FragColor");
- const bool hasFragCoord = NULL != strstr(input, "gl_FragCoord") || hlsl > 3 || hlsl == 2;
- const bool hasFragDepth = NULL != strstr(input, "gl_FragDepth");
- const bool hasFrontFacing = NULL != strstr(input, "gl_FrontFacing");
- const bool hasPrimitiveId = NULL != strstr(input, "gl_PrimitiveID");
-
- bool hasFragData[8] = {};
- uint32_t numFragData = 0;
- for (uint32_t ii = 0; ii < BX_COUNTOF(hasFragData); ++ii)
+ else
{
- char temp[32];
- bx::snprintf(temp, BX_COUNTOF(temp), "gl_FragData[%d]", ii);
- hasFragData[ii] = NULL != strstr(input, temp);
- numFragData += hasFragData[ii];
+ fprintf(stderr, "gl_PrimitiveID builtin is not supported by this D3D9 HLSL.\n");
+ return false;
}
+ }
+
+ preprocessor.writef(
+ " \\\n\t)\n"
+ );
- if (0 == numFragData)
+ if (hasFrontFacing)
+ {
+ if (hlsl >= 3)
{
- // GL errors when both gl_FragColor and gl_FragData is used.
- // This will trigger the same error with HLSL compiler too.
- preprocessor.writef("#define gl_FragColor gl_FragData_0_\n");
-
- // 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;
-
- if (NULL != insert
- && d3d < 11
- && !hasFragColor)
- {
- insert = strInsert(const_cast<char*>(insert+1), "\ngl_FragColor = bgfx_VoidFrag;\n");
- }
+ preprocessor.writef(
+ "#define gl_FrontFacing (__vface <= 0.0)\n"
+ );
}
-
- preprocessor.writef("#define void_main()");
- preprocessor.writef(" \\\n\tvoid main(");
-
- uint32_t arg = 0;
-
- if (hasFragCoord)
+ else
{
- preprocessor.writef(" \\\n\tvec4 gl_FragCoord : SV_POSITION");
- ++arg;
+ preprocessor.writef(
+ "#define gl_FrontFacing false\n"
+ );
}
+ }
+ }
+ else if ('v' == _options.shaderType)
+ {
+ const bool hasVertexId = NULL != bx::strFind(input, "gl_VertexID");
+ const bool hasInstanceId = NULL != bx::strFind(input, "gl_InstanceID");
- for (InOut::const_iterator it = shaderInputs.begin(), itEnd = shaderInputs.end(); it != itEnd; ++it)
+ const char* brace = bx::strFind(entry, "{");
+ if (NULL != brace)
+ {
+ const char* end = bx::strmb(brace, '{', '}');
+ if (NULL != end)
{
- VaryingMap::const_iterator varyingIt = varyingMap.find(*it);
- if (varyingIt != varyingMap.end() )
- {
- const Varying& var = varyingIt->second;
- preprocessor.writef(" \\\n\t%s%s %s %s : %s"
- , arg++ > 0 ? ", " : " "
- , interpolationDx11(var.m_interpolation.c_str() )
- , var.m_type.c_str()
- , var.m_name.c_str()
- , var.m_semantics.c_str()
- );
- }
+ strInsert(const_cast<char*>(end), "__RETURN__;\n");
}
+ }
- const uint32_t maxRT = d3d > 9 ? BX_COUNTOF(hasFragData) : 4;
-
- for (uint32_t ii = 0; ii < BX_COUNTOF(hasFragData); ++ii)
+ preprocessor.writef(
+ "struct Output\n"
+ "{\n"
+ "\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);
+ if (varyingIt != varyingMap.end() )
{
- if (ii < maxRT)
- {
- if (hasFragData[ii])
- {
- addFragData(preprocessor, input, ii, arg++ > 0);
- }
- }
- else
- {
- voidFragData(input, ii);
- }
+ const Varying& var = varyingIt->second;
+ preprocessor.writef("\t%s %s : %s;\n", var.m_type.c_str(), var.m_name.c_str(), var.m_semantics.c_str() );
+ preprocessor.writef("#define %s _varying_.%s\n", var.m_name.c_str(), var.m_name.c_str() );
}
+ }
+ preprocessor.writef(
+ "};\n"
+ );
- if (hasFragDepth)
+ preprocessor.writef("#define void_main() \\\n");
+ preprocessor.writef("Output main(");
+ uint32_t arg = 0;
+ for (InOut::const_iterator it = shaderInputs.begin(), itEnd = shaderInputs.end(); it != itEnd; ++it)
+ {
+ VaryingMap::const_iterator varyingIt = varyingMap.find(*it);
+ if (varyingIt != varyingMap.end() )
{
+ const Varying& var = varyingIt->second;
preprocessor.writef(
- " \\\n\t%sout float gl_FragDepth : SV_DEPTH"
- , arg++ > 0 ? ", " : " "
+ " \\\n\t%s%s %s : %s"
+ , arg++ > 0 ? ", " : ""
+ , var.m_type.c_str()
+ , var.m_name.c_str()
+ , var.m_semantics.c_str()
);
}
+ }
- if (hasFrontFacing
- && hlsl >= 3)
+ if (hasVertexId)
+ {
+ if (d3d > 9)
{
preprocessor.writef(
- " \\\n\t%sfloat __vface : VFACE"
+ " \\\n\t%suint gl_VertexID : SV_VertexID"
, arg++ > 0 ? ", " : " "
);
}
-
- if (hasPrimitiveId)
- {
- if (d3d > 9)
- {
- preprocessor.writef(
- " \\\n\t%suint gl_PrimitiveID : SV_PrimitiveID"
- , arg++ > 0 ? ", " : " "
- );
- }
- else
- {
- fprintf(stderr, "PrimitiveID builtin is not supported by this D3D9 HLSL.\n");
- return EXIT_FAILURE;
- }
- }
-
- preprocessor.writef(
- " \\\n\t)\n"
- );
-
- if (hasFrontFacing)
+ else
{
- if (hlsl >= 3)
- {
- preprocessor.writef(
- "#define gl_FrontFacing (__vface <= 0.0)\n"
- );
- }
- else
- {
- preprocessor.writef(
- "#define gl_FrontFacing false\n"
- );
- }
+ fprintf(stderr, "gl_VertexID builtin is not supported by this D3D9 HLSL.\n");
+ return false;
}
}
- else if ('v' == shaderType)
+
+ if (hasInstanceId)
{
- const char* brace = strstr(entry, "{");
- if (NULL != brace)
+ if (d3d > 9)
{
- const char* end = bx::strmb(brace, '{', '}');
- if (NULL != end)
- {
- strInsert(const_cast<char*>(end), "__RETURN__;\n");
- }
+ preprocessor.writef(
+ " \\\n\t%suint gl_InstanceID : SV_InstanceID"
+ , arg++ > 0 ? ", " : " "
+ );
}
-
- preprocessor.writef(
- "struct Output\n"
- "{\n"
- "\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)
+ else
{
- VaryingMap::const_iterator varyingIt = varyingMap.find(*it);
- if (varyingIt != varyingMap.end() )
- {
- const Varying& var = varyingIt->second;
- preprocessor.writef("\t%s %s : %s;\n", var.m_type.c_str(), var.m_name.c_str(), var.m_semantics.c_str() );
- preprocessor.writef("#define %s _varying_.%s\n", var.m_name.c_str(), var.m_name.c_str() );
- }
+ fprintf(stderr, "gl_InstanceID builtin is not supported by this D3D9 HLSL.\n");
+ return false;
}
- preprocessor.writef(
- "};\n"
- );
+ }
- preprocessor.writef("#define void_main() \\\n");
- preprocessor.writef("Output main(");
- bool first = true;
- for (InOut::const_iterator it = shaderInputs.begin(), itEnd = shaderInputs.end(); it != itEnd; ++it)
- {
- VaryingMap::const_iterator varyingIt = varyingMap.find(*it);
- if (varyingIt != varyingMap.end() )
- {
- const Varying& var = varyingIt->second;
- preprocessor.writef("%s%s %s : %s\\\n", first ? "" : "\t, ", var.m_type.c_str(), var.m_name.c_str(), var.m_semantics.c_str() );
- first = false;
- }
- }
- preprocessor.writef(
- ") \\\n"
- "{ \\\n"
- "\tOutput _varying_;"
- );
+ preprocessor.writef(
+ ") \\\n"
+ "{ \\\n"
+ "\tOutput _varying_;"
+ );
- for (InOut::const_iterator it = shaderOutputs.begin(), itEnd = shaderOutputs.end(); it != itEnd; ++it)
+ for (InOut::const_iterator it = shaderOutputs.begin(), itEnd = shaderOutputs.end(); it != itEnd; ++it)
+ {
+ VaryingMap::const_iterator varyingIt = varyingMap.find(*it);
+ if (varyingIt != varyingMap.end() )
{
- VaryingMap::const_iterator varyingIt = varyingMap.find(*it);
- if (varyingIt != varyingMap.end() )
+ const Varying& var = varyingIt->second;
+ preprocessor.writef(" \\\n\t%s", var.m_name.c_str() );
+ if (!var.m_init.empty() )
{
- const Varying& var = varyingIt->second;
- preprocessor.writef(" \\\n\t%s", var.m_name.c_str() );
- if (!var.m_init.empty() )
- {
- preprocessor.writef(" = %s", var.m_init.c_str() );
- }
- preprocessor.writef(";");
+ preprocessor.writef(" = %s", var.m_init.c_str() );
}
+ preprocessor.writef(";");
}
+ }
- preprocessor.writef(
- "\n#define __RETURN__ \\\n"
- "\t} \\\n"
- );
+ preprocessor.writef(
+ "\n#define __RETURN__ \\\n"
+ "\t} \\\n"
+ );
- if (hlsl != 0
- && hlsl <= 3)
- {
+ if (hlsl != 0
+ && hlsl <= 3)
+ {
// preprocessor.writef(
// "\tgl_Position.xy += u_viewTexel.xy * gl_Position.w; \\\n"
// );
- }
-
- preprocessor.writef(
- "\treturn _varying_"
- );
}
+
+ preprocessor.writef(
+ "\treturn _varying_"
+ );
}
+ }
- if (preprocessor.run(input) )
- {
- BX_TRACE("Input file: %s", filePath);
- BX_TRACE("Output file: %s", outFilePath);
+ if (preprocessor.run(input) )
+ {
+ //BX_TRACE("Input file: %s", filePath);
+ //BX_TRACE("Output file: %s", outFilePath);
- if (preprocessOnly)
+ if (_options.preprocessOnly)
+ {
+ if (0 != glsl)
{
- bx::CrtFileWriter writer;
-
- if (!bx::open(&writer, outFilePath) )
+ if (essl != 0)
{
- fprintf(stderr, "Unable to open output file '%s'.", outFilePath);
- return EXIT_FAILURE;
+ 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() );
- if (0 != glsl)
- {
- if (NULL == profile)
- {
- 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::close(&writer);
+ return true;
+ }
- return EXIT_SUCCESS;
+ {
+ if ('f' == _options.shaderType)
+ {
+ bx::write(_writer, BGFX_CHUNK_MAGIC_FSH);
+ bx::write(_writer, inputHash);
}
-
+ else if ('v' == _options.shaderType)
{
- bx::CrtFileWriter* writer = NULL;
-
- if (NULL != bin2c)
- {
- writer = new Bin2cWriter(bin2c);
- }
- else
- {
- writer = new bx::CrtFileWriter;
- }
-
- if (!bx::open(writer, outFilePath) )
- {
- fprintf(stderr, "Unable to open output file '%s'.", outFilePath);
- return EXIT_FAILURE;
- }
+ bx::write(_writer, BGFX_CHUNK_MAGIC_VSH);
+ bx::write(_writer, outputHash);
+ }
+ else
+ {
+ bx::write(_writer, BGFX_CHUNK_MAGIC_CSH);
+ bx::write(_writer, outputHash);
+ }
- if ('f' == shaderType)
- {
- bx::write(writer, BGFX_CHUNK_MAGIC_FSH);
- bx::write(writer, inputHash);
- }
- else if ('v' == shaderType)
- {
- bx::write(writer, BGFX_CHUNK_MAGIC_VSH);
- bx::write(writer, outputHash);
- }
- else
- {
- bx::write(writer, BGFX_CHUNK_MAGIC_CSH);
- bx::write(writer, outputHash);
- }
+ if (0 != glsl
+ || 0 != essl
+ || 0 != metal)
+ {
+ std::string code;
- if (0 != glsl
- || 0 != essl
- || 0 != metal)
+ if (glsl < 400)
{
- std::string code;
-
const bool usesTextureLod = false
|| !!bx::findIdentifierMatch(input, s_ARB_shader_texture_lod)
|| !!bx::findIdentifierMatch(input, s_EXT_shader_texture_lod)
;
+ const bool usesInstanceID = !!bx::strFind(input, "gl_InstanceID");
+ const bool usesGpuShader4 = !!bx::findIdentifierMatch(input, s_EXT_gpu_shader4);
const bool usesGpuShader5 = !!bx::findIdentifierMatch(input, s_ARB_gpu_shader5);
const bool usesTexelFetch = !!bx::findIdentifierMatch(input, s_texelFetch);
const bool usesTextureMS = !!bx::findIdentifierMatch(input, s_ARB_texture_multisample);
@@ -1873,7 +1809,22 @@ namespace bgfx
}
else
{
- bx::stringPrintf(code, "#version %s\n", need130 ? "130" : profile);
+ bx::stringPrintf(code, "#version %s\n", need130 ? "130" : _options.profile.c_str());
+ glsl = 130;
+ }
+
+ if (usesInstanceID)
+ {
+ bx::stringPrintf(code
+ , "#extension GL_ARB_draw_instanced : enable\n"
+ );
+ }
+
+ if (usesGpuShader4)
+ {
+ bx::stringPrintf(code
+ , "#extension GL_EXT_gpu_shader4 : enable\n"
+ );
}
if (usesGpuShader5)
@@ -1895,8 +1846,7 @@ namespace bgfx
if (usesTextureLod)
{
- if ( (0 != metal || 130 > glsl)
- && 'f' == shaderType)
+ if ('f' == _options.shaderType)
{
ARB_shader_texture_lod = true;
bx::stringPrintf(code
@@ -1954,10 +1904,20 @@ namespace bgfx
);
}
- bx::stringPrintf(code
- , "#define bgfxShadow2D shadow2D\n"
- "#define bgfxShadow2DProj shadow2DProj\n"
- );
+ if (need130)
+ {
+ bx::stringPrintf(code
+ , "#define bgfxShadow2D(_sampler, _coord) vec4_splat(texture(_sampler, _coord))\n"
+ "#define bgfxShadow2DProj(_sampler, _coord) vec4_splat(textureProj(_sampler, _coord))\n"
+ );
+ }
+ else
+ {
+ bx::stringPrintf(code
+ , "#define bgfxShadow2D shadow2D\n"
+ "#define bgfxShadow2DProj shadow2DProj\n"
+ );
+ }
}
else
{
@@ -1967,12 +1927,12 @@ namespace bgfx
{
bx::stringPrintf(code
, "#extension GL_EXT_shader_texture_lod : enable\n"
- "#define texture2DLod texture2DLodEXT\n"
- "#define texture2DGrad texture2DGradEXT\n"
- "#define texture2DProjLod texture2DProjLodEXT\n"
- "#define texture2DProjGrad texture2DProjGradEXT\n"
- "#define textureCubeLod textureCubeLodEXT\n"
- "#define textureCubeGrad textureCubeGradEXT\n"
+ "#define texture2DLod texture2DLodEXT\n"
+ "#define texture2DGrad texture2DGradEXT\n"
+ "#define texture2DProjLod texture2DProjLodEXT\n"
+ "#define texture2DProjGrad texture2DProjGradEXT\n"
+ "#define textureCubeLod textureCubeLodEXT\n"
+ "#define textureCubeGrad textureCubeGradEXT\n"
);
}
@@ -1990,8 +1950,8 @@ namespace bgfx
{
bx::stringPrintf(code
, "#extension GL_EXT_shadow_samplers : enable\n"
- "#define shadow2D shadow2DEXT\n"
- "#define shadow2DProj shadow2DProjEXT\n"
+ "#define shadow2D shadow2DEXT\n"
+ "#define shadow2DProj shadow2DProjEXT\n"
);
}
@@ -2013,7 +1973,7 @@ namespace bgfx
{
bx::stringPrintf(code
, "#extension GL_EXT_frag_depth : enable\n"
- "#define gl_FragDepth gl_FragDepthEXT\n"
+ "#define gl_FragDepth gl_FragDepthEXT\n"
);
}
@@ -2030,74 +1990,309 @@ namespace bgfx
"#define ivec4 vec4\n"
);
}
-
- code += preprocessor.m_preprocessed;
-
- compiled = compileGLSLShader(cmdLine
- , metal ? BX_MAKEFOURCC('M', 'T', 'L', 0) : essl
- , code
- , writer
- );
}
- else if (0 != spirv)
+ else
{
- compiled = compileSPIRVShader(cmdLine
- , 0
- , preprocessor.m_preprocessed
- , writer
- );
+ bx::stringPrintf(code, "#version %d\n", glsl);
}
- else if (0 != pssl)
+
+ code += preprocessor.m_preprocessed;
+
+ if (glsl > 400)
{
- compiled = compilePSSLShader(cmdLine
- , 0
- , preprocessor.m_preprocessed
- , writer
- );
+ bx::write(_writer, uint16_t(0) );
+
+ uint32_t shaderSize = (uint32_t)code.size();
+ bx::write(_writer, shaderSize);
+ bx::write(_writer, code.c_str(), shaderSize);
+ bx::write(_writer, uint8_t(0) );
+
+ compiled = true;
}
else
{
- compiled = compileHLSLShader(cmdLine
- , d3d
- , preprocessor.m_preprocessed
- , writer
+ compiled = compileGLSLShader(_options
+ , metal ? BX_MAKEFOURCC('M', 'T', 'L', 0) : essl
+ , code
+ , _writer
);
}
-
- bx::close(writer);
- delete writer;
}
+ else if (0 != spirv)
+ {
+ compiled = compileSPIRVShader(_options
+ , 0
+ , preprocessor.m_preprocessed
+ , _writer
+ );
+ }
+ else if (0 != pssl)
+ {
+ compiled = compilePSSLShader(_options
+ , 0
+ , preprocessor.m_preprocessed
+ , _writer
+ );
+ }
+ else
+ {
+ compiled = compileHLSLShader(_options
+ , d3d
+ , preprocessor.m_preprocessed
+ , _writer
+ );
+ }
+ }
- if (compiled)
+ if (compiled)
+ {
+ if (_options.depends)
{
- if (depends)
+ std::string ofp = _options.outputFilePath + ".d";
+ bx::FileWriter writer;
+ if (bx::open(&writer, ofp.c_str() ) )
{
- std::string ofp = outFilePath;
- ofp += ".d";
- bx::CrtFileWriter writer;
- if (bx::open(&writer, ofp.c_str() ) )
- {
- writef(&writer, "%s : %s\n", outFilePath, preprocessor.m_depends.c_str() );
- bx::close(&writer);
- }
+ writef(&writer, "%s : %s\n", _options.outputFilePath.c_str(), preprocessor.m_depends.c_str() );
+ bx::close(&writer);
}
}
}
}
}
+ }
+
+ delete [] data;
+
+ return compiled;
+ }
+
+ int compileShader(int _argc, const char* _argv[])
+ {
+ bx::CommandLine cmdLine(_argc, _argv);
+
+ if (cmdLine.hasArg('v', "version") )
+ {
+ fprintf(stderr
+ , "shaderc, bgfx shader compiler tool, version %d.%d.%d.\n"
+ , BGFX_SHADERC_VERSION_MAJOR
+ , BGFX_SHADERC_VERSION_MINOR
+ , BGFX_API_VERSION
+ );
+ return bx::kExitSuccess;
+ }
+
+ if (cmdLine.hasArg('h', "help") )
+ {
+ help();
+ return bx::kExitFailure;
+ }
+
+ g_verbose = cmdLine.hasArg("verbose");
+
+ const char* filePath = cmdLine.findOption('f');
+ if (NULL == filePath)
+ {
+ help("Shader file name must be specified.");
+ return bx::kExitFailure;
+ }
+
+ const char* outFilePath = cmdLine.findOption('o');
+ if (NULL == outFilePath)
+ {
+ help("Output file name must be specified.");
+ return bx::kExitFailure;
+ }
+
+ const char* type = cmdLine.findOption('\0', "type");
+ if (NULL == type)
+ {
+ help("Must specify shader type.");
+ return bx::kExitFailure;
+ }
+
+ Options options;
+ options.inputFilePath = filePath;
+ options.outputFilePath = outFilePath;
+ options.shaderType = bx::toLower(type[0]);
+
+ options.disasm = cmdLine.hasArg('\0', "disasm");
+
+ const char* platform = cmdLine.findOption('\0', "platform");
+ if (NULL == platform)
+ {
+ platform = "";
+ }
+
+ options.platform = platform;
+
+ options.raw = cmdLine.hasArg('\0', "raw");
+
+ const char* profile = cmdLine.findOption('p', "profile");
+
+ if ( NULL != profile)
+ {
+ options.profile = profile;
+ }
+
+ { // hlsl only
+ options.debugInformation = cmdLine.hasArg('\0', "debug");
+ options.avoidFlowControl = cmdLine.hasArg('\0', "avoid-flow-control");
+ options.noPreshader = cmdLine.hasArg('\0', "no-preshader");
+ options.partialPrecision = cmdLine.hasArg('\0', "partial-precision");
+ options.preferFlowControl = cmdLine.hasArg('\0', "prefer-flow-control");
+ options.backwardsCompatibility = cmdLine.hasArg('\0', "backwards-compatibility");
+ options.warningsAreErrors = cmdLine.hasArg('\0', "Werror");
+
+ uint32_t optimization = 3;
+ if (cmdLine.hasArg(optimization, 'O') )
+ {
+ options.optimize = true;
+ options.optimizationLevel = optimization;
+ }
+ }
+
+ const char* bin2c = NULL;
+ if (cmdLine.hasArg("bin2c") )
+ {
+ bin2c = cmdLine.findOption("bin2c");
+ if (NULL == bin2c)
+ {
+ bin2c = baseName(outFilePath);
+ uint32_t len = (uint32_t)bx::strLen(bin2c);
+ char* temp = (char*)alloca(len+1);
+ for (char *out = temp; *bin2c != '\0';)
+ {
+ char ch = *bin2c++;
+ if (isalnum(ch) )
+ {
+ *out++ = ch;
+ }
+ else
+ {
+ *out++ = '_';
+ }
+ }
+ temp[len] = '\0';
+
+ bin2c = temp;
+ }
+ }
+
+ bool depends = cmdLine.hasArg("depends");
+ options.preprocessOnly = cmdLine.hasArg("preprocess");
+ const char* includeDir = cmdLine.findOption('i');
+
+ BX_TRACE("depends: %d", depends);
+ BX_TRACE("preprocessOnly: %d", options.preprocessOnly);
+ BX_TRACE("includeDir: %s", includeDir);
+
+ for (int ii = 1; NULL != includeDir; ++ii)
+ {
+ options.includeDirs.push_back(includeDir);
+ includeDir = cmdLine.findOption(ii, 'i');
+ }
+
+ std::string dir;
+ {
+ const char* base = baseName(filePath);
+
+ if (base != filePath)
+ {
+ dir.assign(filePath, base-filePath);
+ options.includeDirs.push_back(dir.c_str());
+ }
+ }
+
+ const char* defines = cmdLine.findOption("define");
+ while (NULL != defines
+ && '\0' != *defines)
+ {
+ defines = bx::strws(defines);
+ const char* eol = bx::strFind(defines, ';');
+ if (NULL == eol)
+ {
+ eol = defines + bx::strLen(defines);
+ }
+ std::string define(defines, eol);
+ options.defines.push_back(define.c_str() );
+ defines = ';' == *eol ? eol+1 : eol;
+ }
+
+ bool compiled = false;
+
+ bx::FileReader reader;
+ if (!bx::open(&reader, filePath) )
+ {
+ fprintf(stderr, "Unable to open file '%s'.\n", filePath);
+ }
+ else
+ {
+ std::string defaultVarying = dir + "varying.def.sc";
+ const char* varyingdef = cmdLine.findOption("varyingdef", defaultVarying.c_str() );
+ File attribdef(varyingdef);
+ const char* parse = attribdef.getData();
+ if (NULL != parse
+ && *parse != '\0')
+ {
+ options.dependencies.push_back(varyingdef);
+ }
+ else
+ {
+ fprintf(stderr, "ERROR: Failed to parse varying def file: \"%s\" No input/output semantics will be generated in the code!\n", varyingdef);
+ }
+
+ const size_t padding = 4096;
+ uint32_t size = (uint32_t)bx::getSize(&reader);
+ char* data = new char[size+padding+1];
+ size = (uint32_t)bx::read(&reader, data, size);
+
+ if (data[0] == '\xef'
+ && data[1] == '\xbb'
+ && data[2] == '\xbf')
+ {
+ bx::memMove(data, &data[3], size-3);
+ size -= 3;
+ }
+
+ // Compiler generates "error X3000: syntax error: unexpected end of file"
+ // if input doesn't have empty line at EOF.
+ data[size] = '\n';
+ bx::memSet(&data[size+1], 0, padding);
+ bx::close(&reader);
+
+ bx::FileWriter* writer = NULL;
+
+ if (NULL != bin2c)
+ {
+ 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 ( compileShader(attribdef.getData(), data, size, options, writer) )
+ compiled = true;
- delete [] data;
+ bx::close(writer);
+ delete writer;
}
if (compiled)
{
- return EXIT_SUCCESS;
+ return bx::kExitSuccess;
}
remove(outFilePath);
fprintf(stderr, "Failed to build shader.\n");
- return EXIT_FAILURE;
+ return bx::kExitFailure;
}
} // namespace bgfx