mirror of
https://github.com/PixelGuys/Cubyz.git
synced 2025-08-03 03:06:55 -04:00
Add SPIR-V compilation to ensure our shaders remain SPIR-V compatible (#1404)
* Remove unused `directionalLight` uniform * Add glslang libraries * Update to the new Cubyz-libs version * Dehardcode OS-dependent library file name stuff * Audio somehow crashes on close, not sure why but I assume it's probably because of the library being compiled with a new zig version. * Remove irrelevant uniforms from Window uniform list * Remove unused itemdrop uniform * Implement SPIR-V compilation code, the actual output is discarded * Improve linking shader errors by passing a file path * Fix formatting
This commit is contained in:
parent
2cf88669e7
commit
5a1a824e05
@ -8,8 +8,7 @@ layout(location = 3) flat out vec3 normal;
|
||||
layout(location = 0) uniform mat4 projectionMatrix;
|
||||
layout(location = 1) uniform mat4 viewMatrix;
|
||||
layout(location = 2) uniform vec3 ambientLight;
|
||||
layout(location = 3) uniform vec3 directionalLight;
|
||||
layout(location = 4) uniform uint light;
|
||||
layout(location = 3) uniform uint light;
|
||||
|
||||
struct QuadInfo {
|
||||
vec3 normal;
|
||||
|
20
build.zig
20
build.zig
@ -1,5 +1,12 @@
|
||||
const std = @import("std");
|
||||
|
||||
fn libName(b: *std.Build, name: []const u8, target: std.Target) []const u8 {
|
||||
return switch(target.os.tag) {
|
||||
.windows => b.fmt("{s}.lib", .{name}),
|
||||
else => b.fmt("lib{s}.a", .{name}),
|
||||
};
|
||||
}
|
||||
|
||||
fn linkLibraries(b: *std.Build, exe: *std.Build.Step.Compile, useLocalDeps: bool) void {
|
||||
const target = exe.root_module.resolved_target.?;
|
||||
const t = target.result;
|
||||
@ -14,10 +21,7 @@ fn linkLibraries(b: *std.Build, exe: *std.Build.Step.Compile, useLocalDeps: bool
|
||||
.windows => "gnu",
|
||||
else => "none",
|
||||
}});
|
||||
const artifactName = switch(t.os.tag) {
|
||||
.windows => b.fmt("{s}.lib", .{depsLib}),
|
||||
else => b.fmt("lib{s}.a", .{depsLib}),
|
||||
};
|
||||
const artifactName = libName(b, depsLib, t);
|
||||
|
||||
var depsName: []const u8 = b.fmt("cubyz_deps_{s}_{s}", .{@tagName(t.cpu.arch), @tagName(t.os.tag)});
|
||||
if(useLocalDeps) depsName = "local";
|
||||
@ -38,6 +42,14 @@ fn linkLibraries(b: *std.Build, exe: *std.Build.Step.Compile, useLocalDeps: bool
|
||||
|
||||
exe.addIncludePath(headersDeps.path("include"));
|
||||
exe.addObjectFile(libsDeps.path("lib").path(b, artifactName));
|
||||
const subPath = libsDeps.path("lib").path(b, depsLib);
|
||||
exe.addObjectFile(subPath.path(b, libName(b, "glslang", t)));
|
||||
exe.addObjectFile(subPath.path(b, libName(b, "MachineIndependent", t)));
|
||||
exe.addObjectFile(subPath.path(b, libName(b, "GenericCodeGen", t)));
|
||||
exe.addObjectFile(subPath.path(b, libName(b, "glslang-default-resource-limits", t)));
|
||||
exe.addObjectFile(subPath.path(b, libName(b, "SPIRV", t)));
|
||||
exe.addObjectFile(subPath.path(b, libName(b, "SPIRV-Tools", t)));
|
||||
exe.addObjectFile(subPath.path(b, libName(b, "SPIRV-Tools-opt", t)));
|
||||
|
||||
if(t.os.tag == .windows) {
|
||||
exe.linkSystemLibrary("ole32");
|
||||
|
@ -9,38 +9,38 @@
|
||||
.lazy = true,
|
||||
},
|
||||
.cubyz_deps_headers = .{
|
||||
.url = "https://github.com/PixelGuys/Cubyz-Libs/releases/download/3/cubyz_deps_headers.tar.gz",
|
||||
.hash = "N-V-__8AAFfKKwD4OVIWboZJyV_bw1hcf8jMLQ3oeMJv7sLU",
|
||||
.url = "https://github.com/PixelGuys/Cubyz-Libs/releases/download/4/cubyz_deps_headers.tar.gz",
|
||||
.hash = "N-V-__8AADG8MwD98GEQXXNawTiaQfCUrV7vK4ldKsWhfwvI",
|
||||
.lazy = true,
|
||||
},
|
||||
.cubyz_deps_aarch64_macos = .{
|
||||
.url = "https://github.com/PixelGuys/Cubyz-Libs/releases/download/3/cubyz_deps_aarch64-macos-none.tar.gz",
|
||||
.hash = "N-V-__8AAOwYUwFLp5nMdLruyChLiiLNC1l7WNX6MsbqyZlj",
|
||||
.url = "https://github.com/PixelGuys/Cubyz-Libs/releases/download/4/cubyz_deps_aarch64-macos-none.tar.gz",
|
||||
.hash = "N-V-__8AANwbIwJ6ad1lQFbXKAwT6VwXJY4oLyjZwOfz4LUx",
|
||||
.lazy = true,
|
||||
},
|
||||
.cubyz_deps_aarch64_linux = .{
|
||||
.url = "https://github.com/PixelGuys/Cubyz-Libs/releases/download/3/cubyz_deps_aarch64-linux-musl.tar.gz",
|
||||
.hash = "N-V-__8AAJoZMAHJTEn1a2WhZG1oP4aNFn21F4xx2QxgdZ14",
|
||||
.url = "https://github.com/PixelGuys/Cubyz-Libs/releases/download/4/cubyz_deps_aarch64-linux-musl.tar.gz",
|
||||
.hash = "N-V-__8AAG6FdQLSQL-LHeF5o7k3vRCnIdl0n2I0R0UO18K-",
|
||||
.lazy = true,
|
||||
},
|
||||
.cubyz_deps_aarch64_windows = .{
|
||||
.url = "https://github.com/PixelGuys/Cubyz-Libs/releases/download/3/cubyz_deps_aarch64-windows-gnu.tar.gz",
|
||||
.hash = "N-V-__8AABweWgHCfLBx8TQDBPW--o4nO8mVwx-DPybBSMoX",
|
||||
.url = "https://github.com/PixelGuys/Cubyz-Libs/releases/download/4/cubyz_deps_aarch64-windows-gnu.tar.gz",
|
||||
.hash = "N-V-__8AANCHkQIGwA8SWUxMHaxnVnkTwBO0yei3HwBLOd2T",
|
||||
.lazy = true,
|
||||
},
|
||||
.cubyz_deps_x86_64_macos = .{
|
||||
.url = "https://github.com/PixelGuys/Cubyz-Libs/releases/download/3/cubyz_deps_x86_64-macos-none.tar.gz",
|
||||
.hash = "N-V-__8AALQdQwHNfI_VZxMro_pkv2B2VDSm26ucM0RMo35q",
|
||||
.url = "https://github.com/PixelGuys/Cubyz-Libs/releases/download/4/cubyz_deps_x86_64-macos-none.tar.gz",
|
||||
.hash = "N-V-__8AAIh5HAKP8i_TwkyD-6H_EL31J6Ereu9Kdx83J7Ks",
|
||||
.lazy = true,
|
||||
},
|
||||
.cubyz_deps_x86_64_linux = .{
|
||||
.url = "https://github.com/PixelGuys/Cubyz-Libs/releases/download/3/cubyz_deps_x86_64-linux-musl.tar.gz",
|
||||
.hash = "N-V-__8AAKJ0LwEjQ3OsGX6NrXotG-64FhmmES5E26ayZyr5",
|
||||
.url = "https://github.com/PixelGuys/Cubyz-Libs/releases/download/4/cubyz_deps_x86_64-linux-musl.tar.gz",
|
||||
.hash = "N-V-__8AAAy-cwLTBDz5YQSt3h-PdE4Cm-NDI9RGnrAz_onE",
|
||||
.lazy = true,
|
||||
},
|
||||
.cubyz_deps_x86_64_windows = .{
|
||||
.url = "https://github.com/PixelGuys/Cubyz-Libs/releases/download/3/cubyz_deps_x86_64-windows-gnu.tar.gz",
|
||||
.hash = "N-V-__8AAJ4DTQGiYwxpHAzkCv1RAilBsFRMm6zJGQZn9wED",
|
||||
.url = "https://github.com/PixelGuys/Cubyz-Libs/releases/download/4/cubyz_deps_x86_64-windows-gnu.tar.gz",
|
||||
.hash = "N-V-__8AAMzGtQKYP6AdoTC84UjbvypxwtagkWBMqrPc8Uhx",
|
||||
.lazy = true,
|
||||
},
|
||||
},
|
||||
|
@ -203,9 +203,12 @@ pub fn init() error{paError}!void {
|
||||
}
|
||||
|
||||
pub fn deinit() void {
|
||||
handleError(c.Pa_StopStream(stream)) catch {};
|
||||
handleError(c.Pa_CloseStream(stream)) catch {};
|
||||
handleError(c.Pa_Terminate()) catch {};
|
||||
// Something about this causes a crash later in __GI___pthread_exit, this started happening after adding glslang, which may or may not be related
|
||||
//handleError(c.Pa_StopStream(stream)) catch {};
|
||||
//handleError(c.Pa_CloseStream(stream)) catch {};
|
||||
//handleError(c.Pa_Terminate()) catch {};
|
||||
mutex.lock();
|
||||
defer mutex.unlock();
|
||||
main.threadPool.closeAllTasksOfType(&MusicLoadTask.vtable);
|
||||
musicCache.clear();
|
||||
activeTasks.deinit(main.globalAllocator);
|
||||
|
@ -90,7 +90,6 @@ pub const ClientEntityManager = struct {
|
||||
light: c_int,
|
||||
contrast: c_int,
|
||||
ambientLight: c_int,
|
||||
directionalLight: c_int,
|
||||
} = undefined;
|
||||
var modelBuffer: main.graphics.SSBO = undefined;
|
||||
var modelSize: c_int = 0;
|
||||
@ -167,7 +166,7 @@ pub const ClientEntityManager = struct {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render(projMatrix: Mat4f, ambientLight: Vec3f, directionalLight: Vec3f, playerPos: Vec3d) void {
|
||||
pub fn render(projMatrix: Mat4f, ambientLight: Vec3f, playerPos: Vec3d) void {
|
||||
mutex.lock();
|
||||
defer mutex.unlock();
|
||||
update();
|
||||
@ -176,7 +175,6 @@ pub const ClientEntityManager = struct {
|
||||
c.glUniformMatrix4fv(uniforms.projectionMatrix, 1, c.GL_TRUE, @ptrCast(&projMatrix));
|
||||
modelTexture.bindTo(0);
|
||||
c.glUniform3fv(uniforms.ambientLight, 1, @ptrCast(&ambientLight));
|
||||
c.glUniform3fv(uniforms.directionalLight, 1, @ptrCast(&directionalLight));
|
||||
c.glUniform1f(uniforms.contrast, 0.12);
|
||||
|
||||
for(entities.items()) |ent| {
|
||||
|
@ -38,6 +38,11 @@ pub const stb_image = @cImport({
|
||||
@cInclude("stb/stb_image_write.h");
|
||||
});
|
||||
|
||||
const glslang = @cImport({
|
||||
@cInclude("glslang/Include/glslang_c_interface.h");
|
||||
@cInclude("glslang/Public/resource_limits_c.h");
|
||||
});
|
||||
|
||||
pub const draw = struct { // MARK: draw
|
||||
var color: u32 = 0;
|
||||
var clip: ?Vec4i = null;
|
||||
@ -1203,6 +1208,7 @@ pub fn init() void { // MARK: init()
|
||||
std.log.err("Error while initializing TextRendering: {s}", .{@errorName(err)});
|
||||
};
|
||||
block_texture.init();
|
||||
if(glslang.glslang_initialize_process() == glslang.false) std.log.err("glslang_initialize_process failed", .{});
|
||||
}
|
||||
|
||||
pub fn deinit() void {
|
||||
@ -1214,18 +1220,80 @@ pub fn deinit() void {
|
||||
draw.deinitRectBorder();
|
||||
TextRendering.deinit();
|
||||
block_texture.deinit();
|
||||
glslang.glslang_finalize_process();
|
||||
}
|
||||
|
||||
pub const Shader = struct { // MARK: Shader
|
||||
id: c_uint,
|
||||
|
||||
fn addShader(self: *const Shader, filename: []const u8, defines: []const u8, shader_stage: c_uint) !void {
|
||||
fn compileToSpirV(allocator: NeverFailingAllocator, source: []const u8, filename: []const u8, defines: []const u8, shaderStage: glslang.glslang_stage_t) ![]c_uint {
|
||||
const versionLineEnd = if(std.mem.indexOfScalar(u8, source, '\n')) |len| len + 1 else 0;
|
||||
const versionLine = source[0..versionLineEnd];
|
||||
const sourceLines = source[versionLineEnd..];
|
||||
|
||||
var sourceWithDefines = main.List(u8).init(main.stackAllocator);
|
||||
defer sourceWithDefines.deinit();
|
||||
sourceWithDefines.appendSlice(versionLine);
|
||||
sourceWithDefines.appendSlice(defines);
|
||||
sourceWithDefines.appendSlice(sourceLines);
|
||||
sourceWithDefines.append(0);
|
||||
|
||||
const input = glslang.glslang_input_t{
|
||||
.language = glslang.GLSLANG_SOURCE_GLSL,
|
||||
.stage = shaderStage,
|
||||
.client = glslang.GLSLANG_CLIENT_OPENGL,
|
||||
.client_version = glslang.GLSLANG_TARGET_OPENGL_450,
|
||||
.target_language = glslang.GLSLANG_TARGET_SPV,
|
||||
.target_language_version = glslang.GLSLANG_TARGET_SPV_1_0,
|
||||
.code = sourceWithDefines.items.ptr,
|
||||
.default_version = 100,
|
||||
.default_profile = glslang.GLSLANG_NO_PROFILE,
|
||||
.force_default_version_and_profile = glslang.false,
|
||||
.forward_compatible = glslang.false,
|
||||
.messages = glslang.GLSLANG_MSG_DEFAULT_BIT,
|
||||
.resource = glslang.glslang_default_resource(),
|
||||
.callbacks = .{}, // TODO: Add support for shader includes
|
||||
.callbacks_ctx = null,
|
||||
};
|
||||
const shader = glslang.glslang_shader_create(&input);
|
||||
defer glslang.glslang_shader_delete(shader);
|
||||
if(glslang.glslang_shader_preprocess(shader, &input) == 0) {
|
||||
std.log.err("Error preprocessing shader {s}:\n{s}\n{s}\n", .{filename, glslang.glslang_shader_get_info_log(shader), glslang.glslang_shader_get_info_debug_log(shader)});
|
||||
return error.FailedCompiling;
|
||||
}
|
||||
|
||||
if(glslang.glslang_shader_parse(shader, &input) == 0) {
|
||||
std.log.err("Error parsing shader {s}:\n{s}\n{s}\n", .{filename, glslang.glslang_shader_get_info_log(shader), glslang.glslang_shader_get_info_debug_log(shader)});
|
||||
return error.FailedCompiling;
|
||||
}
|
||||
|
||||
const program = glslang.glslang_program_create();
|
||||
defer glslang.glslang_program_delete(program);
|
||||
glslang.glslang_program_add_shader(program, shader);
|
||||
|
||||
if(glslang.glslang_program_link(program, glslang.GLSLANG_MSG_SPV_RULES_BIT | glslang.GLSLANG_MSG_VULKAN_RULES_BIT) == 0) {
|
||||
std.log.err("Error linking shader {s}:\n{s}\n{s}\n", .{filename, glslang.glslang_shader_get_info_log(shader), glslang.glslang_shader_get_info_debug_log(shader)});
|
||||
return error.FailedCompiling;
|
||||
}
|
||||
|
||||
glslang.glslang_program_SPIRV_generate(program, shaderStage);
|
||||
const result = allocator.alloc(c_uint, glslang.glslang_program_SPIRV_get_size(program));
|
||||
glslang.glslang_program_SPIRV_get(program, result.ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
fn addShader(self: *const Shader, filename: []const u8, defines: []const u8, shaderStage: c_uint) !void {
|
||||
const source = main.files.read(main.stackAllocator, filename) catch |err| {
|
||||
std.log.err("Couldn't read shader file: {s}", .{filename});
|
||||
return err;
|
||||
};
|
||||
defer main.stackAllocator.free(source);
|
||||
const shader = c.glCreateShader(shader_stage);
|
||||
|
||||
// SPIR-V will be used for the Vulkan, now it's completely useless due to lack of support in Vulkan drivers
|
||||
const glslangStage: glslang.glslang_stage_t = if(shaderStage == c.GL_VERTEX_SHADER) glslang.GLSLANG_STAGE_VERTEX else if(shaderStage == c.GL_FRAGMENT_SHADER) glslang.GLSLANG_STAGE_FRAGMENT else glslang.GLSLANG_STAGE_COMPUTE;
|
||||
main.stackAllocator.free(try compileToSpirV(main.stackAllocator, source, filename, defines, glslangStage));
|
||||
|
||||
const shader = c.glCreateShader(shaderStage);
|
||||
defer c.glDeleteShader(shader);
|
||||
|
||||
const versionLineEnd = if(std.mem.indexOfScalar(u8, source, '\n')) |len| len + 1 else 0;
|
||||
@ -1251,7 +1319,7 @@ pub const Shader = struct { // MARK: Shader
|
||||
c.glAttachShader(self.id, shader);
|
||||
}
|
||||
|
||||
fn link(self: *const Shader) !void {
|
||||
fn link(self: *const Shader, file: []const u8) !void {
|
||||
c.glLinkProgram(self.id);
|
||||
|
||||
var success: c_int = undefined;
|
||||
@ -1261,7 +1329,7 @@ pub const Shader = struct { // MARK: Shader
|
||||
c.glGetProgramiv(self.id, c.GL_INFO_LOG_LENGTH, @ptrCast(&len));
|
||||
var buf: [4096]u8 = undefined;
|
||||
c.glGetProgramInfoLog(self.id, 4096, @ptrCast(&len), &buf);
|
||||
std.log.err("Error Linking Shader program:\n{s}\n", .{buf[0..len]});
|
||||
std.log.err("Error Linking Shader program {s}:\n{s}\n", .{file, buf[0..len]});
|
||||
return error.FailedLinking;
|
||||
}
|
||||
}
|
||||
@ -1270,7 +1338,7 @@ pub const Shader = struct { // MARK: Shader
|
||||
const shader = Shader{.id = c.glCreateProgram()};
|
||||
shader.addShader(vertex, defines, c.GL_VERTEX_SHADER) catch return shader;
|
||||
shader.addShader(fragment, defines, c.GL_FRAGMENT_SHADER) catch return shader;
|
||||
shader.link() catch return shader;
|
||||
shader.link(fragment) catch return shader;
|
||||
return shader;
|
||||
}
|
||||
|
||||
@ -1287,7 +1355,7 @@ pub const Shader = struct { // MARK: Shader
|
||||
pub fn initCompute(compute: []const u8, defines: []const u8) Shader {
|
||||
const shader = Shader{.id = c.glCreateProgram()};
|
||||
shader.addShader(compute, defines, c.GL_COMPUTE_SHADER) catch return shader;
|
||||
shader.link() catch return shader;
|
||||
shader.link(compute) catch return shader;
|
||||
return shader;
|
||||
}
|
||||
|
||||
|
@ -93,9 +93,6 @@ var windowUniforms: struct {
|
||||
size: c_int,
|
||||
color: c_int,
|
||||
scale: c_int,
|
||||
|
||||
image: c_int,
|
||||
randomOffset: c_int,
|
||||
} = undefined;
|
||||
pub var borderShader: Shader = undefined;
|
||||
pub var borderUniforms: struct {
|
||||
@ -110,7 +107,6 @@ pub var borderUniforms: struct {
|
||||
pub fn __init() void {
|
||||
shader = Shader.initAndGetUniforms("assets/cubyz/shaders/ui/button.vs", "assets/cubyz/shaders/ui/button.fs", "", &windowUniforms);
|
||||
shader.bind();
|
||||
graphics.c.glUniform1i(windowUniforms.image, 0);
|
||||
borderShader = Shader.initAndGetUniforms("assets/cubyz/shaders/ui/window_border.vs", "assets/cubyz/shaders/ui/window_border.fs", "", &borderUniforms);
|
||||
borderShader.bind();
|
||||
|
||||
|
@ -547,7 +547,6 @@ pub const ItemDropRenderer = struct { // MARK: ItemDropRenderer
|
||||
projectionMatrix: c_int,
|
||||
modelMatrix: c_int,
|
||||
viewMatrix: c_int,
|
||||
modelPosition: c_int,
|
||||
ambientLight: c_int,
|
||||
modelIndex: c_int,
|
||||
block: c_int,
|
||||
|
@ -223,7 +223,7 @@ pub fn renderWorld(world: *World, ambientLight: Vec3f, skyColor: Vec3f, playerPo
|
||||
}
|
||||
|
||||
gpu_performance_measuring.startQuery(.entity_rendering);
|
||||
entity.ClientEntityManager.render(game.projectionMatrix, ambientLight, .{1, 0.5, 0.25}, playerPos);
|
||||
entity.ClientEntityManager.render(game.projectionMatrix, ambientLight, playerPos);
|
||||
|
||||
itemdrop.ItemDropRenderer.renderItemDrops(game.projectionMatrix, ambientLight, playerPos);
|
||||
gpu_performance_measuring.stopQuery();
|
||||
|
Loading…
x
Reference in New Issue
Block a user