Skip to content

Instantly share code, notes, and snippets.

@1480c1
Last active October 5, 2020 06:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 1480c1/a460b9978a09e9a112ca0dd789abb437 to your computer and use it in GitHub Desktop.
Save 1480c1/a460b9978a09e9a112ca0dd789abb437 to your computer and use it in GitHub Desktop.
fxc2
From 7f538a65278c9f6c0850115f64489637ecaf893b Mon Sep 17 00:00:00 2001
From: Christopher Degawa <ccom@randomderp.com>
Date: Fri, 25 Sep 2020 18:57:06 +0000
Subject: [PATCH 4/6] Don't use MAX_PATH for the dllPath
Signed-off-by: Christopher Degawa <ccom@randomderp.com>
---
fxc2.cpp | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/fxc2.cpp b/fxc2.cpp
index 14ea4b7..855afbe 100755
--- a/fxc2.cpp
+++ b/fxc2.cpp
@@ -207,14 +207,12 @@ int main(int argc, const char* argv[])
// Shader Compilation
//Find the WINDOWS dll
- char dllPath[ MAX_PATH ];
- int bytes = GetModuleFileName(NULL, dllPath, MAX_PATH);
+ char dllPath[ 4096 ] = {};
+ int bytes = GetModuleFileName(NULL, dllPath, 4096);
if(bytes == 0) {
printf("Could not retrieve the directory of the running executable.\n");
return 1;
}
- //Fill rest of the buffer with NULLs
- memset(dllPath + bytes, '\0', MAX_PATH - bytes);
//Copy the dll location over top fxc2.exe
strcpy(strrchr(dllPath, '\\') + 1, "d3dcompiler_47.dll");
--
2.25.1
From b9962effb7a810bbf0fe1d43184db35d9b67aacd Mon Sep 17 00:00:00 2001
From: Christopher Degawa <ccom@randomderp.com>
Date: Fri, 25 Sep 2020 18:58:38 +0000
Subject: [PATCH 5/6] print*: Combine printf commands
Signed-off-by: Christopher Degawa <ccom@randomderp.com>
---
fxc2.cpp | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/fxc2.cpp b/fxc2.cpp
index 855afbe..b9e2cbc 100755
--- a/fxc2.cpp
+++ b/fxc2.cpp
@@ -43,19 +43,19 @@ static const ProfilePrefix g_profilePrefixTable[] = {
void print_usage_arg() {
// https://msdn.microsoft.com/en-us/library/windows/desktop/bb509709(v=vs.85).aspx
- printf("You have specified an argument that is not handled by fxc2\n");
- printf("This isn't a sign of disaster, odds are it will be very easy to add support for this argument.\n");
- printf("Review the meaning of the argument in the real fxc program, and then add it into fxc2.\n");
+ printf("You have specified an argument that is not handled by fxc2\n"
+ "This isn't a sign of disaster, odds are it will be very easy to add support for this argument.\n"
+ "Review the meaning of the argument in the real fxc program, and then add it into fxc2.\n");
exit(1);
}
void print_usage_missing(const char* arg) {
- printf("fxc2 is missing the %s argument. We expected to receive this, and it's likely things ", arg);
- printf("will not work correctly without it. Review fxc2 and make sure things will work.\n");
+ printf("fxc2 is missing the %s argument. We expected to receive this, and it's likely things "
+ "will not work correctly without it. Review fxc2 and make sure things will work.\n", arg);
exit(1);
}
void print_usage_toomany() {
- printf("You specified multiple input files. We did not expect to receive this, and aren't prepared to handle ");
- printf("multiple input files. You'll have to edit the source to behave the way you want.\n");
+ printf("You specified multiple input files. We did not expect to receive this, and aren't prepared to handle "
+ "multiple input files. You'll have to edit the source to behave the way you want.\n");
exit(1);
}
--
2.25.1
From d7d517df3cec7e77271a6e82f194d931cde36627 Mon Sep 17 00:00:00 2001
From: Christopher Degawa <ccom@randomderp.com>
Date: Fri, 25 Sep 2020 20:07:04 +0000
Subject: [PATCH 6/6] temp
Signed-off-by: Christopher Degawa <ccom@randomderp.com>
---
fxc2.cpp | 530 +++++++++++++++++++++++--------------------------------
1 file changed, 219 insertions(+), 311 deletions(-)
diff --git a/fxc2.cpp b/fxc2.cpp
index b9e2cbc..10ded81 100755
--- a/fxc2.cpp
+++ b/fxc2.cpp
@@ -1,329 +1,237 @@
-#include <d3dcompiler.h>
-#include <d3dcommon.h>
-#include <direct.h>
#include <stdio.h>
-#include <assert.h>
-#include <string>
-#include <wchar.h>
-
-
-#define D3D_COMPILE_STANDARD_FILE_INCLUDE ((ID3DInclude*)(UINT_PTR)1)
-typedef HRESULT(__stdcall *pCompileFromFileg)(LPCWSTR,
- const D3D_SHADER_MACRO[],
- ID3DInclude*,
- LPCSTR,
- LPCSTR,
- UINT,
- UINT,
- ID3DBlob**,
- ID3DBlob**);
-
-struct ProfilePrefix {
- const char* name;
- const char* prefix;
-};
+/*
+ * comdef.h requires stdio.h to be included for snprintf,
+ * but it's not included in comdef
+ */
-static const ProfilePrefix g_profilePrefixTable[] = {
- { "ps_2_0", "g_ps20"},
- { "ps_2_a", "g_ps21"},
- { "ps_2_b", "g_ps21"},
- { "ps_2_sw", "g_ps2ff"},
- { "ps_3_0", "g_ps30"},
- { "ps_3_sw", "g_ps3ff"},
-
- { "vs_1_1", "g_vs11"},
- { "vs_2_0", "g_vs20"},
- { "vs_2_a", "g_vs21"},
- { "vs_2_sw", "g_vs2ff"},
- { "vs_3_0", "g_vs30"},
- { "vs_3_sw", "g_vs3ff"},
-
- { NULL, NULL}
-};
+#include <comdef.h>
+#include <d3dcommon.h>
+#include <d3dcompiler.h>
+#include <direct.h>
+#include <tchar.h>
-void print_usage_arg() {
- // https://msdn.microsoft.com/en-us/library/windows/desktop/bb509709(v=vs.85).aspx
- printf("You have specified an argument that is not handled by fxc2\n"
- "This isn't a sign of disaster, odds are it will be very easy to add support for this argument.\n"
- "Review the meaning of the argument in the real fxc program, and then add it into fxc2.\n");
- exit(1);
-}
-void print_usage_missing(const char* arg) {
- printf("fxc2 is missing the %s argument. We expected to receive this, and it's likely things "
- "will not work correctly without it. Review fxc2 and make sure things will work.\n", arg);
- exit(1);
-}
-void print_usage_toomany() {
- printf("You specified multiple input files. We did not expect to receive this, and aren't prepared to handle "
- "multiple input files. You'll have to edit the source to behave the way you want.\n");
- exit(1);
+#include <algorithm>
+#include <fstream>
+#include <iostream>
+#include <list>
+#include <string>
+#include <vector>
+
+#ifndef D3D_COMPILE_STANDARD_FILE_INCLUDE
+#define D3D_COMPILE_STANDARD_FILE_INCLUDE ((ID3DInclude *)(UINT_PTR)1)
+#endif
+
+static const struct ProfilePrefix {
+ const char *name;
+ const char *prefix;
+} g_profilePrefixTable[] = {
+ {"ps_2_0", "g_ps20"}, {"ps_2_a", "g_ps21"}, {"ps_2_b", "g_ps21"},
+ {"ps_2_sw", "g_ps2ff"}, {"ps_3_0", "g_ps30"}, {"ps_3_sw", "g_ps3ff"},
+
+ {"vs_1_1", "g_vs11"}, {"vs_2_0", "g_vs20"}, {"vs_2_a", "g_vs21"},
+ {"vs_2_sw", "g_vs2ff"}, {"vs_3_0", "g_vs30"}, {"vs_3_sw", "g_vs3ff"}};
+
+[[noreturn]] static void print_usage_missing(const std::string &arg) {
+ std::cerr << "fxc2 is missing the " << arg
+ << " argument. We expected to receive this, and "
+ "it's likely things "
+ "will not work correctly without it. Review fxc2 and make "
+ "sure things "
+ "will work.\n";
+ exit(1);
}
-bool parseOpt( const char* option, int argc, const char** argv, int* index, char** argumentOption )
-{
- assert(option != NULL);
- if (!index || *index >= argc) {
- return false;
+class parseOpt {
+ std::list<std::string> args;
+
+ public:
+ parseOpt(int argc = 1, const char **argv = nullptr)
+ : args(std::list<std::string>(argv + 1, argv + argc)) {}
+ bool end() { return !args.size(); }
+ std::string get() {
+ if (end()) return "";
+ auto temp = *args.begin();
+ args.erase(args.begin());
+ return temp;
}
- const char* argument = argv[*index];
- if (argument[0] == '-' || argument[0] == '/')
- argument++;
- else
- return false;
-
- size_t optionSize = strlen(option);
- if (strncmp(argument, option, optionSize) != 0) {
- return false;
+ bool operator()(const std::string &option) {
+ auto t = std::find_if(
+ args.begin(), args.end(), [&option](const std::string &i) {
+ if ((i.at(0) != '-' && i.at(0) != '/') || i.size() == 1)
+ return false;
+ return i.substr(1) == option;
+ });
+ if (t == args.end()) return false;
+ args.remove(*t);
+ return true;
}
-
- if (argumentOption) {
- argument += optionSize;
- if (*argument == '\0') {
- *index += 1;
- if (*index >= argc) {
- printf("Error: missing required argument for option %s\n", option);
- return false;
+ bool operator()(const std::string &option, std::string &argumentOption) {
+ argumentOption = "";
+ auto t = std::find_if(
+ args.begin(), args.end(), [&option](const std::string &i) {
+ if ((i.at(0) != '-' && i.at(0) != '/') || i.size() == 1)
+ return false;
+ return i.substr(1, option.size()) == option;
+ });
+ if (t == args.end()) return false;
+ auto temp = t->substr(option.size() + 1);
+ if (temp.size())
+ argumentOption = temp;
+ else {
+ if (++t == args.end()) {
+ std::cerr << "Error: missing required argument for option "
+ << option << '\n';
+ return false;
+ }
+ argumentOption = *t;
+ args.erase(t--);
}
- *argumentOption = strdup(argv[*index]);
- } else {
- *argumentOption = strdup(argument);
- }
+ args.erase(t);
+ return true;
}
- *index += 1;
- return true;
-}
+};
-int main(int argc, const char* argv[])
-{
- // ====================================================================================
- // Process Command Line Arguments
-
- int verbose = 1;
-
- char* model = NULL;
- wchar_t* inputFile = NULL;
- char* entryPoint = NULL;
- char* variableName = NULL;
- char* outputFile = NULL;
- char* defineOption = NULL;
- int numDefines = 1;
- D3D_SHADER_MACRO* defines = new D3D_SHADER_MACRO[numDefines];
- defines[numDefines-1].Name = NULL;
- defines[numDefines-1].Definition = NULL;
-
- int index = 1;
- while (1) {
- D3D_SHADER_MACRO* newDefines;
-
- /* Detect the end of the options. */
- if (index >= argc)
- break;
-
- if (parseOpt("nologo", argc, argv, &index, NULL)) {
- continue;
- } else if (parseOpt("T", argc, argv, &index, &model)) {
- if(verbose) {
- printf ("option -T (Shader Model/Profile) with arg '%s'\n", model);
- }
- continue;
- } else if (parseOpt("E", argc, argv, &index, &entryPoint)) {
- if(verbose) {
- printf ("option -E (Entry Point) with arg '%s'\n", entryPoint);
- }
- continue;
- } else if (parseOpt("D", argc, argv, &index, &defineOption)) {
- numDefines++;
- //Copy the old array into the new array, but put the new definition at the beginning
- newDefines = new D3D_SHADER_MACRO[numDefines];
- for(int i=1; i<numDefines; i++)
- newDefines[i] = defines[i-1];
- delete[] defines;
- defines = newDefines;
- defines[0].Name = defineOption;
- defines[0].Definition = "1";
- if(verbose) {
- printf ("option -D with arg %s\n", defineOption);
- }
- continue;
- } else if (parseOpt("Vn", argc, argv, &index, &variableName)) {
- if(verbose) {
- printf ("option -Vn (Variable Name) with arg '%s'\n", variableName);
- }
- continue;
- } else if (parseOpt("Vi", argc, argv, &index, NULL)) {
- if(verbose) {
- printf("option -Vi (Output include process details) acknowledged but ignored.\n");
- }
- continue;
- } else if (parseOpt("Fh", argc, argv, &index, &outputFile)) {
- if(verbose) {
- printf ("option -Fh (Output File) with arg %s\n", outputFile);
- }
- continue;
- } else if (parseOpt("?", argc, argv, &index, NULL)) {
- print_usage_arg();
- continue;
- } else {
- if (!inputFile)
- {
- inputFile = new wchar_t[strlen(argv[index])+1];
- mbstowcs(inputFile, argv[index], strlen(argv[index])+1);
- if(verbose) {
- wprintf(L"input file: %ls\n", inputFile);
- }
- index += 1;
- } else {
- print_usage_toomany();
+int main(int argc, const char *argv[]) {
+ // ====================================================================================
+ // Process Command Line Arguments
+
+ class parseOpt p(argc, argv);
+
+ p("nologo");
+ std::string model;
+ p("T", model);
+ std::string entryPoint;
+ p("E", entryPoint);
+ std::string variableName;
+ p("Vn", variableName);
+ std::string outputFile;
+ p("Fh", outputFile);
+ if (p("Vi"))
+ std::cerr << "option -Vi (Output include process details) "
+ "acknowledged "
+ "but ignored.\n";
+
+ std::string defineOption;
+ std::vector<std::string> defineStrings;
+ while (p("D", defineOption)) {
+ defineStrings.push_back(defineOption);
+ std::cerr << "option -D with arg " << defineOption << '\n';
+ }
+ defineOption.clear();
+
+ std::string inputFile = p.get();
+ if (inputFile.empty()) print_usage_missing("inputFile");
+
+ std::cerr << "input file: " << inputFile << '\n';
+
+ if (!p.end()) {
+ // https://msdn.microsoft.com/en-us/library/windows/desktop/bb509709(v=vs.85).aspx
+ std::cerr << "Error: You have specified an argument that is not "
+ "handled by fxc2\n"
+ "Argument: \n"
+ << p.get()
+ << "\n"
+ "This isn't a sign of disaster, odds are it will be "
+ "very easy to add support for this argument.\n"
+ "Review the meaning of the argument in the real fxc "
+ "program, and then add it into fxc2.\n";
return 1;
- }
}
- }
-
- if(inputFile == NULL)
- print_usage_missing("inputFile");
- if(model == NULL)
- print_usage_missing("model");
- if(entryPoint == NULL)
- print_usage_missing("entryPoint");
- if(defines == NULL)
- print_usage_missing("defines");
- if(outputFile == NULL)
- print_usage_missing("outputFile");
-
- //Default output variable name
- if (variableName == NULL) {
- const char* prefix = "g";
- for (int i = 0; g_profilePrefixTable[i].name != NULL; i++) {
- if (strcmp(g_profilePrefixTable[i].name, model) == 0) {
- prefix = g_profilePrefixTable[i].prefix;
- break;
- }
- }
- variableName = (char*)malloc(strlen(prefix) + strlen(entryPoint) + 2);
- sprintf(variableName, "%s_%s", prefix, entryPoint);
- }
-
- // ====================================================================================
- // Shader Compilation
-
- //Find the WINDOWS dll
- char dllPath[ 4096 ] = {};
- int bytes = GetModuleFileName(NULL, dllPath, 4096);
- if(bytes == 0) {
- printf("Could not retrieve the directory of the running executable.\n");
- return 1;
- }
- //Copy the dll location over top fxc2.exe
- strcpy(strrchr(dllPath, '\\') + 1, "d3dcompiler_47.dll");
-
- HMODULE h = LoadLibrary(dllPath);
- if(h == NULL) {
- printf("Error: could not load d3dcompiler_47.dll from %s\n", dllPath);
- return 1;
- }
-
- pCompileFromFileg ptr = (pCompileFromFileg)GetProcAddress(h, "D3DCompileFromFile");
- if(ptr == NULL) {
- printf("Error: could not get the address of D3DCompileFromFile.\n");
- return 1;
- }
-
- HRESULT hr;
- ID3DBlob* output = NULL;
- ID3DBlob* errors = NULL;
-
- if(verbose) {
- printf("Calling D3DCompileFromFile(\n");
-
- wprintf(L"\t %ls,\n", inputFile);
-
- printf("\t");
- for(int i=0; i<numDefines-1; i++)
- printf(" %s=%s", defines[i].Name, defines[i].Definition);
- printf(",\n");
-
- printf("\t D3D_COMPILE_STANDARD_FILE_INCLUDE,\n");
-
- printf("\t %s,\n", entryPoint);
-
- printf("\t %s,\n", model);
-
- printf("\t 0,\n");
- printf("\t 0,\n");
- printf("\t &output,\n");
- printf("\t &errors);\n");
- }
-
- /*
- HRESULT WINAPI D3DCompileFromFile(
- in LPCWSTR pFileName,
- in_opt const D3D_SHADER_MACRO pDefines,
- in_opt ID3DInclude pInclude,
- in LPCSTR pEntrypoint,
- in LPCSTR pTarget,
- in UINT Flags1,
- in UINT Flags2,
- out ID3DBlob ppCode,
- out_opt ID3DBlob ppErrorMsgs
- );
- */
- hr = ptr(
- inputFile,
- defines,
- D3D_COMPILE_STANDARD_FILE_INCLUDE,
- entryPoint,
- model,
- 0,
- 0,
- &output,
- &errors
- );
-
- // ====================================================================================
- // Output (or errors)
-
- if (FAILED(hr)) {
- if (errors) {
- char* error = (char*)errors->GetBufferPointer();
- printf("Got an error (%i) while compiling:\n%s\n", hr, error);
- errors->Release();
- } else {
- printf("Got an error (%i) while compiling, but no error message from the function.\n", hr);
-
- LPSTR messageBuffer = nullptr;
- size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL, hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL);
- printf("Windows Error Message: %s\n", messageBuffer);
- LocalFree(messageBuffer);
- }
-
- if (output)
- output->Release();
-
- return hr;
- } else {
- char * outString = (char*)output->GetBufferPointer();
- int len = output->GetBufferSize();
-
- FILE* f;
- errno_t err = fopen_s(&f, outputFile, "w");
-
- fprintf(f, "const BYTE %s[] =\n{\n", variableName);
- for (int i = 0; i < len; i++) {
- fprintf(f, "%4i", outString[i]);
- if (i != len - 1)
- fprintf(f, ",");
- if (i % 6 == 5)
- fprintf(f, "\n");
+
+ if (model.empty()) print_usage_missing("model");
+ if (entryPoint.empty()) print_usage_missing("entryPoint");
+ if (outputFile.empty()) print_usage_missing("outputFile");
+ std::cerr << "option -T (Shader Model/Profile) with arg '" << model << "'\n"
+ << "option -E (Entry Point) with arg '" << entryPoint << "'\n"
+ << "option -Fh (Output File) with arg " << outputFile << '\n';
+
+ // Default output variable name
+ if (variableName.empty()) {
+ variableName = "g_" + entryPoint;
+ for (auto &&i : g_profilePrefixTable) {
+ if (i.name != model) continue;
+ variableName = std::string(i.prefix) + '_' + entryPoint;
+ }
+ } else
+ std::cerr << "option -Vn (Variable Name) with arg '" << variableName
+ << "'\n";
+
+ // ====================================================================================
+ // Shader Compilation
+
+ std::vector<char> absPath(
+ GetFullPathNameA(inputFile.c_str(), 0, nullptr, nullptr));
+ GetFullPathNameA(inputFile.c_str(), absPath.size(), absPath.data(),
+ nullptr);
+ inputFile.clear();
+ std::vector<wchar_t> absPathW(4096);
+ absPathW.resize(
+ std::mbstowcs(absPathW.data(), absPath.data(), absPath.size()));
+
+ absPath.clear();
+
+ std::wcerr << L"Calling D3DCompileFromFile(\n\t "
+ << std::wstring(absPathW.data()) << L",\n\t";
+
+ std::vector<D3D_SHADER_MACRO> defines(
+ 1, (D3D_SHADER_MACRO){.Name = nullptr, .Definition = nullptr});
+ for (auto &&i : defineStrings) {
+ defines.insert(defines.begin(), (D3D_SHADER_MACRO){.Name = i.c_str(),
+ .Definition = "1"});
+ std::cerr << ' ' << i << "=1";
}
- fprintf(f, "\n};");
- fclose(f);
+ std::cerr << ",\n\t D3D_COMPILE_STANDARD_FILE_INCLUDE,\n\t " << entryPoint
+ << ",\n\t " << model
+ << ",\n\t 0,\n\t 0,\n\t &output,\n\t &errors);\n";
+
+ ID3DBlob *output = nullptr;
+ ID3DBlob *errors = nullptr;
+ HRESULT hr = D3DCompileFromFile(
+ absPathW.data(), (defines.size() - 1) ? defines.data() : nullptr,
+ D3D_COMPILE_STANDARD_FILE_INCLUDE, entryPoint.c_str(), model.c_str(), 0,
+ 0, &output, &errors);
+
+ absPathW.clear();
+ defines.clear();
+ entryPoint.clear();
+ model.clear();
+
+ // ====================================================================================
+ // Output (or errors)
+
+ if (FAILED(hr)) {
+ if (errors) {
+ std::cerr << "Got an error (" << std::hex << hr
+ << ") while compiling:\n"
+ << static_cast<const char *>(errors->GetBufferPointer())
+ << '\n';
+ errors->Release();
+ } else {
+ std::cerr << "Got an error (" << std::hex << hr
+ << ") while compiling, but no error message from "
+ "the function.\n";
+
+ _tprintf(_T("Windows Error Message: %s\n"),
+ _com_error(hr).ErrorMessage());
+ }
+
+ if (output) output->Release();
- if(verbose) {
- printf("Wrote %i bytes of shader output to %s\n", len, outputFile);
+ return hr;
}
- }
+ const size_t len = output->GetBufferSize();
+ const BYTE *outString = static_cast<BYTE *>(output->GetBufferPointer());
+
+ std::fstream f(outputFile, std::ios_base::out);
+
+ f << "const BYTE " << variableName << "[] =\n{\n";
+
+ for (size_t i = 0; i < len; ++i)
+ f << static_cast<unsigned>(outString[i]) << ','
+ << ((i % 6 == 5) ? '\n' : ' ');
- return 0;
+ f << "\n};";
+ std::cerr << "Wrote " << len << " bytes of shader output to " << outputFile
+ << '\n';
}
--
2.25.1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment