You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Code/Tools/HLSLCrossCompiler/offline/compilerStandalone.cpp

804 lines
22 KiB
C++

// Modifications copyright Amazon.com, Inc. or its affiliates
// Modifications copyright Crytek GmbH
#include <inttypes.h>
#include "hlslcc.hpp"
#include "stdlib.h"
#include "stdio.h"
#include <string>
#include <string.h>
#include "hash.h"
#include "serializeReflection.h"
#include "hlslcc_bin.hpp"
#include <algorithm>
#include <cctype>
#ifdef _WIN32
#include <direct.h>
#else
#include <sys/stat.h>
#endif
#include "timer.h"
#if defined(_WIN32) && !defined(PORTABLE)
//#define VALIDATE_OUTPUT // NOTE: THIS IS OK DURING HLSLcc DEV BUT SHOULD NOT BE USED IN PRODUCTION. SOME EXT USED ARE NO SUPPORTED ON WINDOWS.
#endif
#if defined(VALIDATE_OUTPUT)
#if defined(_WIN32)
#include <windows.h>
#include <gl/GL.h>
#pragma comment(lib, "opengl32.lib")
typedef char GLcharARB; /* native character */
typedef unsigned int GLhandleARB; /* shader object handle */
#define GL_OBJECT_COMPILE_STATUS_ARB 0x8B81
#define GL_OBJECT_LINK_STATUS_ARB 0x8B82
#define GL_OBJECT_INFO_LOG_LENGTH_ARB 0x8B84
typedef void (WINAPI * PFNGLDELETEOBJECTARBPROC)(GLhandleARB obj);
typedef GLhandleARB (WINAPI * PFNGLCREATESHADEROBJECTARBPROC)(GLenum shaderType);
typedef void (WINAPI * PFNGLSHADERSOURCEARBPROC)(GLhandleARB shaderObj, GLsizei count, const GLcharARB** string, const GLint* length);
typedef void (WINAPI * PFNGLCOMPILESHADERARBPROC)(GLhandleARB shaderObj);
typedef void (WINAPI * PFNGLGETINFOLOGARBPROC)(GLhandleARB obj, GLsizei maxLength, GLsizei* length, GLcharARB* infoLog);
typedef void (WINAPI * PFNGLGETOBJECTPARAMETERIVARBPROC)(GLhandleARB obj, GLenum pname, GLint* params);
typedef GLhandleARB (WINAPI * PFNGLCREATEPROGRAMOBJECTARBPROC)(void);
typedef void (WINAPI * PFNGLATTACHOBJECTARBPROC)(GLhandleARB containerObj, GLhandleARB obj);
typedef void (WINAPI * PFNGLLINKPROGRAMARBPROC)(GLhandleARB programObj);
typedef void (WINAPI * PFNGLUSEPROGRAMOBJECTARBPROC)(GLhandleARB programObj);
typedef void (WINAPI * PFNGLGETSHADERINFOLOGPROC)(GLuint shader, GLsizei bufSize, GLsizei* length, GLcharARB* infoLog);
static PFNGLDELETEOBJECTARBPROC glDeleteObjectARB;
static PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB;
static PFNGLSHADERSOURCEARBPROC glShaderSourceARB;
static PFNGLCOMPILESHADERARBPROC glCompileShaderARB;
static PFNGLGETINFOLOGARBPROC glGetInfoLogARB;
static PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB;
static PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB;
static PFNGLATTACHOBJECTARBPROC glAttachObjectARB;
static PFNGLLINKPROGRAMARBPROC glLinkProgramARB;
static PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB;
static PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog;
#define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001
#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
#define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093
#define WGL_CONTEXT_FLAGS_ARB 0x2094
#define ERROR_INVALID_VERSION_ARB 0x2095
#define ERROR_INVALID_PROFILE_ARB 0x2096
#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC hDC, HGLRC hShareContext, const int* attribList);
static PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB;
void InitOpenGL()
{
HGLRC rc;
// setup minimal required GL
HWND wnd = CreateWindowA(
"STATIC",
"GL",
WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
0, 0, 16, 16,
NULL, NULL,
GetModuleHandle(NULL), NULL);
HDC dc = GetDC(wnd);
PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR), 1,
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL,
PFD_TYPE_RGBA, 32,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
16, 0,
0, PFD_MAIN_PLANE, 0, 0, 0, 0
};
int fmt = ChoosePixelFormat(dc, &pfd);
SetPixelFormat(dc, fmt, &pfd);
rc = wglCreateContext(dc);
wglMakeCurrent(dc, rc);
wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB");
if (wglCreateContextAttribsARB)
{
const int OpenGLContextAttribs [] = {
WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
WGL_CONTEXT_MINOR_VERSION_ARB, 3,
#if defined(_DEBUG)
//WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB | WGL_CONTEXT_DEBUG_BIT_ARB,
#else
//WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
#endif
//WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
0, 0
};
const HGLRC OpenGLContext = wglCreateContextAttribsARB(dc, 0, OpenGLContextAttribs);
wglMakeCurrent(dc, OpenGLContext);
wglDeleteContext(rc);
rc = OpenGLContext;
}
glDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC)wglGetProcAddress("glDeleteObjectARB");
glCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC)wglGetProcAddress("glCreateShaderObjectARB");
glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC)wglGetProcAddress("glShaderSourceARB");
glCompileShaderARB = (PFNGLCOMPILESHADERARBPROC)wglGetProcAddress("glCompileShaderARB");
glGetInfoLogARB = (PFNGLGETINFOLOGARBPROC)wglGetProcAddress("glGetInfoLogARB");
glGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC)wglGetProcAddress("glGetObjectParameterivARB");
glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC)wglGetProcAddress("glCreateProgramObjectARB");
glAttachObjectARB = (PFNGLATTACHOBJECTARBPROC)wglGetProcAddress("glAttachObjectARB");
glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC)wglGetProcAddress("glLinkProgramARB");
glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC)wglGetProcAddress("glUseProgramObjectARB");
glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC)wglGetProcAddress("glGetShaderInfoLog");
}
#endif
void PrintSingleLineError(FILE* pFile, const char* error)
{
while (*error != '\0')
{
const char* pLineEnd = strchr(error, '\n');
if (pLineEnd == 0)
{
pLineEnd = error + strlen(error) - 1;
}
fwrite(error, 1, pLineEnd - error, pFile);
fwrite("\r", 1, 1, pFile);
error = pLineEnd + 1;
}
}
int TryCompileShader(GLenum eShaderType, const char* inFilename, const char* shader, double* pCompileTime, int useStdErr)
{
GLint iCompileStatus;
GLuint hShader;
Timer_t timer;
InitTimer(&timer);
InitOpenGL();
hShader = glCreateShaderObjectARB(eShaderType);
glShaderSourceARB(hShader, 1, (const char**)&shader, NULL);
ResetTimer(&timer);
glCompileShaderARB(hShader);
*pCompileTime = ReadTimer(&timer);
/* Check it compiled OK */
glGetObjectParameterivARB (hShader, GL_OBJECT_COMPILE_STATUS_ARB, &iCompileStatus);
if (iCompileStatus != GL_TRUE)
{
FILE* errorFile = NULL;
GLint iInfoLogLength = 0;
char* pszInfoLog;
glGetObjectParameterivARB (hShader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &iInfoLogLength);
pszInfoLog = new char[iInfoLogLength];
printf("Error: Failed to compile GLSL shader\n");
glGetInfoLogARB (hShader, iInfoLogLength, NULL, pszInfoLog);
printf(pszInfoLog);
if (!useStdErr)
{
std::string filename;
filename += inFilename;
filename += "_compileErrors.txt";
//Dump to file
fopen_s(&errorFile, filename.c_str(), "w");
fclose(errorFile);
}
else
{
// Present error to stderror with no "new lines" as required by remote shader compiler
fprintf(stderr, "%s(-) error: ", inFilename);
PrintSingleLineError(stderr, pszInfoLog);
fprintf(stderr, "\rshader: ");
PrintSingleLineError(stderr, shader);
}
delete [] pszInfoLog;
return 0;
}
return 1;
}
#endif
int fileExists(const char* path)
{
FILE* shaderFile;
shaderFile = fopen(path, "rb");
if (shaderFile)
{
fclose(shaderFile);
return 1;
}
return 0;
}
GLLang LanguageFromString(const char* str)
{
if (strcmp(str, "es100") == 0)
{
return LANG_ES_100;
}
if (strcmp(str, "es300") == 0)
{
return LANG_ES_300;
}
if (strcmp(str, "es310") == 0)
{
return LANG_ES_310;
}
if (strcmp(str, "120") == 0)
{
return LANG_120;
}
if (strcmp(str, "130") == 0)
{
return LANG_130;
}
if (strcmp(str, "140") == 0)
{
return LANG_140;
}
if (strcmp(str, "150") == 0)
{
return LANG_150;
}
if (strcmp(str, "330") == 0)
{
return LANG_330;
}
if (strcmp(str, "400") == 0)
{
return LANG_400;
}
if (strcmp(str, "410") == 0)
{
return LANG_410;
}
if (strcmp(str, "420") == 0)
{
return LANG_420;
}
if (strcmp(str, "430") == 0)
{
return LANG_430;
}
if (strcmp(str, "440") == 0)
{
return LANG_440;
}
return LANG_DEFAULT;
}
#define MAX_PATH_CHARS 256
#define MAX_FXC_CMD_CHARS 1024
typedef struct
{
GLLang language;
int flags;
const char* shaderFile;
char* outputShaderFile;
char* reflectPath;
char cacheKey[MAX_PATH_CHARS];
int bUseFxc;
std::string fxcCmdLine;
} Options;
void InitOptions(Options* psOptions)
{
psOptions->language = LANG_DEFAULT;
psOptions->flags = 0;
psOptions->reflectPath = NULL;
psOptions->shaderFile = NULL;
psOptions->bUseFxc = 0;
}
void PrintHelp()
{
printf("Command line options:\n");
printf("\t-lang=X \t GLSL language to use. e.g. es100 or 140 or metal.\n");
printf("\t-flags=X \t The integer value of the HLSLCC_FLAGS to used.\n");
printf("\t-reflect=X \t File to write reflection JSON to.\n");
printf("\t-in=X \t Shader file to compile.\n");
printf("\t-out=X \t File to write the compiled shader from -in to.\n");
printf("\t-hashout=[dir/]out-file-name \t Output file name is a hash of 'out-file-name', put in the directory 'dir'.\n");
printf("\t-fxc=\"CMD\" HLSL compiler command line. If specified the input shader will be first compiled through this command first and then the resulting bytecode translated.\n");
printf("\n");
}
int GetOptions(int argc, char** argv, Options* psOptions)
{
int i;
int fullShaderChain = -1;
InitOptions(psOptions);
for (i = 1; i < argc; i++)
{
char* option;
option = strstr(argv[i], "-help");
if (option != NULL)
{
PrintHelp();
return 0;
}
option = strstr(argv[i], "-reflect=");
if (option != NULL)
{
psOptions->reflectPath = option + strlen("-reflect=");
}
option = strstr(argv[i], "-lang=");
if (option != NULL)
{
psOptions->language = LanguageFromString((&option[strlen("-lang=")]));
}
option = strstr(argv[i], "-flags=");
if (option != NULL)
{
psOptions->flags = atol(&option[strlen("-flags=")]);
}
option = strstr(argv[i], "-in=");
if (option != NULL)
{
fullShaderChain = 0;
psOptions->shaderFile = option + strlen("-in=");
if (!fileExists(psOptions->shaderFile))
{
printf("Invalid path: %s\n", psOptions->shaderFile);
return 0;
}
}
option = strstr(argv[i], "-out=");
if (option != NULL)
{
fullShaderChain = 0;
psOptions->outputShaderFile = option + strlen("-out=");
}
option = strstr(argv[i], "-hashout");
if (option != NULL)
{
fullShaderChain = 0;
psOptions->outputShaderFile = option + strlen("-hashout=");
char* dir;
int64_t length;
uint64_t hash = hash64((const uint8_t*)psOptions->outputShaderFile, (uint32_t)strlen(psOptions->outputShaderFile), 0);
dir = strrchr(psOptions->outputShaderFile, '\\');
if (!dir)
{
dir = strrchr(psOptions->outputShaderFile, '//');
}
if (!dir)
{
length = 0;
}
else
{
length = (int)(dir - psOptions->outputShaderFile) + 1;
}
for (i = 0; i < length; ++i)
{
psOptions->cacheKey[i] = psOptions->outputShaderFile[i];
}
//sprintf(psOptions->cacheKey, "%x%x", high, low);
sprintf(&psOptions->cacheKey[i], "%010" PRIX64, hash);
psOptions->outputShaderFile = psOptions->cacheKey;
}
option = strstr(argv[i], "-fxc=");
if (option != NULL)
{
char* cmdLine = option + strlen("-fxc=");
size_t cmdLineLen = strlen(cmdLine);
if (cmdLineLen == 0 || cmdLineLen + 1 >= MAX_FXC_CMD_CHARS)
{
return 0;
}
psOptions->fxcCmdLine = std::string(cmdLine, cmdLineLen);
psOptions->bUseFxc = 1;
}
}
return 1;
}
void* malloc_hook(size_t size)
{
return malloc(size);
}
void* calloc_hook(size_t num, size_t size)
{
return calloc(num, size);
}
void* realloc_hook(void* p, size_t size)
{
return realloc(p, size);
}
void free_hook(void* p)
{
free(p);
}
int Run(const char* srcPath, const char* destPath, GLLang language, int flags, const char* reflectPath, GLSLShader* shader, int useStdErr)
{
FILE* outputFile;
GLSLShader tempShader;
GLSLShader* result = shader ? shader : &tempShader;
Timer_t timer;
int compiledOK = 0;
double crossCompileTime = 0;
HLSLcc_SetMemoryFunctions(malloc_hook, calloc_hook, free_hook, realloc_hook);
InitTimer(&timer);
ResetTimer(&timer);
GlExtensions ext;
ext.ARB_explicit_attrib_location = 0;
ext.ARB_explicit_uniform_location = 0;
ext.ARB_shading_language_420pack = 0;
compiledOK = TranslateHLSLFromFile(srcPath, flags, language, &ext, result);
crossCompileTime = ReadTimer(&timer);
if (compiledOK)
{
printf("cc time: %.2f us\n", crossCompileTime);
if (destPath)
{
//Dump to file
outputFile = fopen(destPath, "w");
fprintf(outputFile, result->sourceCode);
fclose(outputFile);
}
if (reflectPath)
{
const char* jsonString = SerializeReflection(&result->reflection);
outputFile = fopen(reflectPath, "w");
fprintf(outputFile, jsonString);
fclose(outputFile);
}
#if defined(VALIDATE_OUTPUT)
std::string shaderSource;
if (flags & HLSLCC_FLAG_NO_VERSION_STRING)
{
// Need to add the version string so that the shader will compile
shaderSource = GetVersionString(language);
shaderSource += result->sourceCode;
}
else
{
shaderSource = result->sourceCode;
}
compiledOK = TryCompileShader(result->shaderType, destPath ? destPath : "", shaderSource.c_str(), &glslCompileTime, useStdErr);
if (compiledOK)
{
printf("glsl time: %.2f us\n", glslCompileTime);
}
#endif
if (!shader)
{
FreeGLSLShader(result);
}
}
else if (useStdErr)
{
fprintf(stderr, "TranslateHLSLFromFile failed");
}
return compiledOK;
}
struct SDXBCFile
{
FILE* m_pFile;
bool Read(void* pElements, size_t uSize)
{
return fread(pElements, 1, uSize, m_pFile) == uSize;
}
bool Write(const void* pElements, size_t uSize)
{
return fwrite(pElements, 1, uSize, m_pFile) == uSize;
}
bool SeekRel(int32_t iOffset)
{
return fseek(m_pFile, iOffset, SEEK_CUR) == 0;
}
bool SeekAbs(uint32_t uPosition)
{
return fseek(m_pFile, uPosition, SEEK_SET) == 0;
}
};
int CombineDXBCWithGLSL(char* dxbcFileName, char* outputFileName, GLSLShader* shader)
{
SDXBCFile dxbcFile = { fopen(dxbcFileName, "rb") };
SDXBCFile outputFile = { fopen(outputFileName, "wb") };
bool result =
dxbcFile.m_pFile != NULL && outputFile.m_pFile != NULL &&
DXBCCombineWithGLSL(dxbcFile, outputFile, shader);
if (dxbcFile.m_pFile != NULL)
{
fclose(dxbcFile.m_pFile);
}
if (outputFile.m_pFile != NULL)
{
fclose(outputFile.m_pFile);
}
return result;
}
#if !defined(_MSC_VER)
#define sprintf_s(dest, size, ...) sprintf(dest, __VA_ARGS__)
#endif
#if defined(_WIN32) && defined(PORTABLE)
DWORD FilterException(DWORD uExceptionCode)
{
const char* szExceptionName;
char acTemp[10];
switch (uExceptionCode)
{
#define _CASE(_Name) \
case _Name: \
szExceptionName = #_Name; \
break;
_CASE(EXCEPTION_ACCESS_VIOLATION)
_CASE(EXCEPTION_DATATYPE_MISALIGNMENT)
_CASE(EXCEPTION_BREAKPOINT)
_CASE(EXCEPTION_SINGLE_STEP)
_CASE(EXCEPTION_ARRAY_BOUNDS_EXCEEDED)
_CASE(EXCEPTION_FLT_DENORMAL_OPERAND)
_CASE(EXCEPTION_FLT_DIVIDE_BY_ZERO)
_CASE(EXCEPTION_FLT_INEXACT_RESULT)
_CASE(EXCEPTION_FLT_INVALID_OPERATION)
_CASE(EXCEPTION_FLT_OVERFLOW)
_CASE(EXCEPTION_FLT_STACK_CHECK)
_CASE(EXCEPTION_FLT_UNDERFLOW)
_CASE(EXCEPTION_INT_DIVIDE_BY_ZERO)
_CASE(EXCEPTION_INT_OVERFLOW)
_CASE(EXCEPTION_PRIV_INSTRUCTION)
_CASE(EXCEPTION_IN_PAGE_ERROR)
_CASE(EXCEPTION_ILLEGAL_INSTRUCTION)
_CASE(EXCEPTION_NONCONTINUABLE_EXCEPTION)
_CASE(EXCEPTION_STACK_OVERFLOW)
_CASE(EXCEPTION_INVALID_DISPOSITION)
_CASE(EXCEPTION_GUARD_PAGE)
_CASE(EXCEPTION_INVALID_HANDLE)
//_CASE(EXCEPTION_POSSIBLE_DEADLOCK)
#undef _CASE
default:
sprintf_s(acTemp, "0x%08X", uExceptionCode);
szExceptionName = acTemp;
}
fprintf(stderr, "Hardware exception thrown (%s)\n", szExceptionName);
return 1;
}
#endif
const char* PatchHLSLShaderFile(const char* path)
{
// Need to transform "half" into "min16float" so FXC preserve min precision to the operands.
static char patchedFileName[MAX_PATH_CHARS];
const char* defines = "#define half min16float\n"
"#define half2 min16float2\n"
"#define half3 min16float3\n"
"#define half4 min16float4\n";
sprintf_s(patchedFileName, sizeof(patchedFileName), "%s.hlslPatched", path);
FILE* shaderFile = fopen(path, "rb");
if (!shaderFile)
{
return NULL;
}
FILE* patchedFile = fopen(patchedFileName, "wb");
if (!patchedFile)
{
return NULL;
}
// Get size of file
bool result = false;
fseek(shaderFile, 0, SEEK_END);
long size = ftell(shaderFile);
fseek(shaderFile, 0, SEEK_SET);
unsigned char* data = new unsigned char[size + 1]; // Extra byte for the '/0' character.
if (fread(data, 1, size, shaderFile) == size)
{
data[size] = '\0';
fprintf(patchedFile, "%s%s", defines, data);
result = true;
}
if (shaderFile)
{
fclose(shaderFile);
}
if (patchedFile)
{
fclose(patchedFile);
}
delete[] data;
return result ? patchedFileName : NULL;
}
int main(int argc, char** argv)
{
Options options;
#if defined(_WIN32) && defined(PORTABLE)
__try
{
#endif
if (!GetOptions(argc, argv, &options))
{
return 1;
}
if (options.bUseFxc)
{
char dxbcFileName[MAX_PATH_CHARS];
char glslFileName[MAX_PATH_CHARS];
char fullFxcCmdLine[MAX_FXC_CMD_CHARS];
int retValue;
if (options.flags & HLSLCC_FLAG_HALF_FLOAT_TRANSFORM)
{
options.shaderFile = PatchHLSLShaderFile(options.shaderFile);
if (!options.shaderFile)
{
return 1;
}
}
sprintf_s(dxbcFileName, sizeof(dxbcFileName), "%s.dxbc", options.shaderFile);
sprintf_s(glslFileName, sizeof(glslFileName), "%s.patched", options.shaderFile);
// Need to extract the path to the executable so we can enclose it in quotes
// in case it contains spaces.
const std::string fxcExeName = "fxc.exe";
// Case insensitive search
std::string::iterator fxcPos = std::search(
options.fxcCmdLine.begin(), options.fxcCmdLine.end(),
fxcExeName.begin(), fxcExeName.end(),
[](char ch1, char ch2) { return std::tolower(ch1) == std::tolower(ch2); }
);
if (fxcPos == options.fxcCmdLine.end())
{
fprintf(stderr, "Could not find fxc.exe in command line");
return 1;
}
// Add the fxcExeName so it gets copied to the fxcExe path.
fxcPos += fxcExeName.length();
std::string fxcExe(options.fxcCmdLine.begin(), fxcPos);
std::string fxcArguments(fxcPos, options.fxcCmdLine.end());
#if defined(APPLE)
fprintf(stderr, "fxc.exe cannot be executed on Mac");
return 1;
#else
// Need an extra set of quotes around the full command line because the way "system" executes it using cmd.
sprintf_s(fullFxcCmdLine, sizeof(fullFxcCmdLine), "\"\"%s\" %s \"%s\" \"%s\"\"", fxcExe.c_str(), fxcArguments.c_str(), dxbcFileName, options.shaderFile);
#endif
retValue = system(fullFxcCmdLine);
if (retValue == 0)
{
GLSLShader shader;
retValue = !Run(dxbcFileName, glslFileName, options.language, options.flags, options.reflectPath, &shader, 1);
if (retValue == 0)
{
retValue = !CombineDXBCWithGLSL(dxbcFileName, options.outputShaderFile, &shader);
FreeGLSLShader(&shader);
}
}
remove(dxbcFileName);
remove(glslFileName);
if (options.flags & HLSLCC_FLAG_HALF_FLOAT_TRANSFORM)
{
// Removed the hlsl patched file that was created.
remove(options.shaderFile);
}
return retValue;
}
if (options.shaderFile)
{
if (!Run(options.shaderFile, options.outputShaderFile, options.language, options.flags, options.reflectPath, NULL, 0))
{
return 1;
}
}
#if defined(_WIN32) && defined(PORTABLE)
}
__except (FilterException(GetExceptionCode()))
{
return 1;
}
#endif
return 0;
}