diff --git a/StandAlone/StandAlone.cpp b/StandAlone/StandAlone.cpp index 92991d1b..1e2c8f73 100644 --- a/StandAlone/StandAlone.cpp +++ b/StandAlone/StandAlone.cpp @@ -148,6 +148,10 @@ const char* sourceEntryPointName = nullptr; const char* shaderStageName = nullptr; const char* variableName = nullptr; std::vector IncludeDirectoryList; +int ClientInputSemanticsVersion = 100; // maps to, say, #define VULKAN 100 +int VulkanClientVersion = 100; // would map to, say, Vulkan 1.0 +int OpenGLClientVersion = 450; // doesn't influence anything yet, but maps to OpenGL 4.50 +unsigned int TargetVersion = 0x00001000; // maps to, say, SPIR-V 1.0 std::array baseSamplerBinding; std::array baseTextureBinding; @@ -294,15 +298,15 @@ void ProcessResourceSetBindingBase(int& argc, char**& argv, std::array>& workItem return argv[0] + 2; }; + // read a number attached to a single-letter option + const auto getAttachedNumber = [&](const char* desc) { + int num = atoi(argv[0] + 2); + if (num == 0) { + printf("%s: expected attached non-0 number\n", desc); + exit(EFailUsage); + } + return num; + }; + + // minimum needed (without overriding something else) to target Vulkan SPIR-V + const auto setVulkanSpv = []() { + Options |= EOptionSpv; + Options |= EOptionVulkanRules; + Options |= EOptionLinkProgram; + }; + + // minimum needed (without overriding something else) to target OpenGL SPIR-V + const auto setOpenGlSpv = []() { + Options |= EOptionSpv; + Options |= EOptionLinkProgram; + // undo a -H default to Vulkan + Options &= ~EOptionVulkanRules; + }; + for (bumpArg(); argc >= 1; bumpArg()) { if (argv[0][0] == '-') { switch (argv[0][1]) { @@ -362,12 +391,22 @@ void ProcessArguments(std::vector>& workItem // handle --word style options if (lowerword == "auto-map-bindings" || // synonyms - lowerword == "auto-map-binding" || - lowerword == "amb") { + lowerword == "auto-map-binding" || + lowerword == "amb") { Options |= EOptionAutoMapBindings; } else if (lowerword == "auto-map-locations" || // synonyms lowerword == "aml") { Options |= EOptionAutoMapLocations; + } else if (lowerword == "client") { + if (argc > 1) { + if (strcmp(argv[1], "vulkan100") == 0) + setVulkanSpv(); + else if (strcmp(argv[1], "opengl100") == 0) + setOpenGlSpv(); + else + Error("--client expects vulkan100 or opengl100"); + } + bumpArg(); } else if (lowerword == "flatten-uniform-arrays" || // synonyms lowerword == "flatten-uniform-array" || lowerword == "fua") { @@ -422,6 +461,18 @@ void ProcessArguments(std::vector>& workItem sourceEntryPointName = argv[1]; bumpArg(); break; + } else if (lowerword == "target-env") { + if (argc > 1) { + if (strcmp(argv[1], "vulkan1.0") == 0) { + setVulkanSpv(); + VulkanClientVersion = 100; + } else if (strcmp(argv[1], "opengl") == 0) { + setOpenGlSpv(); + OpenGLClientVersion = 450; + } else + Error("--target-env expected vulkan1.0 or opengl"); + } + bumpArg(); } else if (lowerword == "variable-name" || // synonyms lowerword == "vn") { Options |= EOptionOutputHexadecimal; @@ -448,18 +499,16 @@ void ProcessArguments(std::vector>& workItem Options |= EOptionOutputPreprocessed; break; case 'G': - Options |= EOptionSpv; - Options |= EOptionLinkProgram; - // undo a -H default to Vulkan - Options &= ~EOptionVulkanRules; + // OpenGL Client + setOpenGlSpv(); + if (argv[0][2] != 0) + ClientInputSemanticsVersion = getAttachedNumber("-G client input semantics"); break; case 'H': Options |= EOptionHumanReadableSpv; if ((Options & EOptionSpv) == 0) { // default to Vulkan - Options |= EOptionSpv; - Options |= EOptionVulkanRules; - Options |= EOptionLinkProgram; + setVulkanSpv(); } break; case 'I': @@ -475,9 +524,9 @@ void ProcessArguments(std::vector>& workItem UserPreamble.addUndef(getStringOperand("-U: macro name")); break; case 'V': - Options |= EOptionSpv; - Options |= EOptionVulkanRules; - Options |= EOptionLinkProgram; + setVulkanSpv(); + if (argv[0][2] != 0) + ClientInputSemanticsVersion = getAttachedNumber("-G client input semantics"); break; case 'c': Options |= EOptionDumpConfig; @@ -716,15 +765,15 @@ void CompileAndLinkShaderUnits(std::vector compUnits) if (Options & EOptionVulkanRules) { shader->setEnvInput((Options & EOptionReadHlsl) ? glslang::EShSourceHlsl : glslang::EShSourceGlsl, - compUnit.stage, glslang::EShClientVulkan, 100); - shader->setEnvClient(glslang::EShClientVulkan, 100); - shader->setEnvTarget(glslang::EshTargetSpv, 0x00001000); + compUnit.stage, glslang::EShClientVulkan, ClientInputSemanticsVersion); + shader->setEnvClient(glslang::EShClientVulkan, VulkanClientVersion); + shader->setEnvTarget(glslang::EshTargetSpv, TargetVersion); } else { shader->setEnvInput((Options & EOptionReadHlsl) ? glslang::EShSourceHlsl : glslang::EShSourceGlsl, - compUnit.stage, glslang::EShClientOpenGL, 100); - shader->setEnvClient(glslang::EShClientOpenGL, 450); - shader->setEnvTarget(glslang::EshTargetSpv, 0x00001000); + compUnit.stage, glslang::EShClientOpenGL, ClientInputSemanticsVersion); + shader->setEnvClient(glslang::EShClientOpenGL, OpenGLClientVersion); + shader->setEnvTarget(glslang::EshTargetSpv, TargetVersion); } } @@ -1085,16 +1134,24 @@ void usage() " -D define a pre-processor macro\n" " -E print pre-processed GLSL; cannot be used with -l;\n" " errors will appear on stderr.\n" - " -G create SPIR-V binary, under OpenGL semantics; turns on -l;\n" + " -G[ver] create SPIR-V binary, under OpenGL semantics; turns on -l;\n" " default file name is .spv (-o overrides this)\n" + " 'ver', when present, is the version of the input semantics,\n" + " which will appear in #define GL_SPIRV ver\n" + " '--client opengl100' is the same as -G100\n" + " a '--target-env' for OpenGL will also imply '-G'\n" " -H print human readable form of SPIR-V; turns on -V\n" " -I add dir to the include search path; includer's directory\n" " is searched first, followed by left-to-right order of -I\n" " -S uses specified stage rather than parsing the file extension\n" " choices for are vert, tesc, tese, geom, frag, or comp\n" - " -U undefine a pre-precossor macro\n" - " -V create SPIR-V binary, under Vulkan semantics; turns on -l;\n" + " -U undefine a pre-processor macro\n" + " -V[ver] create SPIR-V binary, under Vulkan semantics; turns on -l;\n" " default file name is .spv (-o overrides this)\n" + " 'ver', when present, is the version of the input semantics,\n" + " which will appear in #define VULKAN ver\n" + " '--client vulkan100' is the same as -V100\n" + " a '--target-env' for Vulkan will also imply '-V'\n" " -c configuration dump;\n" " creates the default configuration file (redirect to a .conf file)\n" " -d default to desktop (#version 110) when there is no shader #version\n" @@ -1119,6 +1176,7 @@ void usage() " --auto-map-locations automatically locate input/output lacking\n" " 'location' (fragile, not cross stage)\n" " --aml synonym for --auto-map-locations\n" + " --client {vulkan|opengl} see -V and -G\n" " --flatten-uniform-arrays flatten uniform texture/sampler arrays to\n" " scalars\n" " --fua synonym for --flatten-uniform-arrays\n" @@ -1147,6 +1205,11 @@ void usage() " --source-entrypoint name the given shader source function is\n" " renamed to be the entry point given in -e\n" " --sep synonym for --source-entrypoint\n" + " --target-env {vulkan1.0|opengl} set the execution environment the generated\n" + " code will execute in (as opposed to language\n" + " semantics selected by --client)\n" + " default is 'vulkan1.0' under '--client vulkan'\n" + " default is 'opengl' under '--client opengl'\n" " --variable-name Creates a C header file that contains a\n" " uint32_t array named \n" " initialized with the shader binary code.\n" diff --git a/Test/runtests b/Test/runtests index e42aaadd..2caa6506 100755 --- a/Test/runtests +++ b/Test/runtests @@ -127,6 +127,16 @@ diff -b $BASEDIR/glsl.-D-U.frag.out $TARGETDIR/glsl.-D-U.frag.out || HASERROR=1 $EXE -D -e main -V -i -DUNDEFED -UIN_SHADER -DFOO=200 -UUNDEFED hlsl.-D-U.frag > $TARGETDIR/hlsl.-D-U.frag.out diff -b $BASEDIR/hlsl.-D-U.frag.out $TARGETDIR/hlsl.-D-U.frag.out || HASERROR=1 +# +# Test --client and --target-env +# +$EXE --client vulkan100 spv.targetVulkan.vert || HASERROR=1 +$EXE --client opengl100 spv.targetOpenGL.vert || HASERROR=1 +$EXE --target-env vulkan1.0 spv.targetVulkan.vert || HASERROR=1 +$EXE --target-env opengl spv.targetOpenGL.vert || HASERROR=1 +$EXE -V100 spv.targetVulkan.vert || HASERROR=1 +$EXE -G100 spv.targetOpenGL.vert || HASERROR=1 + # # Final checking # diff --git a/Test/spv.targetOpenGL.vert b/Test/spv.targetOpenGL.vert new file mode 100755 index 00000000..0920334f --- /dev/null +++ b/Test/spv.targetOpenGL.vert @@ -0,0 +1,9 @@ +#version 450 + +layout(constant_id = 3) const int a = 2; + +uniform float f; + +void main() +{ +} diff --git a/Test/spv.targetVulkan.vert b/Test/spv.targetVulkan.vert new file mode 100755 index 00000000..d879122b --- /dev/null +++ b/Test/spv.targetVulkan.vert @@ -0,0 +1,9 @@ +#version 450 + +layout(constant_id = 3) const int a = 2; + +layout(push_constant) uniform pc { float f; }; + +void main() +{ +}