|
|
@@ -150,6 +150,77 @@ 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 == bx::strCmp(_glsl, "smooth") )
|
|
|
@@ -794,58 +865,9 @@ namespace bgfx
|
|
|
);
|
|
|
}
|
|
|
|
|
|
- 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;
|
|
|
- }
|
|
|
-
|
|
|
- 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;
|
|
|
@@ -853,8 +875,8 @@ 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 == bx::strCmp(&profile[1], "s_4_0_level", 11) )
|
|
|
{
|
|
|
@@ -895,74 +917,16 @@ namespace bgfx
|
|
|
essl = 2;
|
|
|
}
|
|
|
|
|
|
- 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");
|
|
|
- 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 = 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 = bx::strFind(defines, ';');
|
|
|
- if (NULL == eol)
|
|
|
- {
|
|
|
- eol = defines + bx::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");
|
|
|
@@ -990,6 +954,8 @@ namespace bgfx
|
|
|
, essl ? 1 : glsl
|
|
|
);
|
|
|
|
|
|
+ const char* platform = _options.platform.c_str();
|
|
|
+
|
|
|
if (0 == bx::strCmpI(platform, "android") )
|
|
|
{
|
|
|
preprocessor.setDefine("BX_PLATFORM_ANDROID=1");
|
|
|
@@ -1041,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");
|
|
|
@@ -1057,1157 +1022,1266 @@ namespace bgfx
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
- fprintf(stderr, "Unknown type: %s?!", type);
|
|
|
- return bx::kExitFailure;
|
|
|
+ fprintf(stderr, "Unknown type: %c?!", _options.shaderType);
|
|
|
+ return false;
|
|
|
}
|
|
|
|
|
|
bool compiled = false;
|
|
|
|
|
|
- bx::FileReader 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 = bx::strFind(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 == bx::strCmp(typen, "lowp", 4)
|
|
|
- || 0 == bx::strCmp(typen, "mediump", 7)
|
|
|
- || 0 == bx::strCmp(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 == bx::strCmp(typen, "flat", 4)
|
|
|
- || 0 == bx::strCmp(typen, "smooth", 6)
|
|
|
- || 0 == bx::strCmp(typen, "noperspective", 13)
|
|
|
- || 0 == bx::strCmp(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);
|
|
|
+ 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";
|
|
|
- }
|
|
|
-
|
|
|
- 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')
|
|
|
- {
|
|
|
- bx::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';
|
|
|
- bx::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];
|
|
|
- bx::memCopy(data, preprocessor.m_preprocessed.c_str(), size);
|
|
|
- bx::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 == bx::strCmp(str, "input", 5) )
|
|
|
- {
|
|
|
- str += 5;
|
|
|
- const char* comment = bx::strFind(str, "//");
|
|
|
- eol = NULL != comment && comment < eol ? comment : eol;
|
|
|
- inputHash = parseInOut(shaderInputs, str, eol);
|
|
|
- }
|
|
|
- else if (0 == bx::strCmp(str, "output", 6) )
|
|
|
- {
|
|
|
- str += 6;
|
|
|
- const char* comment = bx::strFind(str, "//");
|
|
|
- eol = NULL != comment && comment < eol ? comment : eol;
|
|
|
- outputHash = parseInOut(shaderOutputs, str, eol);
|
|
|
- }
|
|
|
- else if (0 == bx::strCmp(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::FileWriter* 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::FileWriter;
|
|
|
+ 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 bx::kExitFailure;
|
|
|
+ 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)bx::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 (0 != pssl)
|
|
|
+ {
|
|
|
+ compiled = compilePSSLShader(_options, 0, input, _writer);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ compiled = compileHLSLShader(_options, d3d, input, _writer);
|
|
|
}
|
|
|
- else if ('c' == shaderType) // Compute
|
|
|
+ }
|
|
|
+ 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
|
|
|
{
|
|
|
- char* entry = const_cast<char*>(bx::strFind(input, "void main()") );
|
|
|
- if (NULL == entry)
|
|
|
+ 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] = '_';
|
|
|
+ if (hasGlobalInvocationID)
|
|
|
+ {
|
|
|
+ preprocessor.writef(
|
|
|
+ " \\\n\t%sint3 gl_GlobalInvocationID : SV_DispatchThreadID"
|
|
|
+ , arg++ > 0 ? ", " : " "
|
|
|
+ );
|
|
|
+ }
|
|
|
|
|
|
- preprocessor.writef("#define void_main()");
|
|
|
- preprocessor.writef(" \\\n\tvoid main(");
|
|
|
+ if (hasWorkGroupID)
|
|
|
+ {
|
|
|
+ preprocessor.writef(
|
|
|
+ " \\\n\t%sint3 gl_WorkGroupID : SV_GroupID"
|
|
|
+ , arg++ > 0 ? ", " : " "
|
|
|
+ );
|
|
|
+ }
|
|
|
|
|
|
- uint32_t arg = 0;
|
|
|
+ preprocessor.writef(
|
|
|
+ " \\\n\t)\n"
|
|
|
+ );
|
|
|
+ }
|
|
|
|
|
|
- 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 (preprocessor.run(input) )
|
|
|
+ {
|
|
|
+ //BX_TRACE("Input file: %s", filePath);
|
|
|
+ //BX_TRACE("Output file: %s", outFilePath);
|
|
|
|
|
|
- if (hasLocalInvocationID)
|
|
|
- {
|
|
|
- preprocessor.writef(
|
|
|
- " \\\n\t%sint3 gl_LocalInvocationID : SV_GroupThreadID"
|
|
|
- , arg++ > 0 ? ", " : " "
|
|
|
- );
|
|
|
- }
|
|
|
+ if (_options.preprocessOnly)
|
|
|
+ {
|
|
|
+ bx::write(_writer, preprocessor.m_preprocessed.c_str(), (int32_t)preprocessor.m_preprocessed.size() );
|
|
|
|
|
|
- if (hasLocalInvocationIndex)
|
|
|
- {
|
|
|
- preprocessor.writef(
|
|
|
- " \\\n\t%sint gl_LocalInvocationIndex : SV_GroupIndex"
|
|
|
- , arg++ > 0 ? ", " : " "
|
|
|
- );
|
|
|
- }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ {
|
|
|
+ bx::write(_writer, BGFX_CHUNK_MAGIC_CSH);
|
|
|
+ bx::write(_writer, outputHash);
|
|
|
|
|
|
- if (hasGlobalInvocationID)
|
|
|
+ if (0 != glsl
|
|
|
+ || 0 != essl)
|
|
|
{
|
|
|
- preprocessor.writef(
|
|
|
- " \\\n\t%sint3 gl_GlobalInvocationID : SV_DispatchThreadID"
|
|
|
- , arg++ > 0 ? ", " : " "
|
|
|
- );
|
|
|
- }
|
|
|
+ std::string code;
|
|
|
+
|
|
|
+ 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) );
|
|
|
|
|
|
- if (hasWorkGroupID)
|
|
|
+ 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)
|
|
|
{
|
|
|
- preprocessor.writef(
|
|
|
- " \\\n\t%sint3 gl_WorkGroupID : SV_GroupID"
|
|
|
- , arg++ > 0 ? ", " : " "
|
|
|
- );
|
|
|
+ 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);
|
|
|
}
|
|
|
-
|
|
|
- preprocessor.writef(
|
|
|
- " \\\n\t)\n"
|
|
|
- );
|
|
|
}
|
|
|
|
|
|
- if (preprocessor.run(input) )
|
|
|
+ if (compiled)
|
|
|
{
|
|
|
- BX_TRACE("Input file: %s", filePath);
|
|
|
- BX_TRACE("Output file: %s", outFilePath);
|
|
|
-
|
|
|
- if (preprocessOnly)
|
|
|
+ if (_options.depends)
|
|
|
{
|
|
|
+ std::string ofp = _options.outputFilePath;
|
|
|
+ ofp += ".d";
|
|
|
bx::FileWriter writer;
|
|
|
-
|
|
|
- if (!bx::open(&writer, outFilePath) )
|
|
|
+ if (bx::open(&writer, ofp.c_str() ) )
|
|
|
{
|
|
|
- fprintf(stderr, "Unable to open output file '%s'.", outFilePath);
|
|
|
- return bx::kExitFailure;
|
|
|
+ writef(&writer, "%s : %s\n", _options.outputFilePath.c_str(), preprocessor.m_depends.c_str() );
|
|
|
+ bx::close(&writer);
|
|
|
}
|
|
|
-
|
|
|
- bx::write(&writer, preprocessor.m_preprocessed.c_str(), (int32_t)preprocessor.m_preprocessed.size() );
|
|
|
- bx::close(&writer);
|
|
|
-
|
|
|
- return bx::kExitSuccess;
|
|
|
}
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ 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() )
|
|
|
{
|
|
|
- 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;
|
|
|
- }
|
|
|
-
|
|
|
- bx::write(writer, BGFX_CHUNK_MAGIC_CSH);
|
|
|
- bx::write(writer, outputHash);
|
|
|
-
|
|
|
- if (0 != glsl
|
|
|
- || 0 != essl)
|
|
|
- {
|
|
|
- std::string code;
|
|
|
-
|
|
|
- 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) );
|
|
|
+ const Varying& var = varyingIt->second;
|
|
|
+ const char* name = var.m_name.c_str();
|
|
|
|
|
|
- compiled = true;
|
|
|
- #else
|
|
|
- compiled = compileGLSLShader(cmdLine, essl, code, writer);
|
|
|
- #endif // 0
|
|
|
- }
|
|
|
- else if (0 != spirv)
|
|
|
- {
|
|
|
- compiled = compileSPIRVShader(cmdLine, 0, preprocessor.m_preprocessed, writer);
|
|
|
- }
|
|
|
- else if (0 != pssl)
|
|
|
+ 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::FileWriter 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 = 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)
|
|
|
+ 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)
|
|
|
+ {
|
|
|
+ preprocessor.writef(
|
|
|
+ "#define centroid\n"
|
|
|
+ "#define flat\n"
|
|
|
+ "#define noperspective\n"
|
|
|
+ "#define smooth\n"
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ entry[4] = '_';
|
|
|
+
|
|
|
+ if ('f' == _options.shaderType)
|
|
|
{
|
|
|
- if (0 == essl)
|
|
|
+ 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 == 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
|
|
|
- );
|
|
|
- }
|
|
|
- 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 = bx::strFind(entry, "{");
|
|
|
- if (NULL != insert)
|
|
|
+ if (d3d > 9)
|
|
|
+ {
|
|
|
+ preprocessor.writef(
|
|
|
+ " \\\n\t%suint gl_PrimitiveID : SV_PrimitiveID"
|
|
|
+ , arg++ > 0 ? ", " : " "
|
|
|
+ );
|
|
|
+ }
|
|
|
+ else
|
|
|
{
|
|
|
- insert = strInsert(const_cast<char*>(insert+1), "\nvec4 bgfx_VoidFrag = vec4_splat(0.0);\n");
|
|
|
+ fprintf(stderr, "gl_PrimitiveID builtin is not supported by this D3D9 HLSL.\n");
|
|
|
+ return false;
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- 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");
|
|
|
+ preprocessor.writef(
|
|
|
+ " \\\n\t)\n"
|
|
|
+ );
|
|
|
|
|
|
- bool hasFragData[8] = {};
|
|
|
- uint32_t numFragData = 0;
|
|
|
- for (uint32_t ii = 0; ii < BX_COUNTOF(hasFragData); ++ii)
|
|
|
+ if (hasFrontFacing)
|
|
|
+ {
|
|
|
+ if (hlsl >= 3)
|
|
|
{
|
|
|
- char temp[32];
|
|
|
- bx::snprintf(temp, BX_COUNTOF(temp), "gl_FragData[%d]", ii);
|
|
|
- hasFragData[ii] = NULL != bx::strFind(input, temp);
|
|
|
- numFragData += hasFragData[ii];
|
|
|
+ preprocessor.writef(
|
|
|
+ "#define gl_FrontFacing (__vface <= 0.0)\n"
|
|
|
+ );
|
|
|
}
|
|
|
-
|
|
|
- if (0 == numFragData)
|
|
|
+ else
|
|
|
{
|
|
|
- // 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 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");
|
|
|
|
|
|
- preprocessor.writef("#define void_main()");
|
|
|
- preprocessor.writef(" \\\n\tvoid main(");
|
|
|
-
|
|
|
- uint32_t arg = 0;
|
|
|
-
|
|
|
- if (hasFragCoord)
|
|
|
+ const char* brace = bx::strFind(entry, "{");
|
|
|
+ if (NULL != brace)
|
|
|
+ {
|
|
|
+ const char* end = bx::strmb(brace, '{', '}');
|
|
|
+ if (NULL != end)
|
|
|
{
|
|
|
- preprocessor.writef(" \\\n\tvec4 gl_FragCoord : SV_POSITION");
|
|
|
- ++arg;
|
|
|
+ strInsert(const_cast<char*>(end), "__RETURN__;\n");
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- for (InOut::const_iterator it = shaderInputs.begin(), itEnd = shaderInputs.end(); it != itEnd; ++it)
|
|
|
+ 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() )
|
|
|
{
|
|
|
- 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()
|
|
|
- );
|
|
|
- }
|
|
|
+ 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"
|
|
|
+ );
|
|
|
|
|
|
- const uint32_t maxRT = d3d > 9 ? BX_COUNTOF(hasFragData) : 4;
|
|
|
-
|
|
|
- for (uint32_t ii = 0; ii < BX_COUNTOF(hasFragData); ++ii)
|
|
|
+ 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() )
|
|
|
{
|
|
|
- if (ii < maxRT)
|
|
|
- {
|
|
|
- if (hasFragData[ii])
|
|
|
- {
|
|
|
- addFragData(preprocessor, input, ii, arg++ > 0);
|
|
|
- }
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- voidFragData(input, ii);
|
|
|
- }
|
|
|
+ const Varying& var = varyingIt->second;
|
|
|
+ preprocessor.writef(
|
|
|
+ " \\\n\t%s%s %s : %s"
|
|
|
+ , arg++ > 0 ? ", " : ""
|
|
|
+ , var.m_type.c_str()
|
|
|
+ , var.m_name.c_str()
|
|
|
+ , var.m_semantics.c_str()
|
|
|
+ );
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- if (hasFragDepth)
|
|
|
+ if (hasVertexId)
|
|
|
+ {
|
|
|
+ if (d3d > 9)
|
|
|
{
|
|
|
preprocessor.writef(
|
|
|
- " \\\n\t%sout float gl_FragDepth : SV_DEPTH"
|
|
|
+ " \\\n\t%suint gl_VertexID : SV_VertexID"
|
|
|
, arg++ > 0 ? ", " : " "
|
|
|
);
|
|
|
}
|
|
|
+ else
|
|
|
+ {
|
|
|
+ fprintf(stderr, "gl_VertexID builtin is not supported by this D3D9 HLSL.\n");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- if (hasFrontFacing
|
|
|
- && hlsl >= 3)
|
|
|
+ if (hasInstanceId)
|
|
|
+ {
|
|
|
+ if (d3d > 9)
|
|
|
{
|
|
|
preprocessor.writef(
|
|
|
- " \\\n\t%sfloat __vface : VFACE"
|
|
|
+ " \\\n\t%suint gl_InstanceID : SV_InstanceID"
|
|
|
, arg++ > 0 ? ", " : " "
|
|
|
);
|
|
|
}
|
|
|
-
|
|
|
- if (hasPrimitiveId)
|
|
|
+ else
|
|
|
{
|
|
|
- if (d3d > 9)
|
|
|
- {
|
|
|
- preprocessor.writef(
|
|
|
- " \\\n\t%suint gl_PrimitiveID : SV_PrimitiveID"
|
|
|
- , arg++ > 0 ? ", " : " "
|
|
|
- );
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- fprintf(stderr, "gl_PrimitiveID builtin is not supported by this D3D9 HLSL.\n");
|
|
|
- return bx::kExitFailure;
|
|
|
- }
|
|
|
+ fprintf(stderr, "gl_InstanceID builtin is not supported by this D3D9 HLSL.\n");
|
|
|
+ return false;
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- preprocessor.writef(
|
|
|
- " \\\n\t)\n"
|
|
|
- );
|
|
|
+ preprocessor.writef(
|
|
|
+ ") \\\n"
|
|
|
+ "{ \\\n"
|
|
|
+ "\tOutput _varying_;"
|
|
|
+ );
|
|
|
|
|
|
- if (hasFrontFacing)
|
|
|
+ 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 (hlsl >= 3)
|
|
|
- {
|
|
|
- preprocessor.writef(
|
|
|
- "#define gl_FrontFacing (__vface <= 0.0)\n"
|
|
|
- );
|
|
|
- }
|
|
|
- else
|
|
|
+ const Varying& var = varyingIt->second;
|
|
|
+ preprocessor.writef(" \\\n\t%s", var.m_name.c_str() );
|
|
|
+ if (!var.m_init.empty() )
|
|
|
{
|
|
|
- preprocessor.writef(
|
|
|
- "#define gl_FrontFacing false\n"
|
|
|
- );
|
|
|
+ preprocessor.writef(" = %s", var.m_init.c_str() );
|
|
|
}
|
|
|
+ preprocessor.writef(";");
|
|
|
}
|
|
|
}
|
|
|
- else if ('v' == shaderType)
|
|
|
+
|
|
|
+ preprocessor.writef(
|
|
|
+ "\n#define __RETURN__ \\\n"
|
|
|
+ "\t} \\\n"
|
|
|
+ );
|
|
|
+
|
|
|
+ if (hlsl != 0
|
|
|
+ && hlsl <= 3)
|
|
|
{
|
|
|
- const bool hasVertexId = NULL != bx::strFind(input, "gl_VertexID");
|
|
|
- const bool hasInstanceId = NULL != bx::strFind(input, "gl_InstanceID");
|
|
|
+// preprocessor.writef(
|
|
|
+// "\tgl_Position.xy += u_viewTexel.xy * gl_Position.w; \\\n"
|
|
|
+// );
|
|
|
+ }
|
|
|
|
|
|
- const char* brace = bx::strFind(entry, "{");
|
|
|
- if (NULL != brace)
|
|
|
- {
|
|
|
- const char* end = bx::strmb(brace, '{', '}');
|
|
|
- if (NULL != end)
|
|
|
- {
|
|
|
- strInsert(const_cast<char*>(end), "__RETURN__;\n");
|
|
|
- }
|
|
|
- }
|
|
|
+ preprocessor.writef(
|
|
|
+ "\treturn _varying_"
|
|
|
+ );
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- 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)
|
|
|
+ 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)
|
|
|
{
|
|
|
- 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() );
|
|
|
- }
|
|
|
+ writef(_writer
|
|
|
+ , "#ifdef GL_ES\n"
|
|
|
+ "precision highp float;\n"
|
|
|
+ "#endif // GL_ES\n\n"
|
|
|
+ );
|
|
|
}
|
|
|
- preprocessor.writef(
|
|
|
- "};\n"
|
|
|
- );
|
|
|
+ }
|
|
|
+ bx::write(_writer, preprocessor.m_preprocessed.c_str(), (int32_t)preprocessor.m_preprocessed.size() );
|
|
|
|
|
|
- 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%s%s %s : %s"
|
|
|
- , arg++ > 0 ? ", " : ""
|
|
|
- , var.m_type.c_str()
|
|
|
- , var.m_name.c_str()
|
|
|
- , var.m_semantics.c_str()
|
|
|
- );
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (hasVertexId)
|
|
|
- {
|
|
|
- if (d3d > 9)
|
|
|
- {
|
|
|
- preprocessor.writef(
|
|
|
- " \\\n\t%suint gl_VertexID : SV_VertexID"
|
|
|
- , arg++ > 0 ? ", " : " "
|
|
|
- );
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- fprintf(stderr, "gl_VertexID builtin is not supported by this D3D9 HLSL.\n");
|
|
|
- return bx::kExitFailure;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (hasInstanceId)
|
|
|
- {
|
|
|
- if (d3d > 9)
|
|
|
- {
|
|
|
- preprocessor.writef(
|
|
|
- " \\\n\t%suint gl_InstanceID : SV_InstanceID"
|
|
|
- , arg++ > 0 ? ", " : " "
|
|
|
- );
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- fprintf(stderr, "gl_InstanceID builtin is not supported by this D3D9 HLSL.\n");
|
|
|
- return bx::kExitFailure;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- preprocessor.writef(
|
|
|
- ") \\\n"
|
|
|
- "{ \\\n"
|
|
|
- "\tOutput _varying_;"
|
|
|
- );
|
|
|
-
|
|
|
- for (InOut::const_iterator it = shaderOutputs.begin(), itEnd = shaderOutputs.end(); it != itEnd; ++it)
|
|
|
- {
|
|
|
- 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() )
|
|
|
- {
|
|
|
- preprocessor.writef(" = %s", var.m_init.c_str() );
|
|
|
- }
|
|
|
- preprocessor.writef(";");
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- preprocessor.writef(
|
|
|
- "\n#define __RETURN__ \\\n"
|
|
|
- "\t} \\\n"
|
|
|
- );
|
|
|
-
|
|
|
- if (hlsl != 0
|
|
|
- && hlsl <= 3)
|
|
|
- {
|
|
|
-// preprocessor.writef(
|
|
|
-// "\tgl_Position.xy += u_viewTexel.xy * gl_Position.w; \\\n"
|
|
|
-// );
|
|
|
- }
|
|
|
-
|
|
|
- preprocessor.writef(
|
|
|
- "\treturn _varying_"
|
|
|
- );
|
|
|
- }
|
|
|
+ return true;
|
|
|
}
|
|
|
|
|
|
- if (preprocessor.run(input) )
|
|
|
{
|
|
|
- BX_TRACE("Input file: %s", filePath);
|
|
|
- BX_TRACE("Output file: %s", outFilePath);
|
|
|
-
|
|
|
- if (preprocessOnly)
|
|
|
+ if ('f' == _options.shaderType)
|
|
|
{
|
|
|
- bx::FileWriter writer;
|
|
|
-
|
|
|
- if (!bx::open(&writer, outFilePath) )
|
|
|
- {
|
|
|
- fprintf(stderr, "Unable to open output file '%s'.", outFilePath);
|
|
|
- return bx::kExitFailure;
|
|
|
- }
|
|
|
-
|
|
|
- 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 bx::kExitSuccess;
|
|
|
+ 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::FileWriter* writer = NULL;
|
|
|
+ bx::write(_writer, BGFX_CHUNK_MAGIC_CSH);
|
|
|
+ bx::write(_writer, outputHash);
|
|
|
+ }
|
|
|
|
|
|
- if (NULL != bin2c)
|
|
|
- {
|
|
|
- writer = new Bin2cWriter(bin2c);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- writer = new bx::FileWriter;
|
|
|
- }
|
|
|
+ if (0 != glsl
|
|
|
+ || 0 != essl
|
|
|
+ || 0 != metal)
|
|
|
+ {
|
|
|
+ std::string code;
|
|
|
|
|
|
- if (!bx::open(writer, outFilePath) )
|
|
|
+ if (glsl < 400)
|
|
|
{
|
|
|
- fprintf(stderr, "Unable to open output file '%s'.", outFilePath);
|
|
|
- return bx::kExitFailure;
|
|
|
- }
|
|
|
+ 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);
|
|
|
+ const bool usesTextureArray = !!bx::findIdentifierMatch(input, s_textureArray);
|
|
|
+ const bool usesPacking = !!bx::findIdentifierMatch(input, s_ARB_shading_language_packing);
|
|
|
+
|
|
|
+ if (0 == essl)
|
|
|
+ {
|
|
|
+ const bool need130 = 120 == glsl && (false
|
|
|
+ || bx::findIdentifierMatch(input, s_130)
|
|
|
+ || usesTexelFetch
|
|
|
+ );
|
|
|
|
|
|
- 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 != metal)
|
|
|
+ {
|
|
|
+ bx::stringPrintf(code, "#version 120\n");
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ bx::stringPrintf(code, "#version %s\n", need130 ? "130" : _options.profile.c_str());
|
|
|
+ glsl = 130;
|
|
|
+ }
|
|
|
|
|
|
- if (0 != glsl
|
|
|
- || 0 != essl
|
|
|
- || 0 != metal)
|
|
|
- {
|
|
|
- std::string code;
|
|
|
+ if (usesInstanceID)
|
|
|
+ {
|
|
|
+ bx::stringPrintf(code
|
|
|
+ , "#extension GL_ARB_draw_instanced : enable\n"
|
|
|
+ );
|
|
|
+ }
|
|
|
|
|
|
- if (glsl < 400)
|
|
|
- {
|
|
|
- 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);
|
|
|
- const bool usesTextureArray = !!bx::findIdentifierMatch(input, s_textureArray);
|
|
|
- const bool usesPacking = !!bx::findIdentifierMatch(input, s_ARB_shading_language_packing);
|
|
|
-
|
|
|
- if (0 == essl)
|
|
|
+ if (usesGpuShader4)
|
|
|
{
|
|
|
- const bool need130 = 120 == glsl && (false
|
|
|
- || bx::findIdentifierMatch(input, s_130)
|
|
|
- || usesTexelFetch
|
|
|
+ bx::stringPrintf(code
|
|
|
+ , "#extension GL_EXT_gpu_shader4 : enable\n"
|
|
|
);
|
|
|
+ }
|
|
|
|
|
|
- if (0 != metal)
|
|
|
- {
|
|
|
- bx::stringPrintf(code, "#version 120\n");
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- bx::stringPrintf(code, "#version %s\n", need130 ? "130" : profile);
|
|
|
- glsl = 130;
|
|
|
- }
|
|
|
+ if (usesGpuShader5)
|
|
|
+ {
|
|
|
+ bx::stringPrintf(code
|
|
|
+ , "#extension GL_ARB_gpu_shader5 : enable\n"
|
|
|
+ );
|
|
|
+ }
|
|
|
|
|
|
- if (usesInstanceID)
|
|
|
- {
|
|
|
- bx::stringPrintf(code
|
|
|
- , "#extension GL_ARB_draw_instanced : enable\n"
|
|
|
- );
|
|
|
- }
|
|
|
+ if (usesPacking)
|
|
|
+ {
|
|
|
+ bx::stringPrintf(code
|
|
|
+ , "#extension GL_ARB_shading_language_packing : enable\n"
|
|
|
+ );
|
|
|
+ }
|
|
|
|
|
|
- if (usesGpuShader4)
|
|
|
- {
|
|
|
- bx::stringPrintf(code
|
|
|
- , "#extension GL_EXT_gpu_shader4 : enable\n"
|
|
|
- );
|
|
|
- }
|
|
|
+ bool ARB_shader_texture_lod = false;
|
|
|
+ bool EXT_shader_texture_lod = false;
|
|
|
|
|
|
- if (usesGpuShader5)
|
|
|
+ if (usesTextureLod)
|
|
|
+ {
|
|
|
+ if ('f' == _options.shaderType)
|
|
|
{
|
|
|
+ ARB_shader_texture_lod = true;
|
|
|
bx::stringPrintf(code
|
|
|
- , "#extension GL_ARB_gpu_shader5 : enable\n"
|
|
|
+ , "#extension GL_ARB_shader_texture_lod : enable\n"
|
|
|
);
|
|
|
}
|
|
|
-
|
|
|
- if (usesPacking)
|
|
|
+ else
|
|
|
{
|
|
|
+ EXT_shader_texture_lod = true;
|
|
|
bx::stringPrintf(code
|
|
|
- , "#extension GL_ARB_shading_language_packing : enable\n"
|
|
|
+ , "#extension GL_EXT_shader_texture_lod : enable\n"
|
|
|
);
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- bool ARB_shader_texture_lod = false;
|
|
|
- bool EXT_shader_texture_lod = false;
|
|
|
-
|
|
|
- if (usesTextureLod)
|
|
|
- {
|
|
|
- if ('f' == shaderType)
|
|
|
- {
|
|
|
- ARB_shader_texture_lod = true;
|
|
|
- bx::stringPrintf(code
|
|
|
- , "#extension GL_ARB_shader_texture_lod : enable\n"
|
|
|
- );
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- EXT_shader_texture_lod = true;
|
|
|
- bx::stringPrintf(code
|
|
|
- , "#extension GL_EXT_shader_texture_lod : enable\n"
|
|
|
- );
|
|
|
- }
|
|
|
- }
|
|
|
+ if (usesTextureMS)
|
|
|
+ {
|
|
|
+ bx::stringPrintf(code
|
|
|
+ , "#extension GL_ARB_texture_multisample : enable\n"
|
|
|
+ );
|
|
|
+ }
|
|
|
|
|
|
- if (usesTextureMS)
|
|
|
- {
|
|
|
- bx::stringPrintf(code
|
|
|
- , "#extension GL_ARB_texture_multisample : enable\n"
|
|
|
- );
|
|
|
- }
|
|
|
+ if (usesTextureArray)
|
|
|
+ {
|
|
|
+ bx::stringPrintf(code
|
|
|
+ , "#extension GL_EXT_texture_array : enable\n"
|
|
|
+ );
|
|
|
+ }
|
|
|
|
|
|
- if (usesTextureArray)
|
|
|
- {
|
|
|
- bx::stringPrintf(code
|
|
|
- , "#extension GL_EXT_texture_array : enable\n"
|
|
|
- );
|
|
|
- }
|
|
|
+ if (130 > glsl)
|
|
|
+ {
|
|
|
+ bx::stringPrintf(code,
|
|
|
+ "#define ivec2 vec2\n"
|
|
|
+ "#define ivec3 vec3\n"
|
|
|
+ "#define ivec4 vec4\n"
|
|
|
+ );
|
|
|
+ }
|
|
|
|
|
|
- if (130 > glsl)
|
|
|
- {
|
|
|
- bx::stringPrintf(code,
|
|
|
- "#define ivec2 vec2\n"
|
|
|
- "#define ivec3 vec3\n"
|
|
|
- "#define ivec4 vec4\n"
|
|
|
- );
|
|
|
- }
|
|
|
+ if (ARB_shader_texture_lod)
|
|
|
+ {
|
|
|
+ bx::stringPrintf(code,
|
|
|
+ "#define texture2DProjLod texture2DProjLodARB\n"
|
|
|
+ "#define texture2DGrad texture2DGradARB\n"
|
|
|
+ "#define texture2DProjGrad texture2DProjGradARB\n"
|
|
|
+ "#define textureCubeGrad textureCubeGradARB\n"
|
|
|
+ );
|
|
|
+ }
|
|
|
+ else if (EXT_shader_texture_lod)
|
|
|
+ {
|
|
|
+ bx::stringPrintf(code,
|
|
|
+ "#define texture2DProjLod texture2DProjLodEXT\n"
|
|
|
+ "#define texture2DGrad texture2DGradEXT\n"
|
|
|
+ "#define texture2DProjGrad texture2DProjGradEXT\n"
|
|
|
+ "#define textureCubeGrad textureCubeGradEXT\n"
|
|
|
+ );
|
|
|
+ }
|
|
|
|
|
|
- if (ARB_shader_texture_lod)
|
|
|
- {
|
|
|
- bx::stringPrintf(code,
|
|
|
- "#define texture2DProjLod texture2DProjLodARB\n"
|
|
|
- "#define texture2DGrad texture2DGradARB\n"
|
|
|
- "#define texture2DProjGrad texture2DProjGradARB\n"
|
|
|
- "#define textureCubeGrad textureCubeGradARB\n"
|
|
|
- );
|
|
|
- }
|
|
|
- else if (EXT_shader_texture_lod)
|
|
|
- {
|
|
|
- bx::stringPrintf(code,
|
|
|
- "#define texture2DProjLod texture2DProjLodEXT\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
|
|
|
+ {
|
|
|
+ // Pretend that all extensions are available.
|
|
|
+ // This will be stripped later.
|
|
|
+ if (usesTextureLod)
|
|
|
+ {
|
|
|
+ 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"
|
|
|
- );
|
|
|
- }
|
|
|
-
|
|
|
- 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
|
|
|
- {
|
|
|
- // Pretend that all extensions are available.
|
|
|
- // This will be stripped later.
|
|
|
- if (usesTextureLod)
|
|
|
- {
|
|
|
- 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"
|
|
|
- );
|
|
|
- }
|
|
|
-
|
|
|
- if (NULL != bx::findIdentifierMatch(input, s_OES_standard_derivatives) )
|
|
|
- {
|
|
|
- bx::stringPrintf(code, "#extension GL_OES_standard_derivatives : enable\n");
|
|
|
- }
|
|
|
-
|
|
|
- if (NULL != bx::findIdentifierMatch(input, s_OES_texture_3D) )
|
|
|
- {
|
|
|
- bx::stringPrintf(code, "#extension GL_OES_texture_3D : enable\n");
|
|
|
- }
|
|
|
|
|
|
- if (NULL != bx::findIdentifierMatch(input, s_EXT_shadow_samplers) )
|
|
|
- {
|
|
|
- bx::stringPrintf(code
|
|
|
- , "#extension GL_EXT_shadow_samplers : enable\n"
|
|
|
- "#define shadow2D shadow2DEXT\n"
|
|
|
- "#define shadow2DProj shadow2DProjEXT\n"
|
|
|
- );
|
|
|
- }
|
|
|
-
|
|
|
- if (usesGpuShader5)
|
|
|
- {
|
|
|
- bx::stringPrintf(code
|
|
|
- , "#extension GL_ARB_gpu_shader5 : enable\n"
|
|
|
- );
|
|
|
- }
|
|
|
-
|
|
|
- if (usesPacking)
|
|
|
- {
|
|
|
- bx::stringPrintf(code
|
|
|
- , "#extension GL_ARB_shading_language_packing : enable\n"
|
|
|
- );
|
|
|
- }
|
|
|
+ if (NULL != bx::findIdentifierMatch(input, s_OES_standard_derivatives) )
|
|
|
+ {
|
|
|
+ bx::stringPrintf(code, "#extension GL_OES_standard_derivatives : enable\n");
|
|
|
+ }
|
|
|
|
|
|
- if (NULL != bx::findIdentifierMatch(input, "gl_FragDepth") )
|
|
|
- {
|
|
|
- bx::stringPrintf(code
|
|
|
- , "#extension GL_EXT_frag_depth : enable\n"
|
|
|
- "#define gl_FragDepth gl_FragDepthEXT\n"
|
|
|
- );
|
|
|
- }
|
|
|
+ if (NULL != bx::findIdentifierMatch(input, s_OES_texture_3D) )
|
|
|
+ {
|
|
|
+ bx::stringPrintf(code, "#extension GL_OES_texture_3D : enable\n");
|
|
|
+ }
|
|
|
|
|
|
- if (usesTextureArray)
|
|
|
- {
|
|
|
- bx::stringPrintf(code
|
|
|
- , "#extension GL_EXT_texture_array : enable\n"
|
|
|
- );
|
|
|
- }
|
|
|
+ if (NULL != bx::findIdentifierMatch(input, s_EXT_shadow_samplers) )
|
|
|
+ {
|
|
|
+ bx::stringPrintf(code
|
|
|
+ , "#extension GL_EXT_shadow_samplers : enable\n"
|
|
|
+ "#define shadow2D shadow2DEXT\n"
|
|
|
+ "#define shadow2DProj shadow2DProjEXT\n"
|
|
|
+ );
|
|
|
+ }
|
|
|
|
|
|
- bx::stringPrintf(code,
|
|
|
- "#define ivec2 vec2\n"
|
|
|
- "#define ivec3 vec3\n"
|
|
|
- "#define ivec4 vec4\n"
|
|
|
- );
|
|
|
+ if (usesGpuShader5)
|
|
|
+ {
|
|
|
+ bx::stringPrintf(code
|
|
|
+ , "#extension GL_ARB_gpu_shader5 : enable\n"
|
|
|
+ );
|
|
|
}
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- bx::stringPrintf(code, "#version %d\n", glsl);
|
|
|
- }
|
|
|
|
|
|
- code += preprocessor.m_preprocessed;
|
|
|
+ if (usesPacking)
|
|
|
+ {
|
|
|
+ bx::stringPrintf(code
|
|
|
+ , "#extension GL_ARB_shading_language_packing : enable\n"
|
|
|
+ );
|
|
|
+ }
|
|
|
|
|
|
- if (glsl > 400)
|
|
|
- {
|
|
|
- bx::write(writer, uint16_t(0) );
|
|
|
+ if (NULL != bx::findIdentifierMatch(input, "gl_FragDepth") )
|
|
|
+ {
|
|
|
+ bx::stringPrintf(code
|
|
|
+ , "#extension GL_EXT_frag_depth : enable\n"
|
|
|
+ "#define gl_FragDepth gl_FragDepthEXT\n"
|
|
|
+ );
|
|
|
+ }
|
|
|
|
|
|
- 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 (usesTextureArray)
|
|
|
+ {
|
|
|
+ bx::stringPrintf(code
|
|
|
+ , "#extension GL_EXT_texture_array : enable\n"
|
|
|
+ );
|
|
|
+ }
|
|
|
|
|
|
- compiled = true;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- compiled = compileGLSLShader(cmdLine
|
|
|
- , metal ? BX_MAKEFOURCC('M', 'T', 'L', 0) : essl
|
|
|
- , code
|
|
|
- , writer
|
|
|
- );
|
|
|
+ bx::stringPrintf(code,
|
|
|
+ "#define ivec2 vec2\n"
|
|
|
+ "#define ivec3 vec3\n"
|
|
|
+ "#define ivec4 vec4\n"
|
|
|
+ );
|
|
|
}
|
|
|
}
|
|
|
- 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::FileWriter 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)
|