Skip to content

Commit

Permalink
Fixing up examples, fixing bug when making common pipelines
Browse files Browse the repository at this point in the history
  • Loading branch information
Interrupt committed Sep 24, 2024
1 parent 719e9a0 commit c594177
Show file tree
Hide file tree
Showing 15 changed files with 77 additions and 71 deletions.
5 changes: 3 additions & 2 deletions src/examples/collision.zig
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ const Vec2 = math.Vec2;
const Rect = delve.spatial.Rect;
const TextureRegion = delve.graphics.sprites.TextureRegion;

const def_shader = delve.shaders.default;

var shader_default: graphics.Shader = undefined;
var sprite_batch: batcher.SpriteBatcher = undefined;

Expand Down Expand Up @@ -58,14 +60,13 @@ pub fn registerModule() !void {

fn on_init() !void {
debug.log("Collision example module initializing", .{});
shader_default = try graphics.Shader.initDefault(.{});

sprite_batch = batcher.SpriteBatcher.init(.{}) catch {
debug.showErrorScreen("Fatal error during batch init!");
return;
};

shader_default = graphics.Shader.initDefault(.{});

graphics.setClearColor(colors.examples_bg_light);
}

Expand Down
2 changes: 1 addition & 1 deletion src/examples/fonts.zig
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ fn on_init() !void {
_ = try delve.fonts.loadFont("IBMPlexSerif", "assets/fonts/IBMPlexSerif-Regular.ttf", 1024, 200);

// make a shader with alpha blending
shader_blend = graphics.Shader.initDefault(.{ .blend_mode = graphics.BlendMode.BLEND });
shader_blend = try graphics.Shader.initDefault(.{ .blend_mode = graphics.BlendMode.BLEND });
}

fn on_tick(delta: f32) void {
Expand Down
2 changes: 1 addition & 1 deletion src/examples/forest.zig
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ fn on_init() !void {
tex_treesheet = graphics.Texture.init(&treesheet_img);

// make our default shader
shader_blend = graphics.Shader.initDefault(.{ .blend_mode = .NONE, .cull_mode = .NONE });
shader_blend = try graphics.Shader.initDefault(.{ .blend_mode = .NONE, .cull_mode = .NONE });

// set the sky color
graphics.setClearColor(sky_color);
Expand Down
2 changes: 1 addition & 1 deletion src/examples/frustums.zig
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ pub fn main() !void {
}

pub fn on_init() !void {
shader = delve.platform.graphics.Shader.initFromBuiltin(.{ .vertex_attributes = delve.graphics.mesh.getShaderAttributes() }, delve.shaders.default_mesh).?;
shader = try delve.platform.graphics.Shader.initFromBuiltin(.{ .vertex_attributes = delve.graphics.mesh.getShaderAttributes() }, delve.shaders.default_mesh);

// Create some materials
material_frustum = try delve.platform.graphics.Material.init(.{
Expand Down
4 changes: 2 additions & 2 deletions src/examples/lighting.zig
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ fn on_init() !void {
camera.direction = Vec3.new(0.0, 0.0, 1.0);

// make shaders for skinned and unskinned meshes
skinned_shader = graphics.Shader.initFromBuiltin(.{ .vertex_attributes = skinned_mesh.getSkinnedShaderAttributes() }, skinned_lit_shader).?;
static_shader = graphics.Shader.initFromBuiltin(.{ .vertex_attributes = delve.graphics.mesh.getShaderAttributes() }, lit_shader).?;
skinned_shader = try graphics.Shader.initFromBuiltin(.{ .vertex_attributes = skinned_mesh.getSkinnedShaderAttributes() }, skinned_lit_shader);
static_shader = try graphics.Shader.initFromBuiltin(.{ .vertex_attributes = delve.graphics.mesh.getShaderAttributes() }, lit_shader);

var base_img: images.Image = try images.loadFile(mesh_texture_file);
defer base_img.deinit();
Expand Down
4 changes: 2 additions & 2 deletions src/examples/meshbuilder.zig
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,11 @@ pub fn on_init() !void {
defer img.deinit();
const tex = graphics.Texture.init(&img);

const shader = graphics.Shader.initFromBuiltin(.{ .vertex_attributes = delve.graphics.mesh.getShaderAttributes() }, delve.shaders.default_mesh);
const shader = try graphics.Shader.initFromBuiltin(.{ .vertex_attributes = delve.graphics.mesh.getShaderAttributes() }, delve.shaders.default_mesh);

// Create a material out of the texture
material = try graphics.Material.init(.{
.shader = shader.?,
.shader = shader,
.own_shader = true,
.texture_0 = tex,
.samplers = &[_]graphics.FilterMode{.NEAREST},
Expand Down
8 changes: 1 addition & 7 deletions src/examples/meshes.zig
Original file line number Diff line number Diff line change
Expand Up @@ -90,13 +90,7 @@ fn on_init() !void {
const tex_emissive = graphics.Texture.init(&emissive_img);

// Make our emissive shader from one that is pre-compiled
const loaded_shader = graphics.Shader.initFromBuiltin(.{ .vertex_attributes = mesh.getShaderAttributes() }, emissive_shader_builtin);

if (loaded_shader == null) {
debug.log("Could not get emissive shader", .{});
return;
}
shader = loaded_shader.?;
shader = try graphics.Shader.initFromBuiltin(.{ .vertex_attributes = mesh.getShaderAttributes() }, emissive_shader_builtin);

// Create a material out of our shader and textures
material = try graphics.Material.init(.{
Expand Down
2 changes: 1 addition & 1 deletion src/examples/quakemap.zig
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ pub fn on_init() !void {
var err: delve.utils.quakemap.ErrorInfo = undefined;
quake_map = try delve.utils.quakemap.QuakeMap.read(allocator, test_map_file, map_transform, &err);

shader = graphics.Shader.initDefault(.{ .vertex_attributes = delve.graphics.mesh.getShaderAttributes() });
shader = try graphics.Shader.initDefault(.{ .vertex_attributes = delve.graphics.mesh.getShaderAttributes() });

// Create a material out of the texture
fallback_material = try graphics.Material.init(.{
Expand Down
2 changes: 1 addition & 1 deletion src/examples/rays.zig
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ pub fn main() !void {
}

pub fn on_init() !void {
const shader = delve.platform.graphics.Shader.initFromBuiltin(.{ .vertex_attributes = delve.graphics.mesh.getShaderAttributes() }, delve.shaders.default_mesh);
const shader = try delve.platform.graphics.Shader.initFromBuiltin(.{ .vertex_attributes = delve.graphics.mesh.getShaderAttributes() }, delve.shaders.default_mesh);

// Create some materials
material_frustum = try delve.platform.graphics.Material.init(.{
Expand Down
10 changes: 3 additions & 7 deletions src/examples/skinned-meshes.zig
Original file line number Diff line number Diff line change
Expand Up @@ -78,23 +78,19 @@ fn on_init() !void {
camera.direction = Vec3.new(0.0, 0.0, 1.0);

// Make our emissive shader from one that is pre-compiled
const shader = graphics.Shader.initFromBuiltin(.{ .vertex_attributes = skinned_mesh.getSkinnedShaderAttributes() }, shader_builtin);

if (shader == null) {
debug.log("Could not get shader", .{});
return;
}
const shader = try graphics.Shader.initFromBuiltin(.{ .vertex_attributes = skinned_mesh.getSkinnedShaderAttributes() }, shader_builtin);

var base_img: images.Image = images.loadFile(mesh_texture_file) catch {
debug.log("Assets: Error loading image asset: {s}", .{mesh_texture_file});
return;
};
defer base_img.deinit();

const tex_base = graphics.Texture.init(&base_img);

// Create a material out of our shader and textures
material = try delve.platform.graphics.Material.init(.{
.shader = shader.?,
.shader = shader,
.own_shader = true,
.texture_0 = tex_base,
.texture_1 = delve.platform.graphics.createSolidTexture(0x00000000),
Expand Down
4 changes: 2 additions & 2 deletions src/examples/sprites.zig
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@ fn on_init() !void {
texture_2 = graphics.Texture.init(&test_image_2);

// make some shaders for testing
shader_opaque = graphics.Shader.initDefault(.{});
shader_blend = graphics.Shader.initDefault(.{ .blend_mode = graphics.BlendMode.BLEND });
shader_opaque = try graphics.Shader.initDefault(.{});
shader_blend = try graphics.Shader.initDefault(.{ .blend_mode = graphics.BlendMode.BLEND });

// Create some test materials out of our shader and textures
test_material_1 = try graphics.Material.init(.{
Expand Down
2 changes: 1 addition & 1 deletion src/framework/graphics/shaders.zig
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ pub fn loadFromYaml(cfg: graphics.ShaderConfig, file_path: []const u8) !?graphic
break;
}

return graphics.Shader.initFromShaderInfo(cfg, shader_info);
return try graphics.Shader.initFromShaderInfo(cfg, shader_info);
}

fn loadShaderSource(allocator: std.mem.Allocator, shader_path: []const u8) ![:0]const u8 {
Expand Down
77 changes: 41 additions & 36 deletions src/framework/platform/backends/sokol/graphics.zig
Original file line number Diff line number Diff line change
Expand Up @@ -239,20 +239,22 @@ pub const ShaderImpl = struct {
is_instance: bool = false,

// One shader can have many pipelines, so different VertexLayouts can apply it
sokol_pipelines: *std.ArrayList(PipelineBinding),
sokol_pipelines: std.ArrayList(PipelineBinding),

/// Create a new shader using the default
pub fn initDefault(cfg: graphics.ShaderConfig) !Shader {
return try initFromBuiltin(cfg, shader_default);
return initFromBuiltin(cfg, shader_default);
}

/// Creates a shader from a shader built in as a zig file
pub fn initFromBuiltin(cfg: graphics.ShaderConfig, comptime builtin: anytype) !Shader {
const shader_desc_fn = getBuiltinSokolCreateFunction(builtin);
if (shader_desc_fn == null)
if (shader_desc_fn == null) {
debug.log("Shader builtin not found!", .{});
return ShaderInitError.ShaderNotFound;
}

return try initSokolShader(cfg, shader_desc_fn.?(sg.queryBackend()));
return initSokolShader(cfg, shader_desc_fn.?(sg.queryBackend()));
}

fn terminateString(allocator: std.mem.Allocator, in_string: []const u8) ![:0]const u8 {
Expand Down Expand Up @@ -462,28 +464,26 @@ pub const ShaderImpl = struct {
var updated_cfg = cfg;
updated_cfg.shader_program_def = shader_program;

return try initSokolShader(updated_cfg, desc);
return initSokolShader(updated_cfg, desc);
}

pub fn makeNewInstance(cfg: graphics.ShaderConfig, shader: ?Shader) !Shader {
if (shader) |*s| {
const pipeline_list = graphics.allocator.create(std.ArrayList(PipelineBinding)) catch {
debug.err("Could not create new shader instance!", .{});
return s.*;
};
pipeline_list.* = std.ArrayList(PipelineBinding).init(graphics.allocator);
pub fn makeNewInstance(cfg: graphics.ShaderConfig, shader: Shader) !Shader {
const impl = try graphics.allocator.create(ShaderImpl);

// Return a copy of our shader, but mark that this is a clone so that we don't free the sokol shader twice
var newShader = s.*;
newShader.impl.sokol_pipelines = pipeline_list;
newShader.impl.cfg = cfg;
newShader.impl.is_instance = true;
return newShader;
}
// Make a new implementation that uses our existing loaded shader, but a fresh pipeline list
// Mark it as being an instance, so we don't clean up our parent shader on destroy
impl.* = .{
.sokol_pipelines = std.ArrayList(PipelineBinding).init(graphics.allocator),
.sokol_shader = shader.impl.sokol_shader,
.sokol_shader_desc = shader.impl.sokol_shader_desc,
.cfg = cfg,
.is_instance = true,
};

// fallback shader!
// TODO: Should we return null instead?
return try initDefault(cfg);
// Copy the shader, but switch out its guts with our new one
var newShader = shader;
newShader.impl = impl;
return newShader;
}

/// Find the shader function in the builtin that can actually make the ShaderDesc
Expand Down Expand Up @@ -561,29 +561,25 @@ pub const ShaderImpl = struct {
}
}

const pipeline_list = try graphics.allocator.create(std.ArrayList(PipelineBinding));
pipeline_list.* = std.ArrayList(PipelineBinding).init(graphics.allocator);
const impl = try graphics.allocator.create(ShaderImpl);
errdefer graphics.allocator.destroy(impl);
impl.* = .{
.sokol_pipelines = std.ArrayList(PipelineBinding).init(graphics.allocator),
.sokol_shader = shader,
.sokol_shader_desc = shader_desc,
.cfg = cfg,
};

defer graphics.next_shader_handle += 1;
var built_shader = Shader{
.impl = .{
.sokol_pipelines = pipeline_list,
.sokol_shader = shader,
.sokol_shader_desc = shader_desc,
.cfg = cfg,
},
.impl = impl,
.handle = graphics.next_shader_handle,
.cfg = cfg,
.fs_texture_slots = num_fs_images,
.vertex_attributes = cfg.vertex_attributes,
.shader_program_def = cfg.shader_program_def,
};

// Cache some common pipelines
for (common_vertex_layouts) |l| {
_ = built_shader.impl.makePipeline(l);
}

// Set the uniformblocks to use for this shader
for (cfg.vs_uniformblocks, 0..) |block, i| {
built_shader.vs_uniformblocks[i] = block;
Expand All @@ -595,6 +591,13 @@ pub const ShaderImpl = struct {
return built_shader;
}

/// Cache our common pipelines, as an optimization step
pub fn makeCommonPipelines(self: *Shader) void {
for (graphics.getCommonVertexLayouts()) |l| {
_ = self.impl.makePipeline(l);
}
}

pub fn apply(self: *Shader, layout: graphics.VertexLayout) bool {
// Find the pipeline that matches our vertex layout
var pipeline: ?sg.Pipeline = null;
Expand Down Expand Up @@ -639,12 +642,14 @@ pub const ShaderImpl = struct {
for (self.impl.sokol_pipelines.items) |p| {
sg.destroyPipeline(p.sokol_pipeline);
}

self.impl.sokol_pipelines.deinit();
graphics.allocator.destroy(self.impl.sokol_pipelines);

if (!self.impl.is_instance) {
sg.destroyShader(self.impl.sokol_shader);
}

graphics.allocator.destroy(self.impl);
}
};

Expand Down
22 changes: 16 additions & 6 deletions src/framework/platform/graphics.zig
Original file line number Diff line number Diff line change
Expand Up @@ -363,28 +363,32 @@ pub const Shader = struct {

shader_program_def: ?shaders.ShaderProgram = null,

impl: ShaderImpl,
impl: *ShaderImpl,

/// Create a new shader using the default
pub fn initDefault(cfg: ShaderConfig) !Shader {
return try ShaderImpl.initDefault(cfg);
return ShaderImpl.initDefault(cfg);
}

/// Creates a shader from a shader built in as a zig file
pub fn initFromBuiltin(cfg: ShaderConfig, comptime builtin: anytype) !Shader {
return try ShaderImpl.initFromBuiltin(cfg, builtin);
var shader = try ShaderImpl.initFromBuiltin(cfg, builtin);
shader.makeCommonPipelines();
return shader;
}

pub fn initFromShaderInfo(cfg: ShaderConfig, shader_info: shaders.ShaderInfo) !Shader {
return try ShaderImpl.initFromShaderInfo(cfg, shader_info);
var shader = try ShaderImpl.initFromShaderInfo(cfg, shader_info);
shader.makeCommonPipelines();
return shader;
}

/// Returns a new instance of this shader
pub fn makeNewInstance(cfg: ShaderConfig, shader: ?Shader) !Shader {
if (shader != null) {
return try ShaderImpl.makeNewInstance(cfg, shader.?);
return ShaderImpl.makeNewInstance(cfg, shader.?);
}
return try initDefault(cfg);
return initDefault(cfg);
}

/// Updates the graphics state to draw using this shader
Expand Down Expand Up @@ -422,6 +426,10 @@ pub const Shader = struct {
}
}

pub fn makeCommonPipelines(self: *Shader) void {
ShaderImpl.makeCommonPipelines(self);
}

pub fn destroy(self: *Shader) void {
return ShaderImpl.destroy(self);
}
Expand Down Expand Up @@ -1058,6 +1066,8 @@ pub fn init() !void {

// Use the default shader for debug drawing
state.default_shader = try Shader.initDefault(.{ .cull_mode = .NONE });
state.default_shader.makeCommonPipelines();

state.debug_material = try Material.init(.{
.shader = state.default_shader,
.texture_0 = tex_white,
Expand Down
2 changes: 1 addition & 1 deletion src/framework/utils/quakemdl.zig
Original file line number Diff line number Diff line change
Expand Up @@ -465,7 +465,7 @@ pub fn open(in_allocator: Allocator, path: []const u8) !MDL {

// Material
const default_material = try graphics.Material.init(.{
.shader = graphics.Shader.initFromBuiltin(.{ .vertex_attributes = mesh.getShaderAttributes() }, default_mesh),
.shader = try graphics.Shader.initFromBuiltin(.{ .vertex_attributes = mesh.getShaderAttributes() }, default_mesh),
.own_shader = true,
.texture_0 = skins[0].single.texture,
.samplers = &[_]graphics.FilterMode{.NEAREST},
Expand Down

0 comments on commit c594177

Please sign in to comment.