pkg/glslang: shader api

This commit is contained in:
Mitchell Hashimoto
2023-11-15 21:46:07 -08:00
parent 6ebbea84d5
commit 4afaea19d6
6 changed files with 143 additions and 18 deletions

View File

@ -21,6 +21,9 @@ pub fn build(b: *std.Build) !void {
const tests_run = b.addRunArtifact(test_exe);
const test_step = b.step("test", "Run tests");
test_step.dependOn(&tests_run.step);
// Uncomment this if we're debugging tests
b.installArtifact(test_exe);
}
}
@ -42,6 +45,10 @@ fn buildGlslang(
var flags = std.ArrayList([]const u8).init(b.allocator);
defer flags.deinit();
try flags.appendSlice(&.{
"-fno-sanitize=undefined",
"-fno-sanitize-trap=undefined",
});
lib.addCSourceFiles(.{
.dependency = upstream,

9
pkg/glslang/init.zig Normal file
View File

@ -0,0 +1,9 @@
const c = @import("c.zig");
pub fn init() !void {
if (c.glslang_initialize_process() == 0) return error.GlslangInitFailed;
}
pub fn finalize() void {
c.glslang_finalize_process();
}

View File

@ -1,22 +1,7 @@
pub const c = @import("c.zig");
pub usingnamespace @import("init.zig");
pub usingnamespace @import("shader.zig");
test {
const input: c.glslang_input_t = .{
.language = c.GLSLANG_SOURCE_GLSL,
.stage = c.GLSLANG_STAGE_VERTEX,
.client = c.GLSLANG_CLIENT_VULKAN,
.client_version = c.GLSLANG_TARGET_VULKAN_1_2,
.target_language = c.GLSLANG_TARGET_SPV,
.target_language_version = c.GLSLANG_TARGET_SPV_1_5,
.code = "",
.default_version = 100,
.default_profile = c.GLSLANG_NO_PROFILE,
.force_default_version_and_profile = 0,
.forward_compatible = 0,
.messages = c.GLSLANG_MSG_DEFAULT_BIT,
.resource = c.glslang_default_resource(),
};
const shader = c.glslang_shader_create(&input);
_ = shader;
@import("std").testing.refAllDecls(@This());
}

58
pkg/glslang/shader.zig Normal file
View File

@ -0,0 +1,58 @@
const std = @import("std");
const c = @import("c.zig");
const testlib = @import("test.zig");
pub const Shader = opaque {
pub fn create(input: *const c.glslang_input_t) !*Shader {
if (c.glslang_shader_create(input)) |ptr| return @ptrCast(ptr);
return error.OutOfMemory;
}
pub fn delete(self: *Shader) void {
c.glslang_shader_delete(@ptrCast(self));
}
pub fn preprocess(self: *Shader, input: *const c.glslang_input_t) !void {
if (c.glslang_shader_preprocess(@ptrCast(self), input) == 0)
return error.GlslangFailed;
}
pub fn parse(self: *Shader, input: *const c.glslang_input_t) !void {
if (c.glslang_shader_parse(@ptrCast(self), input) == 0)
return error.GlslangFailed;
}
pub fn getInfoLog(self: *Shader) ![:0]const u8 {
const ptr = c.glslang_shader_get_info_log(@ptrCast(self));
return std.mem.sliceTo(ptr, 0);
}
pub fn getDebugInfoLog(self: *Shader) ![:0]const u8 {
const ptr = c.glslang_shader_get_info_debug_log(@ptrCast(self));
return std.mem.sliceTo(ptr, 0);
}
};
test {
const input: c.glslang_input_t = .{
.language = c.GLSLANG_SOURCE_GLSL,
.stage = c.GLSLANG_STAGE_FRAGMENT,
.client = c.GLSLANG_CLIENT_VULKAN,
.client_version = c.GLSLANG_TARGET_VULKAN_1_2,
.target_language = c.GLSLANG_TARGET_SPV,
.target_language_version = c.GLSLANG_TARGET_SPV_1_5,
.code = @embedFile("test/simple.frag"),
.default_version = 100,
.default_profile = c.GLSLANG_NO_PROFILE,
.force_default_version_and_profile = 0,
.forward_compatible = 0,
.messages = c.GLSLANG_MSG_DEFAULT_BIT,
.resource = c.glslang_default_resource(),
};
try testlib.ensureInit();
const shader = try Shader.create(&input);
defer shader.delete();
try shader.preprocess(&input);
try shader.parse(&input);
}

10
pkg/glslang/test.zig Normal file
View File

@ -0,0 +1,10 @@
const glslang = @import("main.zig");
var initialized: bool = false;
/// Call this function before any other tests in this package to ensure that
/// the glslang library is initialized.
pub fn ensureInit() !void {
if (initialized) return;
try glslang.init();
}

View File

@ -0,0 +1,56 @@
#version 430 core
layout(binding = 0) uniform Globals {
uniform vec3 iResolution;
uniform float iTime;
uniform float iTimeDelta;
uniform float iFrameRate;
uniform int iFrame;
uniform float iChannelTime[4];
uniform vec3 iChannelResolution[4];
uniform vec4 iMouse;
uniform vec4 iDate;
uniform float iSampleRate;
};
layout(binding = 0) uniform sampler2D iChannel0;
layout(binding = 1) uniform sampler2D iChannel1;
layout(binding = 2) uniform sampler2D iChannel2;
layout(binding = 3) uniform sampler2D iChannel3;
layout(location = 0) in vec4 gl_FragCoord;
layout(location = 0) out vec4 _fragColor;
#define texture2D texture
void mainImage( out vec4 fragColor, in vec2 fragCoord );
void main() { mainImage (_fragColor, gl_FragCoord.xy); }
#define t iTime
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
// Normalized pixel coordinates (from 0 to 1)
vec2 uv = ( fragCoord - .5*iResolution.xy) / iResolution.y;
vec3 col = vec3(0.);
float a = atan(uv.y,uv.x);
float r = 0.5*length(uv);
float counter = 100.;
a = 4.*a+20.*r+50.*cos(r)*cos(.1*t)+abs(a*r);
float f = 0.02*abs(cos(a))/(r*r);
vec2 v = vec2(0.);
for(float i=0.;i<counter;i++){
v = mat2(v,-v.y,v.x) * v + vec2(2.*f+cos(0.5*t*(exp(-0.2* r))),-cos(t*r*r)*cos(0.5*t));
if(length(v)>2.){
counter = i;
break;
}
}
col=vec3(min(0.9,1.2*exp(-pow(f,0.45)*counter)));
fragColor = min(0.9,1.2*exp(-pow(f,0.45)*counter) )
* ( 0.7 + 0.3* cos(10.*r - 2.*t -vec4(.7,1.4,2.1,0) ) );
}