Added entrypoints to c interface; exports for resource limits; minor additions to buildsystem.

This commit is contained in:
Kai Angulo 2024-05-31 22:23:49 -07:00
parent 6b8daf4802
commit f2f81cf089
7 changed files with 125 additions and 135 deletions

130
build.zig
View file

@ -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_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 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 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| { 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) }); log.err("Error building SPIRV-Tools: {s}", .{ @errorName(err) });
@ -56,20 +58,20 @@ pub fn build(b: *Build) !void {
sources_resource_limits ++ sources_resource_limits ++
sources_c_interface; sources_c_interface;
var lib: *std.Build.Step.Compile = undefined; var glslang_lib: *std.Build.Step.Compile = undefined;
if (shared) { if (shared) {
lib = b.addSharedLibrary(.{ glslang_lib = b.addSharedLibrary(.{
.name = "glslang", .name = "glslang",
.root_source_file = b.addWriteFiles().add("empty.c", ""), .root_source_file = b.addWriteFiles().add("empty.c", ""),
.optimize = optimize, .optimize = optimize,
.target = target, .target = target,
}); });
lib.defineCMacro("GLSLANG_IS_SHARED_LIBRARY", "1"); glslang_lib.defineCMacro("GLSLANG_IS_SHARED_LIBRARY", "");
lib.defineCMacro("GLSLANG_EXPORTING", "1"); glslang_lib.defineCMacro("GLSLANG_EXPORTING", "");
} else { } else {
lib = b.addStaticLibrary(.{ glslang_lib = b.addStaticLibrary(.{
.name = "glslang", .name = "glslang",
.root_source_file = b.addWriteFiles().add("empty.c", ""), .root_source_file = b.addWriteFiles().add("empty.c", ""),
.optimize = optimize, .optimize = optimize,
@ -77,7 +79,7 @@ pub fn build(b: *Build) !void {
}); });
} }
lib.addCSourceFiles(.{ glslang_lib.addCSourceFiles(.{
.files = &sources, .files = &sources,
.flags = cppflags.items, .flags = cppflags.items,
}); });
@ -85,56 +87,122 @@ pub fn build(b: *Build) !void {
const tag = target.result.os.tag; const tag = target.result.os.tag;
if (tag == .windows) { if (tag == .windows) {
lib.addCSourceFiles(.{ glslang_lib.addCSourceFiles(.{
.files = &sources_win, .files = &sources_win,
.flags = cppflags.items, .flags = cppflags.items,
}); });
lib.defineCMacro("GLSLANG_OSINCLUDE_WIN32", ""); glslang_lib.defineCMacro("GLSLANG_OSINCLUDE_WIN32", "");
} else { } else {
lib.addCSourceFiles(.{ glslang_lib.addCSourceFiles(.{
.files = &sources_unix, .files = &sources_unix,
.flags = cppflags.items, .flags = cppflags.items,
}); });
lib.defineCMacro("GLSLANG_OSINCLUDE_UNIX", ""); glslang_lib.defineCMacro("GLSLANG_OSINCLUDE_UNIX", "");
} }
if (enable_hlsl) { if (enable_hlsl) {
lib.addCSourceFiles(.{ glslang_lib.addCSourceFiles(.{
.files = &sources_hlsl, .files = &sources_hlsl,
.flags = cppflags.items, .flags = cppflags.items,
}); });
lib.defineCMacro("ENABLE_HLSL", "1"); glslang_lib.defineCMacro("ENABLE_HLSL", "1");
} else {
glslang_lib.defineCMacro("ENABLE_HLSL", "0");
} }
if (enable_opt) { if (enable_opt) {
lib.addCSourceFiles(.{ glslang_lib.addCSourceFiles(.{
.files = &sources_opt, .files = &sources_opt,
.flags = cppflags.items, .flags = cppflags.items,
}); });
lib.defineCMacro("ENABLE_OPT", "1"); glslang_lib.defineCMacro("ENABLE_OPT", "1");
lib.step.dependOn(&tools_libs.tools_opt.step); glslang_lib.step.dependOn(&tools_libs.tools_opt.step);
lib.step.dependOn(&tools_libs.tools_val.step); glslang_lib.step.dependOn(&tools_libs.tools_val.step);
lib.linkLibrary(tools_libs.tools_opt); glslang_lib.linkLibrary(tools_libs.tools_opt);
lib.linkLibrary(tools_libs.tools_val); glslang_lib.linkLibrary(tools_libs.tools_val);
} else {
glslang_lib.defineCMacro("ENABLE_OPT", "0");
} }
addIncludes(lib); addIncludes(glslang_lib);
spvtools.addSPIRVPublicIncludes(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"); const build_step = b.step("glslang-library", "Build the glslang library");
build_step.dependOn(&b.addInstallArtifact(lib, .{}).step); 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 { 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 // Include generation logic
// ------------------------------------------ // ------------------------------------------
@ -286,7 +352,6 @@ pub const BuildHeadersStep = struct {
}; };
const sources_spirv = [_][]const u8{ const sources_spirv = [_][]const u8{
"SPIRV/GlslangToSpv.cpp", "SPIRV/GlslangToSpv.cpp",
"SPIRV/InReadableOrder.cpp", "SPIRV/InReadableOrder.cpp",
@ -300,6 +365,7 @@ const sources_spirv = [_][]const u8{
const sources_c_interface = [_][]const u8{ const sources_c_interface = [_][]const u8{
"glslang/CInterface/glslang_c_interface.cpp", "glslang/CInterface/glslang_c_interface.cpp",
"SPIRV/CInterface/spirv_c_interface.cpp",
}; };
const sources_resource_limits = [_][]const u8{ const sources_resource_limits = [_][]const u8{
@ -363,4 +429,12 @@ const sources_hlsl = [_][]const u8{
const sources_opt = [_][]const u8{ const sources_opt = [_][]const u8{
"SPIRV/SpvTools.cpp", "SPIRV/SpvTools.cpp",
};
const sources_standalone_glslang = [_][]const u8{
"StandAlone/StandAlone.cpp"
};
const sources_standalone_remap = [_][]const u8{
"StandAlone/spirv-remap.cpp"
}; };

View file

@ -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), shader->shader->setEnvTarget(c_shader_target_language(input->target_language),
c_shader_target_language_version(input->target_language_version)); 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; return shader;
} }

View file

@ -206,6 +206,9 @@ typedef struct glslang_input_s {
glslang_target_language_version_t target_language_version; glslang_target_language_version_t target_language_version;
/** Shader source code */ /** Shader source code */
const char* 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; int default_version;
glslang_profile_t default_profile; glslang_profile_t default_profile;
int force_default_version_and_profile; int force_default_version_and_profile;

View file

@ -36,19 +36,19 @@ extern "C" {
#endif #endif
// Returns a struct that can be use to create custom resource values. // 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 // These are the default resources for TBuiltInResources, used for both
// - parsing this string for the case where the user didn't supply one, // - parsing this string for the case where the user didn't supply one,
// - dumping out a template for user construction of a config file. // - 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. // Returns the DefaultTBuiltInResource as a human-readable string.
// NOTE: User is responsible for freeing this 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|. // 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 #ifdef __cplusplus
} }

View file

@ -32,17 +32,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <string.h> #include <string.h>
#include <string> #include <string>
glslang_resource_t* glslang_resource(void) GLSLANG_EXPORT glslang_resource_t* glslang_resource(void)
{ {
return reinterpret_cast<glslang_resource_t*>(GetResources()); return reinterpret_cast<glslang_resource_t*>(GetResources());
} }
const glslang_resource_t* glslang_default_resource(void) GLSLANG_EXPORT const glslang_resource_t* glslang_default_resource(void)
{ {
return reinterpret_cast<const glslang_resource_t*>(GetDefaultResources()); return reinterpret_cast<const glslang_resource_t*>(GetDefaultResources());
} }
const char* glslang_default_resource_string() GLSLANG_EXPORT const char* glslang_default_resource_string()
{ {
std::string cpp_str = GetDefaultTBuiltInResourceString(); std::string cpp_str = GetDefaultTBuiltInResourceString();
char* c_str = (char*)malloc(cpp_str.length() + 1); char* c_str = (char*)malloc(cpp_str.length() + 1);
@ -50,7 +50,7 @@ const char* glslang_default_resource_string()
return c_str; 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<TBuiltInResource*>(resources), config); DecodeResourceLimits(reinterpret_cast<TBuiltInResource*>(resources), config);
} }

View file

@ -1,13 +0,0 @@
" -D<name[=def]> | --define-macro <name[=def]> | --D <name[=def]>\n"
" define a pre-processor macro\n"
" -H print human readable form of SPIR-V; turns on -V\n"
" -U<name> | --undef-macro <name> | --U <name>\n"
" undefine a pre-processor macro\n"
" -e <name> | --entry-point <name>\n"
" specify <name> 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 <name> the given shader source function is\n"
" renamed to be the <name> given in -e\n"

View file

@ -1,86 +0,0 @@
#define GLSLANG_IS_SHARED_LIBRARY
#include <glslang/Include/glslang_c_interface.h>
#include <glslang/Public/resource_limits_c.h>
#include <iostream>
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)
{
}