{gfx,examples}: update all to new mach.Core module API

Signed-off-by: Stephen Gutekanst <stephen@hexops.com>
This commit is contained in:
Stephen Gutekanst 2024-04-17 11:27:41 -07:00
parent ac4fe65eb2
commit d045b34f70
13 changed files with 910 additions and 689 deletions

View file

@ -1,6 +1,5 @@
const std = @import("std");
const mach = @import("../main.zig");
const core = mach.core;
const gpu = mach.gpu;
const math = mach.math;
@ -89,6 +88,9 @@ pub var cp_transforms: [sprite_buffer_cap]math.Mat4x4 = undefined;
pub var cp_uv_transforms: [sprite_buffer_cap]math.Mat3x3 = undefined;
pub var cp_sizes: [sprite_buffer_cap]math.Vec2 = undefined;
/// Which render pass should be used during .render
render_pass: ?*gpu.RenderPassEncoder = null,
pub const BuiltPipeline = struct {
render: *gpu.RenderPipeline,
texture_sampler: *gpu.Sampler,
@ -144,7 +146,9 @@ fn deinit(sprite_pipeline: *Mod) void {
}
}
fn update(engine: *mach.Engine.Mod, sprite_pipeline: *Mod) !void {
fn update(core: *mach.Core.Mod, sprite_pipeline: *Mod) !void {
sprite_pipeline.init(.{});
// Destroy all sprite render pipelines. We will rebuild them all.
deinit(sprite_pipeline);
@ -158,13 +162,13 @@ fn update(engine: *mach.Engine.Mod, sprite_pipeline: *Mod) !void {
const textures = archetype.slice(.mach_gfx_sprite_pipeline, .texture);
for (ids, textures) |pipeline_id, texture| {
try buildPipeline(engine, sprite_pipeline, pipeline_id, texture);
try buildPipeline(core, sprite_pipeline, pipeline_id, texture);
}
}
}
fn buildPipeline(
engine: *mach.Engine.Mod,
core: *mach.Core.Mod,
sprite_pipeline: *Mod,
pipeline_id: mach.EntityID,
texture: *gpu.Texture,
@ -181,7 +185,7 @@ fn buildPipeline(
const opt_fragment_state = sprite_pipeline.get(pipeline_id, .fragment_state);
const opt_layout = sprite_pipeline.get(pipeline_id, .layout);
const device = engine.state().device;
const device = core.state().device;
// Storage buffers
const transforms = device.createBuffer(&.{
@ -269,7 +273,7 @@ fn buildPipeline(
defer shader_module.release();
const color_target = opt_color_target_state orelse gpu.ColorTargetState{
.format = core.descriptor.format,
.format = mach.core.descriptor.format,
.blend = &blend_state,
.write_mask = gpu.ColorWriteMaskFlags.all,
};
@ -311,10 +315,12 @@ fn buildPipeline(
try sprite_pipeline.set(pipeline_id, .num_sprites, 0);
}
fn preRender(
engine: *mach.Engine.Mod,
sprite_pipeline: *Mod,
) void {
fn preRender(sprite_pipeline: *Mod) void {
const encoder = mach.core.device.createCommandEncoder(&gpu.CommandEncoder.Descriptor{
.label = "SpritePipeline.encoder",
});
defer encoder.release();
var archetypes_iter = sprite_pipeline.entities.query(.{ .all = &.{
.{ .mach_gfx_sprite_pipeline = &.{
.built,
@ -326,10 +332,10 @@ fn preRender(
// Create the projection matrix
// TODO(sprite): move this out of the hot codepath
const proj = math.Mat4x4.projection2D(.{
.left = -@as(f32, @floatFromInt(core.size().width)) / 2,
.right = @as(f32, @floatFromInt(core.size().width)) / 2,
.bottom = -@as(f32, @floatFromInt(core.size().height)) / 2,
.top = @as(f32, @floatFromInt(core.size().height)) / 2,
.left = -@as(f32, @floatFromInt(mach.core.size().width)) / 2,
.right = @as(f32, @floatFromInt(mach.core.size().width)) / 2,
.bottom = -@as(f32, @floatFromInt(mach.core.size().height)) / 2,
.top = @as(f32, @floatFromInt(mach.core.size().height)) / 2,
.near = -0.1,
.far = 100000,
});
@ -343,15 +349,20 @@ fn preRender(
@as(f32, @floatFromInt(built.texture.getHeight())),
),
};
engine.state().encoder.writeBuffer(built.uniforms, 0, &[_]Uniforms{uniforms});
encoder.writeBuffer(built.uniforms, 0, &[_]Uniforms{uniforms});
}
}
var command = encoder.finish(null);
defer command.release();
mach.core.queue.submit(&[_]*gpu.CommandBuffer{command});
}
fn render(
engine: *mach.Engine.Mod,
sprite_pipeline: *Mod,
) !void {
fn render(sprite_pipeline: *Mod) !void {
const render_pass = if (sprite_pipeline.state().render_pass) |rp| rp else std.debug.panic("sprite_pipeline.state().render_pass must be specified", .{});
sprite_pipeline.state().render_pass = null;
// TODO(sprite): need a way to specify order of rendering with multiple pipelines
var archetypes_iter = sprite_pipeline.entities.query(.{ .all = &.{
.{ .mach_gfx_sprite_pipeline = &.{
.built,
@ -362,12 +373,11 @@ fn render(
const built_pipelines = archetype.slice(.mach_gfx_sprite_pipeline, .built);
for (ids, built_pipelines) |pipeline_id, built| {
// Draw the sprite batch
const pass = engine.state().pass;
const total_vertices = sprite_pipeline.get(pipeline_id, .num_sprites).? * 6;
pass.setPipeline(built.render);
render_pass.setPipeline(built.render);
// TODO(sprite): remove dynamic offsets?
pass.setBindGroup(0, built.bind_group, &.{});
pass.draw(total_vertices, 1, 0, 0);
render_pass.setBindGroup(0, built.bind_group, &.{});
render_pass.draw(total_vertices, 1, 0, 0);
}
}
}