diff --git a/build.zig b/build.zig index cc9eedef..065315b1 100644 --- a/build.zig +++ b/build.zig @@ -13,6 +13,8 @@ pub fn build(b: *Build) !void { const enable_hlsl = !(b.option(bool, "no-hlsl", "Skip building glslang HLSL support.") orelse false); const enable_opt = !(b.option(bool, "no-opt", "Skip building spirv-tools optimization.") orelse false); const shared_tools = b.option(bool, "shared-tools", "Build and link spirv-tools as a shared library.") orelse false; + const standalone_glslang = b.option(bool, "standalone", "Build glslang.exe standalone command-line compiler.") orelse false; + const standalone_spvremap = b.option(bool, "standalone-remap", "Build spirv-remap.exe standalone command-line remapper.") orelse false; const tools_libs: spvtools.SPVLibs = spvtools.build_spirv(b, optimize, target, shared_tools, debug) catch |err| { log.err("Error building SPIRV-Tools: {s}", .{ @errorName(err) }); @@ -56,20 +58,20 @@ pub fn build(b: *Build) !void { sources_resource_limits ++ sources_c_interface; - var lib: *std.Build.Step.Compile = undefined; + var glslang_lib: *std.Build.Step.Compile = undefined; if (shared) { - lib = b.addSharedLibrary(.{ + glslang_lib = b.addSharedLibrary(.{ .name = "glslang", .root_source_file = b.addWriteFiles().add("empty.c", ""), .optimize = optimize, .target = target, }); - lib.defineCMacro("GLSLANG_IS_SHARED_LIBRARY", "1"); - lib.defineCMacro("GLSLANG_EXPORTING", "1"); + glslang_lib.defineCMacro("GLSLANG_IS_SHARED_LIBRARY", ""); + glslang_lib.defineCMacro("GLSLANG_EXPORTING", ""); } else { - lib = b.addStaticLibrary(.{ + glslang_lib = b.addStaticLibrary(.{ .name = "glslang", .root_source_file = b.addWriteFiles().add("empty.c", ""), .optimize = optimize, @@ -77,7 +79,7 @@ pub fn build(b: *Build) !void { }); } - lib.addCSourceFiles(.{ + glslang_lib.addCSourceFiles(.{ .files = &sources, .flags = cppflags.items, }); @@ -85,56 +87,122 @@ pub fn build(b: *Build) !void { const tag = target.result.os.tag; if (tag == .windows) { - lib.addCSourceFiles(.{ + glslang_lib.addCSourceFiles(.{ .files = &sources_win, .flags = cppflags.items, }); - lib.defineCMacro("GLSLANG_OSINCLUDE_WIN32", ""); + glslang_lib.defineCMacro("GLSLANG_OSINCLUDE_WIN32", ""); } else { - lib.addCSourceFiles(.{ + glslang_lib.addCSourceFiles(.{ .files = &sources_unix, .flags = cppflags.items, }); - lib.defineCMacro("GLSLANG_OSINCLUDE_UNIX", ""); + glslang_lib.defineCMacro("GLSLANG_OSINCLUDE_UNIX", ""); } if (enable_hlsl) { - lib.addCSourceFiles(.{ + glslang_lib.addCSourceFiles(.{ .files = &sources_hlsl, .flags = cppflags.items, }); - lib.defineCMacro("ENABLE_HLSL", "1"); + glslang_lib.defineCMacro("ENABLE_HLSL", "1"); + } else { + glslang_lib.defineCMacro("ENABLE_HLSL", "0"); } if (enable_opt) { - lib.addCSourceFiles(.{ + glslang_lib.addCSourceFiles(.{ .files = &sources_opt, .flags = cppflags.items, }); - lib.defineCMacro("ENABLE_OPT", "1"); + glslang_lib.defineCMacro("ENABLE_OPT", "1"); - lib.step.dependOn(&tools_libs.tools_opt.step); - lib.step.dependOn(&tools_libs.tools_val.step); - lib.linkLibrary(tools_libs.tools_opt); - lib.linkLibrary(tools_libs.tools_val); + glslang_lib.step.dependOn(&tools_libs.tools_opt.step); + glslang_lib.step.dependOn(&tools_libs.tools_val.step); + glslang_lib.linkLibrary(tools_libs.tools_opt); + glslang_lib.linkLibrary(tools_libs.tools_val); + } else { + glslang_lib.defineCMacro("ENABLE_OPT", "0"); } - addIncludes(lib); - spvtools.addSPIRVPublicIncludes(lib); + addIncludes(glslang_lib); + spvtools.addSPIRVPublicIncludes(glslang_lib); - lib.linkLibCpp(); + glslang_lib.linkLibCpp(); - lib.step.dependOn(&build_headers.step); + glslang_lib.step.dependOn(&build_headers.step); - const build_step = b.step("glslang", "Build glslang"); - build_step.dependOn(&b.addInstallArtifact(lib, .{}).step); + const build_step = b.step("glslang-library", "Build the glslang library"); + build_step.dependOn(&b.addInstallArtifact(glslang_lib, .{}).step); - b.installArtifact(lib); + b.installArtifact(glslang_lib); + + if (standalone_glslang) { + const glslang_exe = b.addExecutable(.{ + .name = "glslang", + .optimize = optimize, + .target = target, + }); + + const install_glslang_step = b.step("glslang-standalone", "Build and install glslang.exe"); + install_glslang_step.dependOn(&b.addInstallArtifact(glslang_exe, .{}).step); + glslang_exe.addCSourceFiles(.{ + .files = &sources_standalone_glslang, + .flags = &.{ "-std=c++17" }, + }); + + addIncludes(glslang_exe); + + b.installArtifact(glslang_exe); + glslang_exe.linkLibrary(glslang_lib); + + if (target.result.os.tag == .windows) { + // windows must be built with LTO disabled due to: + // https://github.com/ziglang/zig/issues/15958 + glslang_exe.want_lto = false; + } + + if (enable_hlsl) { + glslang_exe.defineCMacro("ENABLE_HLSL", "1"); + } else { + glslang_exe.defineCMacro("ENABLE_HLSL", "0"); + } + + if (enable_opt) { + glslang_exe.defineCMacro("ENABLE_OPT", "1"); + } else { + glslang_exe.defineCMacro("ENABLE_OPT", "0"); + } + } + + if (standalone_spvremap) { + const spirv_remap = b.addExecutable(.{ + .name = "spirv-remap", + .optimize = optimize, + .target = target, + }); + + const install_remap_step = b.step("spirv-remap", "Build and install spirv-remap.exe"); + install_remap_step.dependOn(&b.addInstallArtifact(spirv_remap, .{}).step); + spirv_remap.addCSourceFiles(.{ + .files = &sources_standalone_remap, + .flags = &.{ "-std=c++17" }, + }); + + addIncludes(spirv_remap); + + b.installArtifact(spirv_remap); + spirv_remap.linkLibrary(glslang_lib); + + if (target.result.os.tag == .windows) { + spirv_remap.want_lto = false; + } + } } fn addIncludes(step: *std.Build.Step.Compile) void { @@ -198,8 +266,6 @@ fn runPython(allocator: std.mem.Allocator, args: []const []const u8, errMsg: []c }; } - - // ------------------------------------------ // Include generation logic // ------------------------------------------ @@ -286,7 +352,6 @@ pub const BuildHeadersStep = struct { }; - const sources_spirv = [_][]const u8{ "SPIRV/GlslangToSpv.cpp", "SPIRV/InReadableOrder.cpp", @@ -300,6 +365,7 @@ const sources_spirv = [_][]const u8{ const sources_c_interface = [_][]const u8{ "glslang/CInterface/glslang_c_interface.cpp", + "SPIRV/CInterface/spirv_c_interface.cpp", }; const sources_resource_limits = [_][]const u8{ @@ -363,4 +429,12 @@ const sources_hlsl = [_][]const u8{ const sources_opt = [_][]const u8{ "SPIRV/SpvTools.cpp", +}; + +const sources_standalone_glslang = [_][]const u8{ + "StandAlone/StandAlone.cpp" +}; + +const sources_standalone_remap = [_][]const u8{ + "StandAlone/spirv-remap.cpp" }; \ No newline at end of file diff --git a/glslang/CInterface/glslang_c_interface.cpp b/glslang/CInterface/glslang_c_interface.cpp index cea965d4..0fb6f035 100644 --- a/glslang/CInterface/glslang_c_interface.cpp +++ b/glslang/CInterface/glslang_c_interface.cpp @@ -329,6 +329,18 @@ GLSLANG_EXPORT glslang_shader_t* glslang_shader_create(const glslang_input_t* in shader->shader->setEnvTarget(c_shader_target_language(input->target_language), c_shader_target_language_version(input->target_language_version)); + if (input->entrypoint != nullptr) + shader->shader->setEntryPoint(input->entrypoint); + + if (input->source_entrypoint != nullptr) { + if (input->entrypoint == nullptr) + printf("Warning: Setting source entry point name without setting an entry-point name.\n"); + + shader->shader->setSourceEntryPoint(input->source_entrypoint); + } + + shader->shader->setInvertY(input->invert_y); + return shader; } diff --git a/glslang/Include/glslang_c_interface.h b/glslang/Include/glslang_c_interface.h index 7fa1a05d..3e546258 100644 --- a/glslang/Include/glslang_c_interface.h +++ b/glslang/Include/glslang_c_interface.h @@ -206,6 +206,9 @@ typedef struct glslang_input_s { glslang_target_language_version_t target_language_version; /** Shader source code */ const char* code; + const char* entrypoint; // This is what actually gets called by the GPU. Best to leave it at 'main' or something so opengl doesn't trip over itself. + const char* source_entrypoint; // This just renames the source entrypoint in the code to 'entrypoint' and should be what is used to set different entrypoint names. + bool invert_y; int default_version; glslang_profile_t default_profile; int force_default_version_and_profile; diff --git a/glslang/Public/resource_limits_c.h b/glslang/Public/resource_limits_c.h index 05aa8eb0..742b2aca 100644 --- a/glslang/Public/resource_limits_c.h +++ b/glslang/Public/resource_limits_c.h @@ -36,19 +36,19 @@ extern "C" { #endif // Returns a struct that can be use to create custom resource values. -glslang_resource_t* glslang_resource(void); +GLSLANG_EXPORT glslang_resource_t* glslang_resource(void); // These are the default resources for TBuiltInResources, used for both // - parsing this string for the case where the user didn't supply one, // - dumping out a template for user construction of a config file. -const glslang_resource_t* glslang_default_resource(void); +GLSLANG_EXPORT const glslang_resource_t* glslang_default_resource(void); // Returns the DefaultTBuiltInResource as a human-readable string. // NOTE: User is responsible for freeing this string. -const char* glslang_default_resource_string(); +GLSLANG_EXPORT const char* glslang_default_resource_string(); // Decodes the resource limits from |config| to |resources|. -void glslang_decode_resource_limits(glslang_resource_t* resources, char* config); +GLSLANG_EXPORT void glslang_decode_resource_limits(glslang_resource_t* resources, char* config); #ifdef __cplusplus } diff --git a/glslang/ResourceLimits/resource_limits_c.cpp b/glslang/ResourceLimits/resource_limits_c.cpp index 8909d9ef..83bc994a 100644 --- a/glslang/ResourceLimits/resource_limits_c.cpp +++ b/glslang/ResourceLimits/resource_limits_c.cpp @@ -32,17 +32,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -glslang_resource_t* glslang_resource(void) +GLSLANG_EXPORT glslang_resource_t* glslang_resource(void) { return reinterpret_cast(GetResources()); } -const glslang_resource_t* glslang_default_resource(void) +GLSLANG_EXPORT const glslang_resource_t* glslang_default_resource(void) { return reinterpret_cast(GetDefaultResources()); } -const char* glslang_default_resource_string() +GLSLANG_EXPORT const char* glslang_default_resource_string() { std::string cpp_str = GetDefaultTBuiltInResourceString(); char* c_str = (char*)malloc(cpp_str.length() + 1); @@ -50,7 +50,7 @@ const char* glslang_default_resource_string() return c_str; } -void glslang_decode_resource_limits(glslang_resource_t* resources, char* config) +GLSLANG_EXPORT void glslang_decode_resource_limits(glslang_resource_t* resources, char* config) { DecodeResourceLimits(reinterpret_cast(resources), config); } diff --git a/lack.cpp b/lack.cpp deleted file mode 100644 index 305173cf..00000000 --- a/lack.cpp +++ /dev/null @@ -1,13 +0,0 @@ - " -D | --define-macro | --D \n" - " define a pre-processor macro\n" - " -H print human readable form of SPIR-V; turns on -V\n" - " -U | --undef-macro | --U \n" - " undefine a pre-processor macro\n" - " -e | --entry-point \n" - " specify as the entry-point function name\n" - - " --invert-y | --iy invert position.Y output in vertex shader\n" - " --nan-clamp favor non-NaN operand in min, max, and clamp\n" - - " --source-entrypoint the given shader source function is\n" - " renamed to be the given in -e\n" \ No newline at end of file diff --git a/test.cpp b/test.cpp deleted file mode 100644 index 2b737f4b..00000000 --- a/test.cpp +++ /dev/null @@ -1,86 +0,0 @@ -#define GLSLANG_IS_SHARED_LIBRARY -#include -#include -#include - - -typedef struct SpirVBinary { - uint32_t *words; // SPIR-V words - int size; // number of words in SPIR-V binary -} SpirVBinary; - -SpirVBinary compileShaderToSPIRV_Vulkan(glslang_stage_t stage, const char* shaderSource, const char* fileName) { - const glslang_input_t input = { - .language = GLSLANG_SOURCE_HLSL, - .stage = stage, - .client = GLSLANG_CLIENT_VULKAN, - .client_version = GLSLANG_TARGET_VULKAN_1_2, - .target_language = GLSLANG_TARGET_SPV, - .target_language_version = GLSLANG_TARGET_SPV_1_5, - .code = shaderSource, - .default_version = 100, - .default_profile = GLSLANG_NO_PROFILE, - .force_default_version_and_profile = false, - .forward_compatible = false, - .messages = GLSLANG_MSG_DEFAULT_BIT, - .resource = glslang_default_resource(), - }; - - glslang_shader_t* shader = glslang_shader_create(&input); - - SpirVBinary bin = { - .words = NULL, - .size = 0, - }; - - if (!glslang_shader_preprocess(shader, &input)) { - printf("GLSL preprocessing failed %s\n", fileName); - printf("%s\n", glslang_shader_get_info_log(shader)); - printf("%s\n", glslang_shader_get_info_debug_log(shader)); - printf("%s\n", input.code); - glslang_shader_delete(shader); - return bin; - } - - if (!glslang_shader_parse(shader, &input)) { - printf("GLSL parsing failed %s\n", fileName); - printf("%s\n", glslang_shader_get_info_log(shader)); - printf("%s\n", glslang_shader_get_info_debug_log(shader)); - printf("%s\n", glslang_shader_get_preprocessed_code(shader)); - glslang_shader_delete(shader); - return bin; - } - - glslang_program_t* program = glslang_program_create(); - glslang_program_add_shader(program, shader); - - if (!glslang_program_link(program, GLSLANG_MSG_SPV_RULES_BIT | GLSLANG_MSG_VULKAN_RULES_BIT)) { - printf("GLSL linking failed %s\n", fileName); - printf("%s\n", glslang_program_get_info_log(program)); - printf("%s\n", glslang_program_get_info_debug_log(program)); - glslang_program_delete(program); - glslang_shader_delete(shader); - return bin; - } - - glslang_program_SPIRV_generate(program, stage); - - bin.size = glslang_program_SPIRV_get_size(program); - bin.words = malloc(bin.size * sizeof(uint32_t)); - glslang_program_SPIRV_get(program, bin.words); - - const char* spirv_messages = glslang_program_SPIRV_get_messages(program); - if (spirv_messages) - printf("(%s) %s\b", fileName, spirv_messages); - - glslang_program_delete(program); - glslang_shader_delete(shader); - - return bin; -} - - -int main(void) -{ - -} \ No newline at end of file