diff options
Diffstat (limited to 'build/tools/ShaderBuildTool/ShaderBuildTool.cpp')
| -rw-r--r-- | build/tools/ShaderBuildTool/ShaderBuildTool.cpp | 388 |
1 files changed, 388 insertions, 0 deletions
diff --git a/build/tools/ShaderBuildTool/ShaderBuildTool.cpp b/build/tools/ShaderBuildTool/ShaderBuildTool.cpp new file mode 100644 index 0000000..f30f9f9 --- /dev/null +++ b/build/tools/ShaderBuildTool/ShaderBuildTool.cpp @@ -0,0 +1,388 @@ +// ShaderBuildTool.cpp : Defines the entry point for the console application. +// + +#include "stdafx.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <vector> +#include <string> +#include <sstream> + +#define PERMUTATION_KEYWORD "#permutation " +#define SEPARATORS " \n" +#define INDENT " " + +namespace +{ + struct CShaderPermutation + { + std::string Key; + std::vector<std::string> Values; + }; + + struct CShaderDefine + { + std::string Key; + std::string Value; + }; + + struct CShaderInstance + { + std::string GlobalVariableName; + std::vector<CShaderDefine> Defines; + }; + + typedef std::vector<CShaderInstance> CShaderInstances; + typedef std::vector<CShaderPermutation> CShaderPermutations; +}; + +FILE *OpenFile(std::string Path, const char* Mode) +{ + FILE *fp = NULL; + if (fopen_s(&fp, Path.c_str(), Mode) || !fp) + { + fprintf(stderr, "Failed to open file %s\n", Path.c_str()); + exit(1); + } + return fp; +} + +CShaderInstances ExpandShaderInstances(CShaderInstances In, CShaderPermutation Permutation) +{ + CShaderInstances Out; + for (unsigned int InstanceIndex = 0; InstanceIndex < In.size(); ++InstanceIndex) + { + for (unsigned int ValueIndex = 0; ValueIndex < Permutation.Values.size(); ++ValueIndex) + { + CShaderDefine D; + D.Key = Permutation.Key; + D.Value = Permutation.Values[ValueIndex]; + + CShaderInstance Tmp = In[InstanceIndex]; + Tmp.Defines.push_back(D); + Out.push_back(Tmp); + } + } + + return Out; +} + +void MySystem(const char *Command) +{ + //printf("%s\n", Command); + + if (system(Command) != 0) + { + fprintf(stderr, "Failed command: %s\n", Command); + exit(1); + } +} + +struct CArgs +{ + std::string Profile; + std::string Input; + std::string EntryPoint; + std::string OutputDir; + std::string Output_H; + std::string Output_CPP; + std::string CompileTool; + std::string API; + std::string ClassName; +}; + +void ParseInput( + const CArgs& Args, + CShaderPermutations& ShaderPermutations) +{ + FILE *fp = OpenFile(Args.Input, "r"); + + char row[1024]; + while (fgets(row, sizeof(row), fp)) + { + if (strncmp(row, PERMUTATION_KEYWORD, strlen(PERMUTATION_KEYWORD)) == 0) + { + char *Keyword = strtok(row, SEPARATORS); + char *DefineKey = strtok(NULL, SEPARATORS); + if (!DefineKey) break; + + CShaderPermutation P; + P.Key = DefineKey; + + while (1) + { + char *DefineValue = strtok(NULL, SEPARATORS); + if (!DefineValue) break; + + P.Values.push_back(DefineValue); + } + + ShaderPermutations.push_back(P); + } + } + + fclose(fp); +} + +void InitShaderInstances( + const CShaderPermutations& ShaderPermutations, + CShaderInstances& ShaderInstances + ) +{ + ShaderInstances.clear(); + ShaderInstances.push_back(CShaderInstance()); + + for (unsigned int PermutationIndex = 0; PermutationIndex < ShaderPermutations.size(); ++PermutationIndex) + { + CShaderPermutation P = ShaderPermutations[PermutationIndex]; + ShaderInstances = ExpandShaderInstances(ShaderInstances, P); + } +} + +void WriteCPP( + const CArgs& Args, + const CShaderPermutations& ShaderPermutations, + CShaderInstances& ShaderInstances) +{ + remove(Args.Output_CPP.c_str()); + + for (unsigned int InstanceIndex = 0; InstanceIndex < ShaderInstances.size(); ++InstanceIndex) + { + CShaderInstance& Instance = ShaderInstances[InstanceIndex]; + std::string DefineString = "/DAPI_" + Args.API + "=1"; + std::string ShaderName = Args.EntryPoint; + + for (unsigned int i = 0; i < ShaderInstances[i].Defines.size(); ++i) + { + DefineString += " /D" + Instance.Defines[i].Key + "=" + Instance.Defines[i].Value; + ShaderName += "_" + Instance.Defines[i].Key + "_" + Instance.Defines[i].Value; + } + + Instance.GlobalVariableName = "g_" + ShaderName + "_" + Args.API; + + std::string OutputTmp = Args.Output_CPP + ".tmp"; + std::string Command; + Command += "SET SBT_PROFILE=" + Args.Profile; + Command += "& SET SBT_INPUT=" + Args.Input; + Command += "& SET SBT_ENTRY_POINT=" + Args.EntryPoint; + Command += "& SET SBT_DEFINES=" + DefineString; + Command += "& SET SBT_VARIABLE_NAME=" + Instance.GlobalVariableName; + Command += "& SET SBT_OUTPUT=" + OutputTmp; + Command += "& " + Args.CompileTool; + MySystem(Command.c_str()); + + Command = "type " + OutputTmp + " >> " + Args.Output_CPP; + MySystem(Command.c_str()); + + Command = "del " + OutputTmp; + MySystem(Command.c_str()); + } + + FILE *fp = OpenFile(Args.Output_CPP, "a+"); + + fprintf(fp, "\n"); + fprintf(fp, "namespace Generated\n"); + fprintf(fp, "{\n"); + + fprintf(fp, INDENT "void %s::Create(DevicePointer Device)\n", Args.EntryPoint.c_str()); + fprintf(fp, INDENT "{\n"); + for (unsigned int i = 0; i < ShaderInstances.size(); ++i) + { + CShaderInstance Instance = ShaderInstances[i]; + + fprintf(fp, INDENT INDENT "m_Shader"); + for (unsigned int j = 0; j < Instance.Defines.size(); ++j) + { + fprintf(fp, "[ShaderPermutations::%s", Instance.Defines[j].Key.c_str()); + fprintf(fp, "_%s]", Instance.Defines[j].Value.c_str()); + } + fprintf(fp, ".Create(Device, %s, sizeof(%s));\n", Instance.GlobalVariableName.c_str(), Instance.GlobalVariableName.c_str()); + } + fprintf(fp, INDENT "}\n"); + fprintf(fp, "\n"); + + fprintf(fp, INDENT "void %s::Release(DevicePointer Device)\n", Args.EntryPoint.c_str()); + fprintf(fp, INDENT "{\n"); + for (unsigned int i = 0; i < ShaderInstances.size(); ++i) + { + fprintf(fp, INDENT INDENT "m_Shader"); + CShaderInstance Instance = ShaderInstances[i]; + for (unsigned int j = 0; j < Instance.Defines.size(); ++j) + { + fprintf(fp, "[ShaderPermutations::%s", Instance.Defines[j].Key.c_str()); + fprintf(fp, "_%s]", Instance.Defines[j].Value.c_str()); + } + fprintf(fp, ".Release(Device);\n"); + } + fprintf(fp, INDENT "}\n"); + + fprintf(fp, "}\n"); + + fclose(fp); +} + +void WriteHeader( + const CArgs& Args, + const CShaderPermutations& ShaderPermutations, + const CShaderInstances& ShaderInstances) +{ + remove(Args.Output_H.c_str()); + + std::string ClassName = Args.ClassName; + + FILE *fp = OpenFile(Args.Output_H, "a+"); + + fprintf(fp, "//! This file was auto-generated. Do not modify manually.\n"); + fprintf(fp, "#pragma once"); + fprintf(fp, "\n"); + + fprintf(fp, "\n"); + fprintf(fp, "namespace Generated\n"); + fprintf(fp, "{\n"); + fprintf(fp, "\n"); + + fprintf(fp, "namespace ShaderPermutations\n"); + fprintf(fp, "{\n"); + fprintf(fp, "\n"); + + for (unsigned int i = 0; i < ShaderPermutations.size(); ++i) + { + const CShaderPermutation& Permutation = ShaderPermutations[i]; + + std::string PermutationDefine = Permutation.Key + "_DEFINED"; + fprintf(fp, "#ifndef %s\n", PermutationDefine.c_str()); + fprintf(fp, "#define %s\n", PermutationDefine.c_str()); + + fprintf(fp, INDENT "enum %s\n", Permutation.Key.c_str()); + fprintf(fp, INDENT "{\n"); + for (unsigned int j = 0; j < Permutation.Values.size(); ++j) + { + fprintf(fp, INDENT INDENT "%s_%s,\n", Permutation.Key.c_str(), Permutation.Values[j].c_str()); + } + fprintf(fp, INDENT INDENT "%s_COUNT,\n", Permutation.Key.c_str()); + fprintf(fp, INDENT "};\n"); + + fprintf(fp, "#endif\n"); + fprintf(fp, "\n"); + } + + fprintf(fp, "};\n"); + fprintf(fp, "\n"); + + fprintf(fp, "struct %s\n", Args.EntryPoint.c_str()); + fprintf(fp, "{\n"); + + fprintf(fp, INDENT "void Create(DevicePointer Device);\n"); + fprintf(fp, INDENT "void Release(DevicePointer Device);\n"); + + fprintf(fp, INDENT "%s& Get(", ClassName.c_str()); + for (unsigned int i = 0; i < ShaderPermutations.size(); ++i) + { + if (i != 0) + { + fprintf(fp, ", "); + } + fprintf(fp, "ShaderPermutations::%s %c", ShaderPermutations[i].Key.c_str(), 'A' + i); + } + fprintf(fp, ")\n"); + fprintf(fp, INDENT "{\n"); + fprintf(fp, INDENT INDENT "return m_Shader"); + for (unsigned int i = 0; i < ShaderPermutations.size(); ++i) + { + fprintf(fp, "[%c]", 'A' + i); + } + fprintf(fp, ";\n"); + fprintf(fp, INDENT "}\n"); + + fprintf(fp, "\n"); + fprintf(fp, "private:\n"); + + fprintf(fp, INDENT "%s m_Shader", ClassName.c_str()); + for (unsigned int i = 0; i < ShaderPermutations.size(); ++i) + { + fprintf(fp, "[ShaderPermutations::%s_COUNT]", ShaderPermutations[i].Key.c_str()); + } + fprintf(fp, ";\n"); + + fprintf(fp, "#if _WIN32\n"); + for (unsigned int i = 0; i < ShaderPermutations.size(); ++i) + { + fprintf(fp, INDENT "static_assert(ShaderPermutations::%s_COUNT == %d, \"\");\n", + ShaderPermutations[i].Key.c_str(), + (int) ShaderPermutations[i].Values.size()); + } + fprintf(fp, "#endif\n"); + + fprintf(fp, "};\n"); + fprintf(fp, "\n"); + + fprintf(fp, "};\n"); + + fclose(fp); +} + +int main(int argc, char **argv) +{ + if (argc < 7) + { + fprintf(stderr, "Usage: %s PROFILE INPUT_HLSL ENTRY_POINT OUTPUT_DIR COMPILE_TOOL API [CLASS_NAME]\n", argv[0]); + exit(1); + } + + CArgs Args; + int ArgIndex = 1; + if (ArgIndex < argc) + { + Args.Profile = argv[ArgIndex++]; + } + if (ArgIndex < argc) + { + Args.Input = argv[ArgIndex++]; + } + if (ArgIndex < argc) + { + Args.EntryPoint = argv[ArgIndex++]; + } + if (ArgIndex < argc) + { + Args.OutputDir = argv[ArgIndex++]; + } + if (ArgIndex < argc) + { + Args.CompileTool = argv[ArgIndex++]; + } + if (ArgIndex < argc) + { + Args.API = argv[ArgIndex++]; + } + if (ArgIndex < argc) + { + Args.ClassName = argv[ArgIndex++]; + } + + if (Args.ClassName.size() == 0) + { + const bool IsVS = !strcmp(Args.Profile.c_str(), "vs_5_0"); + const bool IsGS = !strcmp(Args.Profile.c_str(), "gs_5_0"); + Args.ClassName = + IsVS ? "VertexShader" : + IsGS ? "GeometryShader" : + "PixelShader"; + } + + CShaderPermutations ShaderPermutations; + ParseInput(Args, ShaderPermutations); + + Args.Output_H = Args.OutputDir + "\\" + Args.EntryPoint + ".h"; + Args.Output_CPP = Args.OutputDir + "\\" + Args.EntryPoint + ".cpp"; + + CShaderInstances ShaderInstances; + InitShaderInstances(ShaderPermutations, ShaderInstances); + + WriteHeader(Args, ShaderPermutations, ShaderInstances); + + WriteCPP(Args, ShaderPermutations, ShaderInstances); + + return 0; +} |