From e6cecc3ebe8296f29793e70ca8fda8c0194c8d1a Mon Sep 17 00:00:00 2001 From: Stephen Gutekanst Date: Sun, 7 Jul 2024 21:25:19 -0700 Subject: [PATCH] core: remove all examples These examples were great at showing how to use the WebGPU and sysgpu APIs but otherwise had poor code quality, depended on zmath instead of mach.math, etc. and so are being removed. Signed-off-by: Stephen Gutekanst --- src/core/examples/LICENSE.webgpu-samples | 26 - src/core/examples/boids/main.zig | 265 ----- src/core/examples/boids/sprite.wgsl | 15 - src/core/examples/boids/updateSprites.wgsl | 90 -- src/core/examples/clear-color/main.zig | 81 -- src/core/examples/clear-color/renderer.zig | 33 - src/core/examples/cubemap/cube_mesh.zig | 49 - src/core/examples/cubemap/main.zig | 395 ------- src/core/examples/cubemap/shader.wgsl | 34 - src/core/examples/fractal-cube/cube_mesh.zig | 49 - src/core/examples/fractal-cube/main.zig | 374 ------- src/core/examples/fractal-cube/shader.wgsl | 36 - src/core/examples/gen-texture-light/cube.wgsl | 75 -- .../examples/gen-texture-light/light.wgsl | 35 - src/core/examples/gen-texture-light/main.zig | 893 ---------------- src/core/examples/image-blur/blur.wgsl | 81 -- .../image-blur/fullscreen_textured_quad.wgsl | 38 - src/core/examples/image-blur/main.zig | 329 ------ .../image/fullscreen_textured_quad.wgsl | 39 - src/core/examples/image/main.zig | 187 ---- .../examples/instanced-cube/cube_mesh.zig | 49 - src/core/examples/instanced-cube/main.zig | 208 ---- src/core/examples/instanced-cube/shader.wgsl | 25 - src/core/examples/map-async/main.wgsl | 16 - src/core/examples/map-async/main.zig | 103 -- .../examples/pixel-post-process/cube_mesh.zig | 49 - src/core/examples/pixel-post-process/main.zig | 464 -------- .../pixel-post-process/normal_frag.wgsl | 6 - .../pixel-post-process/pixel_frag.wgsl | 74 -- .../pixel-post-process/pixel_vert.wgsl | 14 - .../examples/pixel-post-process/quad_mesh.zig | 13 - .../examples/pixel-post-process/shader.wgsl | 27 - .../examples/procedural-primitives/main.zig | 65 -- .../procedural-primitives.zig | 336 ------ .../procedural-primitives/renderer.zig | 328 ------ .../procedural-primitives/shader.wgsl | 33 - src/core/examples/rgb-quad/main.zig | 140 --- src/core/examples/rgb-quad/shader.wgsl | 15 - src/core/examples/rotating-cube/cube_mesh.zig | 49 - src/core/examples/rotating-cube/main.zig | 195 ---- src/core/examples/rotating-cube/shader.wgsl | 24 - src/core/examples/sprite2d/main.zig | 357 ------- src/core/examples/sprite2d/sprite-shader.wgsl | 82 -- src/core/examples/sprite2d/sprites.json | 53 - src/core/examples/sysgpu/boids/main.zig | 268 ----- src/core/examples/sysgpu/boids/sprite.wgsl | 15 - .../examples/sysgpu/boids/updateSprites.wgsl | 90 -- src/core/examples/sysgpu/clear-color/main.zig | 84 -- .../examples/sysgpu/clear-color/renderer.zig | 33 - .../examples/sysgpu/cubemap/cube_mesh.zig | 49 - src/core/examples/sysgpu/cubemap/main.zig | 398 ------- src/core/examples/sysgpu/cubemap/shader.wgsl | 34 - .../sysgpu/fractal-cube/cube_mesh.zig | 49 - .../examples/sysgpu/fractal-cube/main.zig | 377 ------- .../examples/sysgpu/fractal-cube/shader.wgsl | 36 - .../sysgpu/gen-texture-light/cube.wgsl | 71 -- .../sysgpu/gen-texture-light/light.wgsl | 34 - .../sysgpu/gen-texture-light/main.zig | 896 ---------------- src/core/examples/sysgpu/image-blur/blur.wgsl | 82 -- .../image-blur/fullscreen_textured_quad.wgsl | 38 - src/core/examples/sysgpu/image-blur/main.zig | 332 ------ .../image/fullscreen_textured_quad.wgsl | 39 - src/core/examples/sysgpu/image/main.zig | 190 ---- .../sysgpu/instanced-cube/cube_mesh.zig | 49 - .../examples/sysgpu/instanced-cube/main.zig | 211 ---- .../sysgpu/instanced-cube/shader.wgsl | 25 - src/core/examples/sysgpu/map-async/main.wgsl | 16 - src/core/examples/sysgpu/map-async/main.zig | 106 -- .../sysgpu/pixel-post-process/cube_mesh.zig | 49 - .../sysgpu/pixel-post-process/main.zig | 467 -------- .../pixel-post-process/normal_frag.wgsl | 6 - .../sysgpu/pixel-post-process/pixel_frag.wgsl | 77 -- .../sysgpu/pixel-post-process/pixel_vert.wgsl | 14 - .../sysgpu/pixel-post-process/quad_mesh.zig | 13 - .../sysgpu/pixel-post-process/shader.wgsl | 27 - .../sysgpu/procedural-primitives/main.zig | 68 -- .../procedural-primitives.zig | 336 ------ .../sysgpu/procedural-primitives/renderer.zig | 328 ------ .../sysgpu/procedural-primitives/shader.wgsl | 32 - src/core/examples/sysgpu/rgb-quad/main.zig | 143 --- src/core/examples/sysgpu/rgb-quad/shader.wgsl | 15 - .../sysgpu/rotating-cube/cube_mesh.zig | 49 - .../examples/sysgpu/rotating-cube/main.zig | 198 ---- .../examples/sysgpu/rotating-cube/shader.wgsl | 24 - src/core/examples/sysgpu/sprite2d/main.zig | 360 ------- .../sysgpu/sprite2d/sprite-shader.wgsl | 82 -- .../examples/sysgpu/sprite2d/sprites.json | 53 - .../sysgpu/textured-cube/cube_mesh.zig | 49 - .../examples/sysgpu/textured-cube/main.zig | 319 ------ .../examples/sysgpu/textured-cube/shader.wgsl | 29 - .../examples/sysgpu/textured-quad/main.zig | 210 ---- .../examples/sysgpu/textured-quad/shader.wgsl | 21 - .../examples/sysgpu/triangle-msaa/main.zig | 133 --- .../examples/sysgpu/triangle-msaa/shader.wgsl | 14 - src/core/examples/sysgpu/triangle/main.zig | 96 -- src/core/examples/sysgpu/triangle/shader.wgsl | 14 - .../examples/sysgpu/two-cubes/cube_mesh.zig | 49 - src/core/examples/sysgpu/two-cubes/main.zig | 229 ---- .../examples/sysgpu/two-cubes/shader.wgsl | 24 - src/core/examples/textured-cube/cube_mesh.zig | 49 - src/core/examples/textured-cube/main.zig | 316 ------ src/core/examples/textured-cube/shader.wgsl | 29 - src/core/examples/textured-quad/main.zig | 207 ---- src/core/examples/textured-quad/shader.wgsl | 21 - src/core/examples/triangle-msaa/main.zig | 130 --- src/core/examples/triangle-msaa/shader.wgsl | 14 - src/core/examples/triangle/main.zig | 93 -- src/core/examples/triangle/shader.wgsl | 14 - src/core/examples/two-cubes/cube_mesh.zig | 49 - src/core/examples/two-cubes/main.zig | 226 ---- src/core/examples/two-cubes/shader.wgsl | 24 - src/core/examples/wasm-test/main.zig | 37 - src/core/examples/zmath.zig | 996 ------------------ 113 files changed, 15104 deletions(-) delete mode 100644 src/core/examples/LICENSE.webgpu-samples delete mode 100644 src/core/examples/boids/main.zig delete mode 100644 src/core/examples/boids/sprite.wgsl delete mode 100644 src/core/examples/boids/updateSprites.wgsl delete mode 100644 src/core/examples/clear-color/main.zig delete mode 100644 src/core/examples/clear-color/renderer.zig delete mode 100644 src/core/examples/cubemap/cube_mesh.zig delete mode 100644 src/core/examples/cubemap/main.zig delete mode 100644 src/core/examples/cubemap/shader.wgsl delete mode 100644 src/core/examples/fractal-cube/cube_mesh.zig delete mode 100755 src/core/examples/fractal-cube/main.zig delete mode 100644 src/core/examples/fractal-cube/shader.wgsl delete mode 100644 src/core/examples/gen-texture-light/cube.wgsl delete mode 100644 src/core/examples/gen-texture-light/light.wgsl delete mode 100755 src/core/examples/gen-texture-light/main.zig delete mode 100644 src/core/examples/image-blur/blur.wgsl delete mode 100644 src/core/examples/image-blur/fullscreen_textured_quad.wgsl delete mode 100644 src/core/examples/image-blur/main.zig delete mode 100644 src/core/examples/image/fullscreen_textured_quad.wgsl delete mode 100644 src/core/examples/image/main.zig delete mode 100644 src/core/examples/instanced-cube/cube_mesh.zig delete mode 100755 src/core/examples/instanced-cube/main.zig delete mode 100644 src/core/examples/instanced-cube/shader.wgsl delete mode 100644 src/core/examples/map-async/main.wgsl delete mode 100644 src/core/examples/map-async/main.zig delete mode 100644 src/core/examples/pixel-post-process/cube_mesh.zig delete mode 100644 src/core/examples/pixel-post-process/main.zig delete mode 100644 src/core/examples/pixel-post-process/normal_frag.wgsl delete mode 100644 src/core/examples/pixel-post-process/pixel_frag.wgsl delete mode 100644 src/core/examples/pixel-post-process/pixel_vert.wgsl delete mode 100644 src/core/examples/pixel-post-process/quad_mesh.zig delete mode 100644 src/core/examples/pixel-post-process/shader.wgsl delete mode 100644 src/core/examples/procedural-primitives/main.zig delete mode 100644 src/core/examples/procedural-primitives/procedural-primitives.zig delete mode 100644 src/core/examples/procedural-primitives/renderer.zig delete mode 100644 src/core/examples/procedural-primitives/shader.wgsl delete mode 100644 src/core/examples/rgb-quad/main.zig delete mode 100644 src/core/examples/rgb-quad/shader.wgsl delete mode 100644 src/core/examples/rotating-cube/cube_mesh.zig delete mode 100755 src/core/examples/rotating-cube/main.zig delete mode 100644 src/core/examples/rotating-cube/shader.wgsl delete mode 100644 src/core/examples/sprite2d/main.zig delete mode 100644 src/core/examples/sprite2d/sprite-shader.wgsl delete mode 100644 src/core/examples/sprite2d/sprites.json delete mode 100644 src/core/examples/sysgpu/boids/main.zig delete mode 100644 src/core/examples/sysgpu/boids/sprite.wgsl delete mode 100644 src/core/examples/sysgpu/boids/updateSprites.wgsl delete mode 100644 src/core/examples/sysgpu/clear-color/main.zig delete mode 100644 src/core/examples/sysgpu/clear-color/renderer.zig delete mode 100644 src/core/examples/sysgpu/cubemap/cube_mesh.zig delete mode 100644 src/core/examples/sysgpu/cubemap/main.zig delete mode 100644 src/core/examples/sysgpu/cubemap/shader.wgsl delete mode 100644 src/core/examples/sysgpu/fractal-cube/cube_mesh.zig delete mode 100644 src/core/examples/sysgpu/fractal-cube/main.zig delete mode 100644 src/core/examples/sysgpu/fractal-cube/shader.wgsl delete mode 100644 src/core/examples/sysgpu/gen-texture-light/cube.wgsl delete mode 100644 src/core/examples/sysgpu/gen-texture-light/light.wgsl delete mode 100644 src/core/examples/sysgpu/gen-texture-light/main.zig delete mode 100644 src/core/examples/sysgpu/image-blur/blur.wgsl delete mode 100644 src/core/examples/sysgpu/image-blur/fullscreen_textured_quad.wgsl delete mode 100644 src/core/examples/sysgpu/image-blur/main.zig delete mode 100644 src/core/examples/sysgpu/image/fullscreen_textured_quad.wgsl delete mode 100644 src/core/examples/sysgpu/image/main.zig delete mode 100644 src/core/examples/sysgpu/instanced-cube/cube_mesh.zig delete mode 100644 src/core/examples/sysgpu/instanced-cube/main.zig delete mode 100644 src/core/examples/sysgpu/instanced-cube/shader.wgsl delete mode 100644 src/core/examples/sysgpu/map-async/main.wgsl delete mode 100644 src/core/examples/sysgpu/map-async/main.zig delete mode 100644 src/core/examples/sysgpu/pixel-post-process/cube_mesh.zig delete mode 100644 src/core/examples/sysgpu/pixel-post-process/main.zig delete mode 100644 src/core/examples/sysgpu/pixel-post-process/normal_frag.wgsl delete mode 100644 src/core/examples/sysgpu/pixel-post-process/pixel_frag.wgsl delete mode 100644 src/core/examples/sysgpu/pixel-post-process/pixel_vert.wgsl delete mode 100644 src/core/examples/sysgpu/pixel-post-process/quad_mesh.zig delete mode 100644 src/core/examples/sysgpu/pixel-post-process/shader.wgsl delete mode 100644 src/core/examples/sysgpu/procedural-primitives/main.zig delete mode 100644 src/core/examples/sysgpu/procedural-primitives/procedural-primitives.zig delete mode 100644 src/core/examples/sysgpu/procedural-primitives/renderer.zig delete mode 100644 src/core/examples/sysgpu/procedural-primitives/shader.wgsl delete mode 100644 src/core/examples/sysgpu/rgb-quad/main.zig delete mode 100644 src/core/examples/sysgpu/rgb-quad/shader.wgsl delete mode 100644 src/core/examples/sysgpu/rotating-cube/cube_mesh.zig delete mode 100644 src/core/examples/sysgpu/rotating-cube/main.zig delete mode 100644 src/core/examples/sysgpu/rotating-cube/shader.wgsl delete mode 100644 src/core/examples/sysgpu/sprite2d/main.zig delete mode 100644 src/core/examples/sysgpu/sprite2d/sprite-shader.wgsl delete mode 100644 src/core/examples/sysgpu/sprite2d/sprites.json delete mode 100644 src/core/examples/sysgpu/textured-cube/cube_mesh.zig delete mode 100644 src/core/examples/sysgpu/textured-cube/main.zig delete mode 100644 src/core/examples/sysgpu/textured-cube/shader.wgsl delete mode 100644 src/core/examples/sysgpu/textured-quad/main.zig delete mode 100644 src/core/examples/sysgpu/textured-quad/shader.wgsl delete mode 100644 src/core/examples/sysgpu/triangle-msaa/main.zig delete mode 100644 src/core/examples/sysgpu/triangle-msaa/shader.wgsl delete mode 100644 src/core/examples/sysgpu/triangle/main.zig delete mode 100644 src/core/examples/sysgpu/triangle/shader.wgsl delete mode 100644 src/core/examples/sysgpu/two-cubes/cube_mesh.zig delete mode 100644 src/core/examples/sysgpu/two-cubes/main.zig delete mode 100644 src/core/examples/sysgpu/two-cubes/shader.wgsl delete mode 100644 src/core/examples/textured-cube/cube_mesh.zig delete mode 100644 src/core/examples/textured-cube/main.zig delete mode 100644 src/core/examples/textured-cube/shader.wgsl delete mode 100644 src/core/examples/textured-quad/main.zig delete mode 100644 src/core/examples/textured-quad/shader.wgsl delete mode 100644 src/core/examples/triangle-msaa/main.zig delete mode 100644 src/core/examples/triangle-msaa/shader.wgsl delete mode 100644 src/core/examples/triangle/main.zig delete mode 100644 src/core/examples/triangle/shader.wgsl delete mode 100644 src/core/examples/two-cubes/cube_mesh.zig delete mode 100755 src/core/examples/two-cubes/main.zig delete mode 100644 src/core/examples/two-cubes/shader.wgsl delete mode 100644 src/core/examples/wasm-test/main.zig delete mode 100644 src/core/examples/zmath.zig diff --git a/src/core/examples/LICENSE.webgpu-samples b/src/core/examples/LICENSE.webgpu-samples deleted file mode 100644 index e7a21bee..00000000 --- a/src/core/examples/LICENSE.webgpu-samples +++ /dev/null @@ -1,26 +0,0 @@ -Copyright 2019 WebGPU Samples Contributors - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - 3. Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from this - software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/core/examples/boids/main.zig b/src/core/examples/boids/main.zig deleted file mode 100644 index e0489b38..00000000 --- a/src/core/examples/boids/main.zig +++ /dev/null @@ -1,265 +0,0 @@ -/// A port of Austin Eng's "computeBoids" webgpu sample. -/// https://github.com/austinEng/webgpu-samples/blob/main/src/sample/computeBoids/main.ts -const std = @import("std"); - -const mach = @import("mach"); -const core = mach.core; -const gpu = mach.gpu; - -title_timer: core.Timer, -timer: core.Timer, -compute_pipeline: *gpu.ComputePipeline, -render_pipeline: *gpu.RenderPipeline, -sprite_vertex_buffer: *gpu.Buffer, -particle_buffers: [2]*gpu.Buffer, -particle_bind_groups: [2]*gpu.BindGroup, -sim_param_buffer: *gpu.Buffer, -frame_counter: usize, - -pub const App = @This(); - -var gpa = std.heap.GeneralPurposeAllocator(.{}){}; - -const num_particle = 1500; - -var sim_params = [_]f32{ - 0.04, // .delta_T - 0.1, // .rule_1_distance - 0.025, // .rule_2_distance - 0.025, // .rule_3_distance - 0.02, // .rule_1_scale - 0.05, // .rule_2_scale - 0.005, // .rule_3_scale -}; - -pub fn init(app: *App) !void { - try core.init(.{}); - - const sprite_shader_module = core.device.createShaderModuleWGSL( - "sprite.wgsl", - @embedFile("sprite.wgsl"), - ); - defer sprite_shader_module.release(); - - const update_sprite_shader_module = core.device.createShaderModuleWGSL( - "updateSprites.wgsl", - @embedFile("updateSprites.wgsl"), - ); - defer update_sprite_shader_module.release(); - - const instanced_particles_attributes = [_]gpu.VertexAttribute{ - .{ - // instance position - .shader_location = 0, - .offset = 0, - .format = .float32x2, - }, - .{ - // instance velocity - .shader_location = 1, - .offset = 2 * 4, - .format = .float32x2, - }, - }; - - const vertex_buffer_attributes = [_]gpu.VertexAttribute{ - .{ - // vertex positions - .shader_location = 2, - .offset = 0, - .format = .float32x2, - }, - }; - - const render_pipeline = core.device.createRenderPipeline(&gpu.RenderPipeline.Descriptor{ - .vertex = gpu.VertexState.init(.{ - .module = sprite_shader_module, - .entry_point = "vert_main", - .buffers = &.{ - gpu.VertexBufferLayout.init(.{ - // instanced particles buffer - .array_stride = 4 * 4, - .step_mode = .instance, - .attributes = &instanced_particles_attributes, - }), - gpu.VertexBufferLayout.init(.{ - // vertex buffer - .array_stride = 2 * 4, - .step_mode = .vertex, - .attributes = &vertex_buffer_attributes, - }), - }, - }), - .fragment = &gpu.FragmentState.init(.{ - .module = sprite_shader_module, - .entry_point = "frag_main", - .targets = &[_]gpu.ColorTargetState{.{ - .format = core.descriptor.format, - }}, - }), - }); - - const compute_pipeline = core.device.createComputePipeline(&gpu.ComputePipeline.Descriptor{ .compute = gpu.ProgrammableStageDescriptor{ - .module = update_sprite_shader_module, - .entry_point = "main", - } }); - - const vert_buffer_data = [_]f32{ - -0.01, -0.02, 0.01, - -0.02, 0.0, 0.02, - }; - - const sprite_vertex_buffer = core.device.createBuffer(&gpu.Buffer.Descriptor{ - .label = "sprite_vertex_buffer", - .usage = .{ .vertex = true }, - .mapped_at_creation = .true, - .size = vert_buffer_data.len * @sizeOf(f32), - }); - const vertex_mapped = sprite_vertex_buffer.getMappedRange(f32, 0, vert_buffer_data.len); - @memcpy(vertex_mapped.?, vert_buffer_data[0..]); - sprite_vertex_buffer.unmap(); - - const sim_param_buffer = core.device.createBuffer(&gpu.Buffer.Descriptor{ - .label = "sim_param_buffer", - .usage = .{ .uniform = true, .copy_dst = true }, - .size = sim_params.len * @sizeOf(f32), - }); - core.queue.writeBuffer(sim_param_buffer, 0, sim_params[0..]); - - var initial_particle_data: [num_particle * 4]f32 = undefined; - var rng = std.rand.DefaultPrng.init(0); - const random = rng.random(); - var i: usize = 0; - while (i < num_particle) : (i += 1) { - initial_particle_data[4 * i + 0] = 2 * (random.float(f32) - 0.5); - initial_particle_data[4 * i + 1] = 2 * (random.float(f32) - 0.5); - initial_particle_data[4 * i + 2] = 2 * (random.float(f32) - 0.5) * 0.1; - initial_particle_data[4 * i + 3] = 2 * (random.float(f32) - 0.5) * 0.1; - } - - var particle_buffers: [2]*gpu.Buffer = undefined; - var particle_bind_groups: [2]*gpu.BindGroup = undefined; - i = 0; - while (i < 2) : (i += 1) { - particle_buffers[i] = core.device.createBuffer(&gpu.Buffer.Descriptor{ - .label = "particle_buffer", - .mapped_at_creation = .true, - .usage = .{ - .vertex = true, - .storage = true, - }, - .size = initial_particle_data.len * @sizeOf(f32), - }); - const mapped = particle_buffers[i].getMappedRange(f32, 0, initial_particle_data.len); - @memcpy(mapped.?, initial_particle_data[0..]); - particle_buffers[i].unmap(); - } - - i = 0; - while (i < 2) : (i += 1) { - const layout = compute_pipeline.getBindGroupLayout(0); - defer layout.release(); - - particle_bind_groups[i] = core.device.createBindGroup(&gpu.BindGroup.Descriptor.init(.{ - .layout = layout, - .entries = &.{ - gpu.BindGroup.Entry.buffer(0, sim_param_buffer, 0, sim_params.len * @sizeOf(f32)), - gpu.BindGroup.Entry.buffer(1, particle_buffers[i], 0, initial_particle_data.len * @sizeOf(f32)), - gpu.BindGroup.Entry.buffer(2, particle_buffers[(i + 1) % 2], 0, initial_particle_data.len * @sizeOf(f32)), - }, - })); - } - - app.* = .{ - .timer = try core.Timer.start(), - .title_timer = try core.Timer.start(), - .compute_pipeline = compute_pipeline, - .render_pipeline = render_pipeline, - .sprite_vertex_buffer = sprite_vertex_buffer, - .particle_buffers = particle_buffers, - .particle_bind_groups = particle_bind_groups, - .sim_param_buffer = sim_param_buffer, - .frame_counter = 0, - }; -} - -pub fn deinit(app: *App) void { - defer _ = gpa.deinit(); - defer core.deinit(); - - app.compute_pipeline.release(); - app.render_pipeline.release(); - app.sprite_vertex_buffer.release(); - for (app.particle_buffers) |particle_buffer| particle_buffer.release(); - for (app.particle_bind_groups) |particle_bind_group| particle_bind_group.release(); - app.sim_param_buffer.release(); -} - -pub fn update(app: *App) !bool { - const delta_time = app.timer.lap(); - - var iter = core.pollEvents(); - while (iter.next()) |event| { - if (event == .close) return true; - } - - const back_buffer_view = core.swap_chain.getCurrentTextureView().?; - const color_attachment = gpu.RenderPassColorAttachment{ - .view = back_buffer_view, - .clear_value = std.mem.zeroes(gpu.Color), - .load_op = .clear, - .store_op = .store, - }; - - const render_pass_descriptor = gpu.RenderPassDescriptor.init(.{ - .color_attachments = &.{ - color_attachment, - }, - }); - - sim_params[0] = @as(f32, @floatCast(delta_time)); - core.queue.writeBuffer(app.sim_param_buffer, 0, sim_params[0..]); - - const command_encoder = core.device.createCommandEncoder(null); - { - const pass_encoder = command_encoder.beginComputePass(null); - pass_encoder.setPipeline(app.compute_pipeline); - pass_encoder.setBindGroup(0, app.particle_bind_groups[app.frame_counter % 2], null); - pass_encoder.dispatchWorkgroups(@as(u32, @intFromFloat(@ceil(@as(f32, num_particle) / 64))), 1, 1); - pass_encoder.end(); - pass_encoder.release(); - } - { - const pass_encoder = command_encoder.beginRenderPass(&render_pass_descriptor); - pass_encoder.setPipeline(app.render_pipeline); - pass_encoder.setVertexBuffer(0, app.particle_buffers[(app.frame_counter + 1) % 2], 0, num_particle * 4 * @sizeOf(f32)); - pass_encoder.setVertexBuffer(1, app.sprite_vertex_buffer, 0, 6 * @sizeOf(f32)); - pass_encoder.draw(3, num_particle, 0, 0); - pass_encoder.end(); - pass_encoder.release(); - } - - app.frame_counter += 1; - if (app.frame_counter % 60 == 0) { - std.log.info("Frame {}", .{app.frame_counter}); - } - - var command = command_encoder.finish(null); - command_encoder.release(); - core.queue.submit(&[_]*gpu.CommandBuffer{command}); - command.release(); - - core.swap_chain.present(); - back_buffer_view.release(); - - // update the window title every second - if (app.title_timer.read() >= 1.0) { - app.title_timer.reset(); - try core.printTitle("Boids [ {d}fps ] [ Input {d}hz ]", .{ - core.frameRate(), - core.inputRate(), - }); - } - - return false; -} diff --git a/src/core/examples/boids/sprite.wgsl b/src/core/examples/boids/sprite.wgsl deleted file mode 100644 index c97c5c18..00000000 --- a/src/core/examples/boids/sprite.wgsl +++ /dev/null @@ -1,15 +0,0 @@ -@vertex -fn vert_main(@location(0) a_particlePos : vec2, - @location(1) a_particleVel : vec2, - @location(2) a_pos : vec2) -> @builtin(position) vec4 { - let angle = -atan2(a_particleVel.x, a_particleVel.y); - let pos = vec2( - (a_pos.x * cos(angle)) - (a_pos.y * sin(angle)), - (a_pos.x * sin(angle)) + (a_pos.y * cos(angle))); - return vec4(pos + a_particlePos, 0.0, 1.0); -} - -@fragment -fn frag_main() -> @location(0) vec4 { - return vec4(1.0, 1.0, 1.0, 1.0); -} diff --git a/src/core/examples/boids/updateSprites.wgsl b/src/core/examples/boids/updateSprites.wgsl deleted file mode 100644 index 89071499..00000000 --- a/src/core/examples/boids/updateSprites.wgsl +++ /dev/null @@ -1,90 +0,0 @@ -struct Particle { - pos : vec2, - vel : vec2, -}; -struct SimParams { - deltaT : f32, - rule1Distance : f32, - rule2Distance : f32, - rule3Distance : f32, - rule1Scale : f32, - rule2Scale : f32, - rule3Scale : f32, -}; -struct Particles { - particles : array, -}; -@binding(0) @group(0) var params : SimParams; -@binding(1) @group(0) var particlesA : Particles; -@binding(2) @group(0) var particlesB : Particles; - -// https://github.com/austinEng/Project6-Vulkan-Flocking/blob/master/data/shaders/computeparticles/particle.comp -@compute @workgroup_size(64) -fn main(@builtin(global_invocation_id) GlobalInvocationID : vec3) { - var index : u32 = GlobalInvocationID.x; - - if (index >= arrayLength(&particlesA.particles)) { - return; - } - - var vPos = particlesA.particles[index].pos; - var vVel = particlesA.particles[index].vel; - var cMass = vec2(0.0, 0.0); - var cVel = vec2(0.0, 0.0); - var colVel = vec2(0.0, 0.0); - var cMassCount : u32 = 0u; - var cVelCount : u32 = 0u; - var pos : vec2; - var vel : vec2; - - for (var i : u32 = 0u; i < arrayLength(&particlesA.particles); i = i + 1u) { - if (i == index) { - continue; - } - - pos = particlesA.particles[i].pos.xy; - vel = particlesA.particles[i].vel.xy; - if (distance(pos, vPos) < params.rule1Distance) { - cMass = cMass + pos; - cMassCount = cMassCount + 1u; - } - if (distance(pos, vPos) < params.rule2Distance) { - colVel = colVel - (pos - vPos); - } - if (distance(pos, vPos) < params.rule3Distance) { - cVel = cVel + vel; - cVelCount = cVelCount + 1u; - } - } - if (cMassCount > 0u) { - var temp = f32(cMassCount); - cMass = (cMass / vec2(temp, temp)) - vPos; - } - if (cVelCount > 0u) { - var temp = f32(cVelCount); - cVel = cVel / vec2(temp, temp); - } - vVel = vVel + (cMass * params.rule1Scale) + (colVel * params.rule2Scale) + - (cVel * params.rule3Scale); - - // clamp velocity for a more pleasing simulation - vVel = normalize(vVel) * clamp(length(vVel), 0.0, 0.1); - // kinematic update - vPos = vPos + (vVel * params.deltaT); - // Wrap around boundary - if (vPos.x < -1.0) { - vPos.x = 1.0; - } - if (vPos.x > 1.0) { - vPos.x = -1.0; - } - if (vPos.y < -1.0) { - vPos.y = 1.0; - } - if (vPos.y > 1.0) { - vPos.y = -1.0; - } - // Write back - particlesB.particles[index].pos = vPos; - particlesB.particles[index].vel = vVel; -} diff --git a/src/core/examples/clear-color/main.zig b/src/core/examples/clear-color/main.zig deleted file mode 100644 index 9f2f183c..00000000 --- a/src/core/examples/clear-color/main.zig +++ /dev/null @@ -1,81 +0,0 @@ -const std = @import("std"); - -const mach = @import("mach"); -const core = mach.core; -const gpu = mach.gpu; - -const renderer = @import("renderer.zig"); - -pub const App = @This(); - -var gpa = std.heap.GeneralPurposeAllocator(.{}){}; - -title_timer: core.Timer, - -pub fn init(app: *App) !void { - try core.init(.{}); - app.* = .{ - .title_timer = try core.Timer.start(), - }; -} - -pub fn deinit(app: *App) void { - _ = app; - defer _ = gpa.deinit(); - defer core.deinit(); -} - -pub fn update(app: *App) !bool { - var iter = core.pollEvents(); - while (iter.next()) |event| { - switch (event) { - .key_press => |ev| { - if (ev.key == .space) return true; - }, - .close => return true, - else => {}, - } - } - - app.render(); - - // update the window title every second - if (app.title_timer.read() >= 1.0) { - app.title_timer.reset(); - try core.printTitle("Clear Color [ {d}fps ] [ Input {d}hz ]", .{ - core.frameRate(), - core.inputRate(), - }); - } - - return false; -} - -fn render(app: *App) void { - _ = app; - const back_buffer_view = core.swap_chain.getCurrentTextureView().?; - const color_attachment = gpu.RenderPassColorAttachment{ - .view = back_buffer_view, - .clear_value = gpu.Color{ .r = 0.0, .g = 0.0, .b = 1.0, .a = 1.0 }, - .load_op = .clear, - .store_op = .store, - }; - - const encoder = core.device.createCommandEncoder(null); - const render_pass_info = gpu.RenderPassDescriptor.init(.{ - .color_attachments = &.{color_attachment}, - }); - - const pass = encoder.beginRenderPass(&render_pass_info); - pass.end(); - pass.release(); - - var command = encoder.finish(null); - encoder.release(); - - var queue = core.queue; - queue.submit(&[_]*gpu.CommandBuffer{command}); - command.release(); - core.swap_chain.present(); - back_buffer_view.release(); -} diff --git a/src/core/examples/clear-color/renderer.zig b/src/core/examples/clear-color/renderer.zig deleted file mode 100644 index 51c84b69..00000000 --- a/src/core/examples/clear-color/renderer.zig +++ /dev/null @@ -1,33 +0,0 @@ -const mach = @import("mach"); -const core = mach.core; -const gpu = mach.gpu; - -pub const Renderer = @This(); - -pub fn RenderUpdate() void { - const back_buffer_view = core.swap_chain.getCurrentTextureView().?; - const color_attachment = gpu.RenderPassColorAttachment{ - .view = back_buffer_view, - .clear_value = gpu.Color{ .r = 0.0, .g = 0.0, .b = 1.0, .a = 1.0 }, - .load_op = .clear, - .store_op = .store, - }; - - const encoder = core.device.createCommandEncoder(null); - const render_pass_info = gpu.RenderPassDescriptor.init(.{ - .color_attachments = &.{color_attachment}, - }); - - const pass = encoder.beginRenderPass(&render_pass_info); - pass.end(); - pass.release(); - - var command = encoder.finish(null); - encoder.release(); - - const queue = core.queue; - queue.submit(&[_]*gpu.CommandBuffer{command}); - command.release(); - core.swap_chain.present(); - back_buffer_view.release(); -} diff --git a/src/core/examples/cubemap/cube_mesh.zig b/src/core/examples/cubemap/cube_mesh.zig deleted file mode 100644 index ae5b2912..00000000 --- a/src/core/examples/cubemap/cube_mesh.zig +++ /dev/null @@ -1,49 +0,0 @@ -pub const Vertex = extern struct { - pos: @Vector(4, f32), - col: @Vector(4, f32), - uv: @Vector(2, f32), -}; - -pub const vertices = [_]Vertex{ - .{ .pos = .{ 1, -1, 1, 1 }, .col = .{ 1, 0, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, -1, -1, 1 }, .col = .{ 0, 0, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, -1, 1, 1 }, .col = .{ 1, 0, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, -1, -1, 1 }, .col = .{ 0, 0, 0, 1 }, .uv = .{ 1, 0 } }, - - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ 1, -1, 1, 1 }, .col = .{ 1, 0, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, 1, -1, 1 }, .col = .{ 1, 1, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 1, 0 } }, - - .{ .pos = .{ -1, 1, 1, 1 }, .col = .{ 0, 1, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ 1, 1, -1, 1 }, .col = .{ 1, 1, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ -1, 1, 1, 1 }, .col = .{ 0, 1, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ 1, 1, -1, 1 }, .col = .{ 1, 1, 0, 1 }, .uv = .{ 1, 0 } }, - - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, 1, 1, 1 }, .col = .{ 0, 1, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ -1, -1, -1, 1 }, .col = .{ 0, 0, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 1, 0 } }, - - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, 1, 1, 1 }, .col = .{ 0, 1, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, -1, 1, 1 }, .col = .{ 1, 0, 1, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 0, 1 } }, - - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, -1, -1, 1 }, .col = .{ 0, 0, 0, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, 1, -1, 1 }, .col = .{ 1, 1, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 1, 0 } }, -}; diff --git a/src/core/examples/cubemap/main.zig b/src/core/examples/cubemap/main.zig deleted file mode 100644 index 7444cbcd..00000000 --- a/src/core/examples/cubemap/main.zig +++ /dev/null @@ -1,395 +0,0 @@ -const std = @import("std"); - -const mach = @import("mach"); -const core = mach.core; -const gpu = mach.gpu; - -const zm = @import("zmath"); -const zigimg = @import("zigimg"); -const Vertex = @import("cube_mesh.zig").Vertex; -const vertices = @import("cube_mesh.zig").vertices; -const assets = @import("assets"); - -const UniformBufferObject = struct { - mat: zm.Mat, -}; - -var gpa = std.heap.GeneralPurposeAllocator(.{}){}; - -title_timer: core.Timer, -timer: core.Timer, -pipeline: *gpu.RenderPipeline, -vertex_buffer: *gpu.Buffer, -uniform_buffer: *gpu.Buffer, -bind_group: *gpu.BindGroup, -depth_texture: *gpu.Texture, -depth_texture_view: *gpu.TextureView, - -pub const App = @This(); - -pub fn init(app: *App) !void { - try core.init(.{}); - - const allocator = gpa.allocator(); - - const shader_module = core.device.createShaderModuleWGSL("shader.wgsl", @embedFile("shader.wgsl")); - defer shader_module.release(); - - const vertex_attributes = [_]gpu.VertexAttribute{ - .{ .format = .float32x4, .offset = @offsetOf(Vertex, "pos"), .shader_location = 0 }, - .{ .format = .float32x2, .offset = @offsetOf(Vertex, "uv"), .shader_location = 1 }, - }; - - const vertex_buffer_layout = gpu.VertexBufferLayout.init(.{ - .array_stride = @sizeOf(Vertex), - .step_mode = .vertex, - .attributes = &vertex_attributes, - }); - - const blend = gpu.BlendState{ - .color = .{ - .operation = .add, - .src_factor = .src_alpha, - .dst_factor = .one_minus_src_alpha, - }, - .alpha = .{ - .operation = .add, - .src_factor = .one, - .dst_factor = .zero, - }, - }; - const color_target = gpu.ColorTargetState{ - .format = core.descriptor.format, - .blend = &blend, - .write_mask = gpu.ColorWriteMaskFlags.all, - }; - const fragment = gpu.FragmentState.init(.{ - .module = shader_module, - .entry_point = "frag_main", - .targets = &.{color_target}, - }); - - const pipeline_descriptor = gpu.RenderPipeline.Descriptor{ - .fragment = &fragment, - // Enable depth testing so that the fragment closest to the camera - // is rendered in front. - .depth_stencil = &.{ - .format = .depth24_plus, - .depth_write_enabled = .true, - .depth_compare = .less, - }, - .vertex = gpu.VertexState.init(.{ - .module = shader_module, - .entry_point = "vertex_main", - .buffers = &.{vertex_buffer_layout}, - }), - .primitive = .{ - // Since the cube has its face pointing outwards, cull_mode must be - // set to .front or .none here since we are inside the cube looking out. - // Ideally you would set this to .back and have a custom cube primitive - // with the faces pointing towards the inside of the cube. - .cull_mode = .none, - }, - }; - const pipeline = core.device.createRenderPipeline(&pipeline_descriptor); - - const vertex_buffer = core.device.createBuffer(&.{ - .usage = .{ .vertex = true }, - .size = @sizeOf(Vertex) * vertices.len, - .mapped_at_creation = .true, - }); - const vertex_mapped = vertex_buffer.getMappedRange(Vertex, 0, vertices.len); - @memcpy(vertex_mapped.?, vertices[0..]); - vertex_buffer.unmap(); - - const uniform_buffer = core.device.createBuffer(&.{ - .usage = .{ .copy_dst = true, .uniform = true }, - .size = @sizeOf(UniformBufferObject), - .mapped_at_creation = .false, - }); - - // Create a sampler with linear filtering for smooth interpolation. - const sampler = core.device.createSampler(&.{ - .mag_filter = .linear, - .min_filter = .linear, - }); - - const queue = core.queue; - - // WebGPU expects the cubemap textures in this order: (+X,-X,+Y,-Y,+Z,-Z) - var images: [6]zigimg.Image = undefined; - images[0] = try zigimg.Image.fromMemory(allocator, assets.skybox_posx_png); - defer images[0].deinit(); - images[1] = try zigimg.Image.fromMemory(allocator, assets.skybox_negx_png); - defer images[1].deinit(); - images[2] = try zigimg.Image.fromMemory(allocator, assets.skybox_posy_png); - defer images[2].deinit(); - images[3] = try zigimg.Image.fromMemory(allocator, assets.skybox_negy_png); - defer images[3].deinit(); - images[4] = try zigimg.Image.fromMemory(allocator, assets.skybox_posz_png); - defer images[4].deinit(); - images[5] = try zigimg.Image.fromMemory(allocator, assets.skybox_negz_png); - defer images[5].deinit(); - - // Use the first image of the set for sizing - const img_size = gpu.Extent3D{ - .width = @as(u32, @intCast(images[0].width)), - .height = @as(u32, @intCast(images[0].height)), - }; - - // We set depth_or_array_layers to 6 here to indicate there are 6 images in this texture - const tex_size = gpu.Extent3D{ - .width = @as(u32, @intCast(images[0].width)), - .height = @as(u32, @intCast(images[0].height)), - .depth_or_array_layers = 6, - }; - - // Same as a regular texture, but with a Z of 6 (defined in tex_size) - const cube_texture = core.device.createTexture(&.{ - .size = tex_size, - .format = .rgba8_unorm, - .dimension = .dimension_2d, - .usage = .{ - .texture_binding = true, - .copy_dst = true, - .render_attachment = false, - }, - }); - - const data_layout = gpu.Texture.DataLayout{ - .bytes_per_row = @as(u32, @intCast(images[0].width * 4)), - .rows_per_image = @as(u32, @intCast(images[0].height)), - }; - - const encoder = core.device.createCommandEncoder(null); - - // We have to create a staging buffer, copy all the image data into the - // staging buffer at the correct Z offset, encode a command to copy - // the buffer to the texture for each image, then push it to the command - // queue - var staging_buff: [6]*gpu.Buffer = undefined; - var i: u32 = 0; - while (i < 6) : (i += 1) { - staging_buff[i] = core.device.createBuffer(&.{ - .usage = .{ .copy_src = true, .map_write = true }, - .size = @as(u64, @intCast(images[0].width)) * @as(u64, @intCast(images[0].height)) * @sizeOf(u32), - .mapped_at_creation = .true, - }); - switch (images[i].pixels) { - .rgba32 => |pixels| { - // Map a section of the staging buffer - const staging_map = staging_buff[i].getMappedRange(u32, 0, @as(u64, @intCast(images[i].width)) * @as(u64, @intCast(images[i].height))); - // Copy the image data into the mapped buffer - @memcpy(staging_map.?, @as([]u32, @ptrCast(@alignCast(pixels)))); - // And release the mapping - staging_buff[i].unmap(); - }, - .rgb24 => |pixels| { - const staging_map = staging_buff[i].getMappedRange(u32, 0, @as(u64, @intCast(images[i].width)) * @as(u64, @intCast(images[i].height))); - // In this case, we have to convert the data to rgba32 first - const data = try rgb24ToRgba32(allocator, pixels); - defer data.deinit(allocator); - @memcpy(staging_map.?, @as([]u32, @ptrCast(@alignCast(data.rgba32)))); - staging_buff[i].unmap(); - }, - else => @panic("unsupported image color format"), - } - - // These define the source and target for the buffer to texture copy command - const copy_buff = gpu.ImageCopyBuffer{ - .layout = data_layout, - .buffer = staging_buff[i], - }; - const copy_tex = gpu.ImageCopyTexture{ - .texture = cube_texture, - .origin = gpu.Origin3D{ .x = 0, .y = 0, .z = i }, - }; - - // Encode the copy command, we do this for every image in the texture. - encoder.copyBufferToTexture(©_buff, ©_tex, &img_size); - staging_buff[i].release(); - } - // Now that the commands to copy our buffer data to the texture is filled, - // push the encoded commands over to the queue and execute to get the - // texture filled with the image data. - var command = encoder.finish(null); - encoder.release(); - queue.submit(&[_]*gpu.CommandBuffer{command}); - command.release(); - - // The textureView in the bind group needs dimension defined as "dimension_cube". - const cube_texture_view = cube_texture.createView(&gpu.TextureView.Descriptor{ .dimension = .dimension_cube }); - cube_texture.release(); - - const bind_group_layout = pipeline.getBindGroupLayout(0); - const bind_group = core.device.createBindGroup( - &gpu.BindGroup.Descriptor.init(.{ - .layout = bind_group_layout, - .entries = &.{ - gpu.BindGroup.Entry.buffer(0, uniform_buffer, 0, @sizeOf(UniformBufferObject)), - gpu.BindGroup.Entry.sampler(1, sampler), - gpu.BindGroup.Entry.textureView(2, cube_texture_view), - }, - }), - ); - sampler.release(); - cube_texture_view.release(); - bind_group_layout.release(); - - const depth_texture = core.device.createTexture(&gpu.Texture.Descriptor{ - .size = gpu.Extent3D{ - .width = core.descriptor.width, - .height = core.descriptor.height, - }, - .format = .depth24_plus, - .usage = .{ - .render_attachment = true, - .texture_binding = true, - }, - }); - - const depth_texture_view = depth_texture.createView(&gpu.TextureView.Descriptor{ - .format = .depth24_plus, - .dimension = .dimension_2d, - .array_layer_count = 1, - .mip_level_count = 1, - }); - - app.timer = try core.Timer.start(); - app.title_timer = try core.Timer.start(); - app.pipeline = pipeline; - app.vertex_buffer = vertex_buffer; - app.uniform_buffer = uniform_buffer; - app.bind_group = bind_group; - app.depth_texture = depth_texture; - app.depth_texture_view = depth_texture_view; -} - -pub fn deinit(app: *App) void { - defer _ = gpa.deinit(); - defer core.deinit(); - - app.pipeline.release(); - app.vertex_buffer.release(); - app.uniform_buffer.release(); - app.bind_group.release(); - app.depth_texture.release(); - app.depth_texture_view.release(); -} - -pub fn update(app: *App) !bool { - var iter = core.pollEvents(); - while (iter.next()) |event| { - switch (event) { - .key_press => |ev| { - if (ev.key == .space) return true; - }, - .close => return true, - .framebuffer_resize => |ev| { - // If window is resized, recreate depth buffer otherwise we cannot use it. - app.depth_texture.release(); - app.depth_texture = core.device.createTexture(&gpu.Texture.Descriptor{ - .size = gpu.Extent3D{ - .width = ev.width, - .height = ev.height, - }, - .format = .depth24_plus, - .usage = .{ - .render_attachment = true, - .texture_binding = true, - }, - }); - app.depth_texture_view.release(); - app.depth_texture_view = app.depth_texture.createView(&gpu.TextureView.Descriptor{ - .format = .depth24_plus, - .dimension = .dimension_2d, - .array_layer_count = 1, - .mip_level_count = 1, - }); - }, - else => {}, - } - } - - const back_buffer_view = core.swap_chain.getCurrentTextureView().?; - const color_attachment = gpu.RenderPassColorAttachment{ - .view = back_buffer_view, - .clear_value = .{ .r = 0.5, .g = 0.5, .b = 0.5, .a = 0.0 }, - .load_op = .clear, - .store_op = .store, - }; - - const encoder = core.device.createCommandEncoder(null); - const render_pass_info = gpu.RenderPassDescriptor.init(.{ - .color_attachments = &.{color_attachment}, - .depth_stencil_attachment = &.{ - .view = app.depth_texture_view, - .depth_clear_value = 1.0, - .depth_load_op = .clear, - .depth_store_op = .store, - }, - }); - - { - const time = app.timer.read(); - const aspect = @as(f32, @floatFromInt(core.descriptor.width)) / @as(f32, @floatFromInt(core.descriptor.height)); - const proj = zm.perspectiveFovRh((2 * std.math.pi) / 5.0, aspect, 0.1, 3000); - const model = zm.mul( - zm.scaling(1000, 1000, 1000), - zm.rotationX(std.math.pi / 2.0 * 3.0), - ); - const view = zm.mul( - zm.mul( - zm.lookAtRh( - zm.Vec{ 0, 0, 0, 1 }, - zm.Vec{ 1, 0, 0, 1 }, - zm.Vec{ 0, 0, 1, 0 }, - ), - zm.rotationY(time * 0.2), - ), - zm.rotationX((std.math.pi / 10.0) * std.math.sin(time)), - ); - - const mvp = zm.mul(zm.mul(zm.transpose(model), view), proj); - const ubo = UniformBufferObject{ .mat = mvp }; - - encoder.writeBuffer(app.uniform_buffer, 0, &[_]UniformBufferObject{ubo}); - } - - const pass = encoder.beginRenderPass(&render_pass_info); - pass.setPipeline(app.pipeline); - pass.setVertexBuffer(0, app.vertex_buffer, 0, @sizeOf(Vertex) * vertices.len); - pass.setBindGroup(0, app.bind_group, &.{}); - pass.draw(vertices.len, 1, 0, 0); - pass.end(); - pass.release(); - - var command = encoder.finish(null); - encoder.release(); - - const queue = core.queue; - queue.submit(&[_]*gpu.CommandBuffer{command}); - command.release(); - core.swap_chain.present(); - back_buffer_view.release(); - - // update the window title every second - if (app.title_timer.read() >= 1.0) { - app.title_timer.reset(); - try core.printTitle("Cube Map [ {d}fps ] [ Input {d}hz ]", .{ - core.frameRate(), - core.inputRate(), - }); - } - - return false; -} - -fn rgb24ToRgba32(allocator: std.mem.Allocator, in: []zigimg.color.Rgb24) !zigimg.color.PixelStorage { - const out = try zigimg.color.PixelStorage.init(allocator, .rgba32, in.len); - var i: usize = 0; - while (i < in.len) : (i += 1) { - out.rgba32[i] = zigimg.color.Rgba32{ .r = in[i].r, .g = in[i].g, .b = in[i].b, .a = 255 }; - } - return out; -} diff --git a/src/core/examples/cubemap/shader.wgsl b/src/core/examples/cubemap/shader.wgsl deleted file mode 100644 index 1442990c..00000000 --- a/src/core/examples/cubemap/shader.wgsl +++ /dev/null @@ -1,34 +0,0 @@ -struct Uniforms { - modelViewProjectionMatrix : mat4x4, -} -@binding(0) @group(0) var uniforms : Uniforms; - -struct VertexOutput { - @builtin(position) Position : vec4, - @location(0) fragUV : vec2, - @location(1) fragPosition: vec4, -} - -@vertex -fn vertex_main( - @location(0) position : vec4, - @location(1) uv : vec2 -) -> VertexOutput { - var output : VertexOutput; - output.Position = uniforms.modelViewProjectionMatrix * position; - output.fragUV = uv; - output.fragPosition = 0.5 * (position + vec4(1.0, 1.0, 1.0, 1.0)); - return output; -} - -@group(0) @binding(1) var mySampler: sampler; -@group(0) @binding(2) var myTexture: texture_cube; - -@fragment -fn frag_main( - @location(0) fragUV: vec2, - @location(1) fragPosition: vec4 -) -> @location(0) vec4 { - var cubemapVec = fragPosition.xyz - vec3(0.5, 0.5, 0.5); - return textureSample(myTexture, mySampler, cubemapVec); -} diff --git a/src/core/examples/fractal-cube/cube_mesh.zig b/src/core/examples/fractal-cube/cube_mesh.zig deleted file mode 100644 index f26c75ac..00000000 --- a/src/core/examples/fractal-cube/cube_mesh.zig +++ /dev/null @@ -1,49 +0,0 @@ -pub const Vertex = extern struct { - pos: @Vector(4, f32), - col: @Vector(4, f32), - uv: @Vector(2, f32), -}; - -pub const vertices = [_]Vertex{ - .{ .pos = .{ 1, -1, 1, 1 }, .col = .{ 1, 0, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, -1, -1, 1 }, .col = .{ 0, 0, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, -1, 1, 1 }, .col = .{ 1, 0, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, -1, -1, 1 }, .col = .{ 0, 0, 0, 1 }, .uv = .{ 0, 0 } }, - - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ 1, -1, 1, 1 }, .col = .{ 1, 0, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, 1, -1, 1 }, .col = .{ 1, 1, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 0, 0 } }, - - .{ .pos = .{ -1, 1, 1, 1 }, .col = .{ 0, 1, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ 1, 1, -1, 1 }, .col = .{ 1, 1, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ -1, 1, 1, 1 }, .col = .{ 0, 1, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ 1, 1, -1, 1 }, .col = .{ 1, 1, 0, 1 }, .uv = .{ 0, 0 } }, - - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, 1, 1, 1 }, .col = .{ 0, 1, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ -1, -1, -1, 1 }, .col = .{ 0, 0, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 0, 0 } }, - - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, 1, 1, 1 }, .col = .{ 0, 1, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, -1, 1, 1 }, .col = .{ 1, 0, 1, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 1, 1 } }, - - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, -1, -1, 1 }, .col = .{ 0, 0, 0, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, 1, -1, 1 }, .col = .{ 1, 1, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 0, 0 } }, -}; diff --git a/src/core/examples/fractal-cube/main.zig b/src/core/examples/fractal-cube/main.zig deleted file mode 100755 index fe5eb6c2..00000000 --- a/src/core/examples/fractal-cube/main.zig +++ /dev/null @@ -1,374 +0,0 @@ -//! To get the effect we want, we need a texture on which to render; -//! we can't use the swapchain texture directly, but we can get the effect -//! by doing the same render pass twice, on the texture and the swapchain. -//! We also need a second texture to use on the cube (after the render pass -//! it needs to copy the other texture.) We can't use the same texture since -//! it would interfere with the synchronization on the gpu during the render pass. -//! This demo currently does not work on opengl, because core.descriptor.width/height, -//! are set to 0 after core.init() and because webgpu does not implement copyTextureToTexture, -//! for opengl - -const std = @import("std"); - -const mach = @import("mach"); -const core = mach.core; -const gpu = mach.gpu; - -const zm = @import("zmath"); -const Vertex = @import("cube_mesh.zig").Vertex; -const vertices = @import("cube_mesh.zig").vertices; - -pub const App = @This(); - -const UniformBufferObject = struct { - mat: zm.Mat, -}; - -var gpa = std.heap.GeneralPurposeAllocator(.{}){}; - -title_timer: core.Timer, -timer: core.Timer, -pipeline: *gpu.RenderPipeline, -vertex_buffer: *gpu.Buffer, -uniform_buffer: *gpu.Buffer, -bind_group: *gpu.BindGroup, -depth_texture: ?*gpu.Texture, -depth_texture_view: *gpu.TextureView, -cube_texture: *gpu.Texture, -cube_texture_view: *gpu.TextureView, -cube_texture_render: *gpu.Texture, -cube_texture_view_render: *gpu.TextureView, -sampler: *gpu.Sampler, -bgl: *gpu.BindGroupLayout, - -pub fn init(app: *App) !void { - try core.init(.{}); - - const shader_module = core.device.createShaderModuleWGSL("shader.wgsl", @embedFile("shader.wgsl")); - - const vertex_attributes = [_]gpu.VertexAttribute{ - .{ .format = .float32x4, .offset = @offsetOf(Vertex, "pos"), .shader_location = 0 }, - .{ .format = .float32x2, .offset = @offsetOf(Vertex, "uv"), .shader_location = 1 }, - }; - const vertex_buffer_layout = gpu.VertexBufferLayout.init(.{ - .array_stride = @sizeOf(Vertex), - .attributes = &vertex_attributes, - }); - - const blend = gpu.BlendState{}; - const color_target = gpu.ColorTargetState{ - .format = core.descriptor.format, - .blend = &blend, - .write_mask = gpu.ColorWriteMaskFlags.all, - }; - const fragment = gpu.FragmentState.init(.{ - .module = shader_module, - .entry_point = "frag_main", - .targets = &.{color_target}, - }); - - const bgle_buffer = gpu.BindGroupLayout.Entry.buffer(0, .{ .vertex = true }, .uniform, true, 0); - const bgle_sampler = gpu.BindGroupLayout.Entry.sampler(1, .{ .fragment = true }, .filtering); - const bgle_textureview = gpu.BindGroupLayout.Entry.texture(2, .{ .fragment = true }, .float, .dimension_2d, false); - const bgl = core.device.createBindGroupLayout( - &gpu.BindGroupLayout.Descriptor.init(.{ - .entries = &.{ bgle_buffer, bgle_sampler, bgle_textureview }, - }), - ); - - const bind_group_layouts = [_]*gpu.BindGroupLayout{bgl}; - const pipeline_layout = core.device.createPipelineLayout(&gpu.PipelineLayout.Descriptor.init(.{ - .bind_group_layouts = &bind_group_layouts, - })); - - const pipeline_descriptor = gpu.RenderPipeline.Descriptor{ - .fragment = &fragment, - .layout = pipeline_layout, - .depth_stencil = &.{ - .format = .depth24_plus, - .depth_write_enabled = .true, - .depth_compare = .less, - }, - .vertex = gpu.VertexState.init(.{ - .module = shader_module, - .entry_point = "vertex_main", - .buffers = &.{vertex_buffer_layout}, - }), - .primitive = .{ - .cull_mode = .back, - }, - }; - - const vertex_buffer = core.device.createBuffer(&.{ - .usage = .{ .vertex = true }, - .size = @sizeOf(Vertex) * vertices.len, - .mapped_at_creation = .true, - }); - const vertex_mapped = vertex_buffer.getMappedRange(Vertex, 0, vertices.len); - @memcpy(vertex_mapped.?, vertices[0..]); - vertex_buffer.unmap(); - - const uniform_buffer = core.device.createBuffer(&.{ - .usage = .{ .copy_dst = true, .uniform = true }, - .size = @sizeOf(UniformBufferObject), - .mapped_at_creation = .false, - }); - - // The texture to put on the cube - const cube_texture = core.device.createTexture(&gpu.Texture.Descriptor{ - .usage = .{ .texture_binding = true, .copy_dst = true }, - .size = .{ .width = core.descriptor.width, .height = core.descriptor.height }, - .format = core.descriptor.format, - }); - // The texture on which we render - const cube_texture_render = core.device.createTexture(&gpu.Texture.Descriptor{ - .usage = .{ .render_attachment = true, .copy_src = true }, - .size = .{ .width = core.descriptor.width, .height = core.descriptor.height }, - .format = core.descriptor.format, - }); - - const sampler = core.device.createSampler(&gpu.Sampler.Descriptor{ - .mag_filter = .linear, - .min_filter = .linear, - }); - - const cube_texture_view = cube_texture.createView(&gpu.TextureView.Descriptor{ - .format = core.descriptor.format, - .dimension = .dimension_2d, - .mip_level_count = 1, - .array_layer_count = 1, - }); - const cube_texture_view_render = cube_texture_render.createView(&gpu.TextureView.Descriptor{ - .format = core.descriptor.format, - .dimension = .dimension_2d, - .mip_level_count = 1, - .array_layer_count = 1, - }); - - const bind_group = core.device.createBindGroup( - &gpu.BindGroup.Descriptor.init(.{ - .layout = bgl, - .entries = &.{ - gpu.BindGroup.Entry.buffer(0, uniform_buffer, 0, @sizeOf(UniformBufferObject)), - gpu.BindGroup.Entry.sampler(1, sampler), - gpu.BindGroup.Entry.textureView(2, cube_texture_view), - }, - }), - ); - - const depth_texture = core.device.createTexture(&gpu.Texture.Descriptor{ - .usage = .{ .render_attachment = true }, - .size = .{ .width = core.descriptor.width, .height = core.descriptor.height }, - .format = .depth24_plus, - }); - const depth_texture_view = depth_texture.createView(&gpu.TextureView.Descriptor{ - .format = .depth24_plus, - .dimension = .dimension_2d, - .array_layer_count = 1, - .mip_level_count = 1, - }); - - app.timer = try core.Timer.start(); - app.title_timer = try core.Timer.start(); - app.pipeline = core.device.createRenderPipeline(&pipeline_descriptor); - app.vertex_buffer = vertex_buffer; - app.uniform_buffer = uniform_buffer; - app.bind_group = bind_group; - app.depth_texture = depth_texture; - app.depth_texture_view = depth_texture_view; - app.cube_texture = cube_texture; - app.cube_texture_view = cube_texture_view; - app.cube_texture_render = cube_texture_render; - app.cube_texture_view_render = cube_texture_view_render; - app.sampler = sampler; - app.bgl = bgl; - - shader_module.release(); - pipeline_layout.release(); -} - -pub fn deinit(app: *App) void { - defer _ = gpa.deinit(); - defer core.deinit(); - - app.pipeline.release(); - app.bgl.release(); - app.vertex_buffer.release(); - app.uniform_buffer.release(); - app.cube_texture.release(); - app.cube_texture_render.release(); - app.sampler.release(); - app.cube_texture_view.release(); - app.cube_texture_view_render.release(); - app.bind_group.release(); - app.depth_texture.?.release(); - app.depth_texture_view.release(); -} - -pub fn update(app: *App) !bool { - var iter = core.pollEvents(); - while (iter.next()) |event| { - switch (event) { - .key_press => |ev| { - if (ev.key == .space) return true; - }, - .close => return true, - .framebuffer_resize => |ev| { - app.depth_texture.?.release(); - app.depth_texture = core.device.createTexture(&gpu.Texture.Descriptor{ - .usage = .{ .render_attachment = true }, - .size = .{ .width = ev.width, .height = ev.height }, - .format = .depth24_plus, - }); - - app.cube_texture.release(); - app.cube_texture = core.device.createTexture(&gpu.Texture.Descriptor{ - .usage = .{ .texture_binding = true, .copy_dst = true }, - .size = .{ .width = ev.width, .height = ev.height }, - .format = core.descriptor.format, - }); - app.cube_texture_render.release(); - app.cube_texture_render = core.device.createTexture(&gpu.Texture.Descriptor{ - .usage = .{ .render_attachment = true, .copy_src = true }, - .size = .{ .width = ev.width, .height = ev.height }, - .format = core.descriptor.format, - }); - - app.depth_texture_view.release(); - app.depth_texture_view = app.depth_texture.?.createView(&gpu.TextureView.Descriptor{ - .format = .depth24_plus, - .dimension = .dimension_2d, - .array_layer_count = 1, - .mip_level_count = 1, - }); - - app.cube_texture_view.release(); - app.cube_texture_view = app.cube_texture.createView(&gpu.TextureView.Descriptor{ - .format = core.descriptor.format, - .dimension = .dimension_2d, - .mip_level_count = 1, - .array_layer_count = 1, - }); - app.cube_texture_view_render.release(); - app.cube_texture_view_render = app.cube_texture_render.createView(&gpu.TextureView.Descriptor{ - .format = core.descriptor.format, - .dimension = .dimension_2d, - .mip_level_count = 1, - .array_layer_count = 1, - }); - - app.bind_group.release(); - app.bind_group = core.device.createBindGroup( - &gpu.BindGroup.Descriptor.init(.{ - .layout = app.bgl, - .entries = &.{ - gpu.BindGroup.Entry.buffer(0, app.uniform_buffer, 0, @sizeOf(UniformBufferObject)), - gpu.BindGroup.Entry.sampler(1, app.sampler), - gpu.BindGroup.Entry.textureView(2, app.cube_texture_view), - }, - }), - ); - }, - else => {}, - } - } - - const cube_view = app.cube_texture_view_render; - const back_buffer_view = core.swap_chain.getCurrentTextureView().?; - - const cube_color_attachment = gpu.RenderPassColorAttachment{ - .view = cube_view, - .clear_value = gpu.Color{ .r = 0.5, .g = 0.5, .b = 0.5, .a = 1 }, - .load_op = .clear, - .store_op = .store, - }; - const color_attachment = gpu.RenderPassColorAttachment{ - .view = back_buffer_view, - .clear_value = gpu.Color{ .r = 0.5, .g = 0.5, .b = 0.5, .a = 1 }, - .load_op = .clear, - .store_op = .store, - }; - - const depth_stencil_attachment = gpu.RenderPassDepthStencilAttachment{ - .view = app.depth_texture_view, - .depth_load_op = .clear, - .depth_store_op = .store, - .depth_clear_value = 1.0, - }; - - const encoder = core.device.createCommandEncoder(null); - const cube_render_pass_info = gpu.RenderPassDescriptor.init(.{ - .color_attachments = &.{cube_color_attachment}, - .depth_stencil_attachment = &depth_stencil_attachment, - }); - const render_pass_info = gpu.RenderPassDescriptor.init(.{ - .color_attachments = &.{color_attachment}, - .depth_stencil_attachment = &depth_stencil_attachment, - }); - - { - const time = app.timer.read(); - const model = zm.mul(zm.rotationX(time * (std.math.pi / 2.0)), zm.rotationZ(time * (std.math.pi / 2.0))); - const view = zm.lookAtRh( - zm.Vec{ 0, -4, 0, 1 }, - zm.Vec{ 0, 0, 0, 1 }, - zm.Vec{ 0, 0, 1, 0 }, - ); - const proj = zm.perspectiveFovRh( - (std.math.pi * 2.0 / 5.0), - @as(f32, @floatFromInt(core.descriptor.width)) / @as(f32, @floatFromInt(core.descriptor.height)), - 1, - 100, - ); - const ubo = UniformBufferObject{ - .mat = zm.transpose(zm.mul(zm.mul(model, view), proj)), - }; - encoder.writeBuffer(app.uniform_buffer, 0, &[_]UniformBufferObject{ubo}); - } - - const pass = encoder.beginRenderPass(&render_pass_info); - pass.setPipeline(app.pipeline); - pass.setBindGroup(0, app.bind_group, &.{0}); - pass.setVertexBuffer(0, app.vertex_buffer, 0, @sizeOf(Vertex) * vertices.len); - pass.draw(vertices.len, 1, 0, 0); - pass.end(); - pass.release(); - - encoder.copyTextureToTexture( - &gpu.ImageCopyTexture{ - .texture = app.cube_texture_render, - }, - &gpu.ImageCopyTexture{ - .texture = app.cube_texture, - }, - &.{ .width = core.descriptor.width, .height = core.descriptor.height }, - ); - - const cube_pass = encoder.beginRenderPass(&cube_render_pass_info); - cube_pass.setPipeline(app.pipeline); - cube_pass.setBindGroup(0, app.bind_group, &.{0}); - cube_pass.setVertexBuffer(0, app.vertex_buffer, 0, @sizeOf(Vertex) * vertices.len); - cube_pass.draw(vertices.len, 1, 0, 0); - cube_pass.end(); - cube_pass.release(); - - var command = encoder.finish(null); - encoder.release(); - - const queue = core.queue; - queue.submit(&[_]*gpu.CommandBuffer{command}); - command.release(); - core.swap_chain.present(); - back_buffer_view.release(); - - // update the window title every second - if (app.title_timer.read() >= 1.0) { - app.title_timer.reset(); - try core.printTitle("Fractal Cube [ {d}fps ] [ Input {d}hz ]", .{ - core.frameRate(), - core.inputRate(), - }); - } - - return false; -} diff --git a/src/core/examples/fractal-cube/shader.wgsl b/src/core/examples/fractal-cube/shader.wgsl deleted file mode 100644 index d38f0b4e..00000000 --- a/src/core/examples/fractal-cube/shader.wgsl +++ /dev/null @@ -1,36 +0,0 @@ -struct Uniforms { - matrix : mat4x4, -}; - -@binding(0) @group(0) var ubo : Uniforms; - -struct VertexOut { - @builtin(position) Position : vec4, - @location(0) fragUV : vec2, - @location(1) fragPosition: vec4, -} - -@vertex fn vertex_main( - @location(0) position : vec4, - @location(1) uv: vec2 -) -> VertexOut { - var output : VertexOut; - output.Position = position * ubo.matrix; - output.fragUV = uv; - output.fragPosition = 0.5 * (position + vec4(1.0, 1.0, 1.0, 1.0)); - return output; -} - -@binding(1) @group(0) var mySampler: sampler; -@binding(2) @group(0) var myTexture: texture_2d; - -@fragment fn frag_main( - @location(0) fragUV: vec2, - @location(1) fragPosition: vec4 -) -> @location(0) vec4 { - let texColor = textureSample(myTexture, mySampler, fragUV * 0.8 + vec2(0.1, 0.1)); - let f = f32(length(texColor.rgb - vec3(0.5, 0.5, 0.5)) < 0.01); - return (1.0 - f) * texColor + f * fragPosition; - // return vec4(texColor.rgb,1.0); -} - diff --git a/src/core/examples/gen-texture-light/cube.wgsl b/src/core/examples/gen-texture-light/cube.wgsl deleted file mode 100644 index 4081f2dc..00000000 --- a/src/core/examples/gen-texture-light/cube.wgsl +++ /dev/null @@ -1,75 +0,0 @@ -struct CameraUniform { - pos: vec4, - view_proj: mat4x4, -}; - -struct InstanceInput { - @location(3) model_matrix_0: vec4, - @location(4) model_matrix_1: vec4, - @location(5) model_matrix_2: vec4, - @location(6) model_matrix_3: vec4, -}; - -struct VertexInput { - @location(0) position: vec3, - @location(1) normal: vec3, - @location(2) tex_coords: vec2, -}; - -struct VertexOutput { - @builtin(position) clip_position: vec4, - @location(0) tex_coords: vec2, - @location(1) normal: vec3, - @location(2) position: vec3, -}; - -struct Light { - position: vec4, - color: vec4, -}; - -@group(0) @binding(0) var camera: CameraUniform; -@group(1) @binding(0) var t_diffuse: texture_2d; -@group(1) @binding(1) var s_diffuse: sampler; -@group(2) @binding(0) var light: Light; - -@vertex -fn vs_main(model: VertexInput, instance: InstanceInput) -> VertexOutput { - let model_matrix = mat4x4( - instance.model_matrix_0, - instance.model_matrix_1, - instance.model_matrix_2, - instance.model_matrix_3, - ); - var out: VertexOutput; - let world_pos = model_matrix * vec4(model.position, 1.0); - out.position = world_pos.xyz; - out.normal = (model_matrix * vec4(model.normal, 0.0)).xyz; - out.clip_position = camera.view_proj * world_pos; - out.tex_coords = model.tex_coords; - return out; -} - -@fragment -fn fs_main(in: VertexOutput) -> @location(0) vec4 { - let object_color = textureSample(t_diffuse, s_diffuse, in.tex_coords); - - let ambient = 0.1; - let ambient_color = light.color.rbg * ambient; - - let light_dir = normalize(light.position.xyz - in.position); - let diffuse = max(dot(in.normal, light_dir), 0.0); - let diffuse_color = light.color.rgb * diffuse; - - let view_dir = normalize(camera.pos.xyz - in.position); - let half_dir = normalize(view_dir + light_dir); - let specular = pow(max(dot(in.normal, half_dir), 0.0), 32.0); - let specular_color = light.color.rbg * specular; - - let all = ambient_color + diffuse_color + specular_color; - - let result = all * object_color.rgb; - - return vec4(result, object_color.a); - -} diff --git a/src/core/examples/gen-texture-light/light.wgsl b/src/core/examples/gen-texture-light/light.wgsl deleted file mode 100644 index e110af20..00000000 --- a/src/core/examples/gen-texture-light/light.wgsl +++ /dev/null @@ -1,35 +0,0 @@ -struct CameraUniform { - view_pos: vec4, - view_proj: mat4x4, -}; - -struct VertexInput { - @location(0) position: vec3, - @location(1) normal: vec3, - @location(2) tex_coords: vec2, -}; - -struct VertexOutput { - @builtin(position) clip_position: vec4, -}; - -struct Light { - position: vec4, - color: vec4, -}; - -@group(0) @binding(0) var camera: CameraUniform; -@group(1) @binding(0) var light: Light; - -@vertex -fn vs_main(model: VertexInput) -> VertexOutput { - var out: VertexOutput; - let world_pos = vec4(model.position + light.position.xyz, 1.0); - out.clip_position = camera.view_proj * world_pos; - return out; -} - -@fragment -fn fs_main(in: VertexOutput) -> @location(0) vec4 { - return vec4(1.0, 1.0, 1.0, 0.5); -} diff --git a/src/core/examples/gen-texture-light/main.zig b/src/core/examples/gen-texture-light/main.zig deleted file mode 100755 index cae11f65..00000000 --- a/src/core/examples/gen-texture-light/main.zig +++ /dev/null @@ -1,893 +0,0 @@ -// in this example: -// - comptime generated image data for texture -// - Blinn-Phong lighting -// - several pipelines -// -// quit with escape, q or space -// move camera with arrows or wasd - -const std = @import("std"); - -const mach = @import("mach"); -const core = mach.core; -const gpu = mach.gpu; - -const zm = @import("zmath"); -const Vec = zm.Vec; -const Mat = zm.Mat; -const Quat = zm.Quat; - -pub const App = @This(); - -var gpa = std.heap.GeneralPurposeAllocator(.{}){}; - -title_timer: core.Timer, -timer: core.Timer, -cube: Cube, -camera: Camera, -light: Light, -depth: Texture, -keys: u8, - -const Dir = struct { - const up: u8 = 0b0001; - const down: u8 = 0b0010; - const left: u8 = 0b0100; - const right: u8 = 0b1000; -}; - -pub fn init(app: *App) !void { - try core.init(.{}); - - app.title_timer = try core.Timer.start(); - app.timer = try core.Timer.start(); - - const eye = Vec{ 5.0, 7.0, 5.0, 0.0 }; - const target = Vec{ 0.0, 0.0, 0.0, 0.0 }; - - const framebuffer = core.descriptor; - const aspect_ratio = @as(f32, @floatFromInt(framebuffer.width)) / @as(f32, @floatFromInt(framebuffer.height)); - - app.cube = Cube.init(); - app.light = Light.init(); - app.depth = Texture.depth(core.device, framebuffer.width, framebuffer.height); - app.camera = Camera.init(core.device, eye, target, zm.Vec{ 0.0, 1.0, 0.0, 0.0 }, aspect_ratio, 45.0, 0.1, 100.0); - app.keys = 0; -} - -pub fn deinit(app: *App) void { - defer _ = gpa.deinit(); - defer core.deinit(); - - app.cube.deinit(); - app.camera.deinit(); - app.light.deinit(); - app.depth.release(); -} - -pub fn update(app: *App) !bool { - const delta_time = app.timer.lap(); - - var iter = core.pollEvents(); - while (iter.next()) |event| { - switch (event) { - .key_press => |ev| switch (ev.key) { - .q, .escape, .space => return true, - .w, .up => { - app.keys |= Dir.up; - }, - .s, .down => { - app.keys |= Dir.down; - }, - .a, .left => { - app.keys |= Dir.left; - }, - .d, .right => { - app.keys |= Dir.right; - }, - .one => core.setDisplayMode(.windowed), - .two => core.setDisplayMode(.fullscreen), - .three => core.setDisplayMode(.borderless), - else => {}, - }, - .key_release => |ev| switch (ev.key) { - .w, .up => { - app.keys &= ~Dir.up; - }, - .s, .down => { - app.keys &= ~Dir.down; - }, - .a, .left => { - app.keys &= ~Dir.left; - }, - .d, .right => { - app.keys &= ~Dir.right; - }, - else => {}, - }, - .framebuffer_resize => |ev| { - // recreates the sampler, which is a waste, but for an example it's ok - app.depth.release(); - app.depth = Texture.depth(core.device, ev.width, ev.height); - }, - .close => return true, - else => {}, - } - } - - // move camera - const speed = zm.Vec{ delta_time * 5, delta_time * 5, delta_time * 5, delta_time * 5 }; - const fwd = zm.normalize3(app.camera.target - app.camera.eye); - const right = zm.normalize3(zm.cross3(fwd, app.camera.up)); - - if (app.keys & Dir.up != 0) - app.camera.eye += fwd * speed; - - if (app.keys & Dir.down != 0) - app.camera.eye -= fwd * speed; - - if (app.keys & Dir.right != 0) - app.camera.eye += right * speed - else if (app.keys & Dir.left != 0) - app.camera.eye -= right * speed - else - app.camera.eye += right * (speed * @Vector(4, f32){ 0.5, 0.5, 0.5, 0.5 }); - - const queue = core.queue; - app.camera.update(queue); - - // move light - const light_speed = delta_time * 2.5; - app.light.update(queue, light_speed); - - const back_buffer_view = core.swap_chain.getCurrentTextureView().?; - defer back_buffer_view.release(); - - const encoder = core.device.createCommandEncoder(null); - defer encoder.release(); - - const color_attachment = gpu.RenderPassColorAttachment{ - .view = back_buffer_view, - .clear_value = gpu.Color{ .r = 0.0, .g = 0.0, .b = 0.4, .a = 1.0 }, - .load_op = .clear, - .store_op = .store, - }; - - const render_pass_descriptor = gpu.RenderPassDescriptor.init(.{ - .color_attachments = &.{color_attachment}, - .depth_stencil_attachment = &.{ - .view = app.depth.view, - .depth_load_op = .clear, - .depth_store_op = .store, - .depth_clear_value = 1.0, - }, - }); - - const pass = encoder.beginRenderPass(&render_pass_descriptor); - defer pass.release(); - - // brick cubes - pass.setPipeline(app.cube.pipeline); - pass.setBindGroup(0, app.camera.bind_group, &.{}); - pass.setBindGroup(1, app.cube.texture.bind_group.?, &.{}); - pass.setBindGroup(2, app.light.bind_group, &.{}); - pass.setVertexBuffer(0, app.cube.mesh.buffer, 0, app.cube.mesh.size); - pass.setVertexBuffer(1, app.cube.instance.buffer, 0, app.cube.instance.size); - pass.draw(4, app.cube.instance.len, 0, 0); - pass.draw(4, app.cube.instance.len, 4, 0); - pass.draw(4, app.cube.instance.len, 8, 0); - pass.draw(4, app.cube.instance.len, 12, 0); - pass.draw(4, app.cube.instance.len, 16, 0); - pass.draw(4, app.cube.instance.len, 20, 0); - - // light source - pass.setPipeline(app.light.pipeline); - pass.setBindGroup(0, app.camera.bind_group, &.{}); - pass.setBindGroup(1, app.light.bind_group, &.{}); - pass.setVertexBuffer(0, app.cube.mesh.buffer, 0, app.cube.mesh.size); - pass.draw(4, 1, 0, 0); - pass.draw(4, 1, 4, 0); - pass.draw(4, 1, 8, 0); - pass.draw(4, 1, 12, 0); - pass.draw(4, 1, 16, 0); - pass.draw(4, 1, 20, 0); - - pass.end(); - - var command = encoder.finish(null); - defer command.release(); - - queue.submit(&[_]*gpu.CommandBuffer{command}); - core.swap_chain.present(); - - // update the window title every second - if (app.title_timer.read() >= 1.0) { - app.title_timer.reset(); - try core.printTitle("Gen Texture Light [ {d}fps ] [ Input {d}hz ]", .{ - core.frameRate(), - core.inputRate(), - }); - } - - return false; -} - -const Camera = struct { - const Self = @This(); - - eye: Vec, - target: Vec, - up: Vec, - aspect: f32, - fovy: f32, - near: f32, - far: f32, - bind_group: *gpu.BindGroup, - buffer: Buffer, - - const Uniform = extern struct { - pos: Vec, - mat: Mat, - }; - - fn init(device: *gpu.Device, eye: Vec, target: Vec, up: Vec, aspect: f32, fovy: f32, near: f32, far: f32) Self { - var self: Self = .{ - .eye = eye, - .target = target, - .up = up, - .aspect = aspect, - .near = near, - .far = far, - .fovy = fovy, - .buffer = undefined, - .bind_group = undefined, - }; - - const view = self.buildViewProjMatrix(); - - const uniform = Uniform{ - .pos = self.eye, - .mat = view, - }; - - const buffer = .{ - .buffer = initBuffer(device, .{ .uniform = true }, &@as([20]f32, @bitCast(uniform))), - .size = @sizeOf(@TypeOf(uniform)), - }; - - const layout = Self.bindGroupLayout(device); - const bind_group = device.createBindGroup(&gpu.BindGroup.Descriptor.init(.{ - .layout = layout, - .entries = &.{ - gpu.BindGroup.Entry.buffer(0, buffer.buffer, 0, buffer.size), - }, - })); - layout.release(); - - self.buffer = buffer; - self.bind_group = bind_group; - - return self; - } - - fn deinit(self: *Self) void { - self.bind_group.release(); - self.buffer.release(); - } - - fn update(self: *Self, queue: *gpu.Queue) void { - const mat = self.buildViewProjMatrix(); - const uniform = .{ - .pos = self.eye, - .mat = mat, - }; - - queue.writeBuffer(self.buffer.buffer, 0, &[_]Uniform{uniform}); - } - - inline fn buildViewProjMatrix(s: *const Camera) Mat { - const view = zm.lookAtRh(s.eye, s.target, s.up); - const proj = zm.perspectiveFovRh(s.fovy, s.aspect, s.near, s.far); - return zm.mul(view, proj); - } - - inline fn bindGroupLayout(device: *gpu.Device) *gpu.BindGroupLayout { - const visibility = .{ .vertex = true, .fragment = true }; - return device.createBindGroupLayout(&gpu.BindGroupLayout.Descriptor.init(.{ - .entries = &.{ - gpu.BindGroupLayout.Entry.buffer(0, visibility, .uniform, false, 0), - }, - })); - } -}; - -const Buffer = struct { - const Self = @This(); - - buffer: *gpu.Buffer, - size: usize, - len: u32 = 0, - - fn release(self: *Self) void { - self.buffer.release(); - } -}; - -const Cube = struct { - const Self = @This(); - - pipeline: *gpu.RenderPipeline, - mesh: Buffer, - instance: Buffer, - texture: Texture, - - const IPR = 20; // instances per row - const SPACING = 2; // spacing between cubes - const DISPLACEMENT = vec3u(IPR * SPACING / 2, 0, IPR * SPACING / 2); - - fn init() Self { - const device = core.device; - - const texture = Brick.texture(device); - - // instance buffer - var ibuf: [IPR * IPR * 16]f32 = undefined; - - var z: usize = 0; - while (z < IPR) : (z += 1) { - var x: usize = 0; - while (x < IPR) : (x += 1) { - const pos = vec3u(x * SPACING, 0, z * SPACING) - DISPLACEMENT; - const rot = blk: { - if (pos[0] == 0 and pos[2] == 0) { - break :blk zm.rotationZ(0.0); - } else { - break :blk zm.mul(zm.rotationX(zm.clamp(zm.abs(pos[0]), 0, 45.0)), zm.rotationZ(zm.clamp(zm.abs(pos[2]), 0, 45.0))); - } - }; - const index = z * IPR + x; - const inst = Instance{ - .position = pos, - .rotation = rot, - }; - zm.storeMat(ibuf[index * 16 ..], inst.toMat()); - } - } - - const instance = Buffer{ - .buffer = initBuffer(device, .{ .vertex = true }, &ibuf), - .len = IPR * IPR, - .size = @sizeOf(@TypeOf(ibuf)), - }; - - return Self{ - .mesh = mesh(device), - .texture = texture, - .instance = instance, - .pipeline = pipeline(), - }; - } - - fn deinit(self: *Self) void { - self.pipeline.release(); - self.mesh.release(); - self.instance.release(); - self.texture.release(); - } - - fn pipeline() *gpu.RenderPipeline { - const device = core.device; - - const camera_layout = Camera.bindGroupLayout(device); - const texture_layout = Texture.bindGroupLayout(device); - const light_layout = Light.bindGroupLayout(device); - const layout_descriptor = gpu.PipelineLayout.Descriptor.init(.{ - .bind_group_layouts = &.{ - camera_layout, - texture_layout, - light_layout, - }, - }); - defer camera_layout.release(); - defer texture_layout.release(); - defer light_layout.release(); - - const layout = device.createPipelineLayout(&layout_descriptor); - defer layout.release(); - - const shader = device.createShaderModuleWGSL("cube.wgsl", @embedFile("cube.wgsl")); - defer shader.release(); - - const blend = gpu.BlendState{}; - const color_target = gpu.ColorTargetState{ - .format = core.descriptor.format, - .blend = &blend, - }; - - const fragment = gpu.FragmentState.init(.{ - .module = shader, - .entry_point = "fs_main", - .targets = &.{color_target}, - }); - - const descriptor = gpu.RenderPipeline.Descriptor{ - .layout = layout, - .fragment = &fragment, - .vertex = gpu.VertexState.init(.{ - .module = shader, - .entry_point = "vs_main", - .buffers = &.{ - Self.vertexBufferLayout(), - Self.instanceLayout(), - }, - }), - .depth_stencil = &.{ - .format = Texture.DEPTH_FORMAT, - .depth_write_enabled = .true, - .depth_compare = .less, - }, - .primitive = .{ - .cull_mode = .back, - .topology = .triangle_strip, - }, - }; - - return device.createRenderPipeline(&descriptor); - } - - fn mesh(device: *gpu.Device) Buffer { - // generated texture has aspect ratio of 1:2 - // `h` reflects that ratio - // `v` sets how many times texture repeats across surface - const v = 2; - const h = v * 2; - const buf = asFloats(.{ - // z+ face - 0, 0, 1, 0, 0, 1, 0, h, - 1, 0, 1, 0, 0, 1, v, h, - 0, 1, 1, 0, 0, 1, 0, 0, - 1, 1, 1, 0, 0, 1, v, 0, - // z- face - 1, 0, 0, 0, 0, -1, 0, h, - 0, 0, 0, 0, 0, -1, v, h, - 1, 1, 0, 0, 0, -1, 0, 0, - 0, 1, 0, 0, 0, -1, v, 0, - // x+ face - 1, 0, 1, 1, 0, 0, 0, h, - 1, 0, 0, 1, 0, 0, v, h, - 1, 1, 1, 1, 0, 0, 0, 0, - 1, 1, 0, 1, 0, 0, v, 0, - // x- face - 0, 0, 0, -1, 0, 0, 0, h, - 0, 0, 1, -1, 0, 0, v, h, - 0, 1, 0, -1, 0, 0, 0, 0, - 0, 1, 1, -1, 0, 0, v, 0, - // y+ face - 1, 1, 0, 0, 1, 0, 0, h, - 0, 1, 0, 0, 1, 0, v, h, - 1, 1, 1, 0, 1, 0, 0, 0, - 0, 1, 1, 0, 1, 0, v, 0, - // y- face - 0, 0, 0, 0, -1, 0, 0, h, - 1, 0, 0, 0, -1, 0, v, h, - 0, 0, 1, 0, -1, 0, 0, 0, - 1, 0, 1, 0, -1, 0, v, 0, - }); - - return Buffer{ - .buffer = initBuffer(device, .{ .vertex = true }, &buf), - .size = @sizeOf(@TypeOf(buf)), - }; - } - - fn vertexBufferLayout() gpu.VertexBufferLayout { - const attributes = [_]gpu.VertexAttribute{ - .{ - .format = .float32x3, - .offset = 0, - .shader_location = 0, - }, - .{ - .format = .float32x3, - .offset = @sizeOf([3]f32), - .shader_location = 1, - }, - .{ - .format = .float32x2, - .offset = @sizeOf([6]f32), - .shader_location = 2, - }, - }; - return gpu.VertexBufferLayout.init(.{ - .array_stride = @sizeOf([8]f32), - .attributes = &attributes, - }); - } - - fn instanceLayout() gpu.VertexBufferLayout { - const attributes = [_]gpu.VertexAttribute{ - .{ - .format = .float32x4, - .offset = 0, - .shader_location = 3, - }, - .{ - .format = .float32x4, - .offset = @sizeOf([4]f32), - .shader_location = 4, - }, - .{ - .format = .float32x4, - .offset = @sizeOf([8]f32), - .shader_location = 5, - }, - .{ - .format = .float32x4, - .offset = @sizeOf([12]f32), - .shader_location = 6, - }, - }; - - return gpu.VertexBufferLayout.init(.{ - .array_stride = @sizeOf([16]f32), - .step_mode = .instance, - .attributes = &attributes, - }); - } -}; - -fn asFloats(comptime arr: anytype) [arr.len]f32 { - const len = arr.len; - comptime var out: [len]f32 = undefined; - comptime var i = 0; - inline while (i < len) : (i += 1) { - out[i] = @as(f32, @floatFromInt(arr[i])); - } - return out; -} - -const Brick = struct { - const W = 12; - const H = 6; - - fn texture(device: *gpu.Device) Texture { - const slice: []const u8 = &data(); - return Texture.fromData(device, W, H, u8, slice); - } - - fn data() [W * H * 4]u8 { - comptime var out: [W * H * 4]u8 = undefined; - - // fill all the texture with brick color - comptime var i = 0; - inline while (i < H) : (i += 1) { - comptime var j = 0; - inline while (j < W * 4) : (j += 4) { - out[i * W * 4 + j + 0] = 210; - out[i * W * 4 + j + 1] = 30; - out[i * W * 4 + j + 2] = 30; - out[i * W * 4 + j + 3] = 0; - } - } - - const f = 10; - - // fill the cement lines - inline for ([_]comptime_int{ 0, 1 }) |k| { - inline for ([_]comptime_int{ 5 * 4, 11 * 4 }) |m| { - out[k * W * 4 + m + 0] = f; - out[k * W * 4 + m + 1] = f; - out[k * W * 4 + m + 2] = f; - out[k * W * 4 + m + 3] = 0; - } - } - - inline for ([_]comptime_int{ 3, 4 }) |k| { - inline for ([_]comptime_int{ 2 * 4, 8 * 4 }) |m| { - out[k * W * 4 + m + 0] = f; - out[k * W * 4 + m + 1] = f; - out[k * W * 4 + m + 2] = f; - out[k * W * 4 + m + 3] = 0; - } - } - - inline for ([_]comptime_int{ 2, 5 }) |k| { - comptime var m = 0; - inline while (m < W * 4) : (m += 4) { - out[k * W * 4 + m + 0] = f; - out[k * W * 4 + m + 1] = f; - out[k * W * 4 + m + 2] = f; - out[k * W * 4 + m + 3] = 0; - } - } - - return out; - } -}; - -// don't confuse with gpu.Texture -const Texture = struct { - const Self = @This(); - - texture: *gpu.Texture, - view: *gpu.TextureView, - sampler: *gpu.Sampler, - bind_group: ?*gpu.BindGroup, - - const DEPTH_FORMAT = .depth32_float; - const FORMAT = .rgba8_unorm; - - fn release(self: *Self) void { - self.texture.release(); - self.view.release(); - self.sampler.release(); - if (self.bind_group) |bind_group| bind_group.release(); - } - - fn fromData(device: *gpu.Device, width: u32, height: u32, comptime T: type, data: []const T) Self { - const extent = gpu.Extent3D{ - .width = width, - .height = height, - }; - - const texture = device.createTexture(&gpu.Texture.Descriptor{ - .size = extent, - .format = FORMAT, - .usage = .{ .copy_dst = true, .texture_binding = true }, - }); - - const view = texture.createView(&gpu.TextureView.Descriptor{ - .format = FORMAT, - .dimension = .dimension_2d, - .array_layer_count = 1, - .mip_level_count = 1, - }); - - const sampler = device.createSampler(&gpu.Sampler.Descriptor{ - .address_mode_u = .repeat, - .address_mode_v = .repeat, - .address_mode_w = .repeat, - .mag_filter = .linear, - .min_filter = .linear, - .mipmap_filter = .linear, - .max_anisotropy = 1, // 1,2,4,8,16 - }); - - core.queue.writeTexture( - &gpu.ImageCopyTexture{ - .texture = texture, - }, - &gpu.Texture.DataLayout{ - .bytes_per_row = 4 * width, - .rows_per_image = height, - }, - &extent, - data, - ); - - const bind_group_layout = Self.bindGroupLayout(device); - const bind_group = device.createBindGroup(&gpu.BindGroup.Descriptor.init(.{ - .layout = bind_group_layout, - .entries = &.{ - gpu.BindGroup.Entry.textureView(0, view), - gpu.BindGroup.Entry.sampler(1, sampler), - }, - })); - bind_group_layout.release(); - - return Self{ - .view = view, - .texture = texture, - .sampler = sampler, - .bind_group = bind_group, - }; - } - - fn depth(device: *gpu.Device, width: u32, height: u32) Self { - const extent = gpu.Extent3D{ - .width = width, - .height = height, - }; - - const texture = device.createTexture(&gpu.Texture.Descriptor{ - .size = extent, - .format = DEPTH_FORMAT, - .usage = .{ - .render_attachment = true, - .texture_binding = true, - }, - }); - - const view = texture.createView(&gpu.TextureView.Descriptor{ - .dimension = .dimension_2d, - .array_layer_count = 1, - .mip_level_count = 1, - }); - - const sampler = device.createSampler(&gpu.Sampler.Descriptor{ - .mag_filter = .linear, - .compare = .less_equal, - }); - - return Self{ - .texture = texture, - .view = view, - .sampler = sampler, - .bind_group = null, // not used - }; - } - - inline fn bindGroupLayout(device: *gpu.Device) *gpu.BindGroupLayout { - const visibility = .{ .fragment = true }; - const Entry = gpu.BindGroupLayout.Entry; - return device.createBindGroupLayout(&gpu.BindGroupLayout.Descriptor.init(.{ - .entries = &.{ - Entry.texture(0, visibility, .float, .dimension_2d, false), - Entry.sampler(1, visibility, .filtering), - }, - })); - } -}; - -const Light = struct { - const Self = @This(); - - uniform: Uniform, - buffer: Buffer, - bind_group: *gpu.BindGroup, - pipeline: *gpu.RenderPipeline, - - const Uniform = extern struct { - position: Vec, - color: Vec, - }; - - fn init() Self { - const device = core.device; - const uniform = Uniform{ - .color = vec3u(1, 1, 1), - .position = vec3u(3, 7, 2), - }; - - const buffer = .{ - .buffer = initBuffer(device, .{ .uniform = true }, &@as([8]f32, @bitCast(uniform))), - .size = @sizeOf(@TypeOf(uniform)), - }; - - const layout = Self.bindGroupLayout(device); - const bind_group = device.createBindGroup(&gpu.BindGroup.Descriptor.init(.{ - .layout = layout, - .entries = &.{ - gpu.BindGroup.Entry.buffer(0, buffer.buffer, 0, buffer.size), - }, - })); - layout.release(); - - return Self{ - .buffer = buffer, - .uniform = uniform, - .bind_group = bind_group, - .pipeline = Self.pipeline(), - }; - } - - fn deinit(self: *Self) void { - self.buffer.release(); - self.bind_group.release(); - self.pipeline.release(); - } - - fn update(self: *Self, queue: *gpu.Queue, delta: f32) void { - const old = self.uniform; - const new = Light.Uniform{ - .position = zm.qmul(zm.quatFromAxisAngle(vec3u(0, 1, 0), delta), old.position), - .color = old.color, - }; - queue.writeBuffer(self.buffer.buffer, 0, &[_]Light.Uniform{new}); - self.uniform = new; - } - - inline fn bindGroupLayout(device: *gpu.Device) *gpu.BindGroupLayout { - const visibility = .{ .vertex = true, .fragment = true }; - const Entry = gpu.BindGroupLayout.Entry; - return device.createBindGroupLayout(&gpu.BindGroupLayout.Descriptor.init(.{ - .entries = &.{ - Entry.buffer(0, visibility, .uniform, false, 0), - }, - })); - } - - fn pipeline() *gpu.RenderPipeline { - const device = core.device; - - const camera_layout = Camera.bindGroupLayout(device); - const light_layout = Light.bindGroupLayout(device); - const layout_descriptor = gpu.PipelineLayout.Descriptor.init(.{ - .bind_group_layouts = &.{ - camera_layout, - light_layout, - }, - }); - defer camera_layout.release(); - defer light_layout.release(); - - const layout = device.createPipelineLayout(&layout_descriptor); - defer layout.release(); - - const shader = core.device.createShaderModuleWGSL("light.wgsl", @embedFile("light.wgsl")); - defer shader.release(); - - const blend = gpu.BlendState{}; - const color_target = gpu.ColorTargetState{ - .format = core.descriptor.format, - .blend = &blend, - }; - - const fragment = gpu.FragmentState.init(.{ - .module = shader, - .entry_point = "fs_main", - .targets = &.{color_target}, - }); - - const descriptor = gpu.RenderPipeline.Descriptor{ - .layout = layout, - .fragment = &fragment, - .vertex = gpu.VertexState.init(.{ - .module = shader, - .entry_point = "vs_main", - .buffers = &.{ - Cube.vertexBufferLayout(), - }, - }), - .depth_stencil = &.{ - .format = Texture.DEPTH_FORMAT, - .depth_write_enabled = .true, - .depth_compare = .less, - }, - .primitive = .{ - .cull_mode = .back, - .topology = .triangle_strip, - }, - }; - - return device.createRenderPipeline(&descriptor); - } -}; - -inline fn initBuffer(device: *gpu.Device, usage: gpu.Buffer.UsageFlags, data: anytype) *gpu.Buffer { - std.debug.assert(@typeInfo(@TypeOf(data)) == .Pointer); - const T = std.meta.Elem(@TypeOf(data)); - - var u = usage; - u.copy_dst = true; - const buffer = device.createBuffer(&.{ - .size = @sizeOf(T) * data.len, - .usage = u, - .mapped_at_creation = .true, - }); - - const mapped = buffer.getMappedRange(T, 0, data.len); - @memcpy(mapped.?, data); - buffer.unmap(); - return buffer; -} - -fn vec3i(x: isize, y: isize, z: isize) Vec { - return Vec{ @floatFromInt(x), @floatFromInt(y), @floatFromInt(z), 0.0 }; -} - -fn vec3u(x: usize, y: usize, z: usize) Vec { - return zm.Vec{ @floatFromInt(x), @floatFromInt(y), @floatFromInt(z), 0.0 }; -} - -// todo indside Cube -const Instance = struct { - const Self = @This(); - - position: Vec, - rotation: Mat, - - fn toMat(self: *const Self) Mat { - return zm.mul(self.rotation, zm.translationV(self.position)); - } -}; diff --git a/src/core/examples/image-blur/blur.wgsl b/src/core/examples/image-blur/blur.wgsl deleted file mode 100644 index e8c5d1be..00000000 --- a/src/core/examples/image-blur/blur.wgsl +++ /dev/null @@ -1,81 +0,0 @@ -struct Params { - filterDim : i32, - blockDim : u32, -} - -@group(0) @binding(0) var samp : sampler; -@group(0) @binding(1) var params : Params; -@group(1) @binding(1) var inputTex : texture_2d; -@group(1) @binding(2) var outputTex : texture_storage_2d; - -struct Flip { - value : u32, -} -@group(1) @binding(3) var flip : Flip; - -// This shader blurs the input texture in one direction, depending on whether -// |flip.value| is 0 or 1. -// It does so by running (128 / 4) threads per workgroup to load 128 -// texels into 4 rows of shared memory. Each thread loads a -// 4 x 4 block of texels to take advantage of the texture sampling -// hardware. -// Then, each thread computes the blur result by averaging the adjacent texel values -// in shared memory. -// Because we're operating on a subset of the texture, we cannot compute all of the -// results since not all of the neighbors are available in shared memory. -// Specifically, with 128 x 128 tiles, we can only compute and write out -// square blocks of size 128 - (filterSize - 1). We compute the number of blocks -// needed in Javascript and dispatch that amount. - -var tile : array, 128>, 4>; - -@compute @workgroup_size(32, 1, 1) -fn main( - @builtin(workgroup_id) WorkGroupID : vec3, - @builtin(local_invocation_id) LocalInvocationID : vec3 -) { - let filterOffset = (params.filterDim - 1) / 2; - let dims = vec2(textureDimensions(inputTex, 0)); - let baseIndex = vec2(WorkGroupID.xy * vec2(params.blockDim, 4) + - LocalInvocationID.xy * vec2(4, 1)) - - vec2(filterOffset, 0); - - for (var r = 0; r < 4; r++) { - for (var c = 0; c < 4; c++) { - var loadIndex = baseIndex + vec2(c, r); - if (flip.value != 0u) { - loadIndex = loadIndex.yx; - } - - tile[r][4 * LocalInvocationID.x + u32(c)] = textureSampleLevel( - inputTex, - samp, - (vec2(loadIndex) + vec2(0.25, 0.25)) / vec2(dims), - 0.0 - ).rgb; - } - } - - workgroupBarrier(); - - for (var r = 0; r < 4; r++) { - for (var c = 0; c < 4; c++) { - var writeIndex = baseIndex + vec2(c, r); - if (flip.value != 0) { - writeIndex = writeIndex.yx; - } - - let center = i32(4 * LocalInvocationID.x) + c; - if (center >= filterOffset && - center < 128 - filterOffset && - all(writeIndex < dims)) { - var acc = vec3(0.0, 0.0, 0.0); - for (var f = 0; f < params.filterDim; f++) { - var i = center + f - filterOffset; - acc = acc + (1.0 / f32(params.filterDim)) * tile[r][i]; - } - textureStore(outputTex, writeIndex, vec4(acc, 1.0)); - } - } - } -} diff --git a/src/core/examples/image-blur/fullscreen_textured_quad.wgsl b/src/core/examples/image-blur/fullscreen_textured_quad.wgsl deleted file mode 100644 index 61c461c0..00000000 --- a/src/core/examples/image-blur/fullscreen_textured_quad.wgsl +++ /dev/null @@ -1,38 +0,0 @@ -@group(0) @binding(0) var mySampler : sampler; -@group(0) @binding(1) var myTexture : texture_2d; - -struct VertexOutput { - @builtin(position) Position : vec4, - @location(0) fragUV : vec2, -} - -@vertex -fn vert_main(@builtin(vertex_index) VertexIndex : u32) -> VertexOutput { - var pos = array, 6>( - vec2( 1.0, 1.0), - vec2( 1.0, -1.0), - vec2(-1.0, -1.0), - vec2( 1.0, 1.0), - vec2(-1.0, -1.0), - vec2(-1.0, 1.0) - ); - - var uv = array, 6>( - vec2(1.0, 0.0), - vec2(1.0, 1.0), - vec2(0.0, 1.0), - vec2(1.0, 0.0), - vec2(0.0, 1.0), - vec2(0.0, 0.0) - ); - - var output : VertexOutput; - output.Position = vec4(pos[VertexIndex], 0.0, 1.0); - output.fragUV = uv[VertexIndex]; - return output; -} - -@fragment -fn frag_main(@location(0) fragUV : vec2) -> @location(0) vec4 { - return textureSample(myTexture, mySampler, fragUV); -} diff --git a/src/core/examples/image-blur/main.zig b/src/core/examples/image-blur/main.zig deleted file mode 100644 index 7851d85a..00000000 --- a/src/core/examples/image-blur/main.zig +++ /dev/null @@ -1,329 +0,0 @@ -const std = @import("std"); - -const mach = @import("mach"); -const core = mach.core; -const gpu = mach.gpu; - -const zigimg = @import("zigimg"); -const assets = @import("assets"); - -title_timer: core.Timer, -blur_pipeline: *gpu.ComputePipeline, -fullscreen_quad_pipeline: *gpu.RenderPipeline, -cube_texture: *gpu.Texture, -textures: [2]*gpu.Texture, -blur_params_buffer: *gpu.Buffer, -compute_constants: *gpu.BindGroup, -compute_bind_group_0: *gpu.BindGroup, -compute_bind_group_1: *gpu.BindGroup, -compute_bind_group_2: *gpu.BindGroup, -show_result_bind_group: *gpu.BindGroup, -img_size: gpu.Extent3D, - -pub const App = @This(); - -// Constants from the blur.wgsl shader -const tile_dimension: u32 = 128; -const batch: [2]u32 = .{ 4, 4 }; - -// Currently hardcoded -const filter_size: u32 = 15; -const iterations: u32 = 2; -var block_dimension: u32 = tile_dimension - (filter_size - 1); -var gpa = std.heap.GeneralPurposeAllocator(.{}){}; - -pub fn init(app: *App) !void { - try core.init(.{}); - const allocator = gpa.allocator(); - - const queue = core.queue; - - const blur_shader_module = core.device.createShaderModuleWGSL("blur.wgsl", @embedFile("blur.wgsl")); - - const blur_pipeline_descriptor = gpu.ComputePipeline.Descriptor{ - .compute = gpu.ProgrammableStageDescriptor{ - .module = blur_shader_module, - .entry_point = "main", - }, - }; - - const blur_pipeline = core.device.createComputePipeline(&blur_pipeline_descriptor); - blur_shader_module.release(); - - const fullscreen_quad_vs_module = core.device.createShaderModuleWGSL( - "fullscreen_textured_quad.wgsl", - @embedFile("fullscreen_textured_quad.wgsl"), - ); - - const fullscreen_quad_fs_module = core.device.createShaderModuleWGSL( - "fullscreen_textured_quad.wgsl", - @embedFile("fullscreen_textured_quad.wgsl"), - ); - - const blend = gpu.BlendState{}; - const color_target = gpu.ColorTargetState{ - .format = core.descriptor.format, - .blend = &blend, - .write_mask = gpu.ColorWriteMaskFlags.all, - }; - - const fragment_state = gpu.FragmentState.init(.{ - .module = fullscreen_quad_fs_module, - .entry_point = "frag_main", - .targets = &.{color_target}, - }); - - const fullscreen_quad_pipeline_descriptor = gpu.RenderPipeline.Descriptor{ - .fragment = &fragment_state, - .vertex = .{ - .module = fullscreen_quad_vs_module, - .entry_point = "vert_main", - }, - }; - - const fullscreen_quad_pipeline = core.device.createRenderPipeline(&fullscreen_quad_pipeline_descriptor); - fullscreen_quad_vs_module.release(); - fullscreen_quad_fs_module.release(); - - const sampler = core.device.createSampler(&.{ - .mag_filter = .linear, - .min_filter = .linear, - }); - - var img = try zigimg.Image.fromMemory(allocator, assets.gotta_go_fast_png); - defer img.deinit(); - - const img_size = gpu.Extent3D{ .width = @as(u32, @intCast(img.width)), .height = @as(u32, @intCast(img.height)) }; - - const cube_texture = core.device.createTexture(&.{ - .size = img_size, - .format = .rgba8_unorm, - .usage = .{ - .texture_binding = true, - .copy_dst = true, - .render_attachment = true, - }, - }); - - const data_layout = gpu.Texture.DataLayout{ - .bytes_per_row = @as(u32, @intCast(img.width * 4)), - .rows_per_image = @as(u32, @intCast(img.height)), - }; - - switch (img.pixels) { - .rgba32 => |pixels| queue.writeTexture(&.{ .texture = cube_texture }, &data_layout, &img_size, pixels), - .rgb24 => |pixels| { - const data = try rgb24ToRgba32(allocator, pixels); - defer data.deinit(allocator); - queue.writeTexture(&.{ .texture = cube_texture }, &data_layout, &img_size, data.rgba32); - }, - else => @panic("unsupported image color format"), - } - - var textures: [2]*gpu.Texture = undefined; - for (textures, 0..) |_, i| { - textures[i] = core.device.createTexture(&.{ - .size = img_size, - .format = .rgba8_unorm, - .usage = .{ - .storage_binding = true, - .texture_binding = true, - .copy_dst = true, - }, - }); - } - - // the shader blurs the input texture in one direction, - // depending on whether flip value is 0 or 1 - var flip: [2]*gpu.Buffer = undefined; - for (flip, 0..) |_, i| { - const buffer = core.device.createBuffer(&.{ - .usage = .{ .uniform = true }, - .size = @sizeOf(u32), - .mapped_at_creation = .true, - }); - - const buffer_mapped = buffer.getMappedRange(u32, 0, 1); - buffer_mapped.?[0] = @as(u32, @intCast(i)); - buffer.unmap(); - - flip[i] = buffer; - } - - const blur_params_buffer = core.device.createBuffer(&.{ - .size = 8, - .usage = .{ .copy_dst = true, .uniform = true }, - }); - - const blur_bind_group_layout0 = blur_pipeline.getBindGroupLayout(0); - const blur_bind_group_layout1 = blur_pipeline.getBindGroupLayout(1); - const fullscreen_bind_group_layout = fullscreen_quad_pipeline.getBindGroupLayout(0); - const cube_texture_view = cube_texture.createView(&gpu.TextureView.Descriptor{}); - const texture0_view = textures[0].createView(&gpu.TextureView.Descriptor{}); - const texture1_view = textures[1].createView(&gpu.TextureView.Descriptor{}); - - const compute_constants = core.device.createBindGroup(&gpu.BindGroup.Descriptor.init(.{ - .layout = blur_bind_group_layout0, - .entries = &.{ - gpu.BindGroup.Entry.sampler(0, sampler), - gpu.BindGroup.Entry.buffer(1, blur_params_buffer, 0, 8), - }, - })); - - const compute_bind_group_0 = core.device.createBindGroup(&gpu.BindGroup.Descriptor.init(.{ - .layout = blur_bind_group_layout1, - .entries = &.{ - gpu.BindGroup.Entry.textureView(1, cube_texture_view), - gpu.BindGroup.Entry.textureView(2, texture0_view), - gpu.BindGroup.Entry.buffer(3, flip[0], 0, 4), - }, - })); - - const compute_bind_group_1 = core.device.createBindGroup(&gpu.BindGroup.Descriptor.init(.{ - .layout = blur_bind_group_layout1, - .entries = &.{ - gpu.BindGroup.Entry.textureView(1, texture0_view), - gpu.BindGroup.Entry.textureView(2, texture1_view), - gpu.BindGroup.Entry.buffer(3, flip[1], 0, 4), - }, - })); - - const compute_bind_group_2 = core.device.createBindGroup(&gpu.BindGroup.Descriptor.init(.{ - .layout = blur_bind_group_layout1, - .entries = &.{ - gpu.BindGroup.Entry.textureView(1, texture1_view), - gpu.BindGroup.Entry.textureView(2, texture0_view), - gpu.BindGroup.Entry.buffer(3, flip[0], 0, 4), - }, - })); - - const show_result_bind_group = core.device.createBindGroup(&gpu.BindGroup.Descriptor.init(.{ - .layout = fullscreen_bind_group_layout, - .entries = &.{ - gpu.BindGroup.Entry.sampler(0, sampler), - gpu.BindGroup.Entry.textureView(1, texture1_view), - }, - })); - - blur_bind_group_layout0.release(); - blur_bind_group_layout1.release(); - fullscreen_bind_group_layout.release(); - sampler.release(); - flip[0].release(); - flip[1].release(); - cube_texture_view.release(); - texture0_view.release(); - texture1_view.release(); - - const blur_params_buffer_data = [_]u32{ filter_size, block_dimension }; - queue.writeBuffer(blur_params_buffer, 0, &blur_params_buffer_data); - - app.title_timer = try core.Timer.start(); - app.blur_pipeline = blur_pipeline; - app.fullscreen_quad_pipeline = fullscreen_quad_pipeline; - app.cube_texture = cube_texture; - app.textures = textures; - app.blur_params_buffer = blur_params_buffer; - app.compute_constants = compute_constants; - app.compute_bind_group_0 = compute_bind_group_0; - app.compute_bind_group_1 = compute_bind_group_1; - app.compute_bind_group_2 = compute_bind_group_2; - app.show_result_bind_group = show_result_bind_group; - app.img_size = img_size; -} - -pub fn deinit(app: *App) void { - defer _ = gpa.deinit(); - defer core.deinit(); - - app.blur_pipeline.release(); - app.fullscreen_quad_pipeline.release(); - app.cube_texture.release(); - app.textures[0].release(); - app.textures[1].release(); - app.blur_params_buffer.release(); - app.compute_constants.release(); - app.compute_bind_group_0.release(); - app.compute_bind_group_1.release(); - app.compute_bind_group_2.release(); - app.show_result_bind_group.release(); -} - -pub fn update(app: *App) !bool { - var iter = core.pollEvents(); - while (iter.next()) |event| { - if (event == .close) return true; - } - - const back_buffer_view = core.swap_chain.getCurrentTextureView().?; - const encoder = core.device.createCommandEncoder(null); - - const compute_pass = encoder.beginComputePass(null); - compute_pass.setPipeline(app.blur_pipeline); - compute_pass.setBindGroup(0, app.compute_constants, &.{}); - - const width: u32 = @as(u32, @intCast(app.img_size.width)); - const height: u32 = @as(u32, @intCast(app.img_size.height)); - compute_pass.setBindGroup(1, app.compute_bind_group_0, &.{}); - compute_pass.dispatchWorkgroups(try std.math.divCeil(u32, width, block_dimension), try std.math.divCeil(u32, height, batch[1]), 1); - - compute_pass.setBindGroup(1, app.compute_bind_group_1, &.{}); - compute_pass.dispatchWorkgroups(try std.math.divCeil(u32, height, block_dimension), try std.math.divCeil(u32, width, batch[1]), 1); - - var i: u32 = 0; - while (i < iterations - 1) : (i += 1) { - compute_pass.setBindGroup(1, app.compute_bind_group_2, &.{}); - compute_pass.dispatchWorkgroups(try std.math.divCeil(u32, width, block_dimension), try std.math.divCeil(u32, height, batch[1]), 1); - - compute_pass.setBindGroup(1, app.compute_bind_group_1, &.{}); - compute_pass.dispatchWorkgroups(try std.math.divCeil(u32, height, block_dimension), try std.math.divCeil(u32, width, batch[1]), 1); - } - compute_pass.end(); - compute_pass.release(); - - const color_attachment = gpu.RenderPassColorAttachment{ - .view = back_buffer_view, - .clear_value = std.mem.zeroes(gpu.Color), - .load_op = .clear, - .store_op = .store, - }; - - const render_pass_descriptor = gpu.RenderPassDescriptor.init(.{ - .color_attachments = &.{color_attachment}, - }); - - const render_pass = encoder.beginRenderPass(&render_pass_descriptor); - render_pass.setPipeline(app.fullscreen_quad_pipeline); - render_pass.setBindGroup(0, app.show_result_bind_group, &.{}); - render_pass.draw(6, 1, 0, 0); - render_pass.end(); - render_pass.release(); - - var command = encoder.finish(null); - encoder.release(); - const queue = core.queue; - queue.submit(&[_]*gpu.CommandBuffer{command}); - command.release(); - core.swap_chain.present(); - back_buffer_view.release(); - - // update the window title every second - if (app.title_timer.read() >= 1.0) { - app.title_timer.reset(); - try core.printTitle("Image Blur [ {d}fps ] [ Input {d}hz ]", .{ - core.frameRate(), - core.inputRate(), - }); - } - - return false; -} - -fn rgb24ToRgba32(allocator: std.mem.Allocator, in: []zigimg.color.Rgb24) !zigimg.color.PixelStorage { - const out = try zigimg.color.PixelStorage.init(allocator, .rgba32, in.len); - var i: usize = 0; - while (i < in.len) : (i += 1) { - out.rgba32[i] = zigimg.color.Rgba32{ .r = in[i].r, .g = in[i].g, .b = in[i].b, .a = 255 }; - } - return out; -} diff --git a/src/core/examples/image/fullscreen_textured_quad.wgsl b/src/core/examples/image/fullscreen_textured_quad.wgsl deleted file mode 100644 index 3238e6a4..00000000 --- a/src/core/examples/image/fullscreen_textured_quad.wgsl +++ /dev/null @@ -1,39 +0,0 @@ -@group(0) @binding(0) var mySampler : sampler; -@group(0) @binding(1) var myTexture : texture_2d; - -struct VertexOutput { - @builtin(position) Position : vec4, - @location(0) fragUV : vec2, -} - -@vertex -fn vert_main(@builtin(vertex_index) VertexIndex : u32) -> VertexOutput { - // Draw a fullscreen quad using two triangles, with UV coordinates (normalized pixel coordinates) - // that would have the full texture be displayed. - var pos = array, 6>( - vec2( 1.0, 1.0), // right, top - vec2( 1.0, -1.0), // right, bottom - vec2(-1.0, -1.0), // left, bottom - vec2( 1.0, 1.0), // right, top - vec2(-1.0, -1.0), // left, bottom - vec2(-1.0, 1.0) // left, top - ); - var uv = array, 6>( - vec2(1.0, 0.0), - vec2(1.0, 1.0), - vec2(0.0, 1.0), - vec2(1.0, 0.0), - vec2(0.0, 1.0), - vec2(0.0, 0.0) - ); - - var output : VertexOutput; - output.Position = vec4(pos[VertexIndex], 0.0, 1.0); - output.fragUV = uv[VertexIndex]; - return output; -} - -@fragment -fn frag_main(@location(0) fragUV : vec2) -> @location(0) vec4 { - return textureSample(myTexture, mySampler, fragUV); -} diff --git a/src/core/examples/image/main.zig b/src/core/examples/image/main.zig deleted file mode 100644 index a9a3800d..00000000 --- a/src/core/examples/image/main.zig +++ /dev/null @@ -1,187 +0,0 @@ -const std = @import("std"); - -const mach = @import("mach"); -const core = mach.core; -const gpu = mach.gpu; - -const zigimg = @import("zigimg"); -const assets = @import("assets"); - -title_timer: core.Timer, -pipeline: *gpu.RenderPipeline, -texture: *gpu.Texture, -bind_group: *gpu.BindGroup, -img_size: gpu.Extent3D, - -pub const App = @This(); - -var gpa = std.heap.GeneralPurposeAllocator(.{}){}; - -pub fn init(app: *App) !void { - try core.init(.{}); - const allocator = gpa.allocator(); - - // Load our shader that will render a fullscreen textured quad using two triangles, needed to - // get the image on screen. - const fullscreen_quad_vs_module = core.device.createShaderModuleWGSL( - "fullscreen_textured_quad.wgsl", - @embedFile("fullscreen_textured_quad.wgsl"), - ); - defer fullscreen_quad_vs_module.release(); - const fullscreen_quad_fs_module = core.device.createShaderModuleWGSL( - "fullscreen_textured_quad.wgsl", - @embedFile("fullscreen_textured_quad.wgsl"), - ); - defer fullscreen_quad_fs_module.release(); - - // Create our render pipeline - const blend = gpu.BlendState{}; - const color_target = gpu.ColorTargetState{ - .format = core.descriptor.format, - .blend = &blend, - .write_mask = gpu.ColorWriteMaskFlags.all, - }; - const fragment_state = gpu.FragmentState.init(.{ - .module = fullscreen_quad_fs_module, - .entry_point = "frag_main", - .targets = &.{color_target}, - }); - const pipeline_descriptor = gpu.RenderPipeline.Descriptor{ - .fragment = &fragment_state, - .vertex = .{ - .module = fullscreen_quad_vs_module, - .entry_point = "vert_main", - }, - }; - const pipeline = core.device.createRenderPipeline(&pipeline_descriptor); - - // Create a texture sampler. This determines what happens when the texture doesn't match the - // dimensions of the screen it's being displayed on. If the image needs to be magnified or - // minified to fit, it can be linearly interpolated (i.e. 'blurred', .linear) or the nearest - // pixel may be used (i.e. 'pixelated', .nearest) - const sampler = core.device.createSampler(&.{ - .mag_filter = .linear, - .min_filter = .linear, - }); - defer sampler.release(); - - // Load the pixels of the image - var img = try zigimg.Image.fromMemory(allocator, assets.gotta_go_fast_png); - defer img.deinit(); - const img_size = gpu.Extent3D{ .width = @as(u32, @intCast(img.width)), .height = @as(u32, @intCast(img.height)) }; - - // Create a texture - const texture = core.device.createTexture(&.{ - .size = img_size, - .format = .rgba8_unorm, - .usage = .{ - .texture_binding = true, - .copy_dst = true, - .render_attachment = true, - }, - }); - - // Upload the pixels (from the CPU) to the GPU. You could e.g. do this once per frame if you - // wanted the image to be updated dynamically. - const data_layout = gpu.Texture.DataLayout{ - .bytes_per_row = @as(u32, @intCast(img.width * 4)), - .rows_per_image = @as(u32, @intCast(img.height)), - }; - switch (img.pixels) { - .rgba32 => |pixels| core.queue.writeTexture(&.{ .texture = texture }, &data_layout, &img_size, pixels), - .rgb24 => |pixels| { - const data = try rgb24ToRgba32(allocator, pixels); - defer data.deinit(allocator); - core.queue.writeTexture(&.{ .texture = texture }, &data_layout, &img_size, data.rgba32); - }, - else => @panic("unsupported image color format"), - } - - // Describe which data we will pass to our shader (GPU program) - const bind_group_layout = pipeline.getBindGroupLayout(0); - defer bind_group_layout.release(); - const texture_view = texture.createView(&gpu.TextureView.Descriptor{}); - defer texture_view.release(); - const bind_group = core.device.createBindGroup(&gpu.BindGroup.Descriptor.init(.{ - .layout = bind_group_layout, - .entries = &.{ - gpu.BindGroup.Entry.sampler(0, sampler), - gpu.BindGroup.Entry.textureView(1, texture_view), - }, - })); - - app.* = .{ - .title_timer = try core.Timer.start(), - .pipeline = pipeline, - .texture = texture, - .bind_group = bind_group, - .img_size = img_size, - }; -} - -pub fn deinit(app: *App) void { - defer _ = gpa.deinit(); - defer core.deinit(); - app.pipeline.release(); - app.texture.release(); - app.bind_group.release(); -} - -pub fn update(app: *App) !bool { - const back_buffer_view = core.swap_chain.getCurrentTextureView().?; - defer back_buffer_view.release(); - - // Poll for events (keyboard input, etc.) - var iter = core.pollEvents(); - while (iter.next()) |event| { - if (event == .close) return true; - } - - const encoder = core.device.createCommandEncoder(null); - defer encoder.release(); - - // Begin our render pass by clearing the pixels that were on the screen from the previous frame. - const color_attachment = gpu.RenderPassColorAttachment{ - .view = back_buffer_view, - .clear_value = std.mem.zeroes(gpu.Color), - .load_op = .clear, - .store_op = .store, - }; - const render_pass_descriptor = gpu.RenderPassDescriptor.init(.{ - .color_attachments = &.{color_attachment}, - }); - const render_pass = encoder.beginRenderPass(&render_pass_descriptor); - defer render_pass.release(); - - // Render using our pipeline - render_pass.setPipeline(app.pipeline); - render_pass.setBindGroup(0, app.bind_group, &.{}); - render_pass.draw(6, 1, 0, 0); // Tell the GPU to draw 6 vertices, one object - render_pass.end(); - - // Submit all the commands to the GPU and render the frame. - var command = encoder.finish(null); - defer command.release(); - core.queue.submit(&[_]*gpu.CommandBuffer{command}); - core.swap_chain.present(); - - // update the window title every second to have the FPS - if (app.title_timer.read() >= 1.0) { - app.title_timer.reset(); - try core.printTitle("Image [ {d}fps ] [ Input {d}hz ]", .{ - core.frameRate(), - core.inputRate(), - }); - } - - return false; -} - -fn rgb24ToRgba32(allocator: std.mem.Allocator, in: []zigimg.color.Rgb24) !zigimg.color.PixelStorage { - const out = try zigimg.color.PixelStorage.init(allocator, .rgba32, in.len); - var i: usize = 0; - while (i < in.len) : (i += 1) { - out.rgba32[i] = zigimg.color.Rgba32{ .r = in[i].r, .g = in[i].g, .b = in[i].b, .a = 255 }; - } - return out; -} diff --git a/src/core/examples/instanced-cube/cube_mesh.zig b/src/core/examples/instanced-cube/cube_mesh.zig deleted file mode 100644 index f26c75ac..00000000 --- a/src/core/examples/instanced-cube/cube_mesh.zig +++ /dev/null @@ -1,49 +0,0 @@ -pub const Vertex = extern struct { - pos: @Vector(4, f32), - col: @Vector(4, f32), - uv: @Vector(2, f32), -}; - -pub const vertices = [_]Vertex{ - .{ .pos = .{ 1, -1, 1, 1 }, .col = .{ 1, 0, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, -1, -1, 1 }, .col = .{ 0, 0, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, -1, 1, 1 }, .col = .{ 1, 0, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, -1, -1, 1 }, .col = .{ 0, 0, 0, 1 }, .uv = .{ 0, 0 } }, - - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ 1, -1, 1, 1 }, .col = .{ 1, 0, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, 1, -1, 1 }, .col = .{ 1, 1, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 0, 0 } }, - - .{ .pos = .{ -1, 1, 1, 1 }, .col = .{ 0, 1, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ 1, 1, -1, 1 }, .col = .{ 1, 1, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ -1, 1, 1, 1 }, .col = .{ 0, 1, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ 1, 1, -1, 1 }, .col = .{ 1, 1, 0, 1 }, .uv = .{ 0, 0 } }, - - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, 1, 1, 1 }, .col = .{ 0, 1, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ -1, -1, -1, 1 }, .col = .{ 0, 0, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 0, 0 } }, - - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, 1, 1, 1 }, .col = .{ 0, 1, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, -1, 1, 1 }, .col = .{ 1, 0, 1, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 1, 1 } }, - - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, -1, -1, 1 }, .col = .{ 0, 0, 0, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, 1, -1, 1 }, .col = .{ 1, 1, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 0, 0 } }, -}; diff --git a/src/core/examples/instanced-cube/main.zig b/src/core/examples/instanced-cube/main.zig deleted file mode 100755 index 3f0eabe8..00000000 --- a/src/core/examples/instanced-cube/main.zig +++ /dev/null @@ -1,208 +0,0 @@ -const std = @import("std"); - -const mach = @import("mach"); -const core = mach.core; -const gpu = mach.gpu; - -const zm = @import("zmath"); -const Vertex = @import("cube_mesh.zig").Vertex; -const vertices = @import("cube_mesh.zig").vertices; - -const UniformBufferObject = struct { - mat: zm.Mat, -}; - -var gpa = std.heap.GeneralPurposeAllocator(.{}){}; - -title_timer: core.Timer, - -timer: core.Timer, -pipeline: *gpu.RenderPipeline, -vertex_buffer: *gpu.Buffer, -uniform_buffer: *gpu.Buffer, -bind_group: *gpu.BindGroup, - -pub const App = @This(); - -pub fn init(app: *App) !void { - try core.init(.{}); - app.timer = try core.Timer.start(); - - const shader_module = core.device.createShaderModuleWGSL("shader.wgsl", @embedFile("shader.wgsl")); - - const vertex_attributes = [_]gpu.VertexAttribute{ - .{ .format = .float32x4, .offset = @offsetOf(Vertex, "pos"), .shader_location = 0 }, - .{ .format = .float32x2, .offset = @offsetOf(Vertex, "uv"), .shader_location = 1 }, - }; - const vertex_buffer_layout = gpu.VertexBufferLayout.init(.{ - .array_stride = @sizeOf(Vertex), - .step_mode = .vertex, - .attributes = &vertex_attributes, - }); - - const color_target = gpu.ColorTargetState{ - .format = core.descriptor.format, - .write_mask = gpu.ColorWriteMaskFlags.all, - }; - const fragment = gpu.FragmentState.init(.{ - .module = shader_module, - .entry_point = "frag_main", - .targets = &.{color_target}, - }); - - const bgle = gpu.BindGroupLayout.Entry.buffer(0, .{ .vertex = true }, .uniform, true, 0); - const bgl = core.device.createBindGroupLayout( - &gpu.BindGroupLayout.Descriptor.init(.{ - .entries = &.{bgle}, - }), - ); - - const bind_group_layouts = [_]*gpu.BindGroupLayout{bgl}; - const pipeline_layout = core.device.createPipelineLayout(&gpu.PipelineLayout.Descriptor.init(.{ - .bind_group_layouts = &bind_group_layouts, - })); - - const pipeline_descriptor = gpu.RenderPipeline.Descriptor{ - .fragment = &fragment, - .layout = pipeline_layout, - .vertex = gpu.VertexState.init(.{ - .module = shader_module, - .entry_point = "vertex_main", - .buffers = &.{vertex_buffer_layout}, - }), - .primitive = .{ - .cull_mode = .back, - }, - }; - - const vertex_buffer = core.device.createBuffer(&.{ - .usage = .{ .vertex = true }, - .size = @sizeOf(Vertex) * vertices.len, - .mapped_at_creation = .true, - }); - const vertex_mapped = vertex_buffer.getMappedRange(Vertex, 0, vertices.len); - @memcpy(vertex_mapped.?, vertices[0..]); - vertex_buffer.unmap(); - - const x_count = 4; - const y_count = 4; - const num_instances = x_count * y_count; - - const uniform_buffer = core.device.createBuffer(&.{ - .usage = .{ .copy_dst = true, .uniform = true }, - .size = @sizeOf(UniformBufferObject) * num_instances, - .mapped_at_creation = .false, - }); - const bind_group = core.device.createBindGroup( - &gpu.BindGroup.Descriptor.init(.{ - .layout = bgl, - .entries = &.{ - gpu.BindGroup.Entry.buffer(0, uniform_buffer, 0, @sizeOf(UniformBufferObject) * num_instances), - }, - }), - ); - - app.title_timer = try core.Timer.start(); - app.pipeline = core.device.createRenderPipeline(&pipeline_descriptor); - app.vertex_buffer = vertex_buffer; - app.uniform_buffer = uniform_buffer; - app.bind_group = bind_group; - - shader_module.release(); - pipeline_layout.release(); - bgl.release(); -} - -pub fn deinit(app: *App) void { - defer _ = gpa.deinit(); - defer core.deinit(); - - app.pipeline.release(); - app.vertex_buffer.release(); - app.bind_group.release(); - app.uniform_buffer.release(); -} - -pub fn update(app: *App) !bool { - var iter = core.pollEvents(); - while (iter.next()) |event| { - switch (event) { - .key_press => |ev| { - if (ev.key == .space) return true; - }, - .close => return true, - else => {}, - } - } - - const back_buffer_view = core.swap_chain.getCurrentTextureView().?; - const color_attachment = gpu.RenderPassColorAttachment{ - .view = back_buffer_view, - .clear_value = std.mem.zeroes(gpu.Color), - .load_op = .clear, - .store_op = .store, - }; - - const encoder = core.device.createCommandEncoder(null); - const render_pass_info = gpu.RenderPassDescriptor.init(.{ - .color_attachments = &.{color_attachment}, - }); - - { - const proj = zm.perspectiveFovRh( - (std.math.pi / 3.0), - @as(f32, @floatFromInt(core.descriptor.width)) / @as(f32, @floatFromInt(core.descriptor.height)), - 10, - 30, - ); - - var ubos: [16]UniformBufferObject = undefined; - const time = app.timer.read(); - const step: f32 = 4.0; - var m: u8 = 0; - var x: u8 = 0; - while (x < 4) : (x += 1) { - var y: u8 = 0; - while (y < 4) : (y += 1) { - const trans = zm.translation(step * (@as(f32, @floatFromInt(x)) - 2.0 + 0.5), step * (@as(f32, @floatFromInt(y)) - 2.0 + 0.5), -20); - const localTime = time + @as(f32, @floatFromInt(m)) * 0.5; - const model = zm.mul(zm.mul(zm.mul(zm.rotationX(localTime * (std.math.pi / 2.1)), zm.rotationY(localTime * (std.math.pi / 0.9))), zm.rotationZ(localTime * (std.math.pi / 1.3))), trans); - const mvp = zm.mul(model, proj); - const ubo = UniformBufferObject{ - .mat = mvp, - }; - ubos[m] = ubo; - m += 1; - } - } - encoder.writeBuffer(app.uniform_buffer, 0, &ubos); - } - - const pass = encoder.beginRenderPass(&render_pass_info); - pass.setPipeline(app.pipeline); - pass.setVertexBuffer(0, app.vertex_buffer, 0, @sizeOf(Vertex) * vertices.len); - pass.setBindGroup(0, app.bind_group, &.{0}); - pass.draw(vertices.len, 16, 0, 0); - pass.end(); - pass.release(); - - var command = encoder.finish(null); - encoder.release(); - - const queue = core.queue; - queue.submit(&[_]*gpu.CommandBuffer{command}); - command.release(); - core.swap_chain.present(); - back_buffer_view.release(); - - // update the window title every second - if (app.title_timer.read() >= 1.0) { - app.title_timer.reset(); - try core.printTitle("Instanced Cube [ {d}fps ] [ Input {d}hz ]", .{ - core.frameRate(), - core.inputRate(), - }); - } - - return false; -} diff --git a/src/core/examples/instanced-cube/shader.wgsl b/src/core/examples/instanced-cube/shader.wgsl deleted file mode 100644 index 1e279d8d..00000000 --- a/src/core/examples/instanced-cube/shader.wgsl +++ /dev/null @@ -1,25 +0,0 @@ -@binding(0) @group(0) var ubos : array, 16>; - -struct VertexOutput { - @builtin(position) position_clip : vec4, - @location(0) fragUV : vec2, - @location(1) fragPosition: vec4, -}; - -@vertex -fn vertex_main(@builtin(instance_index) instanceIdx : u32, - @location(0) position : vec4, - @location(1) uv : vec2) -> VertexOutput { - var output : VertexOutput; - output.position_clip = ubos[instanceIdx] * position; - output.fragUV = uv; - output.fragPosition = 0.5 * (position + vec4(1.0, 1.0, 1.0, 1.0)); - return output; -} - -@fragment fn frag_main( - @location(0) fragUV: vec2, - @location(1) fragPosition: vec4 -) -> @location(0) vec4 { - return fragPosition; -} \ No newline at end of file diff --git a/src/core/examples/map-async/main.wgsl b/src/core/examples/map-async/main.wgsl deleted file mode 100644 index a4270992..00000000 --- a/src/core/examples/map-async/main.wgsl +++ /dev/null @@ -1,16 +0,0 @@ -@group(0) @binding(0) var output: array; - -@compute @workgroup_size(64, 1, 1) -fn main( - @builtin(global_invocation_id) - global_id : vec3, - - @builtin(local_invocation_id) - local_id : vec3, -) { - if (global_id.x >= arrayLength(&output)) { - return; - } - output[global_id.x] = - f32(global_id.x) * 1000. + f32(local_id.x); -} diff --git a/src/core/examples/map-async/main.zig b/src/core/examples/map-async/main.zig deleted file mode 100644 index 594e2ae7..00000000 --- a/src/core/examples/map-async/main.zig +++ /dev/null @@ -1,103 +0,0 @@ -const std = @import("std"); - -const mach = @import("mach"); -const core = mach.core; -const gpu = mach.gpu; - -pub const App = @This(); - -var gpa = std.heap.GeneralPurposeAllocator(.{}){}; - -const workgroup_size = 64; -const buffer_size = 1000; - -pub fn init(app: *App) !void { - try core.init(.{}); - app.* = .{}; - - const output = core.device.createBuffer(&.{ - .usage = .{ .storage = true, .copy_src = true }, - .size = buffer_size * @sizeOf(f32), - .mapped_at_creation = .false, - }); - defer output.release(); - - const staging = core.device.createBuffer(&.{ - .usage = .{ .map_read = true, .copy_dst = true }, - .size = buffer_size * @sizeOf(f32), - .mapped_at_creation = .false, - }); - defer staging.release(); - - const compute_module = core.device.createShaderModuleWGSL("main.wgsl", @embedFile("main.wgsl")); - - const compute_pipeline = core.device.createComputePipeline(&gpu.ComputePipeline.Descriptor{ .compute = gpu.ProgrammableStageDescriptor{ - .module = compute_module, - .entry_point = "main", - } }); - defer compute_pipeline.release(); - - const layout = compute_pipeline.getBindGroupLayout(0); - defer layout.release(); - - const compute_bind_group = core.device.createBindGroup(&gpu.BindGroup.Descriptor.init(.{ - .layout = layout, - .entries = &.{ - gpu.BindGroup.Entry.buffer(0, output, 0, buffer_size * @sizeOf(f32)), - }, - })); - defer compute_bind_group.release(); - - compute_module.release(); - - const encoder = core.device.createCommandEncoder(null); - - const compute_pass = encoder.beginComputePass(null); - compute_pass.setPipeline(compute_pipeline); - compute_pass.setBindGroup(0, compute_bind_group, &.{}); - compute_pass.dispatchWorkgroups(try std.math.divCeil(u32, buffer_size, workgroup_size), 1, 1); - compute_pass.end(); - compute_pass.release(); - - encoder.copyBufferToBuffer(output, 0, staging, 0, buffer_size * @sizeOf(f32)); - - var command = encoder.finish(null); - encoder.release(); - - var response: gpu.Buffer.MapAsyncStatus = undefined; - const callback = (struct { - pub inline fn callback(ctx: *gpu.Buffer.MapAsyncStatus, status: gpu.Buffer.MapAsyncStatus) void { - ctx.* = status; - } - }).callback; - - var queue = core.queue; - queue.submit(&[_]*gpu.CommandBuffer{command}); - command.release(); - - staging.mapAsync(.{ .read = true }, 0, buffer_size * @sizeOf(f32), &response, callback); - while (true) { - if (response == gpu.Buffer.MapAsyncStatus.success) { - break; - } else { - core.device.tick(); - } - } - - const staging_mapped = staging.getConstMappedRange(f32, 0, buffer_size); - for (staging_mapped.?) |v| { - std.debug.print("{d} ", .{v}); - } - std.debug.print("\n", .{}); - staging.unmap(); -} - -pub fn deinit(app: *App) void { - _ = app; - defer _ = gpa.deinit(); - core.deinit(); -} - -pub fn update(_: *App) !bool { - return true; -} diff --git a/src/core/examples/pixel-post-process/cube_mesh.zig b/src/core/examples/pixel-post-process/cube_mesh.zig deleted file mode 100644 index edf25840..00000000 --- a/src/core/examples/pixel-post-process/cube_mesh.zig +++ /dev/null @@ -1,49 +0,0 @@ -pub const Vertex = extern struct { - pos: @Vector(3, f32), - normal: @Vector(3, f32), - uv: @Vector(2, f32), -}; - -pub const vertices = [_]Vertex{ - .{ .pos = .{ 1, -1, 1 }, .normal = .{ 0, -1, 0 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, -1, 1 }, .normal = .{ 0, -1, 0 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, -1, -1 }, .normal = .{ 0, -1, 0 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, -1, -1 }, .normal = .{ 0, -1, 0 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, -1, 1 }, .normal = .{ 0, -1, 0 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, -1, -1 }, .normal = .{ 0, -1, 0 }, .uv = .{ 0, 0 } }, - - .{ .pos = .{ 1, 1, 1 }, .normal = .{ 1, 0, 0 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ 1, -1, 1 }, .normal = .{ 1, 0, 0 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ 1, -1, -1 }, .normal = .{ 1, 0, 0 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, 1, -1 }, .normal = .{ 1, 0, 0 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, 1, 1 }, .normal = .{ 1, 0, 0 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ 1, -1, -1 }, .normal = .{ 1, 0, 0 }, .uv = .{ 0, 0 } }, - - .{ .pos = .{ -1, 1, 1 }, .normal = .{ 0, 1, 0 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ 1, 1, 1 }, .normal = .{ 0, 1, 0 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ 1, 1, -1 }, .normal = .{ 0, 1, 0 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ -1, 1, -1 }, .normal = .{ 0, 1, 0 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ -1, 1, 1 }, .normal = .{ 0, 1, 0 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ 1, 1, -1 }, .normal = .{ 0, 1, 0 }, .uv = .{ 0, 0 } }, - - .{ .pos = .{ -1, -1, 1 }, .normal = .{ -1, 0, 0 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, 1, 1 }, .normal = .{ -1, 0, 0 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, 1, -1 }, .normal = .{ -1, 0, 0 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ -1, -1, -1 }, .normal = .{ -1, 0, 0 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ -1, -1, 1 }, .normal = .{ -1, 0, 0 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, 1, -1 }, .normal = .{ -1, 0, 0 }, .uv = .{ 0, 0 } }, - - .{ .pos = .{ 1, 1, 1 }, .normal = .{ 0, 0, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, 1, 1 }, .normal = .{ 0, 0, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, -1, 1 }, .normal = .{ 0, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ -1, -1, 1 }, .normal = .{ 0, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, -1, 1 }, .normal = .{ 0, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, 1, 1 }, .normal = .{ 0, 0, 1 }, .uv = .{ 1, 1 } }, - - .{ .pos = .{ 1, -1, -1 }, .normal = .{ 0, 0, -1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, -1, -1 }, .normal = .{ 0, 0, -1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, 1, -1 }, .normal = .{ 0, 0, -1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, 1, -1 }, .normal = .{ 0, 0, -1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, -1, -1 }, .normal = .{ 0, 0, -1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, 1, -1 }, .normal = .{ 0, 0, -1 }, .uv = .{ 0, 0 } }, -}; diff --git a/src/core/examples/pixel-post-process/main.zig b/src/core/examples/pixel-post-process/main.zig deleted file mode 100644 index 56f10949..00000000 --- a/src/core/examples/pixel-post-process/main.zig +++ /dev/null @@ -1,464 +0,0 @@ -const std = @import("std"); - -const mach = @import("mach"); -const core = mach.core; -const gpu = mach.gpu; - -const zm = @import("zmath"); - -const Vertex = @import("cube_mesh.zig").Vertex; -const vertices = @import("cube_mesh.zig").vertices; -const Quad = @import("quad_mesh.zig").Quad; -const quad = @import("quad_mesh.zig").quad; - -pub const App = @This(); - -const pixel_size = 8; - -const UniformBufferObject = struct { - mat: zm.Mat, -}; -const PostUniformBufferObject = extern struct { - width: u32, - height: u32, - pixel_size: u32 = pixel_size, -}; -var gpa = std.heap.GeneralPurposeAllocator(.{}){}; - -title_timer: core.Timer, -timer: core.Timer, - -pipeline: *gpu.RenderPipeline, -normal_pipeline: *gpu.RenderPipeline, -vertex_buffer: *gpu.Buffer, -uniform_buffer: *gpu.Buffer, -bind_group: *gpu.BindGroup, - -post_pipeline: *gpu.RenderPipeline, -post_vertex_buffer: *gpu.Buffer, -post_uniform_buffer: *gpu.Buffer, -post_bind_group: *gpu.BindGroup, - -draw_texture_view: *gpu.TextureView, -depth_texture_view: *gpu.TextureView, -normal_texture_view: *gpu.TextureView, - -pub fn init(app: *App) !void { - try core.init(.{}); - app.title_timer = try core.Timer.start(); - app.timer = try core.Timer.start(); - - try app.createRenderTextures(); - app.createDrawPipeline(); - app.createPostPipeline(); -} - -pub fn deinit(app: *App) void { - defer _ = gpa.deinit(); - defer core.deinit(); - - app.cleanup(); -} - -pub fn update(app: *App) !bool { - var iter = core.pollEvents(); - while (iter.next()) |event| { - switch (event) { - .key_press => |ev| { - if (ev.key == .space) return true; - }, - .close => return true, - .framebuffer_resize => { - app.cleanup(); - try app.createRenderTextures(); - app.createDrawPipeline(); - app.createPostPipeline(); - }, - else => {}, - } - } - - const size = core.size(); - const encoder = core.device.createCommandEncoder(null); - encoder.writeBuffer(app.post_uniform_buffer, 0, &[_]PostUniformBufferObject{ - PostUniformBufferObject{ - .width = size.width, - .height = size.height, - }, - }); - - { - const time = app.timer.read() * 0.5; - const model = zm.mul(zm.rotationX(time * (std.math.pi / 2.0)), zm.rotationZ(time * (std.math.pi / 2.0))); - const view = zm.lookAtRh( - zm.Vec{ 0, 5, 2, 1 }, - zm.Vec{ 0, 0, 0, 1 }, - zm.Vec{ 0, 0, 1, 0 }, - ); - const proj = zm.perspectiveFovRh( - (std.math.pi / 4.0), - @as(f32, @floatFromInt(core.descriptor.width)) / @as(f32, @floatFromInt(core.descriptor.height)), - 0.1, - 10, - ); - const mvp = zm.mul(zm.mul(model, view), proj); - const ubo = UniformBufferObject{ - .mat = zm.transpose(mvp), - }; - encoder.writeBuffer(app.uniform_buffer, 0, &[_]UniformBufferObject{ubo}); - } - - { - // render scene to downscaled texture - const color_attachment = gpu.RenderPassColorAttachment{ - .view = app.draw_texture_view, - .clear_value = std.mem.zeroes(gpu.Color), - .load_op = .clear, - .store_op = .store, - }; - const render_pass_info = gpu.RenderPassDescriptor.init(.{ - .color_attachments = &.{color_attachment}, - .depth_stencil_attachment = &gpu.RenderPassDepthStencilAttachment{ - .view = app.depth_texture_view, - .depth_load_op = .clear, - .depth_store_op = .store, - .depth_clear_value = 1.0, - }, - }); - - const pass = encoder.beginRenderPass(&render_pass_info); - pass.setPipeline(app.pipeline); - pass.setVertexBuffer(0, app.vertex_buffer, 0, @sizeOf(Vertex) * vertices.len); - pass.setBindGroup(0, app.bind_group, &.{0}); - pass.draw(vertices.len, 1, 0, 0); - pass.end(); - pass.release(); - } - - { - // render scene normals to texture - const normal_color_attachment = gpu.RenderPassColorAttachment{ - .view = app.normal_texture_view, - .clear_value = .{ .r = 0.5, .b = 0.5, .g = 0.5, .a = 1.0 }, - .load_op = .clear, - .store_op = .store, - }; - const normal_render_pass_info = gpu.RenderPassDescriptor.init(.{ - .color_attachments = &.{normal_color_attachment}, - }); - - const normal_pass = encoder.beginRenderPass(&normal_render_pass_info); - normal_pass.setPipeline(app.normal_pipeline); - normal_pass.setVertexBuffer(0, app.vertex_buffer, 0, @sizeOf(Vertex) * vertices.len); - normal_pass.setBindGroup(0, app.bind_group, &.{0}); - normal_pass.draw(vertices.len, 1, 0, 0); - normal_pass.end(); - normal_pass.release(); - } - - const back_buffer_view = core.swap_chain.getCurrentTextureView().?; - { - // render to swap chain using previous passes - const post_color_attachment = gpu.RenderPassColorAttachment{ - .view = back_buffer_view, - .clear_value = std.mem.zeroes(gpu.Color), - .load_op = .clear, - .store_op = .store, - }; - const post_render_pass_info = gpu.RenderPassDescriptor.init(.{ - .color_attachments = &.{post_color_attachment}, - }); - - const draw_pass = encoder.beginRenderPass(&post_render_pass_info); - draw_pass.setPipeline(app.post_pipeline); - draw_pass.setVertexBuffer(0, app.post_vertex_buffer, 0, @sizeOf(Quad) * quad.len); - draw_pass.setBindGroup(0, app.post_bind_group, &.{0}); - draw_pass.draw(quad.len, 1, 0, 0); - draw_pass.end(); - draw_pass.release(); - } - - var command = encoder.finish(null); - encoder.release(); - - const queue = core.queue; - queue.submit(&[_]*gpu.CommandBuffer{command}); - command.release(); - core.swap_chain.present(); - back_buffer_view.release(); - - // update the window title every second - if (app.title_timer.read() >= 1.0) { - app.title_timer.reset(); - try core.printTitle("Pixel Post Process [ {d}fps ] [ Input {d}hz ]", .{ - core.frameRate(), - core.inputRate(), - }); - } - - return false; -} - -fn cleanup(app: *App) void { - app.pipeline.release(); - app.normal_pipeline.release(); - app.vertex_buffer.release(); - app.uniform_buffer.release(); - app.bind_group.release(); - - app.post_pipeline.release(); - app.post_vertex_buffer.release(); - app.post_uniform_buffer.release(); - app.post_bind_group.release(); - - app.draw_texture_view.release(); - app.depth_texture_view.release(); - app.normal_texture_view.release(); -} - -fn createRenderTextures(app: *App) !void { - const size = core.size(); - - const draw_texture_desc = gpu.Texture.Descriptor.init(.{ - .size = .{ .width = size.width / pixel_size, .height = size.height / pixel_size }, - .format = .bgra8_unorm, - .usage = .{ .texture_binding = true, .copy_dst = true, .render_attachment = true }, - }); - const draw_texture = core.device.createTexture(&draw_texture_desc); - app.draw_texture_view = draw_texture.createView(null); - draw_texture.release(); - - const depth_texture_desc = gpu.Texture.Descriptor.init(.{ - .size = .{ .width = size.width / pixel_size, .height = size.height / pixel_size }, - .format = .depth32_float, - .usage = .{ .texture_binding = true, .copy_dst = true, .render_attachment = true }, - }); - const depth_texture = core.device.createTexture(&depth_texture_desc); - app.depth_texture_view = depth_texture.createView(null); - depth_texture.release(); - - const normal_texture_desc = gpu.Texture.Descriptor.init(.{ - .size = .{ .width = size.width / pixel_size, .height = size.height / pixel_size }, - .format = .bgra8_unorm, - .usage = .{ .texture_binding = true, .copy_dst = true, .render_attachment = true }, - }); - const normal_texture = core.device.createTexture(&normal_texture_desc); - app.normal_texture_view = normal_texture.createView(null); - normal_texture.release(); -} - -fn createDrawPipeline(app: *App) void { - const shader_module = core.device.createShaderModuleWGSL("shader.wgsl", @embedFile("shader.wgsl")); - const vertex_attributes = [_]gpu.VertexAttribute{ - .{ .format = .float32x3, .offset = @offsetOf(Vertex, "pos"), .shader_location = 0 }, - .{ .format = .float32x3, .offset = @offsetOf(Vertex, "normal"), .shader_location = 1 }, - .{ .format = .float32x2, .offset = @offsetOf(Vertex, "uv"), .shader_location = 2 }, - }; - const vertex_buffer_layout = gpu.VertexBufferLayout.init(.{ - .array_stride = @sizeOf(Vertex), - .step_mode = .vertex, - .attributes = &vertex_attributes, - }); - const vertex = gpu.VertexState.init(.{ - .module = shader_module, - .entry_point = "vertex_main", - .buffers = &.{vertex_buffer_layout}, - }); - - const blend = gpu.BlendState{}; - const color_target = gpu.ColorTargetState{ - .format = core.descriptor.format, - .blend = &blend, - .write_mask = gpu.ColorWriteMaskFlags.all, - }; - const fragment = gpu.FragmentState.init(.{ - .module = shader_module, - .entry_point = "frag_main", - .targets = &.{color_target}, - }); - - const bgle = gpu.BindGroupLayout.Entry.buffer(0, .{ .vertex = true }, .uniform, true, 0); - const bgl = core.device.createBindGroupLayout( - &gpu.BindGroupLayout.Descriptor.init(.{ - .entries = &.{bgle}, - }), - ); - - const bind_group_layouts = [_]*gpu.BindGroupLayout{bgl}; - const pipeline_layout = core.device.createPipelineLayout( - &gpu.PipelineLayout.Descriptor.init(.{ - .bind_group_layouts = &bind_group_layouts, - }), - ); - - const vertex_buffer = core.device.createBuffer(&.{ - .usage = .{ .vertex = true }, - .size = @sizeOf(Vertex) * vertices.len, - .mapped_at_creation = .true, - }); - const vertex_mapped = vertex_buffer.getMappedRange(Vertex, 0, vertices.len); - @memcpy(vertex_mapped.?, vertices[0..]); - vertex_buffer.unmap(); - - const uniform_buffer = core.device.createBuffer(&.{ - .usage = .{ .copy_dst = true, .uniform = true }, - .size = @sizeOf(UniformBufferObject), - .mapped_at_creation = .false, - }); - const bind_group = core.device.createBindGroup( - &gpu.BindGroup.Descriptor.init(.{ - .layout = bgl, - .entries = &.{ - gpu.BindGroup.Entry.buffer(0, uniform_buffer, 0, @sizeOf(UniformBufferObject)), - }, - }), - ); - - const pipeline_descriptor = gpu.RenderPipeline.Descriptor{ - .fragment = &fragment, - .layout = pipeline_layout, - .vertex = vertex, - .primitive = .{ - .cull_mode = .back, - }, - .depth_stencil = &gpu.DepthStencilState{ - .format = .depth32_float, - .depth_write_enabled = .true, - .depth_compare = .less, - }, - }; - - { - // "same" pipeline, different fragment shader to create a texture with normal information - const normal_fs_module = core.device.createShaderModuleWGSL("normal_frag.wgsl", @embedFile("normal_frag.wgsl")); - const normal_fragment = gpu.FragmentState.init(.{ - .module = normal_fs_module, - .entry_point = "main", - .targets = &.{color_target}, - }); - const normal_pipeline_descriptor = gpu.RenderPipeline.Descriptor{ - .fragment = &normal_fragment, - .layout = pipeline_layout, - .vertex = vertex, - .primitive = .{ - .cull_mode = .back, - }, - }; - app.normal_pipeline = core.device.createRenderPipeline(&normal_pipeline_descriptor); - - normal_fs_module.release(); - } - - app.pipeline = core.device.createRenderPipeline(&pipeline_descriptor); - app.vertex_buffer = vertex_buffer; - app.uniform_buffer = uniform_buffer; - app.bind_group = bind_group; - - shader_module.release(); - pipeline_layout.release(); - bgl.release(); -} - -fn createPostPipeline(app: *App) void { - const vs_module = core.device.createShaderModuleWGSL("pixel_vert.wgsl", @embedFile("pixel_vert.wgsl")); - const vertex_attributes = [_]gpu.VertexAttribute{ - .{ .format = .float32x3, .offset = @offsetOf(Quad, "pos"), .shader_location = 0 }, - .{ .format = .float32x2, .offset = @offsetOf(Quad, "uv"), .shader_location = 1 }, - }; - const vertex_buffer_layout = gpu.VertexBufferLayout.init(.{ - .array_stride = @sizeOf(Quad), - .step_mode = .vertex, - .attributes = &vertex_attributes, - }); - const vertex = gpu.VertexState.init(.{ - .module = vs_module, - .entry_point = "main", - .buffers = &.{vertex_buffer_layout}, - }); - - const fs_module = core.device.createShaderModuleWGSL("pixel_frag.wgsl", @embedFile("pixel_frag.wgsl")); - const blend = gpu.BlendState{}; - const color_target = gpu.ColorTargetState{ - .format = core.descriptor.format, - .blend = &blend, - .write_mask = gpu.ColorWriteMaskFlags.all, - }; - const fragment = gpu.FragmentState.init(.{ - .module = fs_module, - .entry_point = "main", - .targets = &.{color_target}, - }); - - const bgl = core.device.createBindGroupLayout( - &gpu.BindGroupLayout.Descriptor.init(.{ - .entries = &.{ - gpu.BindGroupLayout.Entry.texture(0, .{ .fragment = true }, .float, .dimension_2d, false), - gpu.BindGroupLayout.Entry.sampler(1, .{ .fragment = true }, .filtering), - gpu.BindGroupLayout.Entry.texture(2, .{ .fragment = true }, .depth, .dimension_2d, false), - gpu.BindGroupLayout.Entry.sampler(3, .{ .fragment = true }, .filtering), - gpu.BindGroupLayout.Entry.texture(4, .{ .fragment = true }, .float, .dimension_2d, false), - gpu.BindGroupLayout.Entry.sampler(5, .{ .fragment = true }, .filtering), - gpu.BindGroupLayout.Entry.buffer(6, .{ .fragment = true }, .uniform, true, 0), - }, - }), - ); - - const bind_group_layouts = [_]*gpu.BindGroupLayout{bgl}; - const pipeline_layout = core.device.createPipelineLayout(&gpu.PipelineLayout.Descriptor.init(.{ - .bind_group_layouts = &bind_group_layouts, - })); - - const vertex_buffer = core.device.createBuffer(&.{ - .usage = .{ .vertex = true }, - .size = @sizeOf(Quad) * quad.len, - .mapped_at_creation = .true, - }); - const vertex_mapped = vertex_buffer.getMappedRange(Quad, 0, quad.len); - @memcpy(vertex_mapped.?, quad[0..]); - vertex_buffer.unmap(); - - const draw_sampler = core.device.createSampler(null); - const depth_sampler = core.device.createSampler(null); - const normal_sampler = core.device.createSampler(null); - const uniform_buffer = core.device.createBuffer(&.{ - .usage = .{ .copy_dst = true, .uniform = true }, - .size = @sizeOf(PostUniformBufferObject), - .mapped_at_creation = .false, - }); - const bind_group = core.device.createBindGroup( - &gpu.BindGroup.Descriptor.init(.{ - .layout = bgl, - .entries = &[_]gpu.BindGroup.Entry{ - gpu.BindGroup.Entry.textureView(0, app.draw_texture_view), - gpu.BindGroup.Entry.sampler(1, draw_sampler), - gpu.BindGroup.Entry.textureView(2, app.depth_texture_view), - gpu.BindGroup.Entry.sampler(3, depth_sampler), - gpu.BindGroup.Entry.textureView(4, app.normal_texture_view), - gpu.BindGroup.Entry.sampler(5, normal_sampler), - gpu.BindGroup.Entry.buffer(6, uniform_buffer, 0, @sizeOf(PostUniformBufferObject)), - }, - }), - ); - draw_sampler.release(); - depth_sampler.release(); - normal_sampler.release(); - - const pipeline_descriptor = gpu.RenderPipeline.Descriptor{ - .fragment = &fragment, - .layout = pipeline_layout, - .vertex = vertex, - .primitive = .{ - .cull_mode = .back, - }, - }; - - app.post_pipeline = core.device.createRenderPipeline(&pipeline_descriptor); - app.post_vertex_buffer = vertex_buffer; - app.post_uniform_buffer = uniform_buffer; - app.post_bind_group = bind_group; - - vs_module.release(); - fs_module.release(); - pipeline_layout.release(); - bgl.release(); -} diff --git a/src/core/examples/pixel-post-process/normal_frag.wgsl b/src/core/examples/pixel-post-process/normal_frag.wgsl deleted file mode 100644 index 28f7407c..00000000 --- a/src/core/examples/pixel-post-process/normal_frag.wgsl +++ /dev/null @@ -1,6 +0,0 @@ -@fragment fn main( - @location(0) normal: vec3, - @location(1) uv: vec2, -) -> @location(0) vec4 { - return vec4(normal / 2 + 0.5, 1.0); -} diff --git a/src/core/examples/pixel-post-process/pixel_frag.wgsl b/src/core/examples/pixel-post-process/pixel_frag.wgsl deleted file mode 100644 index 6932530f..00000000 --- a/src/core/examples/pixel-post-process/pixel_frag.wgsl +++ /dev/null @@ -1,74 +0,0 @@ -@group(0) @binding(0) -var draw_texture: texture_2d; -@group(0) @binding(1) -var draw_texture_sampler: sampler; - -@group(0) @binding(2) -var depth_texture: texture_depth_2d; -@group(0) @binding(3) -var depth_texture_sampler: sampler; - -@group(0) @binding(4) -var normal_texture: texture_2d; -@group(0) @binding(5) -var normal_texture_sampler: sampler; - -struct View { - @location(0) width: u32, - @location(1) height: u32, - @location(2) pixel_size: u32, -} -@group(0) @binding(6) -var view: View; - -fn sample_depth(uv: vec2, x: f32, y: f32) -> f32 { - return textureSample( - depth_texture, - depth_texture_sampler, - uv + vec2(x * f32(view.pixel_size) / f32(view.width), y * f32(view.pixel_size) / f32(view.height)) - ); -} - -fn sample_normal(uv: vec2, x: f32, y: f32) -> vec3 { - return textureSample( - normal_texture, - normal_texture_sampler, - uv + vec2(x * f32(view.pixel_size) / f32(view.width), y * f32(view.pixel_size) / f32(view.height)) - ).xyz; -} - -fn normal_indicator(uv: vec2, x: f32, y: f32) -> f32 { - var depth_diff = sample_depth(uv, 0, 0) - sample_depth(uv, x, y); - var dx = sample_normal(uv, 0, 0); - var dy = sample_normal(uv, x, y); - if (depth_diff > 0) { - // only sample normals from closest pixel - return 0; - } - return distance(dx, dy); -} - -@fragment fn main( - @builtin(position) position: vec4, - @location(0) uv: vec2 -) -> @location(0) vec4 { - var depth = sample_depth(uv, 0, 0); - var depth_diff: f32 = 0; - depth_diff += abs(depth - sample_depth(uv, -1, 0)); - depth_diff += abs(depth - sample_depth(uv, 1, 0)); - depth_diff += abs(depth - sample_depth(uv, 0, -1)); - depth_diff += abs(depth - sample_depth(uv, 0, 1)); - - var normal_diff: f32 = 0; - normal_diff += normal_indicator(uv, -1, 0); - normal_diff += normal_indicator(uv, 1, 0); - normal_diff += normal_indicator(uv, 0, -1); - normal_diff += normal_indicator(uv, 0, 1); - - var color = textureSample(draw_texture, draw_texture_sampler, uv); - if (depth_diff > 0.007) { // magic number from testing - return color * 0.7; - } - // add instead of multiply so really dark pixels get brighter - return color + (vec4(1) * step(0.1, normal_diff) * 0.7); -} diff --git a/src/core/examples/pixel-post-process/pixel_vert.wgsl b/src/core/examples/pixel-post-process/pixel_vert.wgsl deleted file mode 100644 index 734f629e..00000000 --- a/src/core/examples/pixel-post-process/pixel_vert.wgsl +++ /dev/null @@ -1,14 +0,0 @@ -struct VertexOut { - @builtin(position) position_clip: vec4, - @location(0) uv: vec2 -} - -@vertex fn main( - @location(0) position: vec3, - @location(1) uv: vec2 -) -> VertexOut { - var output : VertexOut; - output.position_clip = vec4(position.xy, 0.0, 1.0); - output.uv = uv; - return output; -} diff --git a/src/core/examples/pixel-post-process/quad_mesh.zig b/src/core/examples/pixel-post-process/quad_mesh.zig deleted file mode 100644 index 57db212f..00000000 --- a/src/core/examples/pixel-post-process/quad_mesh.zig +++ /dev/null @@ -1,13 +0,0 @@ -pub const Quad = extern struct { - pos: @Vector(3, f32), - uv: @Vector(2, f32), -}; - -pub const quad = [_]Quad{ - .{ .pos = .{ -1.0, 1.0, 0.0 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1.0, -1.0, 0.0 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1.0, 1.0, 0.0 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ 1.0, 1.0, 0.0 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1.0, -1.0, 0.0 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1.0, -1.0, 0.0 }, .uv = .{ 1, 0 } }, -}; diff --git a/src/core/examples/pixel-post-process/shader.wgsl b/src/core/examples/pixel-post-process/shader.wgsl deleted file mode 100644 index 325391cd..00000000 --- a/src/core/examples/pixel-post-process/shader.wgsl +++ /dev/null @@ -1,27 +0,0 @@ -@group(0) @binding(0) var ubo: mat4x4; - -struct VertexOut { - @builtin(position) position_clip: vec4, - @location(0) normal: vec3, - @location(1) uv: vec2, -} - -@vertex fn vertex_main( - @location(0) position: vec3, - @location(1) normal: vec3, - @location(2) uv: vec2 -) -> VertexOut { - var output: VertexOut; - output.position_clip = vec4(position, 1) * ubo; - output.normal = (vec4(normal, 0) * ubo).xyz; - output.uv = uv; - return output; -} - -@fragment fn frag_main( - @location(0) normal: vec3, - @location(1) uv: vec2, -) -> @location(0) vec4 { - var color = floor((uv * 0.5 + 0.25) * 32) / 32; - return vec4(color, 1, 1); -} \ No newline at end of file diff --git a/src/core/examples/procedural-primitives/main.zig b/src/core/examples/procedural-primitives/main.zig deleted file mode 100644 index e8a570f9..00000000 --- a/src/core/examples/procedural-primitives/main.zig +++ /dev/null @@ -1,65 +0,0 @@ -const std = @import("std"); - -const mach = @import("mach"); -const core = mach.core; -const gpu = mach.gpu; - -const renderer = @import("renderer.zig"); - -pub const App = @This(); - -var gpa = std.heap.GeneralPurposeAllocator(.{}){}; - -title_timer: core.Timer, - -pub fn init(app: *App) !void { - try core.init(.{ .required_limits = gpu.Limits{ - .max_vertex_buffers = 1, - .max_vertex_attributes = 2, - .max_bind_groups = 1, - .max_uniform_buffers_per_shader_stage = 1, - .max_uniform_buffer_binding_size = 16 * 1 * @sizeOf(f32), - } }); - - const allocator = gpa.allocator(); - const timer = try core.Timer.start(); - try renderer.init(allocator, timer); - app.* = .{ .title_timer = try core.Timer.start() }; -} - -pub fn deinit(app: *App) void { - _ = app; - defer _ = gpa.deinit(); - defer core.deinit(); - defer renderer.deinit(); -} - -pub fn update(app: *App) !bool { - var iter = core.pollEvents(); - while (iter.next()) |event| { - switch (event) { - .key_press => |ev| { - if (ev.key == .space) return true; - if (ev.key == .right) { - renderer.curr_primitive_index += 1; - renderer.curr_primitive_index %= 7; - } - }, - .close => return true, - else => {}, - } - } - - renderer.update(); - - // update the window title every second - if (app.title_timer.read() >= 1.0) { - app.title_timer.reset(); - try core.printTitle("Procedural Primitives [ {d}fps ] [ Input {d}hz ]", .{ - core.frameRate(), - core.inputRate(), - }); - } - - return false; -} diff --git a/src/core/examples/procedural-primitives/procedural-primitives.zig b/src/core/examples/procedural-primitives/procedural-primitives.zig deleted file mode 100644 index ae1c74ab..00000000 --- a/src/core/examples/procedural-primitives/procedural-primitives.zig +++ /dev/null @@ -1,336 +0,0 @@ -const std = @import("std"); -const zmath = @import("zmath"); - -const PI = 3.1415927410125732421875; - -pub const F32x3 = @Vector(3, f32); -pub const F32x4 = @Vector(4, f32); -pub const VertexData = struct { - position: F32x3, - normal: F32x3, -}; - -pub const PrimitiveType = enum(u4) { none, triangle, quad, plane, circle, uv_sphere, ico_sphere, cylinder, cone, torus }; - -pub const Primitive = struct { - vertex_data: std.ArrayList(VertexData), - vertex_count: u32, - index_data: std.ArrayList(u32), - index_count: u32, - type: PrimitiveType = .none, -}; - -// 2D Primitives -pub fn createTrianglePrimitive(allocator: std.mem.Allocator, size: f32) !Primitive { - const vertex_count = 3; - const index_count = 3; - var vertex_data = try std.ArrayList(VertexData).initCapacity(allocator, vertex_count); - - const edge = size / 2.0; - - vertex_data.appendSliceAssumeCapacity(&[vertex_count]VertexData{ - VertexData{ .position = F32x3{ -edge, -edge, 0.0 }, .normal = F32x3{ -edge, -edge, 0.0 } }, - VertexData{ .position = F32x3{ edge, -edge, 0.0 }, .normal = F32x3{ edge, -edge, 0.0 } }, - VertexData{ .position = F32x3{ 0.0, edge, 0.0 }, .normal = F32x3{ 0.0, edge, 0.0 } }, - }); - - var index_data = try std.ArrayList(u32).initCapacity(allocator, index_count); - index_data.appendSliceAssumeCapacity(&[index_count]u32{ 0, 1, 2 }); - - return Primitive{ .vertex_data = vertex_data, .vertex_count = 3, .index_data = index_data, .index_count = 3, .type = .triangle }; -} - -pub fn createQuadPrimitive(allocator: std.mem.Allocator, size: f32) !Primitive { - const vertex_count = 4; - const index_count = 6; - var vertex_data = try std.ArrayList(VertexData).initCapacity(allocator, vertex_count); - - const edge = size / 2.0; - - vertex_data.appendSliceAssumeCapacity(&[vertex_count]VertexData{ - VertexData{ .position = F32x3{ -edge, -edge, 0.0 }, .normal = F32x3{ -edge, -edge, 0.0 } }, - VertexData{ .position = F32x3{ edge, -edge, 0.0 }, .normal = F32x3{ edge, -edge, 0.0 } }, - VertexData{ .position = F32x3{ -edge, edge, 0.0 }, .normal = F32x3{ -edge, edge, 0.0 } }, - VertexData{ .position = F32x3{ edge, edge, 0.0 }, .normal = F32x3{ edge, edge, 0.0 } }, - }); - - var index_data = try std.ArrayList(u32).initCapacity(allocator, index_count); - index_data.appendSliceAssumeCapacity(&[index_count]u32{ - 0, 1, 2, - 1, 3, 2, - }); - - return Primitive{ .vertex_data = vertex_data, .vertex_count = 4, .index_data = index_data, .index_count = 6, .type = .quad }; -} - -pub fn createPlanePrimitive(allocator: std.mem.Allocator, x_subdivision: u32, y_subdivision: u32, size: f32) !Primitive { - const x_num_vertices = x_subdivision + 1; - const y_num_vertices = y_subdivision + 1; - const vertex_count = x_num_vertices * y_num_vertices; - var vertex_data = try std.ArrayList(VertexData).initCapacity(allocator, vertex_count); - - const vertices_distance_y = (size / @as(f32, @floatFromInt(y_subdivision))); - const vertices_distance_x = (size / @as(f32, @floatFromInt(x_subdivision))); - var y: u32 = 0; - while (y < y_num_vertices) : (y += 1) { - var x: u32 = 0; - const pos_y = (-size / 2.0) + @as(f32, @floatFromInt(y)) * vertices_distance_y; - while (x < x_num_vertices) : (x += 1) { - const pos_x = (-size / 2.0) + @as(f32, @floatFromInt(x)) * vertices_distance_x; - vertex_data.appendAssumeCapacity(VertexData{ .position = F32x3{ pos_x, pos_y, 0.0 }, .normal = F32x3{ pos_x, pos_y, 0.0 } }); - } - } - - const index_count = x_subdivision * y_subdivision * 2 * 3; - var index_data = try std.ArrayList(u32).initCapacity(allocator, index_count); - - y = 0; - while (y < y_subdivision) : (y += 1) { - var x: u32 = 0; - while (x < x_subdivision) : (x += 1) { - // First Triangle of Quad - index_data.appendAssumeCapacity(x + y * y_num_vertices); - index_data.appendAssumeCapacity(x + 1 + y * y_num_vertices); - index_data.appendAssumeCapacity(x + (y + 1) * y_num_vertices); - - // Second Triangle of Quad - index_data.appendAssumeCapacity(x + 1 + y * y_num_vertices); - index_data.appendAssumeCapacity(x + (y + 1) * y_num_vertices + 1); - index_data.appendAssumeCapacity(x + (y + 1) * y_num_vertices); - } - } - - return Primitive{ .vertex_data = vertex_data, .vertex_count = vertex_count, .index_data = index_data, .index_count = index_count, .type = .plane }; -} - -pub fn createCirclePrimitive(allocator: std.mem.Allocator, vertices: u32, radius: f32) !Primitive { - const vertex_count = vertices + 1; - var vertex_data = try std.ArrayList(VertexData).initCapacity(allocator, vertex_count); - - // Mid point of circle - vertex_data.appendAssumeCapacity(VertexData{ .position = F32x3{ 0, 0, 0.0 }, .normal = F32x3{ 0, 0, 0.0 } }); - - var x: u32 = 0; - const angle = 2 * PI / @as(f32, @floatFromInt(vertices)); - while (x < vertices) : (x += 1) { - const x_f = @as(f32, @floatFromInt(x)); - const pos_x = radius * zmath.cos(angle * x_f); - const pos_y = radius * zmath.sin(angle * x_f); - - vertex_data.appendAssumeCapacity(VertexData{ .position = F32x3{ pos_x, pos_y, 0.0 }, .normal = F32x3{ pos_x, pos_y, 0.0 } }); - } - - const index_count = (vertices + 1) * 3; - var index_data = try std.ArrayList(u32).initCapacity(allocator, index_count); - - x = 1; - while (x <= vertices) : (x += 1) { - index_data.appendAssumeCapacity(0); - index_data.appendAssumeCapacity(x); - index_data.appendAssumeCapacity(x + 1); - } - - index_data.appendAssumeCapacity(0); - index_data.appendAssumeCapacity(vertices); - index_data.appendAssumeCapacity(1); - - return Primitive{ .vertex_data = vertex_data, .vertex_count = vertex_count, .index_data = index_data, .index_count = index_count, .type = .plane }; -} - -// 3D Primitives -pub fn createCubePrimitive(allocator: std.mem.Allocator, size: f32) !Primitive { - const vertex_count = 8; - const index_count = 36; - var vertex_data = try std.ArrayList(VertexData).initCapacity(allocator, vertex_count); - - const edge = size / 2.0; - - vertex_data.appendSliceAssumeCapacity(&[vertex_count]VertexData{ - // Front positions - VertexData{ .position = F32x3{ -edge, -edge, edge }, .normal = F32x3{ -edge, -edge, edge } }, - VertexData{ .position = F32x3{ edge, -edge, edge }, .normal = F32x3{ edge, -edge, edge } }, - VertexData{ .position = F32x3{ edge, edge, edge }, .normal = F32x3{ edge, edge, edge } }, - VertexData{ .position = F32x3{ -edge, edge, edge }, .normal = F32x3{ -edge, edge, edge } }, - // Back positions - VertexData{ .position = F32x3{ -edge, -edge, -edge }, .normal = F32x3{ -edge, -edge, -edge } }, - VertexData{ .position = F32x3{ edge, -edge, -edge }, .normal = F32x3{ edge, -edge, -edge } }, - VertexData{ .position = F32x3{ edge, edge, -edge }, .normal = F32x3{ edge, edge, -edge } }, - VertexData{ .position = F32x3{ -edge, edge, -edge }, .normal = F32x3{ -edge, edge, -edge } }, - }); - - var index_data = try std.ArrayList(u32).initCapacity(allocator, index_count); - - index_data.appendSliceAssumeCapacity(&[index_count]u32{ - // front quad - 0, 1, 2, - 2, 3, 0, - // right quad - 1, 5, 6, - 6, 2, 1, - // back quad - 7, 6, 5, - 5, 4, 7, - // left quad - 4, 0, 3, - 3, 7, 4, - // bottom quad - 4, 5, 1, - 1, 0, 4, - // top quad - 3, 2, 6, - 6, 7, 3, - }); - - return Primitive{ .vertex_data = vertex_data, .vertex_count = vertex_count, .index_data = index_data, .index_count = index_count, .type = .quad }; -} - -const VertexDataMAL = std.MultiArrayList(VertexData); - -pub fn createCylinderPrimitive(allocator: std.mem.Allocator, radius: f32, height: f32, num_sides: u32) !Primitive { - const alloc_amt_vert: u32 = num_sides * 2 + 2; - const alloc_amt_idx: u32 = num_sides * 12; - - var vertex_data = VertexDataMAL{}; - try vertex_data.ensureTotalCapacity(allocator, alloc_amt_vert); - defer vertex_data.deinit(allocator); - - var out_vertex_data = try std.ArrayList(VertexData).initCapacity(allocator, alloc_amt_vert); - var index_data = try std.ArrayList(u32).initCapacity(allocator, alloc_amt_idx); - - vertex_data.appendAssumeCapacity(VertexData{ .position = F32x3{ 0.0, (height / 2.0), 0.0 }, .normal = undefined }); - vertex_data.appendAssumeCapacity(VertexData{ .position = F32x3{ 0.0, -(height / 2.0), 0.0 }, .normal = undefined }); - - const angle = 2.0 * PI / @as(f32, @floatFromInt(num_sides)); - - for (1..num_sides + 1) |i| { - const float_i = @as(f32, @floatFromInt(i)); - - const x: f32 = radius * zmath.sin(angle * float_i); - const y: f32 = radius * zmath.cos(angle * float_i); - - vertex_data.appendAssumeCapacity(VertexData{ .position = F32x3{ x, (height / 2.0), y }, .normal = undefined }); - vertex_data.appendAssumeCapacity(VertexData{ .position = F32x3{ x, -(height / 2.0), y }, .normal = undefined }); - } - - var group1: u32 = 1; - var group2: u32 = 3; - - for (0..num_sides) |_| { - if (group2 >= num_sides * 2) group2 = 1; - index_data.appendSliceAssumeCapacity(&[_]u32{ - 0, group1 + 1, group2 + 1, - group1 + 1, group1 + 2, group2 + 1, - group1 + 2, group2 + 2, group2 + 1, - group2 + 2, group1 + 2, 1, - }); - group1 += 2; - group2 += 2; - } - - { - var i: u32 = 0; - while (i < alloc_amt_idx) : (i += 3) { - const indexA: u32 = index_data.items[i]; - const indexB: u32 = index_data.items[i + 1]; - const indexC: u32 = index_data.items[i + 2]; - - const vert1: F32x4 = F32x4{ vertex_data.get(indexA).position[0], vertex_data.get(indexA).position[1], vertex_data.get(indexA).position[2], 1.0 }; - const vert2: F32x4 = F32x4{ vertex_data.get(indexB).position[0], vertex_data.get(indexB).position[1], vertex_data.get(indexB).position[2], 1.0 }; - const vert3: F32x4 = F32x4{ vertex_data.get(indexC).position[0], vertex_data.get(indexC).position[1], vertex_data.get(indexC).position[2], 1.0 }; - - const edgeAB: F32x4 = vert2 - vert1; - const edgeAC: F32x4 = vert3 - vert1; - - const cross = zmath.cross3(edgeAB, edgeAC); - - vertex_data.items(.normal)[indexA][0] += cross[0]; - vertex_data.items(.normal)[indexA][1] += cross[1]; - vertex_data.items(.normal)[indexA][2] += cross[2]; - vertex_data.items(.normal)[indexB][0] += cross[0]; - vertex_data.items(.normal)[indexB][1] += cross[1]; - vertex_data.items(.normal)[indexB][2] += cross[2]; - vertex_data.items(.normal)[indexC][0] += cross[0]; - vertex_data.items(.normal)[indexC][1] += cross[1]; - vertex_data.items(.normal)[indexC][2] += cross[2]; - } - } - - for (vertex_data.items(.position), vertex_data.items(.normal)) |pos, nor| { - out_vertex_data.appendAssumeCapacity(VertexData{ .position = pos, .normal = nor }); - } - - return Primitive{ .vertex_data = out_vertex_data, .vertex_count = alloc_amt_vert, .index_data = index_data, .index_count = alloc_amt_idx, .type = .cylinder }; -} - -pub fn createConePrimitive(allocator: std.mem.Allocator, radius: f32, height: f32, num_sides: u32) !Primitive { - const alloc_amt_vert: u32 = num_sides + 2; - const alloc_amt_idx: u32 = num_sides * 6; - - var vertex_data = VertexDataMAL{}; - try vertex_data.ensureTotalCapacity(allocator, alloc_amt_vert); - defer vertex_data.deinit(allocator); - - var out_vertex_data = try std.ArrayList(VertexData).initCapacity(allocator, alloc_amt_vert); - var index_data = try std.ArrayList(u32).initCapacity(allocator, alloc_amt_idx); - - vertex_data.appendAssumeCapacity(VertexData{ .position = F32x3{ 0.0, (height / 2.0), 0.0 }, .normal = undefined }); - vertex_data.appendAssumeCapacity(VertexData{ .position = F32x3{ 0.0, -(height / 2.0), 0.0 }, .normal = undefined }); - - const angle = 2.0 * PI / @as(f32, @floatFromInt(num_sides)); - - for (1..num_sides + 1) |i| { - const float_i = @as(f32, @floatFromInt(i)); - - const x: f32 = radius * zmath.sin(angle * float_i); - const y: f32 = radius * zmath.cos(angle * float_i); - - vertex_data.appendAssumeCapacity(VertexData{ .position = F32x3{ x, -(height / 2.0), y }, .normal = undefined }); - } - - var group1: u32 = 1; - var group2: u32 = 2; - - for (0..num_sides) |_| { - if (group2 >= num_sides + 1) group2 = 1; - index_data.appendSliceAssumeCapacity(&[_]u32{ - 0, group1 + 1, group2 + 1, - group2 + 1, group1 + 1, 1, - }); - group1 += 1; - group2 += 1; - } - - { - var i: u32 = 0; - while (i < alloc_amt_idx) : (i += 3) { - const indexA: u32 = index_data.items[i]; - const indexB: u32 = index_data.items[i + 1]; - const indexC: u32 = index_data.items[i + 2]; - - const vert1: F32x4 = F32x4{ vertex_data.get(indexA).position[0], vertex_data.get(indexA).position[1], vertex_data.get(indexA).position[2], 1.0 }; - const vert2: F32x4 = F32x4{ vertex_data.get(indexB).position[0], vertex_data.get(indexB).position[1], vertex_data.get(indexB).position[2], 1.0 }; - const vert3: F32x4 = F32x4{ vertex_data.get(indexC).position[0], vertex_data.get(indexC).position[1], vertex_data.get(indexC).position[2], 1.0 }; - - const edgeAB: F32x4 = vert2 - vert1; - const edgeAC: F32x4 = vert3 - vert1; - - const cross = zmath.cross3(edgeAB, edgeAC); - - vertex_data.items(.normal)[indexA][0] += cross[0]; - vertex_data.items(.normal)[indexA][1] += cross[1]; - vertex_data.items(.normal)[indexA][2] += cross[2]; - vertex_data.items(.normal)[indexB][0] += cross[0]; - vertex_data.items(.normal)[indexB][1] += cross[1]; - vertex_data.items(.normal)[indexB][2] += cross[2]; - vertex_data.items(.normal)[indexC][0] += cross[0]; - vertex_data.items(.normal)[indexC][1] += cross[1]; - vertex_data.items(.normal)[indexC][2] += cross[2]; - } - } - - for (vertex_data.items(.position), vertex_data.items(.normal)) |pos, nor| { - out_vertex_data.appendAssumeCapacity(VertexData{ .position = pos, .normal = nor }); - } - - return Primitive{ .vertex_data = out_vertex_data, .vertex_count = alloc_amt_vert, .index_data = index_data, .index_count = alloc_amt_idx, .type = .cone }; -} diff --git a/src/core/examples/procedural-primitives/renderer.zig b/src/core/examples/procedural-primitives/renderer.zig deleted file mode 100644 index 11be2b57..00000000 --- a/src/core/examples/procedural-primitives/renderer.zig +++ /dev/null @@ -1,328 +0,0 @@ -const std = @import("std"); - -const mach = @import("mach"); -const core = mach.core; -const gpu = mach.gpu; - -const zm = @import("zmath"); -const primitives = @import("procedural-primitives.zig"); -const Primitive = primitives.Primitive; -const VertexData = primitives.VertexData; - -pub const Renderer = @This(); - -var queue: *gpu.Queue = undefined; -var pipeline: *gpu.RenderPipeline = undefined; -var app_timer: core.Timer = undefined; -var depth_texture: *gpu.Texture = undefined; -var depth_texture_view: *gpu.TextureView = undefined; - -const PrimitiveRenderData = struct { - vertex_buffer: *gpu.Buffer, - index_buffer: *gpu.Buffer, - vertex_count: u32, - index_count: u32, -}; - -const UniformBufferObject = struct { - mvp_matrix: zm.Mat, -}; -var uniform_buffer: *gpu.Buffer = undefined; -var bind_group: *gpu.BindGroup = undefined; - -var primitives_data: [7]PrimitiveRenderData = undefined; - -pub var curr_primitive_index: u4 = 0; - -pub fn init(allocator: std.mem.Allocator, timer: core.Timer) !void { - queue = core.queue; - app_timer = timer; - - { - const triangle_primitive = try primitives.createTrianglePrimitive(allocator, 1); - primitives_data[0] = PrimitiveRenderData{ .vertex_buffer = createVertexBuffer(triangle_primitive), .index_buffer = createIndexBuffer(triangle_primitive), .vertex_count = triangle_primitive.vertex_count, .index_count = triangle_primitive.index_count }; - defer triangle_primitive.vertex_data.deinit(); - defer triangle_primitive.index_data.deinit(); - } - - { - const quad_primitive = try primitives.createQuadPrimitive(allocator, 1.4); - primitives_data[1] = PrimitiveRenderData{ .vertex_buffer = createVertexBuffer(quad_primitive), .index_buffer = createIndexBuffer(quad_primitive), .vertex_count = quad_primitive.vertex_count, .index_count = quad_primitive.index_count }; - defer quad_primitive.vertex_data.deinit(); - defer quad_primitive.index_data.deinit(); - } - - { - const plane_primitive = try primitives.createPlanePrimitive(allocator, 1000, 1000, 1.5); - primitives_data[2] = PrimitiveRenderData{ .vertex_buffer = createVertexBuffer(plane_primitive), .index_buffer = createIndexBuffer(plane_primitive), .vertex_count = plane_primitive.vertex_count, .index_count = plane_primitive.index_count }; - defer plane_primitive.vertex_data.deinit(); - defer plane_primitive.index_data.deinit(); - } - - { - const circle_primitive = try primitives.createCirclePrimitive(allocator, 64, 1); - primitives_data[3] = PrimitiveRenderData{ .vertex_buffer = createVertexBuffer(circle_primitive), .index_buffer = createIndexBuffer(circle_primitive), .vertex_count = circle_primitive.vertex_count, .index_count = circle_primitive.index_count }; - defer circle_primitive.vertex_data.deinit(); - defer circle_primitive.index_data.deinit(); - } - - { - const cube_primitive = try primitives.createCubePrimitive(allocator, 0.5); - primitives_data[4] = PrimitiveRenderData{ .vertex_buffer = createVertexBuffer(cube_primitive), .index_buffer = createIndexBuffer(cube_primitive), .vertex_count = cube_primitive.vertex_count, .index_count = cube_primitive.index_count }; - defer cube_primitive.vertex_data.deinit(); - defer cube_primitive.index_data.deinit(); - } - - { - const cylinder_primitive = try primitives.createCylinderPrimitive(allocator, 1.0, 1.0, 6); - primitives_data[5] = PrimitiveRenderData{ .vertex_buffer = createVertexBuffer(cylinder_primitive), .index_buffer = createIndexBuffer(cylinder_primitive), .vertex_count = cylinder_primitive.vertex_count, .index_count = cylinder_primitive.index_count }; - defer cylinder_primitive.vertex_data.deinit(); - defer cylinder_primitive.index_data.deinit(); - } - - { - const cone_primitive = try primitives.createConePrimitive(allocator, 0.7, 1.0, 15); - primitives_data[6] = PrimitiveRenderData{ .vertex_buffer = createVertexBuffer(cone_primitive), .index_buffer = createIndexBuffer(cone_primitive), .vertex_count = cone_primitive.vertex_count, .index_count = cone_primitive.index_count }; - defer cone_primitive.vertex_data.deinit(); - defer cone_primitive.index_data.deinit(); - } - var bind_group_layout = createBindGroupLayout(); - defer bind_group_layout.release(); - - createBindBuffer(bind_group_layout); - - createDepthTexture(); - - var shader = core.device.createShaderModuleWGSL("shader.wgsl", @embedFile("shader.wgsl")); - defer shader.release(); - - pipeline = createPipeline(shader, bind_group_layout); -} - -fn createVertexBuffer(primitive: Primitive) *gpu.Buffer { - const vertex_buffer_descriptor = gpu.Buffer.Descriptor{ - .size = primitive.vertex_count * @sizeOf(VertexData), - .usage = .{ .vertex = true, .copy_dst = true }, - .mapped_at_creation = .false, - }; - - const vertex_buffer = core.device.createBuffer(&vertex_buffer_descriptor); - queue.writeBuffer(vertex_buffer, 0, primitive.vertex_data.items[0..]); - - return vertex_buffer; -} - -fn createIndexBuffer(primitive: Primitive) *gpu.Buffer { - const index_buffer_descriptor = gpu.Buffer.Descriptor{ - .size = primitive.index_count * @sizeOf(u32), - .usage = .{ .index = true, .copy_dst = true }, - .mapped_at_creation = .false, - }; - const index_buffer = core.device.createBuffer(&index_buffer_descriptor); - queue.writeBuffer(index_buffer, 0, primitive.index_data.items[0..]); - - return index_buffer; -} - -fn createBindGroupLayout() *gpu.BindGroupLayout { - const bgle = gpu.BindGroupLayout.Entry.buffer(0, .{ .vertex = true, .fragment = false }, .uniform, true, 0); - return core.device.createBindGroupLayout( - &gpu.BindGroupLayout.Descriptor.init(.{ - .entries = &.{bgle}, - }), - ); -} - -fn createBindBuffer(bind_group_layout: *gpu.BindGroupLayout) void { - uniform_buffer = core.device.createBuffer(&.{ - .usage = .{ .copy_dst = true, .uniform = true }, - .size = @sizeOf(UniformBufferObject), - .mapped_at_creation = .false, - }); - - bind_group = core.device.createBindGroup( - &gpu.BindGroup.Descriptor.init(.{ - .layout = bind_group_layout, - .entries = &.{ - gpu.BindGroup.Entry.buffer(0, uniform_buffer, 0, @sizeOf(UniformBufferObject)), - }, - }), - ); -} - -fn createDepthTexture() void { - depth_texture = core.device.createTexture(&gpu.Texture.Descriptor{ - .usage = .{ .render_attachment = true }, - .size = .{ .width = core.descriptor.width, .height = core.descriptor.height }, - .format = .depth24_plus, - }); - - depth_texture_view = depth_texture.createView(&gpu.TextureView.Descriptor{ - .format = .depth24_plus, - .dimension = .dimension_2d, - .array_layer_count = 1, - .mip_level_count = 1, - }); -} - -fn createPipeline(shader_module: *gpu.ShaderModule, bind_group_layout: *gpu.BindGroupLayout) *gpu.RenderPipeline { - const vertex_attributes = [_]gpu.VertexAttribute{ - .{ .format = .float32x3, .shader_location = 0, .offset = 0 }, - .{ .format = .float32x3, .shader_location = 1, .offset = @sizeOf(primitives.F32x3) }, - }; - - const vertex_buffer_layout = gpu.VertexBufferLayout.init(.{ - .array_stride = @sizeOf(VertexData), - .step_mode = .vertex, - .attributes = &vertex_attributes, - }); - - const vertex_pipeline_state = gpu.VertexState.init(.{ .module = shader_module, .entry_point = "vertex_main", .buffers = &.{vertex_buffer_layout} }); - - const primitive_pipeline_state = gpu.PrimitiveState{ - .topology = .triangle_list, - .front_face = .ccw, - .cull_mode = .back, - }; - - // Fragment Pipeline State - const blend = gpu.BlendState{ - .color = gpu.BlendComponent{ .operation = .add, .src_factor = .src_alpha, .dst_factor = .one_minus_src_alpha }, - .alpha = gpu.BlendComponent{ .operation = .add, .src_factor = .zero, .dst_factor = .one }, - }; - const color_target = gpu.ColorTargetState{ - .format = core.descriptor.format, - .blend = &blend, - .write_mask = gpu.ColorWriteMaskFlags.all, - }; - const fragment_pipeline_state = gpu.FragmentState.init(.{ - .module = shader_module, - .entry_point = "frag_main", - .targets = &.{color_target}, - }); - - const depth_stencil_state = gpu.DepthStencilState{ - .format = .depth24_plus, - .depth_write_enabled = .true, - .depth_compare = .less, - }; - - const multi_sample_state = gpu.MultisampleState{ - .count = 1, - .mask = 0xFFFFFFFF, - .alpha_to_coverage_enabled = .false, - }; - - const bind_group_layouts = [_]*gpu.BindGroupLayout{bind_group_layout}; - // Pipeline Layout - const pipeline_layout_descriptor = gpu.PipelineLayout.Descriptor.init(.{ - .bind_group_layouts = &bind_group_layouts, - }); - const pipeline_layout = core.device.createPipelineLayout(&pipeline_layout_descriptor); - defer pipeline_layout.release(); - - const pipeline_descriptor = gpu.RenderPipeline.Descriptor{ - .label = "Main Pipeline", - .layout = pipeline_layout, - .vertex = vertex_pipeline_state, - .primitive = primitive_pipeline_state, - .depth_stencil = &depth_stencil_state, - .multisample = multi_sample_state, - .fragment = &fragment_pipeline_state, - }; - - return core.device.createRenderPipeline(&pipeline_descriptor); -} - -pub const F32x1 = @Vector(1, f32); - -pub fn update() void { - const back_buffer_view = core.swap_chain.getCurrentTextureView().?; - const color_attachment = gpu.RenderPassColorAttachment{ - .view = back_buffer_view, - .clear_value = gpu.Color{ .r = 0.2, .g = 0.2, .b = 0.2, .a = 1.0 }, - .load_op = .clear, - .store_op = .store, - }; - - const depth_stencil_attachment = gpu.RenderPassDepthStencilAttachment{ - .view = depth_texture_view, - .depth_load_op = .clear, - .depth_store_op = .store, - .depth_clear_value = 1.0, - }; - - const encoder = core.device.createCommandEncoder(null); - const render_pass_info = gpu.RenderPassDescriptor.init(.{ - .color_attachments = &.{color_attachment}, - .depth_stencil_attachment = &depth_stencil_attachment, - }); - - if (curr_primitive_index >= 4) { - const time = app_timer.read() / 5; - const model = zm.mul(zm.rotationX(time * (std.math.pi / 2.0)), zm.rotationZ(time * (std.math.pi / 2.0))); - const view = zm.lookAtRh( - zm.Vec{ 0, 4, 2, 1 }, - zm.Vec{ 0, 0, 0, 1 }, - zm.Vec{ 0, 0, 1, 0 }, - ); - const proj = zm.perspectiveFovRh( - (std.math.pi / 4.0), - @as(f32, @floatFromInt(core.descriptor.width)) / @as(f32, @floatFromInt(core.descriptor.height)), - 0.1, - 10, - ); - - const mvp = zm.mul(zm.mul(model, view), proj); - - const ubo = UniformBufferObject{ - .mvp_matrix = zm.transpose(mvp), - }; - encoder.writeBuffer(uniform_buffer, 0, &[_]UniformBufferObject{ubo}); - } else { - const ubo = UniformBufferObject{ - .mvp_matrix = zm.identity(), - }; - encoder.writeBuffer(uniform_buffer, 0, &[_]UniformBufferObject{ubo}); - } - - const pass = encoder.beginRenderPass(&render_pass_info); - - pass.setPipeline(pipeline); - - const vertex_buffer = primitives_data[curr_primitive_index].vertex_buffer; - const vertex_count = primitives_data[curr_primitive_index].vertex_count; - pass.setVertexBuffer(0, vertex_buffer, 0, @sizeOf(VertexData) * vertex_count); - - pass.setBindGroup(0, bind_group, &.{0}); - - const index_buffer = primitives_data[curr_primitive_index].index_buffer; - const index_count = primitives_data[curr_primitive_index].index_count; - pass.setIndexBuffer(index_buffer, .uint32, 0, @sizeOf(u32) * index_count); - pass.drawIndexed(index_count, 1, 0, 0, 0); - - pass.end(); - pass.release(); - - var command = encoder.finish(null); - encoder.release(); - - queue.submit(&[_]*gpu.CommandBuffer{command}); - command.release(); - core.swap_chain.present(); - back_buffer_view.release(); -} - -pub fn deinit() void { - var i: u4 = 0; - while (i < 7) : (i += 1) { - primitives_data[i].vertex_buffer.release(); - primitives_data[i].index_buffer.release(); - } - - bind_group.release(); - uniform_buffer.release(); - depth_texture.release(); - depth_texture_view.release(); - pipeline.release(); -} diff --git a/src/core/examples/procedural-primitives/shader.wgsl b/src/core/examples/procedural-primitives/shader.wgsl deleted file mode 100644 index 5370c204..00000000 --- a/src/core/examples/procedural-primitives/shader.wgsl +++ /dev/null @@ -1,33 +0,0 @@ -struct Uniforms { - mvp_matrix : mat4x4, -}; - -@binding(0) @group(0) var ubo : Uniforms; - -struct VertexInput { - @location(0) position: vec3, - @location(1) normal: vec3, -}; - -struct VertexOutput { - @builtin(position) position: vec4, - @location(0) normal: vec3, -}; - -@vertex fn vertex_main(in : VertexInput) -> VertexOutput { - var out: VertexOutput; - out.position = vec4(in.position, 1.0) * ubo.mvp_matrix; - out.normal = in.normal; - return out; -} - -struct FragmentOutput { - @location(0) pixel_color: vec4 -}; - -@fragment fn frag_main(in: VertexOutput) -> FragmentOutput { - var out : FragmentOutput; - - out.pixel_color = vec4((in.normal + 1) / 2, 1.0); - return out; -} \ No newline at end of file diff --git a/src/core/examples/rgb-quad/main.zig b/src/core/examples/rgb-quad/main.zig deleted file mode 100644 index 50cbfdff..00000000 --- a/src/core/examples/rgb-quad/main.zig +++ /dev/null @@ -1,140 +0,0 @@ -const std = @import("std"); - -const mach = @import("mach"); -const core = mach.core; -const gpu = mach.gpu; - -const Vertex = extern struct { - pos: @Vector(2, f32), - col: @Vector(3, f32), -}; -const vertices = [_]Vertex{ - .{ .pos = .{ -0.5, -0.5 }, .col = .{ 1, 0, 0 } }, - .{ .pos = .{ 0.5, -0.5 }, .col = .{ 0, 1, 0 } }, - .{ .pos = .{ 0.5, 0.5 }, .col = .{ 0, 0, 1 } }, - .{ .pos = .{ -0.5, 0.5 }, .col = .{ 1, 1, 1 } }, -}; -const index_data = [_]u32{ 0, 1, 2, 2, 3, 0 }; - -pub const App = @This(); - -var gpa = std.heap.GeneralPurposeAllocator(.{}){}; - -title_timer: core.Timer, -pipeline: *gpu.RenderPipeline, -vertex_buffer: *gpu.Buffer, -index_buffer: *gpu.Buffer, - -pub fn init(app: *App) !void { - try core.init(.{}); - - const shader_module = core.device.createShaderModuleWGSL("shader.wgsl", @embedFile("shader.wgsl")); - defer shader_module.release(); - - const vertex_attributes = [_]gpu.VertexAttribute{ - .{ .format = .float32x2, .offset = @offsetOf(Vertex, "pos"), .shader_location = 0 }, - .{ .format = .float32x3, .offset = @offsetOf(Vertex, "col"), .shader_location = 1 }, - }; - const vertex_buffer_layout = gpu.VertexBufferLayout.init(.{ - .array_stride = @sizeOf(Vertex), - .step_mode = .vertex, - .attributes = &vertex_attributes, - }); - - const color_target = gpu.ColorTargetState{ - .format = core.descriptor.format, - .blend = &.{}, - .write_mask = gpu.ColorWriteMaskFlags.all, - }; - const fragment = gpu.FragmentState.init(.{ - .module = shader_module, - .entry_point = "frag_main", - .targets = &.{color_target}, - }); - - const pipeline_layout = core.device.createPipelineLayout(&gpu.PipelineLayout.Descriptor.init(.{})); - defer pipeline_layout.release(); - - const pipeline_descriptor = gpu.RenderPipeline.Descriptor{ - .fragment = &fragment, - .layout = pipeline_layout, - .vertex = gpu.VertexState.init(.{ - .module = shader_module, - .entry_point = "vertex_main", - .buffers = &.{vertex_buffer_layout}, - }), - .primitive = .{ .cull_mode = .back }, - }; - - const vertex_buffer = core.device.createBuffer(&.{ - .usage = .{ .vertex = true }, - .size = @sizeOf(Vertex) * vertices.len, - .mapped_at_creation = .true, - }); - const vertex_mapped = vertex_buffer.getMappedRange(Vertex, 0, vertices.len); - @memcpy(vertex_mapped.?, vertices[0..]); - vertex_buffer.unmap(); - - const index_buffer = core.device.createBuffer(&.{ - .usage = .{ .index = true }, - .size = @sizeOf(u32) * index_data.len, - .mapped_at_creation = .true, - }); - const index_mapped = index_buffer.getMappedRange(u32, 0, index_data.len); - @memcpy(index_mapped.?, index_data[0..]); - index_buffer.unmap(); - - app.title_timer = try core.Timer.start(); - app.pipeline = core.device.createRenderPipeline(&pipeline_descriptor); - app.vertex_buffer = vertex_buffer; - app.index_buffer = index_buffer; -} - -pub fn deinit(app: *App) void { - app.vertex_buffer.release(); - app.index_buffer.release(); - app.pipeline.release(); - core.deinit(); - _ = gpa.deinit(); -} - -pub fn update(app: *App) !bool { - var iter = core.pollEvents(); - while (iter.next()) |event| if (event == .close) return true; - - const back_buffer_view = core.swap_chain.getCurrentTextureView().?; - const encoder = core.device.createCommandEncoder(null); - const color_attachment = gpu.RenderPassColorAttachment{ - .view = back_buffer_view, - .clear_value = .{ .r = 0, .g = 0, .b = 0, .a = 1 }, - .load_op = .clear, - .store_op = .store, - }; - const render_pass_info = gpu.RenderPassDescriptor.init(.{ .color_attachments = &.{color_attachment} }); - - const pass = encoder.beginRenderPass(&render_pass_info); - pass.setPipeline(app.pipeline); - pass.setVertexBuffer(0, app.vertex_buffer, 0, @sizeOf(Vertex) * vertices.len); - pass.setIndexBuffer(app.index_buffer, .uint32, 0, @sizeOf(u32) * index_data.len); - pass.drawIndexed(index_data.len, 1, 0, 0, 0); - pass.end(); - pass.release(); - - var command = encoder.finish(null); - encoder.release(); - core.queue.submit(&.{command}); - command.release(); - core.swap_chain.present(); - back_buffer_view.release(); - - // update the window title every second - if (app.title_timer.read() >= 1.0) { - app.title_timer.reset(); - try core.printTitle("RGB Quad [ {d}fps ] [ Input {d}hz ]", .{ - core.frameRate(), - core.inputRate(), - }); - } - - return false; -} diff --git a/src/core/examples/rgb-quad/shader.wgsl b/src/core/examples/rgb-quad/shader.wgsl deleted file mode 100644 index 85f687bc..00000000 --- a/src/core/examples/rgb-quad/shader.wgsl +++ /dev/null @@ -1,15 +0,0 @@ -struct Output { - @builtin(position) pos: vec4, - @location(0) color: vec3, -}; - -@vertex fn vertex_main(@location(0) pos: vec2, @location(1) color: vec3) -> Output { - var output: Output; - output.pos = vec4(pos, 0, 1); - output.color = color; - return output; -} - -@fragment fn frag_main(@location(0) color: vec3) -> @location(0) vec4 { - return vec4(color, 1); -} \ No newline at end of file diff --git a/src/core/examples/rotating-cube/cube_mesh.zig b/src/core/examples/rotating-cube/cube_mesh.zig deleted file mode 100644 index f26c75ac..00000000 --- a/src/core/examples/rotating-cube/cube_mesh.zig +++ /dev/null @@ -1,49 +0,0 @@ -pub const Vertex = extern struct { - pos: @Vector(4, f32), - col: @Vector(4, f32), - uv: @Vector(2, f32), -}; - -pub const vertices = [_]Vertex{ - .{ .pos = .{ 1, -1, 1, 1 }, .col = .{ 1, 0, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, -1, -1, 1 }, .col = .{ 0, 0, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, -1, 1, 1 }, .col = .{ 1, 0, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, -1, -1, 1 }, .col = .{ 0, 0, 0, 1 }, .uv = .{ 0, 0 } }, - - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ 1, -1, 1, 1 }, .col = .{ 1, 0, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, 1, -1, 1 }, .col = .{ 1, 1, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 0, 0 } }, - - .{ .pos = .{ -1, 1, 1, 1 }, .col = .{ 0, 1, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ 1, 1, -1, 1 }, .col = .{ 1, 1, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ -1, 1, 1, 1 }, .col = .{ 0, 1, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ 1, 1, -1, 1 }, .col = .{ 1, 1, 0, 1 }, .uv = .{ 0, 0 } }, - - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, 1, 1, 1 }, .col = .{ 0, 1, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ -1, -1, -1, 1 }, .col = .{ 0, 0, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 0, 0 } }, - - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, 1, 1, 1 }, .col = .{ 0, 1, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, -1, 1, 1 }, .col = .{ 1, 0, 1, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 1, 1 } }, - - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, -1, -1, 1 }, .col = .{ 0, 0, 0, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, 1, -1, 1 }, .col = .{ 1, 1, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 0, 0 } }, -}; diff --git a/src/core/examples/rotating-cube/main.zig b/src/core/examples/rotating-cube/main.zig deleted file mode 100755 index 2b119b4a..00000000 --- a/src/core/examples/rotating-cube/main.zig +++ /dev/null @@ -1,195 +0,0 @@ -const std = @import("std"); - -const mach = @import("mach"); -const core = mach.core; -const gpu = mach.gpu; - -const zm = @import("zmath"); -const Vertex = @import("cube_mesh.zig").Vertex; -const vertices = @import("cube_mesh.zig").vertices; - -pub const App = @This(); - -var gpa = std.heap.GeneralPurposeAllocator(.{}){}; -const UniformBufferObject = struct { - mat: zm.Mat, -}; - -title_timer: core.Timer, -timer: core.Timer, -pipeline: *gpu.RenderPipeline, -vertex_buffer: *gpu.Buffer, -uniform_buffer: *gpu.Buffer, -bind_group: *gpu.BindGroup, - -pub fn init(app: *App) !void { - try core.init(.{}); - - const shader_module = core.device.createShaderModuleWGSL("shader.wgsl", @embedFile("shader.wgsl")); - - const vertex_attributes = [_]gpu.VertexAttribute{ - .{ .format = .float32x4, .offset = @offsetOf(Vertex, "pos"), .shader_location = 0 }, - .{ .format = .float32x2, .offset = @offsetOf(Vertex, "uv"), .shader_location = 1 }, - }; - const vertex_buffer_layout = gpu.VertexBufferLayout.init(.{ - .array_stride = @sizeOf(Vertex), - .step_mode = .vertex, - .attributes = &vertex_attributes, - }); - - const blend = gpu.BlendState{}; - const color_target = gpu.ColorTargetState{ - .format = core.descriptor.format, - .blend = &blend, - .write_mask = gpu.ColorWriteMaskFlags.all, - }; - const fragment = gpu.FragmentState.init(.{ - .module = shader_module, - .entry_point = "frag_main", - .targets = &.{color_target}, - }); - - const bgle = gpu.BindGroupLayout.Entry.buffer(0, .{ .vertex = true }, .uniform, true, 0); - const bgl = core.device.createBindGroupLayout( - &gpu.BindGroupLayout.Descriptor.init(.{ - .entries = &.{bgle}, - }), - ); - - const bind_group_layouts = [_]*gpu.BindGroupLayout{bgl}; - const pipeline_layout = core.device.createPipelineLayout(&gpu.PipelineLayout.Descriptor.init(.{ - .bind_group_layouts = &bind_group_layouts, - })); - - const pipeline_descriptor = gpu.RenderPipeline.Descriptor{ - .fragment = &fragment, - .layout = pipeline_layout, - .vertex = gpu.VertexState.init(.{ - .module = shader_module, - .entry_point = "vertex_main", - .buffers = &.{vertex_buffer_layout}, - }), - .primitive = .{ - .cull_mode = .back, - }, - }; - - const vertex_buffer = core.device.createBuffer(&.{ - .usage = .{ .vertex = true }, - .size = @sizeOf(Vertex) * vertices.len, - .mapped_at_creation = .true, - }); - const vertex_mapped = vertex_buffer.getMappedRange(Vertex, 0, vertices.len); - @memcpy(vertex_mapped.?, vertices[0..]); - vertex_buffer.unmap(); - - const uniform_buffer = core.device.createBuffer(&.{ - .usage = .{ .copy_dst = true, .uniform = true }, - .size = @sizeOf(UniformBufferObject), - .mapped_at_creation = .false, - }); - const bind_group = core.device.createBindGroup( - &gpu.BindGroup.Descriptor.init(.{ - .layout = bgl, - .entries = &.{ - gpu.BindGroup.Entry.buffer(0, uniform_buffer, 0, @sizeOf(UniformBufferObject)), - }, - }), - ); - - app.title_timer = try core.Timer.start(); - app.timer = try core.Timer.start(); - app.pipeline = core.device.createRenderPipeline(&pipeline_descriptor); - app.vertex_buffer = vertex_buffer; - app.uniform_buffer = uniform_buffer; - app.bind_group = bind_group; - - shader_module.release(); - pipeline_layout.release(); - bgl.release(); -} - -pub fn deinit(app: *App) void { - defer _ = gpa.deinit(); - defer core.deinit(); - - app.vertex_buffer.release(); - app.uniform_buffer.release(); - app.bind_group.release(); - app.pipeline.release(); -} - -pub fn update(app: *App) !bool { - var iter = core.pollEvents(); - while (iter.next()) |event| { - switch (event) { - .key_press => |ev| { - if (ev.key == .space) return true; - }, - .close => return true, - else => {}, - } - } - - const back_buffer_view = core.swap_chain.getCurrentTextureView().?; - const color_attachment = gpu.RenderPassColorAttachment{ - .view = back_buffer_view, - .clear_value = std.mem.zeroes(gpu.Color), - .load_op = .clear, - .store_op = .store, - }; - - const queue = core.queue; - const encoder = core.device.createCommandEncoder(null); - const render_pass_info = gpu.RenderPassDescriptor.init(.{ - .color_attachments = &.{color_attachment}, - }); - - { - const time = app.timer.read(); - const model = zm.mul(zm.rotationX(time * (std.math.pi / 2.0)), zm.rotationZ(time * (std.math.pi / 2.0))); - const view = zm.lookAtRh( - zm.Vec{ 0, 4, 2, 1 }, - zm.Vec{ 0, 0, 0, 1 }, - zm.Vec{ 0, 0, 1, 0 }, - ); - const proj = zm.perspectiveFovRh( - (std.math.pi / 4.0), - @as(f32, @floatFromInt(core.descriptor.width)) / @as(f32, @floatFromInt(core.descriptor.height)), - 0.1, - 10, - ); - const mvp = zm.mul(zm.mul(model, view), proj); - const ubo = UniformBufferObject{ - .mat = zm.transpose(mvp), - }; - queue.writeBuffer(app.uniform_buffer, 0, &[_]UniformBufferObject{ubo}); - } - - const pass = encoder.beginRenderPass(&render_pass_info); - pass.setPipeline(app.pipeline); - pass.setVertexBuffer(0, app.vertex_buffer, 0, @sizeOf(Vertex) * vertices.len); - pass.setBindGroup(0, app.bind_group, &.{0}); - pass.draw(vertices.len, 1, 0, 0); - pass.end(); - pass.release(); - - var command = encoder.finish(null); - encoder.release(); - - queue.submit(&[_]*gpu.CommandBuffer{command}); - command.release(); - core.swap_chain.present(); - back_buffer_view.release(); - - // update the window title every second - if (app.title_timer.read() >= 1.0) { - app.title_timer.reset(); - try core.printTitle("Rotating Cube [ {d}fps ] [ Input {d}hz ]", .{ - core.frameRate(), - core.inputRate(), - }); - } - - return false; -} diff --git a/src/core/examples/rotating-cube/shader.wgsl b/src/core/examples/rotating-cube/shader.wgsl deleted file mode 100644 index 6b7291ee..00000000 --- a/src/core/examples/rotating-cube/shader.wgsl +++ /dev/null @@ -1,24 +0,0 @@ -@group(0) @binding(0) var ubo : mat4x4; -struct VertexOut { - @builtin(position) position_clip : vec4, - @location(0) fragUV : vec2, - @location(1) fragPosition: vec4, -} - -@vertex fn vertex_main( - @location(0) position : vec4, - @location(1) uv: vec2 -) -> VertexOut { - var output : VertexOut; - output.position_clip = position * ubo; - output.fragUV = uv; - output.fragPosition = 0.5 * (position + vec4(1.0, 1.0, 1.0, 1.0)); - return output; -} - -@fragment fn frag_main( - @location(0) fragUV: vec2, - @location(1) fragPosition: vec4 -) -> @location(0) vec4 { - return fragPosition; -} \ No newline at end of file diff --git a/src/core/examples/sprite2d/main.zig b/src/core/examples/sprite2d/main.zig deleted file mode 100644 index efb8132d..00000000 --- a/src/core/examples/sprite2d/main.zig +++ /dev/null @@ -1,357 +0,0 @@ -const std = @import("std"); - -const mach = @import("mach"); -const core = mach.core; -const gpu = mach.gpu; - -const zm = @import("zmath"); -const zigimg = @import("zigimg"); -const assets = @import("assets"); -const json = std.json; - -pub const App = @This(); - -const speed = 2.0 * 100.0; // pixels per second - -const Vec2 = @Vector(2, f32); - -const UniformBufferObject = struct { - mat: zm.Mat, -}; -const Sprite = extern struct { - pos: Vec2, - size: Vec2, - world_pos: Vec2, - sheet_size: Vec2, -}; -const SpriteFrames = extern struct { - up: Vec2, - down: Vec2, - left: Vec2, - right: Vec2, -}; -const JSONFrames = struct { - up: []f32, - down: []f32, - left: []f32, - right: []f32, -}; -const JSONSprite = struct { - pos: []f32, - size: []f32, - world_pos: []f32, - is_player: bool = false, - frames: JSONFrames, -}; -const SpriteSheet = struct { - width: f32, - height: f32, -}; -const JSONData = struct { - sheet: SpriteSheet, - sprites: []JSONSprite, -}; -var gpa = std.heap.GeneralPurposeAllocator(.{}){}; - -title_timer: core.Timer, -timer: core.Timer, -fps_timer: core.Timer, -pipeline: *gpu.RenderPipeline, -uniform_buffer: *gpu.Buffer, -bind_group: *gpu.BindGroup, -sheet: SpriteSheet, -sprites_buffer: *gpu.Buffer, -sprites: std.ArrayList(Sprite), -sprites_frames: std.ArrayList(SpriteFrames), -player_pos: Vec2, -direction: Vec2, -player_sprite_index: usize, - -pub fn init(app: *App) !void { - try core.init(.{}); - - const allocator = gpa.allocator(); - - const sprites_file = try std.fs.cwd().openFile("../../examples/sprite2d/sprites.json", .{ .mode = .read_only }); - defer sprites_file.close(); - const file_size = (try sprites_file.stat()).size; - const buffer = try allocator.alloc(u8, file_size); - defer allocator.free(buffer); - try sprites_file.reader().readNoEof(buffer); - const root = try std.json.parseFromSlice(JSONData, allocator, buffer, .{}); - defer root.deinit(); - - app.player_pos = Vec2{ 0, 0 }; - app.direction = Vec2{ 0, 0 }; - app.sheet = root.value.sheet; - std.log.info("Sheet Dimensions: {} {}", .{ app.sheet.width, app.sheet.height }); - app.sprites = std.ArrayList(Sprite).init(allocator); - app.sprites_frames = std.ArrayList(SpriteFrames).init(allocator); - for (root.value.sprites) |sprite| { - std.log.info("Sprite World Position: {} {}", .{ sprite.world_pos[0], sprite.world_pos[1] }); - std.log.info("Sprite Texture Position: {} {}", .{ sprite.pos[0], sprite.pos[1] }); - std.log.info("Sprite Dimensions: {} {}", .{ sprite.size[0], sprite.size[1] }); - if (sprite.is_player) { - app.player_sprite_index = app.sprites.items.len; - } - try app.sprites.append(.{ - .pos = Vec2{ sprite.pos[0], sprite.pos[1] }, - .size = Vec2{ sprite.size[0], sprite.size[1] }, - .world_pos = Vec2{ sprite.world_pos[0], sprite.world_pos[1] }, - .sheet_size = Vec2{ app.sheet.width, app.sheet.height }, - }); - try app.sprites_frames.append(.{ .up = Vec2{ sprite.frames.up[0], sprite.frames.up[1] }, .down = Vec2{ sprite.frames.down[0], sprite.frames.down[1] }, .left = Vec2{ sprite.frames.left[0], sprite.frames.left[1] }, .right = Vec2{ sprite.frames.right[0], sprite.frames.right[1] } }); - } - std.log.info("Number of sprites: {}", .{app.sprites.items.len}); - - const shader_module = core.device.createShaderModuleWGSL("sprite-shader.wgsl", @embedFile("sprite-shader.wgsl")); - - const blend = gpu.BlendState{ - .color = .{ - .operation = .add, - .src_factor = .src_alpha, - .dst_factor = .one_minus_src_alpha, - }, - .alpha = .{ - .operation = .add, - .src_factor = .one, - .dst_factor = .zero, - }, - }; - const color_target = gpu.ColorTargetState{ - .format = core.descriptor.format, - .blend = &blend, - .write_mask = gpu.ColorWriteMaskFlags.all, - }; - const fragment = gpu.FragmentState.init(.{ - .module = shader_module, - .entry_point = "frag_main", - .targets = &.{color_target}, - }); - - const pipeline_descriptor = gpu.RenderPipeline.Descriptor{ - .fragment = &fragment, - .vertex = gpu.VertexState.init(.{ - .module = shader_module, - .entry_point = "vertex_main", - }), - }; - const pipeline = core.device.createRenderPipeline(&pipeline_descriptor); - - const sprites_buffer = core.device.createBuffer(&.{ - .usage = .{ .storage = true, .copy_dst = true }, - .size = @sizeOf(Sprite) * app.sprites.items.len, - .mapped_at_creation = .true, - }); - const sprites_mapped = sprites_buffer.getMappedRange(Sprite, 0, app.sprites.items.len); - @memcpy(sprites_mapped.?, app.sprites.items[0..]); - sprites_buffer.unmap(); - - // Create a sampler with linear filtering for smooth interpolation. - const sampler = core.device.createSampler(&.{ - .mag_filter = .linear, - .min_filter = .linear, - }); - const queue = core.queue; - var img = try zigimg.Image.fromMemory(allocator, assets.sprites_sheet_png); - defer img.deinit(); - const img_size = gpu.Extent3D{ .width = @as(u32, @intCast(img.width)), .height = @as(u32, @intCast(img.height)) }; - std.log.info("Image Dimensions: {} {}", .{ img.width, img.height }); - const texture = core.device.createTexture(&.{ - .size = img_size, - .format = .rgba8_unorm, - .usage = .{ - .texture_binding = true, - .copy_dst = true, - .render_attachment = true, - }, - }); - const data_layout = gpu.Texture.DataLayout{ - .bytes_per_row = @as(u32, @intCast(img.width * 4)), - .rows_per_image = @as(u32, @intCast(img.height)), - }; - switch (img.pixels) { - .rgba32 => |pixels| queue.writeTexture(&.{ .texture = texture }, &data_layout, &img_size, pixels), - .rgb24 => |pixels| { - const data = try rgb24ToRgba32(allocator, pixels); - defer data.deinit(allocator); - queue.writeTexture(&.{ .texture = texture }, &data_layout, &img_size, data.rgba32); - }, - else => @panic("unsupported image color format"), - } - - const uniform_buffer = core.device.createBuffer(&.{ - .usage = .{ .copy_dst = true, .uniform = true }, - .size = @sizeOf(UniformBufferObject), - .mapped_at_creation = .false, - }); - - const texture_view = texture.createView(&gpu.TextureView.Descriptor{}); - texture.release(); - - const bind_group_layout = pipeline.getBindGroupLayout(0); - const bind_group = core.device.createBindGroup( - &gpu.BindGroup.Descriptor.init(.{ - .layout = bind_group_layout, - .entries = &.{ - gpu.BindGroup.Entry.buffer(0, uniform_buffer, 0, @sizeOf(UniformBufferObject)), - gpu.BindGroup.Entry.sampler(1, sampler), - gpu.BindGroup.Entry.textureView(2, texture_view), - gpu.BindGroup.Entry.buffer(3, sprites_buffer, 0, @sizeOf(Sprite) * app.sprites.items.len), - }, - }), - ); - texture_view.release(); - sampler.release(); - bind_group_layout.release(); - - app.title_timer = try core.Timer.start(); - app.timer = try core.Timer.start(); - app.fps_timer = try core.Timer.start(); - app.pipeline = pipeline; - app.uniform_buffer = uniform_buffer; - app.bind_group = bind_group; - app.sprites_buffer = sprites_buffer; - - shader_module.release(); -} - -pub fn deinit(app: *App) void { - defer _ = gpa.deinit(); - defer core.deinit(); - - app.pipeline.release(); - app.sprites.deinit(); - app.sprites_frames.deinit(); - app.uniform_buffer.release(); - app.bind_group.release(); - app.sprites_buffer.release(); -} - -pub fn update(app: *App) !bool { - // Handle input by determining the direction the player wants to go. - var iter = core.pollEvents(); - while (iter.next()) |event| { - switch (event) { - .key_press => |ev| { - switch (ev.key) { - .space => return true, - .left => app.direction[0] += 1, - .right => app.direction[0] -= 1, - .up => app.direction[1] += 1, - .down => app.direction[1] -= 1, - else => {}, - } - }, - .key_release => |ev| { - switch (ev.key) { - .left => app.direction[0] -= 1, - .right => app.direction[0] += 1, - .up => app.direction[1] -= 1, - .down => app.direction[1] += 1, - else => {}, - } - }, - .close => return true, - else => {}, - } - } - - // Calculate the player position, by moving in the direction the player wants to go - // by the speed amount. Multiply by delta_time to ensure that movement is the same speed - // regardless of the frame rate. - const delta_time = app.fps_timer.lap(); - app.player_pos += app.direction * Vec2{ speed, speed } * Vec2{ delta_time, delta_time }; - - // Render the frame - try app.render(); - - // update the window title every second - if (app.title_timer.read() >= 1.0) { - app.title_timer.reset(); - try core.printTitle("Sprite2D [ {d}fps ] [ Input {d}hz ]", .{ - core.frameRate(), - core.inputRate(), - }); - } - - return false; -} - -fn render(app: *App) !void { - const back_buffer_view = core.swap_chain.getCurrentTextureView().?; - const color_attachment = gpu.RenderPassColorAttachment{ - .view = back_buffer_view, - // sky blue background color: - .clear_value = .{ .r = 0.52, .g = 0.8, .b = 0.92, .a = 1.0 }, - .load_op = .clear, - .store_op = .store, - }; - - const encoder = core.device.createCommandEncoder(null); - const render_pass_info = gpu.RenderPassDescriptor.init(.{ - .color_attachments = &.{color_attachment}, - }); - - const player_sprite = &app.sprites.items[app.player_sprite_index]; - const player_sprite_frame = &app.sprites_frames.items[app.player_sprite_index]; - if (app.direction[0] == -1.0) { - player_sprite.pos = player_sprite_frame.left; - } else if (app.direction[0] == 1.0) { - player_sprite.pos = player_sprite_frame.right; - } else if (app.direction[1] == -1.0) { - player_sprite.pos = player_sprite_frame.down; - } else if (app.direction[1] == 1.0) { - player_sprite.pos = player_sprite_frame.up; - } - player_sprite.world_pos = app.player_pos; - - // One pixel in our scene will equal one window pixel (i.e. be roughly the same size - // irrespective of whether the user has a Retina/HDPI display.) - const proj = zm.orthographicRh( - @as(f32, @floatFromInt(core.size().width)), - @as(f32, @floatFromInt(core.size().height)), - 0.1, - 1000, - ); - const view = zm.lookAtRh( - zm.Vec{ 0, 1000, 0, 1 }, - zm.Vec{ 0, 0, 0, 1 }, - zm.Vec{ 0, 0, 1, 0 }, - ); - const mvp = zm.mul(view, proj); - const ubo = UniformBufferObject{ - .mat = zm.transpose(mvp), - }; - - // Pass the latest uniform values & sprite values to the shader program. - encoder.writeBuffer(app.uniform_buffer, 0, &[_]UniformBufferObject{ubo}); - encoder.writeBuffer(app.sprites_buffer, 0, app.sprites.items); - - // Draw the sprite batch - const total_vertices = @as(u32, @intCast(app.sprites.items.len * 6)); - const pass = encoder.beginRenderPass(&render_pass_info); - pass.setPipeline(app.pipeline); - pass.setBindGroup(0, app.bind_group, &.{}); - pass.draw(total_vertices, 1, 0, 0); - pass.end(); - pass.release(); - - // Submit the frame. - var command = encoder.finish(null); - encoder.release(); - const queue = core.queue; - queue.submit(&[_]*gpu.CommandBuffer{command}); - command.release(); - core.swap_chain.present(); - back_buffer_view.release(); -} - -fn rgb24ToRgba32(allocator: std.mem.Allocator, in: []zigimg.color.Rgb24) !zigimg.color.PixelStorage { - const out = try zigimg.color.PixelStorage.init(allocator, .rgba32, in.len); - var i: usize = 0; - while (i < in.len) : (i += 1) { - out.rgba32[i] = zigimg.color.Rgba32{ .r = in[i].r, .g = in[i].g, .b = in[i].b, .a = 255 }; - } - return out; -} diff --git a/src/core/examples/sprite2d/sprite-shader.wgsl b/src/core/examples/sprite2d/sprite-shader.wgsl deleted file mode 100644 index 979c14de..00000000 --- a/src/core/examples/sprite2d/sprite-shader.wgsl +++ /dev/null @@ -1,82 +0,0 @@ -struct Uniforms { - modelViewProjectionMatrix : mat4x4, -}; -@binding(0) @group(0) var uniforms : Uniforms; - -struct VertexOutput { - @builtin(position) Position : vec4, - @location(0) fragUV : vec2, - @location(1) spriteIndex : f32, -}; - -struct Sprite { - pos: vec2, - size: vec2, - world_pos: vec2, - sheet_size: vec2, -}; -@binding(3) @group(0) var sprites: array; - -@vertex -fn vertex_main( - @builtin(vertex_index) VertexIndex : u32 -) -> VertexOutput { - var sprite = sprites[VertexIndex / 6]; - - // Calculate the vertex position - var positions = array, 6>( - vec2(0.0, 0.0), // bottom-left - vec2(0.0, 1.0), // top-left - vec2(1.0, 0.0), // bottom-right - vec2(1.0, 0.0), // bottom-right - vec2(0.0, 1.0), // top-left - vec2(1.0, 1.0), // top-right - ); - var pos = positions[VertexIndex % 6]; - pos.x *= sprite.size.x; - pos.y *= sprite.size.y; - pos.x += sprite.world_pos.x; - pos.y += sprite.world_pos.y; - - // Calculate the UV coordinate - var uvs = array, 6>( - vec2(0.0, 1.0), // bottom-left - vec2(0.0, 0.0), // top-left - vec2(1.0, 1.0), // bottom-right - vec2(1.0, 1.0), // bottom-right - vec2(0.0, 0.0), // top-left - vec2(1.0, 0.0), // top-right - ); - var uv = uvs[VertexIndex % 6]; - uv.x *= sprite.size.x / sprite.sheet_size.x; - uv.y *= sprite.size.y / sprite.sheet_size.y; - uv.x += sprite.pos.x / sprite.sheet_size.x; - uv.y += sprite.pos.y / sprite.sheet_size.y; - - var output : VertexOutput; - output.Position = vec4(pos.x, 0.0, pos.y, 1.0) * uniforms.modelViewProjectionMatrix; - output.fragUV = uv; - output.spriteIndex = f32(VertexIndex / 6); - return output; -} - -@group(0) @binding(1) var spriteSampler: sampler; -@group(0) @binding(2) var spriteTexture: texture_2d; - -@fragment -fn frag_main( - @location(0) fragUV: vec2, - @location(1) spriteIndex: f32 -) -> @location(0) vec4 { - var color = textureSample(spriteTexture, spriteSampler, fragUV); - if (spriteIndex == 0.0) { - if (color[3] > 0.0) { - color[0] = 0.3; - color[1] = 0.2; - color[2] = 0.5; - color[3] = 1.0; - } - } - - return color; -} \ No newline at end of file diff --git a/src/core/examples/sprite2d/sprites.json b/src/core/examples/sprite2d/sprites.json deleted file mode 100644 index 37d5ab13..00000000 --- a/src/core/examples/sprite2d/sprites.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "sheet": { - "width": 352.0, - "height": 32.0 - }, - "sprites": [ - { - "pos": [ 0.0, 0.0 ], - "size": [ 32.0, 32.0 ], - "world_pos": [ 0.0, 0.0 ], - "is_player": true, - "frames": { - "down": [ 0.0, 0.0 ], - "left": [ 32.0, 0.0 ], - "right": [ 64.0, 0.0 ], - "up": [ 96.0, 0.0 ] - } - }, - { - "pos": [ 128.0, 0.0 ], - "size": [ 32.0, 32.0 ], - "world_pos": [ 32.0, 32.0 ], - "frames": { - "down": [ 128.0, 0.0 ], - "left": [ 160.0, 0.0 ], - "right": [ 192.0, 0.0 ], - "up": [ 224.0, 0.0 ] - } - }, - { - "pos": [ 128.0, 0.0 ], - "size": [ 32.0, 32.0 ], - "world_pos": [ 64.0, 64.0 ], - "frames": { - "down": [ 0.0, 0.0 ], - "left": [ 0.0, 0.0 ], - "right": [ 0.0, 0.0 ], - "up": [ 0.0, 0.0 ] - } - }, - { - "pos": [ 256.0, 0.0 ], - "size": [ 32.0, 32.0 ], - "world_pos": [ 96.0, 96.0 ], - "frames": { - "down": [ 0.0, 0.0 ], - "left": [ 0.0, 0.0 ], - "right": [ 0.0, 0.0 ], - "up": [ 0.0, 0.0 ] - } - } - ] -} \ No newline at end of file diff --git a/src/core/examples/sysgpu/boids/main.zig b/src/core/examples/sysgpu/boids/main.zig deleted file mode 100644 index e0e910bd..00000000 --- a/src/core/examples/sysgpu/boids/main.zig +++ /dev/null @@ -1,268 +0,0 @@ -/// A port of Austin Eng's "computeBoids" webgpu sample. -/// https://github.com/austinEng/webgpu-samples/blob/main/src/sample/computeBoids/main.ts -const std = @import("std"); - -const mach = @import("mach"); -const core = mach.core; -const gpu = mach.gpu; - -title_timer: core.Timer, -timer: core.Timer, -compute_pipeline: *gpu.ComputePipeline, -render_pipeline: *gpu.RenderPipeline, -sprite_vertex_buffer: *gpu.Buffer, -particle_buffers: [2]*gpu.Buffer, -particle_bind_groups: [2]*gpu.BindGroup, -sim_param_buffer: *gpu.Buffer, -frame_counter: usize, - -pub const App = @This(); - -// Use experimental sysgpu graphics API -pub const use_sysgpu = true; - -var gpa = std.heap.GeneralPurposeAllocator(.{}){}; - -const num_particle = 1500; - -var sim_params = [_]f32{ - 0.04, // .delta_T - 0.1, // .rule_1_distance - 0.025, // .rule_2_distance - 0.025, // .rule_3_distance - 0.02, // .rule_1_scale - 0.05, // .rule_2_scale - 0.005, // .rule_3_scale -}; - -pub fn init(app: *App) !void { - try core.init(.{}); - - const sprite_shader_module = core.device.createShaderModuleWGSL( - "sprite.wgsl", - @embedFile("sprite.wgsl"), - ); - defer sprite_shader_module.release(); - - const update_sprite_shader_module = core.device.createShaderModuleWGSL( - "updateSprites.wgsl", - @embedFile("updateSprites.wgsl"), - ); - defer update_sprite_shader_module.release(); - - const instanced_particles_attributes = [_]gpu.VertexAttribute{ - .{ - // instance position - .shader_location = 0, - .offset = 0, - .format = .float32x2, - }, - .{ - // instance velocity - .shader_location = 1, - .offset = 2 * 4, - .format = .float32x2, - }, - }; - - const vertex_buffer_attributes = [_]gpu.VertexAttribute{ - .{ - // vertex positions - .shader_location = 2, - .offset = 0, - .format = .float32x2, - }, - }; - - const render_pipeline = core.device.createRenderPipeline(&gpu.RenderPipeline.Descriptor{ - .vertex = gpu.VertexState.init(.{ - .module = sprite_shader_module, - .entry_point = "vert_main", - .buffers = &.{ - gpu.VertexBufferLayout.init(.{ - // instanced particles buffer - .array_stride = 4 * 4, - .step_mode = .instance, - .attributes = &instanced_particles_attributes, - }), - gpu.VertexBufferLayout.init(.{ - // vertex buffer - .array_stride = 2 * 4, - .step_mode = .vertex, - .attributes = &vertex_buffer_attributes, - }), - }, - }), - .fragment = &gpu.FragmentState.init(.{ - .module = sprite_shader_module, - .entry_point = "frag_main", - .targets = &[_]gpu.ColorTargetState{.{ - .format = core.descriptor.format, - }}, - }), - }); - - const compute_pipeline = core.device.createComputePipeline(&gpu.ComputePipeline.Descriptor{ .compute = gpu.ProgrammableStageDescriptor{ - .module = update_sprite_shader_module, - .entry_point = "main", - } }); - - const vert_buffer_data = [_]f32{ - -0.01, -0.02, 0.01, - -0.02, 0.0, 0.02, - }; - - const sprite_vertex_buffer = core.device.createBuffer(&gpu.Buffer.Descriptor{ - .label = "sprite_vertex_buffer", - .usage = .{ .vertex = true }, - .mapped_at_creation = .true, - .size = vert_buffer_data.len * @sizeOf(f32), - }); - const vertex_mapped = sprite_vertex_buffer.getMappedRange(f32, 0, vert_buffer_data.len); - @memcpy(vertex_mapped.?, vert_buffer_data[0..]); - sprite_vertex_buffer.unmap(); - - const sim_param_buffer = core.device.createBuffer(&gpu.Buffer.Descriptor{ - .label = "sim_param_buffer", - .usage = .{ .uniform = true, .copy_dst = true }, - .size = sim_params.len * @sizeOf(f32), - }); - core.queue.writeBuffer(sim_param_buffer, 0, sim_params[0..]); - - var initial_particle_data: [num_particle * 4]f32 = undefined; - var rng = std.rand.DefaultPrng.init(0); - const random = rng.random(); - var i: usize = 0; - while (i < num_particle) : (i += 1) { - initial_particle_data[4 * i + 0] = 2 * (random.float(f32) - 0.5); - initial_particle_data[4 * i + 1] = 2 * (random.float(f32) - 0.5); - initial_particle_data[4 * i + 2] = 2 * (random.float(f32) - 0.5) * 0.1; - initial_particle_data[4 * i + 3] = 2 * (random.float(f32) - 0.5) * 0.1; - } - - var particle_buffers: [2]*gpu.Buffer = undefined; - var particle_bind_groups: [2]*gpu.BindGroup = undefined; - i = 0; - while (i < 2) : (i += 1) { - particle_buffers[i] = core.device.createBuffer(&gpu.Buffer.Descriptor{ - .label = "particle_buffer", - .mapped_at_creation = .true, - .usage = .{ - .vertex = true, - .storage = true, - }, - .size = initial_particle_data.len * @sizeOf(f32), - }); - const mapped = particle_buffers[i].getMappedRange(f32, 0, initial_particle_data.len); - @memcpy(mapped.?, initial_particle_data[0..]); - particle_buffers[i].unmap(); - } - - i = 0; - while (i < 2) : (i += 1) { - const layout = compute_pipeline.getBindGroupLayout(0); - defer layout.release(); - - particle_bind_groups[i] = core.device.createBindGroup(&gpu.BindGroup.Descriptor.init(.{ - .layout = layout, - .entries = &.{ - gpu.BindGroup.Entry.buffer(0, sim_param_buffer, 0, sim_params.len * @sizeOf(f32), sim_params.len * @sizeOf(f32)), - gpu.BindGroup.Entry.buffer(1, particle_buffers[i], 0, initial_particle_data.len * @sizeOf(f32), 4 * @sizeOf(f32)), - gpu.BindGroup.Entry.buffer(2, particle_buffers[(i + 1) % 2], 0, initial_particle_data.len * @sizeOf(f32), 4 * @sizeOf(f32)), - }, - })); - } - - app.* = .{ - .timer = try core.Timer.start(), - .title_timer = try core.Timer.start(), - .compute_pipeline = compute_pipeline, - .render_pipeline = render_pipeline, - .sprite_vertex_buffer = sprite_vertex_buffer, - .particle_buffers = particle_buffers, - .particle_bind_groups = particle_bind_groups, - .sim_param_buffer = sim_param_buffer, - .frame_counter = 0, - }; -} - -pub fn deinit(app: *App) void { - defer _ = gpa.deinit(); - defer core.deinit(); - - app.compute_pipeline.release(); - app.render_pipeline.release(); - app.sprite_vertex_buffer.release(); - for (app.particle_buffers) |particle_buffer| particle_buffer.release(); - for (app.particle_bind_groups) |particle_bind_group| particle_bind_group.release(); - app.sim_param_buffer.release(); -} - -pub fn update(app: *App) !bool { - const delta_time = app.timer.lap(); - - var iter = core.pollEvents(); - while (iter.next()) |event| { - if (event == .close) return true; - } - - const back_buffer_view = core.swap_chain.getCurrentTextureView().?; - const color_attachment = gpu.RenderPassColorAttachment{ - .view = back_buffer_view, - .clear_value = std.mem.zeroes(gpu.Color), - .load_op = .clear, - .store_op = .store, - }; - - const render_pass_descriptor = gpu.RenderPassDescriptor.init(.{ - .color_attachments = &.{ - color_attachment, - }, - }); - - sim_params[0] = @as(f32, @floatCast(delta_time)); - core.queue.writeBuffer(app.sim_param_buffer, 0, sim_params[0..]); - - const command_encoder = core.device.createCommandEncoder(null); - { - const pass_encoder = command_encoder.beginComputePass(null); - pass_encoder.setPipeline(app.compute_pipeline); - pass_encoder.setBindGroup(0, app.particle_bind_groups[app.frame_counter % 2], null); - pass_encoder.dispatchWorkgroups(@as(u32, @intFromFloat(@ceil(@as(f32, num_particle) / 64))), 1, 1); - pass_encoder.end(); - pass_encoder.release(); - } - { - const pass_encoder = command_encoder.beginRenderPass(&render_pass_descriptor); - pass_encoder.setPipeline(app.render_pipeline); - pass_encoder.setVertexBuffer(0, app.particle_buffers[(app.frame_counter + 1) % 2], 0, num_particle * 4 * @sizeOf(f32)); - pass_encoder.setVertexBuffer(1, app.sprite_vertex_buffer, 0, 6 * @sizeOf(f32)); - pass_encoder.draw(3, num_particle, 0, 0); - pass_encoder.end(); - pass_encoder.release(); - } - - app.frame_counter += 1; - if (app.frame_counter % 60 == 0) { - std.log.info("Frame {}", .{app.frame_counter}); - } - - var command = command_encoder.finish(null); - command_encoder.release(); - core.queue.submit(&[_]*gpu.CommandBuffer{command}); - command.release(); - - core.swap_chain.present(); - back_buffer_view.release(); - - // update the window title every second - if (app.title_timer.read() >= 1.0) { - app.title_timer.reset(); - try core.printTitle("Boids [ {d}fps ] [ Input {d}hz ]", .{ - core.frameRate(), - core.inputRate(), - }); - } - - return false; -} diff --git a/src/core/examples/sysgpu/boids/sprite.wgsl b/src/core/examples/sysgpu/boids/sprite.wgsl deleted file mode 100644 index c97c5c18..00000000 --- a/src/core/examples/sysgpu/boids/sprite.wgsl +++ /dev/null @@ -1,15 +0,0 @@ -@vertex -fn vert_main(@location(0) a_particlePos : vec2, - @location(1) a_particleVel : vec2, - @location(2) a_pos : vec2) -> @builtin(position) vec4 { - let angle = -atan2(a_particleVel.x, a_particleVel.y); - let pos = vec2( - (a_pos.x * cos(angle)) - (a_pos.y * sin(angle)), - (a_pos.x * sin(angle)) + (a_pos.y * cos(angle))); - return vec4(pos + a_particlePos, 0.0, 1.0); -} - -@fragment -fn frag_main() -> @location(0) vec4 { - return vec4(1.0, 1.0, 1.0, 1.0); -} diff --git a/src/core/examples/sysgpu/boids/updateSprites.wgsl b/src/core/examples/sysgpu/boids/updateSprites.wgsl deleted file mode 100644 index 89071499..00000000 --- a/src/core/examples/sysgpu/boids/updateSprites.wgsl +++ /dev/null @@ -1,90 +0,0 @@ -struct Particle { - pos : vec2, - vel : vec2, -}; -struct SimParams { - deltaT : f32, - rule1Distance : f32, - rule2Distance : f32, - rule3Distance : f32, - rule1Scale : f32, - rule2Scale : f32, - rule3Scale : f32, -}; -struct Particles { - particles : array, -}; -@binding(0) @group(0) var params : SimParams; -@binding(1) @group(0) var particlesA : Particles; -@binding(2) @group(0) var particlesB : Particles; - -// https://github.com/austinEng/Project6-Vulkan-Flocking/blob/master/data/shaders/computeparticles/particle.comp -@compute @workgroup_size(64) -fn main(@builtin(global_invocation_id) GlobalInvocationID : vec3) { - var index : u32 = GlobalInvocationID.x; - - if (index >= arrayLength(&particlesA.particles)) { - return; - } - - var vPos = particlesA.particles[index].pos; - var vVel = particlesA.particles[index].vel; - var cMass = vec2(0.0, 0.0); - var cVel = vec2(0.0, 0.0); - var colVel = vec2(0.0, 0.0); - var cMassCount : u32 = 0u; - var cVelCount : u32 = 0u; - var pos : vec2; - var vel : vec2; - - for (var i : u32 = 0u; i < arrayLength(&particlesA.particles); i = i + 1u) { - if (i == index) { - continue; - } - - pos = particlesA.particles[i].pos.xy; - vel = particlesA.particles[i].vel.xy; - if (distance(pos, vPos) < params.rule1Distance) { - cMass = cMass + pos; - cMassCount = cMassCount + 1u; - } - if (distance(pos, vPos) < params.rule2Distance) { - colVel = colVel - (pos - vPos); - } - if (distance(pos, vPos) < params.rule3Distance) { - cVel = cVel + vel; - cVelCount = cVelCount + 1u; - } - } - if (cMassCount > 0u) { - var temp = f32(cMassCount); - cMass = (cMass / vec2(temp, temp)) - vPos; - } - if (cVelCount > 0u) { - var temp = f32(cVelCount); - cVel = cVel / vec2(temp, temp); - } - vVel = vVel + (cMass * params.rule1Scale) + (colVel * params.rule2Scale) + - (cVel * params.rule3Scale); - - // clamp velocity for a more pleasing simulation - vVel = normalize(vVel) * clamp(length(vVel), 0.0, 0.1); - // kinematic update - vPos = vPos + (vVel * params.deltaT); - // Wrap around boundary - if (vPos.x < -1.0) { - vPos.x = 1.0; - } - if (vPos.x > 1.0) { - vPos.x = -1.0; - } - if (vPos.y < -1.0) { - vPos.y = 1.0; - } - if (vPos.y > 1.0) { - vPos.y = -1.0; - } - // Write back - particlesB.particles[index].pos = vPos; - particlesB.particles[index].vel = vVel; -} diff --git a/src/core/examples/sysgpu/clear-color/main.zig b/src/core/examples/sysgpu/clear-color/main.zig deleted file mode 100644 index 8f7b8a56..00000000 --- a/src/core/examples/sysgpu/clear-color/main.zig +++ /dev/null @@ -1,84 +0,0 @@ -const std = @import("std"); - -const mach = @import("mach"); -const core = mach.core; -const gpu = mach.gpu; - -const renderer = @import("renderer.zig"); - -pub const App = @This(); - -// Use experimental sysgpu graphics API -pub const use_sysgpu = true; - -var gpa = std.heap.GeneralPurposeAllocator(.{}){}; - -title_timer: core.Timer, - -pub fn init(app: *App) !void { - try core.init(.{}); - app.* = .{ - .title_timer = try core.Timer.start(), - }; -} - -pub fn deinit(app: *App) void { - _ = app; - defer _ = gpa.deinit(); - defer core.deinit(); -} - -pub fn update(app: *App) !bool { - var iter = core.pollEvents(); - while (iter.next()) |event| { - switch (event) { - .key_press => |ev| { - if (ev.key == .space) return true; - }, - .close => return true, - else => {}, - } - } - - app.render(); - - // update the window title every second - if (app.title_timer.read() >= 1.0) { - app.title_timer.reset(); - try core.printTitle("Clear Color [ {d}fps ] [ Input {d}hz ]", .{ - core.frameRate(), - core.inputRate(), - }); - } - - return false; -} - -fn render(app: *App) void { - _ = app; - const back_buffer_view = core.swap_chain.getCurrentTextureView().?; - const color_attachment = gpu.RenderPassColorAttachment{ - .view = back_buffer_view, - .clear_value = gpu.Color{ .r = 0.0, .g = 0.0, .b = 1.0, .a = 1.0 }, - .load_op = .clear, - .store_op = .store, - }; - - const encoder = core.device.createCommandEncoder(null); - const render_pass_info = gpu.RenderPassDescriptor.init(.{ - .color_attachments = &.{color_attachment}, - }); - - const pass = encoder.beginRenderPass(&render_pass_info); - pass.end(); - pass.release(); - - var command = encoder.finish(null); - encoder.release(); - - var queue = core.queue; - queue.submit(&[_]*gpu.CommandBuffer{command}); - command.release(); - core.swap_chain.present(); - back_buffer_view.release(); -} diff --git a/src/core/examples/sysgpu/clear-color/renderer.zig b/src/core/examples/sysgpu/clear-color/renderer.zig deleted file mode 100644 index 51c84b69..00000000 --- a/src/core/examples/sysgpu/clear-color/renderer.zig +++ /dev/null @@ -1,33 +0,0 @@ -const mach = @import("mach"); -const core = mach.core; -const gpu = mach.gpu; - -pub const Renderer = @This(); - -pub fn RenderUpdate() void { - const back_buffer_view = core.swap_chain.getCurrentTextureView().?; - const color_attachment = gpu.RenderPassColorAttachment{ - .view = back_buffer_view, - .clear_value = gpu.Color{ .r = 0.0, .g = 0.0, .b = 1.0, .a = 1.0 }, - .load_op = .clear, - .store_op = .store, - }; - - const encoder = core.device.createCommandEncoder(null); - const render_pass_info = gpu.RenderPassDescriptor.init(.{ - .color_attachments = &.{color_attachment}, - }); - - const pass = encoder.beginRenderPass(&render_pass_info); - pass.end(); - pass.release(); - - var command = encoder.finish(null); - encoder.release(); - - const queue = core.queue; - queue.submit(&[_]*gpu.CommandBuffer{command}); - command.release(); - core.swap_chain.present(); - back_buffer_view.release(); -} diff --git a/src/core/examples/sysgpu/cubemap/cube_mesh.zig b/src/core/examples/sysgpu/cubemap/cube_mesh.zig deleted file mode 100644 index ae5b2912..00000000 --- a/src/core/examples/sysgpu/cubemap/cube_mesh.zig +++ /dev/null @@ -1,49 +0,0 @@ -pub const Vertex = extern struct { - pos: @Vector(4, f32), - col: @Vector(4, f32), - uv: @Vector(2, f32), -}; - -pub const vertices = [_]Vertex{ - .{ .pos = .{ 1, -1, 1, 1 }, .col = .{ 1, 0, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, -1, -1, 1 }, .col = .{ 0, 0, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, -1, 1, 1 }, .col = .{ 1, 0, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, -1, -1, 1 }, .col = .{ 0, 0, 0, 1 }, .uv = .{ 1, 0 } }, - - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ 1, -1, 1, 1 }, .col = .{ 1, 0, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, 1, -1, 1 }, .col = .{ 1, 1, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 1, 0 } }, - - .{ .pos = .{ -1, 1, 1, 1 }, .col = .{ 0, 1, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ 1, 1, -1, 1 }, .col = .{ 1, 1, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ -1, 1, 1, 1 }, .col = .{ 0, 1, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ 1, 1, -1, 1 }, .col = .{ 1, 1, 0, 1 }, .uv = .{ 1, 0 } }, - - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, 1, 1, 1 }, .col = .{ 0, 1, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ -1, -1, -1, 1 }, .col = .{ 0, 0, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 1, 0 } }, - - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, 1, 1, 1 }, .col = .{ 0, 1, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, -1, 1, 1 }, .col = .{ 1, 0, 1, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 0, 1 } }, - - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, -1, -1, 1 }, .col = .{ 0, 0, 0, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, 1, -1, 1 }, .col = .{ 1, 1, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 1, 0 } }, -}; diff --git a/src/core/examples/sysgpu/cubemap/main.zig b/src/core/examples/sysgpu/cubemap/main.zig deleted file mode 100644 index b7c6edc3..00000000 --- a/src/core/examples/sysgpu/cubemap/main.zig +++ /dev/null @@ -1,398 +0,0 @@ -const std = @import("std"); - -const mach = @import("mach"); -const core = mach.core; -const gpu = mach.gpu; - -const zm = @import("zmath"); -const zigimg = @import("zigimg"); -const Vertex = @import("cube_mesh.zig").Vertex; -const vertices = @import("cube_mesh.zig").vertices; -const assets = @import("assets"); - -const UniformBufferObject = struct { - mat: zm.Mat, -}; - -var gpa = std.heap.GeneralPurposeAllocator(.{}){}; - -title_timer: core.Timer, -timer: core.Timer, -pipeline: *gpu.RenderPipeline, -vertex_buffer: *gpu.Buffer, -uniform_buffer: *gpu.Buffer, -bind_group: *gpu.BindGroup, -depth_texture: *gpu.Texture, -depth_texture_view: *gpu.TextureView, - -pub const App = @This(); - -// Use experimental sysgpu graphics API -pub const use_sysgpu = true; - -pub fn init(app: *App) !void { - try core.init(.{}); - - const allocator = gpa.allocator(); - - const shader_module = core.device.createShaderModuleWGSL("shader.wgsl", @embedFile("shader.wgsl")); - defer shader_module.release(); - - const vertex_attributes = [_]gpu.VertexAttribute{ - .{ .format = .float32x4, .offset = @offsetOf(Vertex, "pos"), .shader_location = 0 }, - .{ .format = .float32x2, .offset = @offsetOf(Vertex, "uv"), .shader_location = 1 }, - }; - - const vertex_buffer_layout = gpu.VertexBufferLayout.init(.{ - .array_stride = @sizeOf(Vertex), - .step_mode = .vertex, - .attributes = &vertex_attributes, - }); - - const blend = gpu.BlendState{ - .color = .{ - .operation = .add, - .src_factor = .src_alpha, - .dst_factor = .one_minus_src_alpha, - }, - .alpha = .{ - .operation = .add, - .src_factor = .one, - .dst_factor = .zero, - }, - }; - const color_target = gpu.ColorTargetState{ - .format = core.descriptor.format, - .blend = &blend, - .write_mask = gpu.ColorWriteMaskFlags.all, - }; - const fragment = gpu.FragmentState.init(.{ - .module = shader_module, - .entry_point = "frag_main", - .targets = &.{color_target}, - }); - - const pipeline_descriptor = gpu.RenderPipeline.Descriptor{ - .fragment = &fragment, - // Enable depth testing so that the fragment closest to the camera - // is rendered in front. - .depth_stencil = &.{ - .format = .depth24_plus, - .depth_write_enabled = .true, - .depth_compare = .less, - }, - .vertex = gpu.VertexState.init(.{ - .module = shader_module, - .entry_point = "vertex_main", - .buffers = &.{vertex_buffer_layout}, - }), - .primitive = .{ - // Since the cube has its face pointing outwards, cull_mode must be - // set to .front or .none here since we are inside the cube looking out. - // Ideally you would set this to .back and have a custom cube primitive - // with the faces pointing towards the inside of the cube. - .cull_mode = .none, - }, - }; - const pipeline = core.device.createRenderPipeline(&pipeline_descriptor); - - const vertex_buffer = core.device.createBuffer(&.{ - .usage = .{ .vertex = true }, - .size = @sizeOf(Vertex) * vertices.len, - .mapped_at_creation = .true, - }); - const vertex_mapped = vertex_buffer.getMappedRange(Vertex, 0, vertices.len); - @memcpy(vertex_mapped.?, vertices[0..]); - vertex_buffer.unmap(); - - const uniform_buffer = core.device.createBuffer(&.{ - .usage = .{ .copy_dst = true, .uniform = true }, - .size = @sizeOf(UniformBufferObject), - .mapped_at_creation = .false, - }); - - // Create a sampler with linear filtering for smooth interpolation. - const sampler = core.device.createSampler(&.{ - .mag_filter = .linear, - .min_filter = .linear, - }); - - const queue = core.queue; - - // WebGPU expects the cubemap textures in this order: (+X,-X,+Y,-Y,+Z,-Z) - var images: [6]zigimg.Image = undefined; - images[0] = try zigimg.Image.fromMemory(allocator, assets.skybox_posx_png); - defer images[0].deinit(); - images[1] = try zigimg.Image.fromMemory(allocator, assets.skybox_negx_png); - defer images[1].deinit(); - images[2] = try zigimg.Image.fromMemory(allocator, assets.skybox_posy_png); - defer images[2].deinit(); - images[3] = try zigimg.Image.fromMemory(allocator, assets.skybox_negy_png); - defer images[3].deinit(); - images[4] = try zigimg.Image.fromMemory(allocator, assets.skybox_posz_png); - defer images[4].deinit(); - images[5] = try zigimg.Image.fromMemory(allocator, assets.skybox_negz_png); - defer images[5].deinit(); - - // Use the first image of the set for sizing - const img_size = gpu.Extent3D{ - .width = @as(u32, @intCast(images[0].width)), - .height = @as(u32, @intCast(images[0].height)), - }; - - // We set depth_or_array_layers to 6 here to indicate there are 6 images in this texture - const tex_size = gpu.Extent3D{ - .width = @as(u32, @intCast(images[0].width)), - .height = @as(u32, @intCast(images[0].height)), - .depth_or_array_layers = 6, - }; - - // Same as a regular texture, but with a Z of 6 (defined in tex_size) - const cube_texture = core.device.createTexture(&.{ - .size = tex_size, - .format = .rgba8_unorm, - .dimension = .dimension_2d, - .usage = .{ - .texture_binding = true, - .copy_dst = true, - .render_attachment = false, - }, - }); - - const data_layout = gpu.Texture.DataLayout{ - .bytes_per_row = @as(u32, @intCast(images[0].width * 4)), - .rows_per_image = @as(u32, @intCast(images[0].height)), - }; - - const encoder = core.device.createCommandEncoder(null); - - // We have to create a staging buffer, copy all the image data into the - // staging buffer at the correct Z offset, encode a command to copy - // the buffer to the texture for each image, then push it to the command - // queue - var staging_buff: [6]*gpu.Buffer = undefined; - var i: u32 = 0; - while (i < 6) : (i += 1) { - staging_buff[i] = core.device.createBuffer(&.{ - .usage = .{ .copy_src = true, .map_write = true }, - .size = @as(u64, @intCast(images[0].width)) * @as(u64, @intCast(images[0].height)) * @sizeOf(u32), - .mapped_at_creation = .true, - }); - switch (images[i].pixels) { - .rgba32 => |pixels| { - // Map a section of the staging buffer - const staging_map = staging_buff[i].getMappedRange(u32, 0, @as(u64, @intCast(images[i].width)) * @as(u64, @intCast(images[i].height))); - // Copy the image data into the mapped buffer - @memcpy(staging_map.?, @as([]u32, @ptrCast(@alignCast(pixels)))); - // And release the mapping - staging_buff[i].unmap(); - }, - .rgb24 => |pixels| { - const staging_map = staging_buff[i].getMappedRange(u32, 0, @as(u64, @intCast(images[i].width)) * @as(u64, @intCast(images[i].height))); - // In this case, we have to convert the data to rgba32 first - const data = try rgb24ToRgba32(allocator, pixels); - defer data.deinit(allocator); - @memcpy(staging_map.?, @as([]u32, @ptrCast(@alignCast(data.rgba32)))); - staging_buff[i].unmap(); - }, - else => @panic("unsupported image color format"), - } - - // These define the source and target for the buffer to texture copy command - const copy_buff = gpu.ImageCopyBuffer{ - .layout = data_layout, - .buffer = staging_buff[i], - }; - const copy_tex = gpu.ImageCopyTexture{ - .texture = cube_texture, - .origin = gpu.Origin3D{ .x = 0, .y = 0, .z = i }, - }; - - // Encode the copy command, we do this for every image in the texture. - encoder.copyBufferToTexture(©_buff, ©_tex, &img_size); - staging_buff[i].release(); - } - // Now that the commands to copy our buffer data to the texture is filled, - // push the encoded commands over to the queue and execute to get the - // texture filled with the image data. - var command = encoder.finish(null); - encoder.release(); - queue.submit(&[_]*gpu.CommandBuffer{command}); - command.release(); - - // The textureView in the bind group needs dimension defined as "dimension_cube". - const cube_texture_view = cube_texture.createView(&gpu.TextureView.Descriptor{ .dimension = .dimension_cube }); - cube_texture.release(); - - const bind_group_layout = pipeline.getBindGroupLayout(0); - const bind_group = core.device.createBindGroup( - &gpu.BindGroup.Descriptor.init(.{ - .layout = bind_group_layout, - .entries = &.{ - gpu.BindGroup.Entry.buffer(0, uniform_buffer, 0, @sizeOf(UniformBufferObject), @sizeOf(UniformBufferObject)), - gpu.BindGroup.Entry.sampler(1, sampler), - gpu.BindGroup.Entry.textureView(2, cube_texture_view), - }, - }), - ); - sampler.release(); - cube_texture_view.release(); - bind_group_layout.release(); - - const depth_texture = core.device.createTexture(&gpu.Texture.Descriptor{ - .size = gpu.Extent3D{ - .width = core.descriptor.width, - .height = core.descriptor.height, - }, - .format = .depth24_plus, - .usage = .{ - .render_attachment = true, - .texture_binding = true, - }, - }); - - const depth_texture_view = depth_texture.createView(&gpu.TextureView.Descriptor{ - .format = .depth24_plus, - .dimension = .dimension_2d, - .array_layer_count = 1, - .mip_level_count = 1, - }); - - app.timer = try core.Timer.start(); - app.title_timer = try core.Timer.start(); - app.pipeline = pipeline; - app.vertex_buffer = vertex_buffer; - app.uniform_buffer = uniform_buffer; - app.bind_group = bind_group; - app.depth_texture = depth_texture; - app.depth_texture_view = depth_texture_view; -} - -pub fn deinit(app: *App) void { - defer _ = gpa.deinit(); - defer core.deinit(); - - app.pipeline.release(); - app.vertex_buffer.release(); - app.uniform_buffer.release(); - app.bind_group.release(); - app.depth_texture.release(); - app.depth_texture_view.release(); -} - -pub fn update(app: *App) !bool { - var iter = core.pollEvents(); - while (iter.next()) |event| { - switch (event) { - .key_press => |ev| { - if (ev.key == .space) return true; - }, - .close => return true, - .framebuffer_resize => |ev| { - // If window is resized, recreate depth buffer otherwise we cannot use it. - app.depth_texture.release(); - app.depth_texture = core.device.createTexture(&gpu.Texture.Descriptor{ - .size = gpu.Extent3D{ - .width = ev.width, - .height = ev.height, - }, - .format = .depth24_plus, - .usage = .{ - .render_attachment = true, - .texture_binding = true, - }, - }); - app.depth_texture_view.release(); - app.depth_texture_view = app.depth_texture.createView(&gpu.TextureView.Descriptor{ - .format = .depth24_plus, - .dimension = .dimension_2d, - .array_layer_count = 1, - .mip_level_count = 1, - }); - }, - else => {}, - } - } - - const back_buffer_view = core.swap_chain.getCurrentTextureView().?; - const color_attachment = gpu.RenderPassColorAttachment{ - .view = back_buffer_view, - .clear_value = .{ .r = 0.5, .g = 0.5, .b = 0.5, .a = 0.0 }, - .load_op = .clear, - .store_op = .store, - }; - - const encoder = core.device.createCommandEncoder(null); - const render_pass_info = gpu.RenderPassDescriptor.init(.{ - .color_attachments = &.{color_attachment}, - .depth_stencil_attachment = &.{ - .view = app.depth_texture_view, - .depth_clear_value = 1.0, - .depth_load_op = .clear, - .depth_store_op = .store, - }, - }); - - { - const time = app.timer.read(); - const aspect = @as(f32, @floatFromInt(core.descriptor.width)) / @as(f32, @floatFromInt(core.descriptor.height)); - const proj = zm.perspectiveFovRh((2 * std.math.pi) / 5.0, aspect, 0.1, 3000); - const model = zm.mul( - zm.scaling(1000, 1000, 1000), - zm.rotationX(std.math.pi / 2.0 * 3.0), - ); - const view = zm.mul( - zm.mul( - zm.lookAtRh( - zm.Vec{ 0, 0, 0, 1 }, - zm.Vec{ 1, 0, 0, 1 }, - zm.Vec{ 0, 0, 1, 0 }, - ), - zm.rotationY(time * 0.2), - ), - zm.rotationX((std.math.pi / 10.0) * std.math.sin(time)), - ); - - const mvp = zm.mul(zm.mul(zm.transpose(model), view), proj); - const ubo = UniformBufferObject{ .mat = mvp }; - - encoder.writeBuffer(app.uniform_buffer, 0, &[_]UniformBufferObject{ubo}); - } - - const pass = encoder.beginRenderPass(&render_pass_info); - pass.setPipeline(app.pipeline); - pass.setVertexBuffer(0, app.vertex_buffer, 0, @sizeOf(Vertex) * vertices.len); - pass.setBindGroup(0, app.bind_group, &.{}); - pass.draw(vertices.len, 1, 0, 0); - pass.end(); - pass.release(); - - var command = encoder.finish(null); - encoder.release(); - - const queue = core.queue; - queue.submit(&[_]*gpu.CommandBuffer{command}); - command.release(); - core.swap_chain.present(); - back_buffer_view.release(); - - // update the window title every second - if (app.title_timer.read() >= 1.0) { - app.title_timer.reset(); - try core.printTitle("Cube Map [ {d}fps ] [ Input {d}hz ]", .{ - core.frameRate(), - core.inputRate(), - }); - } - - return false; -} - -fn rgb24ToRgba32(allocator: std.mem.Allocator, in: []zigimg.color.Rgb24) !zigimg.color.PixelStorage { - const out = try zigimg.color.PixelStorage.init(allocator, .rgba32, in.len); - var i: usize = 0; - while (i < in.len) : (i += 1) { - out.rgba32[i] = zigimg.color.Rgba32{ .r = in[i].r, .g = in[i].g, .b = in[i].b, .a = 255 }; - } - return out; -} diff --git a/src/core/examples/sysgpu/cubemap/shader.wgsl b/src/core/examples/sysgpu/cubemap/shader.wgsl deleted file mode 100644 index 1442990c..00000000 --- a/src/core/examples/sysgpu/cubemap/shader.wgsl +++ /dev/null @@ -1,34 +0,0 @@ -struct Uniforms { - modelViewProjectionMatrix : mat4x4, -} -@binding(0) @group(0) var uniforms : Uniforms; - -struct VertexOutput { - @builtin(position) Position : vec4, - @location(0) fragUV : vec2, - @location(1) fragPosition: vec4, -} - -@vertex -fn vertex_main( - @location(0) position : vec4, - @location(1) uv : vec2 -) -> VertexOutput { - var output : VertexOutput; - output.Position = uniforms.modelViewProjectionMatrix * position; - output.fragUV = uv; - output.fragPosition = 0.5 * (position + vec4(1.0, 1.0, 1.0, 1.0)); - return output; -} - -@group(0) @binding(1) var mySampler: sampler; -@group(0) @binding(2) var myTexture: texture_cube; - -@fragment -fn frag_main( - @location(0) fragUV: vec2, - @location(1) fragPosition: vec4 -) -> @location(0) vec4 { - var cubemapVec = fragPosition.xyz - vec3(0.5, 0.5, 0.5); - return textureSample(myTexture, mySampler, cubemapVec); -} diff --git a/src/core/examples/sysgpu/fractal-cube/cube_mesh.zig b/src/core/examples/sysgpu/fractal-cube/cube_mesh.zig deleted file mode 100644 index f26c75ac..00000000 --- a/src/core/examples/sysgpu/fractal-cube/cube_mesh.zig +++ /dev/null @@ -1,49 +0,0 @@ -pub const Vertex = extern struct { - pos: @Vector(4, f32), - col: @Vector(4, f32), - uv: @Vector(2, f32), -}; - -pub const vertices = [_]Vertex{ - .{ .pos = .{ 1, -1, 1, 1 }, .col = .{ 1, 0, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, -1, -1, 1 }, .col = .{ 0, 0, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, -1, 1, 1 }, .col = .{ 1, 0, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, -1, -1, 1 }, .col = .{ 0, 0, 0, 1 }, .uv = .{ 0, 0 } }, - - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ 1, -1, 1, 1 }, .col = .{ 1, 0, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, 1, -1, 1 }, .col = .{ 1, 1, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 0, 0 } }, - - .{ .pos = .{ -1, 1, 1, 1 }, .col = .{ 0, 1, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ 1, 1, -1, 1 }, .col = .{ 1, 1, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ -1, 1, 1, 1 }, .col = .{ 0, 1, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ 1, 1, -1, 1 }, .col = .{ 1, 1, 0, 1 }, .uv = .{ 0, 0 } }, - - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, 1, 1, 1 }, .col = .{ 0, 1, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ -1, -1, -1, 1 }, .col = .{ 0, 0, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 0, 0 } }, - - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, 1, 1, 1 }, .col = .{ 0, 1, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, -1, 1, 1 }, .col = .{ 1, 0, 1, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 1, 1 } }, - - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, -1, -1, 1 }, .col = .{ 0, 0, 0, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, 1, -1, 1 }, .col = .{ 1, 1, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 0, 0 } }, -}; diff --git a/src/core/examples/sysgpu/fractal-cube/main.zig b/src/core/examples/sysgpu/fractal-cube/main.zig deleted file mode 100644 index f7fdb31b..00000000 --- a/src/core/examples/sysgpu/fractal-cube/main.zig +++ /dev/null @@ -1,377 +0,0 @@ -//! To get the effect we want, we need a texture on which to render; -//! we can't use the swapchain texture directly, but we can get the effect -//! by doing the same render pass twice, on the texture and the swapchain. -//! We also need a second texture to use on the cube (after the render pass -//! it needs to copy the other texture.) We can't use the same texture since -//! it would interfere with the synchronization on the gpu during the render pass. -//! This demo currently does not work on opengl, because core.descriptor.width/height, -//! are set to 0 after core.init() and because webgpu does not implement copyTextureToTexture, -//! for opengl - -const std = @import("std"); - -const mach = @import("mach"); -const core = mach.core; -const gpu = mach.gpu; - -const zm = @import("zmath"); -const Vertex = @import("cube_mesh.zig").Vertex; -const vertices = @import("cube_mesh.zig").vertices; - -pub const App = @This(); - -// Use experimental sysgpu graphics API -pub const use_sysgpu = true; - -const UniformBufferObject = struct { - mat: zm.Mat, -}; - -var gpa = std.heap.GeneralPurposeAllocator(.{}){}; - -title_timer: core.Timer, -timer: core.Timer, -pipeline: *gpu.RenderPipeline, -vertex_buffer: *gpu.Buffer, -uniform_buffer: *gpu.Buffer, -bind_group: *gpu.BindGroup, -depth_texture: ?*gpu.Texture, -depth_texture_view: *gpu.TextureView, -cube_texture: *gpu.Texture, -cube_texture_view: *gpu.TextureView, -cube_texture_render: *gpu.Texture, -cube_texture_view_render: *gpu.TextureView, -sampler: *gpu.Sampler, -bgl: *gpu.BindGroupLayout, - -pub fn init(app: *App) !void { - try core.init(.{}); - - const shader_module = core.device.createShaderModuleWGSL("shader.wgsl", @embedFile("shader.wgsl")); - - const vertex_attributes = [_]gpu.VertexAttribute{ - .{ .format = .float32x4, .offset = @offsetOf(Vertex, "pos"), .shader_location = 0 }, - .{ .format = .float32x2, .offset = @offsetOf(Vertex, "uv"), .shader_location = 1 }, - }; - const vertex_buffer_layout = gpu.VertexBufferLayout.init(.{ - .array_stride = @sizeOf(Vertex), - .attributes = &vertex_attributes, - }); - - const blend = gpu.BlendState{}; - const color_target = gpu.ColorTargetState{ - .format = core.descriptor.format, - .blend = &blend, - .write_mask = gpu.ColorWriteMaskFlags.all, - }; - const fragment = gpu.FragmentState.init(.{ - .module = shader_module, - .entry_point = "frag_main", - .targets = &.{color_target}, - }); - - const bgle_buffer = gpu.BindGroupLayout.Entry.buffer(0, .{ .vertex = true }, .uniform, true, 0); - const bgle_sampler = gpu.BindGroupLayout.Entry.sampler(1, .{ .fragment = true }, .filtering); - const bgle_textureview = gpu.BindGroupLayout.Entry.texture(2, .{ .fragment = true }, .float, .dimension_2d, false); - const bgl = core.device.createBindGroupLayout( - &gpu.BindGroupLayout.Descriptor.init(.{ - .entries = &.{ bgle_buffer, bgle_sampler, bgle_textureview }, - }), - ); - - const bind_group_layouts = [_]*gpu.BindGroupLayout{bgl}; - const pipeline_layout = core.device.createPipelineLayout(&gpu.PipelineLayout.Descriptor.init(.{ - .bind_group_layouts = &bind_group_layouts, - })); - - const pipeline_descriptor = gpu.RenderPipeline.Descriptor{ - .fragment = &fragment, - .layout = pipeline_layout, - .depth_stencil = &.{ - .format = .depth24_plus, - .depth_write_enabled = .true, - .depth_compare = .less, - }, - .vertex = gpu.VertexState.init(.{ - .module = shader_module, - .entry_point = "vertex_main", - .buffers = &.{vertex_buffer_layout}, - }), - .primitive = .{ - .cull_mode = .back, - }, - }; - - const vertex_buffer = core.device.createBuffer(&.{ - .usage = .{ .vertex = true }, - .size = @sizeOf(Vertex) * vertices.len, - .mapped_at_creation = .true, - }); - const vertex_mapped = vertex_buffer.getMappedRange(Vertex, 0, vertices.len); - @memcpy(vertex_mapped.?, vertices[0..]); - vertex_buffer.unmap(); - - const uniform_buffer = core.device.createBuffer(&.{ - .usage = .{ .copy_dst = true, .uniform = true }, - .size = @sizeOf(UniformBufferObject), - .mapped_at_creation = .false, - }); - - // The texture to put on the cube - const cube_texture = core.device.createTexture(&gpu.Texture.Descriptor{ - .usage = .{ .texture_binding = true, .copy_dst = true }, - .size = .{ .width = core.descriptor.width, .height = core.descriptor.height }, - .format = core.descriptor.format, - }); - // The texture on which we render - const cube_texture_render = core.device.createTexture(&gpu.Texture.Descriptor{ - .usage = .{ .render_attachment = true, .copy_src = true }, - .size = .{ .width = core.descriptor.width, .height = core.descriptor.height }, - .format = core.descriptor.format, - }); - - const sampler = core.device.createSampler(&gpu.Sampler.Descriptor{ - .mag_filter = .linear, - .min_filter = .linear, - }); - - const cube_texture_view = cube_texture.createView(&gpu.TextureView.Descriptor{ - .format = core.descriptor.format, - .dimension = .dimension_2d, - .mip_level_count = 1, - .array_layer_count = 1, - }); - const cube_texture_view_render = cube_texture_render.createView(&gpu.TextureView.Descriptor{ - .format = core.descriptor.format, - .dimension = .dimension_2d, - .mip_level_count = 1, - .array_layer_count = 1, - }); - - const bind_group = core.device.createBindGroup( - &gpu.BindGroup.Descriptor.init(.{ - .layout = bgl, - .entries = &.{ - gpu.BindGroup.Entry.buffer(0, uniform_buffer, 0, @sizeOf(UniformBufferObject), @sizeOf(UniformBufferObject)), - gpu.BindGroup.Entry.sampler(1, sampler), - gpu.BindGroup.Entry.textureView(2, cube_texture_view), - }, - }), - ); - - const depth_texture = core.device.createTexture(&gpu.Texture.Descriptor{ - .usage = .{ .render_attachment = true }, - .size = .{ .width = core.descriptor.width, .height = core.descriptor.height }, - .format = .depth24_plus, - }); - const depth_texture_view = depth_texture.createView(&gpu.TextureView.Descriptor{ - .format = .depth24_plus, - .dimension = .dimension_2d, - .array_layer_count = 1, - .mip_level_count = 1, - }); - - app.timer = try core.Timer.start(); - app.title_timer = try core.Timer.start(); - app.pipeline = core.device.createRenderPipeline(&pipeline_descriptor); - app.vertex_buffer = vertex_buffer; - app.uniform_buffer = uniform_buffer; - app.bind_group = bind_group; - app.depth_texture = depth_texture; - app.depth_texture_view = depth_texture_view; - app.cube_texture = cube_texture; - app.cube_texture_view = cube_texture_view; - app.cube_texture_render = cube_texture_render; - app.cube_texture_view_render = cube_texture_view_render; - app.sampler = sampler; - app.bgl = bgl; - - shader_module.release(); - pipeline_layout.release(); -} - -pub fn deinit(app: *App) void { - defer _ = gpa.deinit(); - defer core.deinit(); - - app.pipeline.release(); - app.bgl.release(); - app.vertex_buffer.release(); - app.uniform_buffer.release(); - app.cube_texture.release(); - app.cube_texture_render.release(); - app.sampler.release(); - app.cube_texture_view.release(); - app.cube_texture_view_render.release(); - app.bind_group.release(); - app.depth_texture.?.release(); - app.depth_texture_view.release(); -} - -pub fn update(app: *App) !bool { - var iter = core.pollEvents(); - while (iter.next()) |event| { - switch (event) { - .key_press => |ev| { - if (ev.key == .space) return true; - }, - .close => return true, - .framebuffer_resize => |ev| { - app.depth_texture.?.release(); - app.depth_texture = core.device.createTexture(&gpu.Texture.Descriptor{ - .usage = .{ .render_attachment = true }, - .size = .{ .width = ev.width, .height = ev.height }, - .format = .depth24_plus, - }); - - app.cube_texture.release(); - app.cube_texture = core.device.createTexture(&gpu.Texture.Descriptor{ - .usage = .{ .texture_binding = true, .copy_dst = true }, - .size = .{ .width = ev.width, .height = ev.height }, - .format = core.descriptor.format, - }); - app.cube_texture_render.release(); - app.cube_texture_render = core.device.createTexture(&gpu.Texture.Descriptor{ - .usage = .{ .render_attachment = true, .copy_src = true }, - .size = .{ .width = ev.width, .height = ev.height }, - .format = core.descriptor.format, - }); - - app.depth_texture_view.release(); - app.depth_texture_view = app.depth_texture.?.createView(&gpu.TextureView.Descriptor{ - .format = .depth24_plus, - .dimension = .dimension_2d, - .array_layer_count = 1, - .mip_level_count = 1, - }); - - app.cube_texture_view.release(); - app.cube_texture_view = app.cube_texture.createView(&gpu.TextureView.Descriptor{ - .format = core.descriptor.format, - .dimension = .dimension_2d, - .mip_level_count = 1, - .array_layer_count = 1, - }); - app.cube_texture_view_render.release(); - app.cube_texture_view_render = app.cube_texture_render.createView(&gpu.TextureView.Descriptor{ - .format = core.descriptor.format, - .dimension = .dimension_2d, - .mip_level_count = 1, - .array_layer_count = 1, - }); - - app.bind_group.release(); - app.bind_group = core.device.createBindGroup( - &gpu.BindGroup.Descriptor.init(.{ - .layout = app.bgl, - .entries = &.{ - gpu.BindGroup.Entry.buffer(0, app.uniform_buffer, 0, @sizeOf(UniformBufferObject), @sizeOf(UniformBufferObject)), - gpu.BindGroup.Entry.sampler(1, app.sampler), - gpu.BindGroup.Entry.textureView(2, app.cube_texture_view), - }, - }), - ); - }, - else => {}, - } - } - - const cube_view = app.cube_texture_view_render; - const back_buffer_view = core.swap_chain.getCurrentTextureView().?; - - const cube_color_attachment = gpu.RenderPassColorAttachment{ - .view = cube_view, - .clear_value = gpu.Color{ .r = 0.5, .g = 0.5, .b = 0.5, .a = 1 }, - .load_op = .clear, - .store_op = .store, - }; - const color_attachment = gpu.RenderPassColorAttachment{ - .view = back_buffer_view, - .clear_value = gpu.Color{ .r = 0.5, .g = 0.5, .b = 0.5, .a = 1 }, - .load_op = .clear, - .store_op = .store, - }; - - const depth_stencil_attachment = gpu.RenderPassDepthStencilAttachment{ - .view = app.depth_texture_view, - .depth_load_op = .clear, - .depth_store_op = .store, - .depth_clear_value = 1.0, - }; - - const encoder = core.device.createCommandEncoder(null); - const cube_render_pass_info = gpu.RenderPassDescriptor.init(.{ - .color_attachments = &.{cube_color_attachment}, - .depth_stencil_attachment = &depth_stencil_attachment, - }); - const render_pass_info = gpu.RenderPassDescriptor.init(.{ - .color_attachments = &.{color_attachment}, - .depth_stencil_attachment = &depth_stencil_attachment, - }); - - { - const time = app.timer.read(); - const model = zm.mul(zm.rotationX(time * (std.math.pi / 2.0)), zm.rotationZ(time * (std.math.pi / 2.0))); - const view = zm.lookAtRh( - zm.Vec{ 0, -4, 0, 1 }, - zm.Vec{ 0, 0, 0, 1 }, - zm.Vec{ 0, 0, 1, 0 }, - ); - const proj = zm.perspectiveFovRh( - (std.math.pi * 2.0 / 5.0), - @as(f32, @floatFromInt(core.descriptor.width)) / @as(f32, @floatFromInt(core.descriptor.height)), - 1, - 100, - ); - const ubo = UniformBufferObject{ - .mat = zm.transpose(zm.mul(zm.mul(model, view), proj)), - }; - encoder.writeBuffer(app.uniform_buffer, 0, &[_]UniformBufferObject{ubo}); - } - - const pass = encoder.beginRenderPass(&render_pass_info); - pass.setPipeline(app.pipeline); - pass.setBindGroup(0, app.bind_group, &.{0}); - pass.setVertexBuffer(0, app.vertex_buffer, 0, @sizeOf(Vertex) * vertices.len); - pass.draw(vertices.len, 1, 0, 0); - pass.end(); - pass.release(); - - encoder.copyTextureToTexture( - &gpu.ImageCopyTexture{ - .texture = app.cube_texture_render, - }, - &gpu.ImageCopyTexture{ - .texture = app.cube_texture, - }, - &.{ .width = core.descriptor.width, .height = core.descriptor.height }, - ); - - const cube_pass = encoder.beginRenderPass(&cube_render_pass_info); - cube_pass.setPipeline(app.pipeline); - cube_pass.setBindGroup(0, app.bind_group, &.{0}); - cube_pass.setVertexBuffer(0, app.vertex_buffer, 0, @sizeOf(Vertex) * vertices.len); - cube_pass.draw(vertices.len, 1, 0, 0); - cube_pass.end(); - cube_pass.release(); - - var command = encoder.finish(null); - encoder.release(); - - const queue = core.queue; - queue.submit(&[_]*gpu.CommandBuffer{command}); - command.release(); - core.swap_chain.present(); - back_buffer_view.release(); - - // update the window title every second - if (app.title_timer.read() >= 1.0) { - app.title_timer.reset(); - try core.printTitle("Fractal Cube [ {d}fps ] [ Input {d}hz ]", .{ - core.frameRate(), - core.inputRate(), - }); - } - - return false; -} diff --git a/src/core/examples/sysgpu/fractal-cube/shader.wgsl b/src/core/examples/sysgpu/fractal-cube/shader.wgsl deleted file mode 100644 index d38f0b4e..00000000 --- a/src/core/examples/sysgpu/fractal-cube/shader.wgsl +++ /dev/null @@ -1,36 +0,0 @@ -struct Uniforms { - matrix : mat4x4, -}; - -@binding(0) @group(0) var ubo : Uniforms; - -struct VertexOut { - @builtin(position) Position : vec4, - @location(0) fragUV : vec2, - @location(1) fragPosition: vec4, -} - -@vertex fn vertex_main( - @location(0) position : vec4, - @location(1) uv: vec2 -) -> VertexOut { - var output : VertexOut; - output.Position = position * ubo.matrix; - output.fragUV = uv; - output.fragPosition = 0.5 * (position + vec4(1.0, 1.0, 1.0, 1.0)); - return output; -} - -@binding(1) @group(0) var mySampler: sampler; -@binding(2) @group(0) var myTexture: texture_2d; - -@fragment fn frag_main( - @location(0) fragUV: vec2, - @location(1) fragPosition: vec4 -) -> @location(0) vec4 { - let texColor = textureSample(myTexture, mySampler, fragUV * 0.8 + vec2(0.1, 0.1)); - let f = f32(length(texColor.rgb - vec3(0.5, 0.5, 0.5)) < 0.01); - return (1.0 - f) * texColor + f * fragPosition; - // return vec4(texColor.rgb,1.0); -} - diff --git a/src/core/examples/sysgpu/gen-texture-light/cube.wgsl b/src/core/examples/sysgpu/gen-texture-light/cube.wgsl deleted file mode 100644 index bc59632d..00000000 --- a/src/core/examples/sysgpu/gen-texture-light/cube.wgsl +++ /dev/null @@ -1,71 +0,0 @@ -struct CameraUniform { - pos: vec4, - view_proj: mat4x4, -}; - -struct VertexOutput { - @builtin(position) clip_position: vec4, - @location(0) tex_coords: vec2, - @location(1) normal: vec3, - @location(2) position: vec3, -}; - -struct Light { - position: vec4, - color: vec4, -}; - -@group(0) @binding(0) var camera: CameraUniform; -@group(1) @binding(0) var t_diffuse: texture_2d; -@group(1) @binding(1) var s_diffuse: sampler; -@group(2) @binding(0) var light: Light; - -@vertex -fn vs_main( - // TODO - struct input - @location(0) model_position: vec3, - @location(1) model_normal: vec3, - @location(2) model_tex_coords: vec2, - @location(3) instance_model_matrix_0: vec4, - @location(4) instance_model_matrix_1: vec4, - @location(5) instance_model_matrix_2: vec4, - @location(6) instance_model_matrix_3: vec4) --> VertexOutput { - let model_matrix = mat4x4( - instance_model_matrix_0, - instance_model_matrix_1, - instance_model_matrix_2, - instance_model_matrix_3, - ); - var out: VertexOutput; - let world_pos = model_matrix * vec4(model_position, 1.0); - out.position = world_pos.xyz; - out.normal = (model_matrix * vec4(model_normal, 0.0)).xyz; - out.clip_position = camera.view_proj * world_pos; - out.tex_coords = model_tex_coords; - return out; -} - -@fragment -fn fs_main(in: VertexOutput) -> @location(0) vec4 { - let object_color = textureSample(t_diffuse, s_diffuse, in.tex_coords); - - let ambient = 0.1; - let ambient_color = light.color.rbg * ambient; - - let light_dir = normalize(light.position.xyz - in.position); - let diffuse = max(dot(in.normal, light_dir), 0.0); - let diffuse_color = light.color.rgb * diffuse; - - let view_dir = normalize(camera.pos.xyz - in.position); - let half_dir = normalize(view_dir + light_dir); - let specular = pow(max(dot(in.normal, half_dir), 0.0), 32.0); - let specular_color = light.color.rbg * specular; - - let all = ambient_color + diffuse_color + specular_color; - - let result = all * object_color.rgb; - - return vec4(result, object_color.a); - -} diff --git a/src/core/examples/sysgpu/gen-texture-light/light.wgsl b/src/core/examples/sysgpu/gen-texture-light/light.wgsl deleted file mode 100644 index a272ccf0..00000000 --- a/src/core/examples/sysgpu/gen-texture-light/light.wgsl +++ /dev/null @@ -1,34 +0,0 @@ -struct CameraUniform { - view_pos: vec4, - view_proj: mat4x4, -}; - -struct VertexOutput { - @builtin(position) clip_position: vec4, -}; - -struct Light { - position: vec4, - color: vec4, -}; - -@group(0) @binding(0) var camera: CameraUniform; -@group(1) @binding(0) var light: Light; - -@vertex -fn vs_main( - // TODO - struct input - @location(0) model_position: vec3, - @location(1) model_normal: vec3, - @location(2) model_tex_coords: vec2, -) -> VertexOutput { - var out: VertexOutput; - let world_pos = vec4(model_position + light.position.xyz, 1.0); - out.clip_position = camera.view_proj * world_pos; - return out; -} - -@fragment -fn fs_main(in: VertexOutput) -> @location(0) vec4 { - return vec4(1.0, 1.0, 1.0, 0.5); -} diff --git a/src/core/examples/sysgpu/gen-texture-light/main.zig b/src/core/examples/sysgpu/gen-texture-light/main.zig deleted file mode 100644 index 2cf160fe..00000000 --- a/src/core/examples/sysgpu/gen-texture-light/main.zig +++ /dev/null @@ -1,896 +0,0 @@ -// in this example: -// - comptime generated image data for texture -// - Blinn-Phong lighting -// - several pipelines -// -// quit with escape, q or space -// move camera with arrows or wasd - -const std = @import("std"); - -const mach = @import("mach"); -const core = mach.core; -const gpu = mach.gpu; - -const zm = @import("zmath"); -const Vec = zm.Vec; -const Mat = zm.Mat; -const Quat = zm.Quat; - -pub const App = @This(); - -// Use experimental sysgpu graphics API -pub const use_sysgpu = true; - -var gpa = std.heap.GeneralPurposeAllocator(.{}){}; - -title_timer: core.Timer, -timer: core.Timer, -cube: Cube, -camera: Camera, -light: Light, -depth: Texture, -keys: u8, - -const Dir = struct { - const up: u8 = 0b0001; - const down: u8 = 0b0010; - const left: u8 = 0b0100; - const right: u8 = 0b1000; -}; - -pub fn init(app: *App) !void { - try core.init(.{}); - - app.title_timer = try core.Timer.start(); - app.timer = try core.Timer.start(); - - const eye = Vec{ 5.0, 7.0, 5.0, 0.0 }; - const target = Vec{ 0.0, 0.0, 0.0, 0.0 }; - - const framebuffer = core.descriptor; - const aspect_ratio = @as(f32, @floatFromInt(framebuffer.width)) / @as(f32, @floatFromInt(framebuffer.height)); - - app.cube = Cube.init(); - app.light = Light.init(); - app.depth = Texture.depth(core.device, framebuffer.width, framebuffer.height); - app.camera = Camera.init(core.device, eye, target, zm.Vec{ 0.0, 1.0, 0.0, 0.0 }, aspect_ratio, 45.0, 0.1, 100.0); - app.keys = 0; -} - -pub fn deinit(app: *App) void { - defer _ = gpa.deinit(); - defer core.deinit(); - - app.cube.deinit(); - app.camera.deinit(); - app.light.deinit(); - app.depth.release(); -} - -pub fn update(app: *App) !bool { - const delta_time = app.timer.lap(); - - var iter = core.pollEvents(); - while (iter.next()) |event| { - switch (event) { - .key_press => |ev| switch (ev.key) { - .q, .escape, .space => return true, - .w, .up => { - app.keys |= Dir.up; - }, - .s, .down => { - app.keys |= Dir.down; - }, - .a, .left => { - app.keys |= Dir.left; - }, - .d, .right => { - app.keys |= Dir.right; - }, - .one => core.setDisplayMode(.windowed), - .two => core.setDisplayMode(.fullscreen), - .three => core.setDisplayMode(.borderless), - else => {}, - }, - .key_release => |ev| switch (ev.key) { - .w, .up => { - app.keys &= ~Dir.up; - }, - .s, .down => { - app.keys &= ~Dir.down; - }, - .a, .left => { - app.keys &= ~Dir.left; - }, - .d, .right => { - app.keys &= ~Dir.right; - }, - else => {}, - }, - .framebuffer_resize => |ev| { - // recreates the sampler, which is a waste, but for an example it's ok - app.depth.release(); - app.depth = Texture.depth(core.device, ev.width, ev.height); - }, - .close => return true, - else => {}, - } - } - - // move camera - const speed = zm.Vec{ delta_time * 5, delta_time * 5, delta_time * 5, delta_time * 5 }; - const fwd = zm.normalize3(app.camera.target - app.camera.eye); - const right = zm.normalize3(zm.cross3(fwd, app.camera.up)); - - if (app.keys & Dir.up != 0) - app.camera.eye += fwd * speed; - - if (app.keys & Dir.down != 0) - app.camera.eye -= fwd * speed; - - if (app.keys & Dir.right != 0) - app.camera.eye += right * speed - else if (app.keys & Dir.left != 0) - app.camera.eye -= right * speed - else - app.camera.eye += right * (speed * @Vector(4, f32){ 0.5, 0.5, 0.5, 0.5 }); - - const queue = core.queue; - app.camera.update(queue); - - // move light - const light_speed = delta_time * 2.5; - app.light.update(queue, light_speed); - - const back_buffer_view = core.swap_chain.getCurrentTextureView().?; - defer back_buffer_view.release(); - - const encoder = core.device.createCommandEncoder(null); - defer encoder.release(); - - const color_attachment = gpu.RenderPassColorAttachment{ - .view = back_buffer_view, - .clear_value = gpu.Color{ .r = 0.0, .g = 0.0, .b = 0.4, .a = 1.0 }, - .load_op = .clear, - .store_op = .store, - }; - - const render_pass_descriptor = gpu.RenderPassDescriptor.init(.{ - .color_attachments = &.{color_attachment}, - .depth_stencil_attachment = &.{ - .view = app.depth.view, - .depth_load_op = .clear, - .depth_store_op = .store, - .depth_clear_value = 1.0, - }, - }); - - const pass = encoder.beginRenderPass(&render_pass_descriptor); - defer pass.release(); - - // brick cubes - pass.setPipeline(app.cube.pipeline); - pass.setBindGroup(0, app.camera.bind_group, &.{}); - pass.setBindGroup(1, app.cube.texture.bind_group.?, &.{}); - pass.setBindGroup(2, app.light.bind_group, &.{}); - pass.setVertexBuffer(0, app.cube.mesh.buffer, 0, app.cube.mesh.size); - pass.setVertexBuffer(1, app.cube.instance.buffer, 0, app.cube.instance.size); - pass.draw(4, app.cube.instance.len, 0, 0); - pass.draw(4, app.cube.instance.len, 4, 0); - pass.draw(4, app.cube.instance.len, 8, 0); - pass.draw(4, app.cube.instance.len, 12, 0); - pass.draw(4, app.cube.instance.len, 16, 0); - pass.draw(4, app.cube.instance.len, 20, 0); - - // light source - pass.setPipeline(app.light.pipeline); - pass.setBindGroup(0, app.camera.bind_group, &.{}); - pass.setBindGroup(1, app.light.bind_group, &.{}); - pass.setVertexBuffer(0, app.cube.mesh.buffer, 0, app.cube.mesh.size); - pass.draw(4, 1, 0, 0); - pass.draw(4, 1, 4, 0); - pass.draw(4, 1, 8, 0); - pass.draw(4, 1, 12, 0); - pass.draw(4, 1, 16, 0); - pass.draw(4, 1, 20, 0); - - pass.end(); - - var command = encoder.finish(null); - defer command.release(); - - queue.submit(&[_]*gpu.CommandBuffer{command}); - core.swap_chain.present(); - - // update the window title every second - if (app.title_timer.read() >= 1.0) { - app.title_timer.reset(); - try core.printTitle("Gen Texture Light [ {d}fps ] [ Input {d}hz ]", .{ - core.frameRate(), - core.inputRate(), - }); - } - - return false; -} - -const Camera = struct { - const Self = @This(); - - eye: Vec, - target: Vec, - up: Vec, - aspect: f32, - fovy: f32, - near: f32, - far: f32, - bind_group: *gpu.BindGroup, - buffer: Buffer, - - const Uniform = extern struct { - pos: Vec, - mat: Mat, - }; - - fn init(device: *gpu.Device, eye: Vec, target: Vec, up: Vec, aspect: f32, fovy: f32, near: f32, far: f32) Self { - var self: Self = .{ - .eye = eye, - .target = target, - .up = up, - .aspect = aspect, - .near = near, - .far = far, - .fovy = fovy, - .buffer = undefined, - .bind_group = undefined, - }; - - const view = self.buildViewProjMatrix(); - - const uniform = Uniform{ - .pos = self.eye, - .mat = view, - }; - - const buffer = .{ - .buffer = initBuffer(device, .{ .uniform = true }, &@as([20]f32, @bitCast(uniform))), - .size = @sizeOf(@TypeOf(uniform)), - }; - - const layout = Self.bindGroupLayout(device); - const bind_group = device.createBindGroup(&gpu.BindGroup.Descriptor.init(.{ - .layout = layout, - .entries = &.{ - gpu.BindGroup.Entry.buffer(0, buffer.buffer, 0, buffer.size, buffer.size), - }, - })); - layout.release(); - - self.buffer = buffer; - self.bind_group = bind_group; - - return self; - } - - fn deinit(self: *Self) void { - self.bind_group.release(); - self.buffer.release(); - } - - fn update(self: *Self, queue: *gpu.Queue) void { - const mat = self.buildViewProjMatrix(); - const uniform = .{ - .pos = self.eye, - .mat = mat, - }; - - queue.writeBuffer(self.buffer.buffer, 0, &[_]Uniform{uniform}); - } - - inline fn buildViewProjMatrix(s: *const Camera) Mat { - const view = zm.lookAtRh(s.eye, s.target, s.up); - const proj = zm.perspectiveFovRh(s.fovy, s.aspect, s.near, s.far); - return zm.mul(view, proj); - } - - inline fn bindGroupLayout(device: *gpu.Device) *gpu.BindGroupLayout { - const visibility = .{ .vertex = true, .fragment = true }; - return device.createBindGroupLayout(&gpu.BindGroupLayout.Descriptor.init(.{ - .entries = &.{ - gpu.BindGroupLayout.Entry.buffer(0, visibility, .uniform, false, 0), - }, - })); - } -}; - -const Buffer = struct { - const Self = @This(); - - buffer: *gpu.Buffer, - size: usize, - len: u32 = 0, - - fn release(self: *Self) void { - self.buffer.release(); - } -}; - -const Cube = struct { - const Self = @This(); - - pipeline: *gpu.RenderPipeline, - mesh: Buffer, - instance: Buffer, - texture: Texture, - - const IPR = 20; // instances per row - const SPACING = 2; // spacing between cubes - const DISPLACEMENT = vec3u(IPR * SPACING / 2, 0, IPR * SPACING / 2); - - fn init() Self { - const device = core.device; - - const texture = Brick.texture(device); - - // instance buffer - var ibuf: [IPR * IPR * 16]f32 = undefined; - - var z: usize = 0; - while (z < IPR) : (z += 1) { - var x: usize = 0; - while (x < IPR) : (x += 1) { - const pos = vec3u(x * SPACING, 0, z * SPACING) - DISPLACEMENT; - const rot = blk: { - if (pos[0] == 0 and pos[2] == 0) { - break :blk zm.rotationZ(0.0); - } else { - break :blk zm.mul(zm.rotationX(zm.clamp(zm.abs(pos[0]), 0, 45.0)), zm.rotationZ(zm.clamp(zm.abs(pos[2]), 0, 45.0))); - } - }; - const index = z * IPR + x; - const inst = Instance{ - .position = pos, - .rotation = rot, - }; - zm.storeMat(ibuf[index * 16 ..], inst.toMat()); - } - } - - const instance = Buffer{ - .buffer = initBuffer(device, .{ .vertex = true }, &ibuf), - .len = IPR * IPR, - .size = @sizeOf(@TypeOf(ibuf)), - }; - - return Self{ - .mesh = mesh(device), - .texture = texture, - .instance = instance, - .pipeline = pipeline(), - }; - } - - fn deinit(self: *Self) void { - self.pipeline.release(); - self.mesh.release(); - self.instance.release(); - self.texture.release(); - } - - fn pipeline() *gpu.RenderPipeline { - const device = core.device; - - const camera_layout = Camera.bindGroupLayout(device); - const texture_layout = Texture.bindGroupLayout(device); - const light_layout = Light.bindGroupLayout(device); - const layout_descriptor = gpu.PipelineLayout.Descriptor.init(.{ - .bind_group_layouts = &.{ - camera_layout, - texture_layout, - light_layout, - }, - }); - defer camera_layout.release(); - defer texture_layout.release(); - defer light_layout.release(); - - const layout = device.createPipelineLayout(&layout_descriptor); - defer layout.release(); - - const shader = device.createShaderModuleWGSL("cube.wgsl", @embedFile("cube.wgsl")); - defer shader.release(); - - const blend = gpu.BlendState{}; - const color_target = gpu.ColorTargetState{ - .format = core.descriptor.format, - .blend = &blend, - }; - - const fragment = gpu.FragmentState.init(.{ - .module = shader, - .entry_point = "fs_main", - .targets = &.{color_target}, - }); - - const descriptor = gpu.RenderPipeline.Descriptor{ - .layout = layout, - .fragment = &fragment, - .vertex = gpu.VertexState.init(.{ - .module = shader, - .entry_point = "vs_main", - .buffers = &.{ - Self.vertexBufferLayout(), - Self.instanceLayout(), - }, - }), - .depth_stencil = &.{ - .format = Texture.DEPTH_FORMAT, - .depth_write_enabled = .true, - .depth_compare = .less, - }, - .primitive = .{ - .cull_mode = .back, - .topology = .triangle_strip, - }, - }; - - return device.createRenderPipeline(&descriptor); - } - - fn mesh(device: *gpu.Device) Buffer { - // generated texture has aspect ratio of 1:2 - // `h` reflects that ratio - // `v` sets how many times texture repeats across surface - const v = 2; - const h = v * 2; - const buf = asFloats(.{ - // z+ face - 0, 0, 1, 0, 0, 1, 0, h, - 1, 0, 1, 0, 0, 1, v, h, - 0, 1, 1, 0, 0, 1, 0, 0, - 1, 1, 1, 0, 0, 1, v, 0, - // z- face - 1, 0, 0, 0, 0, -1, 0, h, - 0, 0, 0, 0, 0, -1, v, h, - 1, 1, 0, 0, 0, -1, 0, 0, - 0, 1, 0, 0, 0, -1, v, 0, - // x+ face - 1, 0, 1, 1, 0, 0, 0, h, - 1, 0, 0, 1, 0, 0, v, h, - 1, 1, 1, 1, 0, 0, 0, 0, - 1, 1, 0, 1, 0, 0, v, 0, - // x- face - 0, 0, 0, -1, 0, 0, 0, h, - 0, 0, 1, -1, 0, 0, v, h, - 0, 1, 0, -1, 0, 0, 0, 0, - 0, 1, 1, -1, 0, 0, v, 0, - // y+ face - 1, 1, 0, 0, 1, 0, 0, h, - 0, 1, 0, 0, 1, 0, v, h, - 1, 1, 1, 0, 1, 0, 0, 0, - 0, 1, 1, 0, 1, 0, v, 0, - // y- face - 0, 0, 0, 0, -1, 0, 0, h, - 1, 0, 0, 0, -1, 0, v, h, - 0, 0, 1, 0, -1, 0, 0, 0, - 1, 0, 1, 0, -1, 0, v, 0, - }); - - return Buffer{ - .buffer = initBuffer(device, .{ .vertex = true }, &buf), - .size = @sizeOf(@TypeOf(buf)), - }; - } - - fn vertexBufferLayout() gpu.VertexBufferLayout { - const attributes = [_]gpu.VertexAttribute{ - .{ - .format = .float32x3, - .offset = 0, - .shader_location = 0, - }, - .{ - .format = .float32x3, - .offset = @sizeOf([3]f32), - .shader_location = 1, - }, - .{ - .format = .float32x2, - .offset = @sizeOf([6]f32), - .shader_location = 2, - }, - }; - return gpu.VertexBufferLayout.init(.{ - .array_stride = @sizeOf([8]f32), - .attributes = &attributes, - }); - } - - fn instanceLayout() gpu.VertexBufferLayout { - const attributes = [_]gpu.VertexAttribute{ - .{ - .format = .float32x4, - .offset = 0, - .shader_location = 3, - }, - .{ - .format = .float32x4, - .offset = @sizeOf([4]f32), - .shader_location = 4, - }, - .{ - .format = .float32x4, - .offset = @sizeOf([8]f32), - .shader_location = 5, - }, - .{ - .format = .float32x4, - .offset = @sizeOf([12]f32), - .shader_location = 6, - }, - }; - - return gpu.VertexBufferLayout.init(.{ - .array_stride = @sizeOf([16]f32), - .step_mode = .instance, - .attributes = &attributes, - }); - } -}; - -fn asFloats(comptime arr: anytype) [arr.len]f32 { - const len = arr.len; - comptime var out: [len]f32 = undefined; - comptime var i = 0; - inline while (i < len) : (i += 1) { - out[i] = @as(f32, @floatFromInt(arr[i])); - } - return out; -} - -const Brick = struct { - const W = 12; - const H = 6; - - fn texture(device: *gpu.Device) Texture { - const slice: []const u8 = &data(); - return Texture.fromData(device, W, H, u8, slice); - } - - fn data() [W * H * 4]u8 { - comptime var out: [W * H * 4]u8 = undefined; - - // fill all the texture with brick color - comptime var i = 0; - inline while (i < H) : (i += 1) { - comptime var j = 0; - inline while (j < W * 4) : (j += 4) { - out[i * W * 4 + j + 0] = 210; - out[i * W * 4 + j + 1] = 30; - out[i * W * 4 + j + 2] = 30; - out[i * W * 4 + j + 3] = 0; - } - } - - const f = 10; - - // fill the cement lines - inline for ([_]comptime_int{ 0, 1 }) |k| { - inline for ([_]comptime_int{ 5 * 4, 11 * 4 }) |m| { - out[k * W * 4 + m + 0] = f; - out[k * W * 4 + m + 1] = f; - out[k * W * 4 + m + 2] = f; - out[k * W * 4 + m + 3] = 0; - } - } - - inline for ([_]comptime_int{ 3, 4 }) |k| { - inline for ([_]comptime_int{ 2 * 4, 8 * 4 }) |m| { - out[k * W * 4 + m + 0] = f; - out[k * W * 4 + m + 1] = f; - out[k * W * 4 + m + 2] = f; - out[k * W * 4 + m + 3] = 0; - } - } - - inline for ([_]comptime_int{ 2, 5 }) |k| { - comptime var m = 0; - inline while (m < W * 4) : (m += 4) { - out[k * W * 4 + m + 0] = f; - out[k * W * 4 + m + 1] = f; - out[k * W * 4 + m + 2] = f; - out[k * W * 4 + m + 3] = 0; - } - } - - return out; - } -}; - -// don't confuse with gpu.Texture -const Texture = struct { - const Self = @This(); - - texture: *gpu.Texture, - view: *gpu.TextureView, - sampler: *gpu.Sampler, - bind_group: ?*gpu.BindGroup, - - const DEPTH_FORMAT = .depth32_float; - const FORMAT = .rgba8_unorm; - - fn release(self: *Self) void { - self.texture.release(); - self.view.release(); - self.sampler.release(); - if (self.bind_group) |bind_group| bind_group.release(); - } - - fn fromData(device: *gpu.Device, width: u32, height: u32, comptime T: type, data: []const T) Self { - const extent = gpu.Extent3D{ - .width = width, - .height = height, - }; - - const texture = device.createTexture(&gpu.Texture.Descriptor{ - .size = extent, - .format = FORMAT, - .usage = .{ .copy_dst = true, .texture_binding = true }, - }); - - const view = texture.createView(&gpu.TextureView.Descriptor{ - .format = FORMAT, - .dimension = .dimension_2d, - .array_layer_count = 1, - .mip_level_count = 1, - }); - - const sampler = device.createSampler(&gpu.Sampler.Descriptor{ - .address_mode_u = .repeat, - .address_mode_v = .repeat, - .address_mode_w = .repeat, - .mag_filter = .linear, - .min_filter = .linear, - .mipmap_filter = .linear, - .max_anisotropy = 1, // 1,2,4,8,16 - }); - - core.queue.writeTexture( - &gpu.ImageCopyTexture{ - .texture = texture, - }, - &gpu.Texture.DataLayout{ - .bytes_per_row = 4 * width, - .rows_per_image = height, - }, - &extent, - data, - ); - - const bind_group_layout = Self.bindGroupLayout(device); - const bind_group = device.createBindGroup(&gpu.BindGroup.Descriptor.init(.{ - .layout = bind_group_layout, - .entries = &.{ - gpu.BindGroup.Entry.textureView(0, view), - gpu.BindGroup.Entry.sampler(1, sampler), - }, - })); - bind_group_layout.release(); - - return Self{ - .view = view, - .texture = texture, - .sampler = sampler, - .bind_group = bind_group, - }; - } - - fn depth(device: *gpu.Device, width: u32, height: u32) Self { - const extent = gpu.Extent3D{ - .width = width, - .height = height, - }; - - const texture = device.createTexture(&gpu.Texture.Descriptor{ - .size = extent, - .format = DEPTH_FORMAT, - .usage = .{ - .render_attachment = true, - .texture_binding = true, - }, - }); - - const view = texture.createView(&gpu.TextureView.Descriptor{ - .dimension = .dimension_2d, - .array_layer_count = 1, - .mip_level_count = 1, - }); - - const sampler = device.createSampler(&gpu.Sampler.Descriptor{ - .mag_filter = .linear, - .compare = .less_equal, - }); - - return Self{ - .texture = texture, - .view = view, - .sampler = sampler, - .bind_group = null, // not used - }; - } - - inline fn bindGroupLayout(device: *gpu.Device) *gpu.BindGroupLayout { - const visibility = .{ .fragment = true }; - const Entry = gpu.BindGroupLayout.Entry; - return device.createBindGroupLayout(&gpu.BindGroupLayout.Descriptor.init(.{ - .entries = &.{ - Entry.texture(0, visibility, .float, .dimension_2d, false), - Entry.sampler(1, visibility, .filtering), - }, - })); - } -}; - -const Light = struct { - const Self = @This(); - - uniform: Uniform, - buffer: Buffer, - bind_group: *gpu.BindGroup, - pipeline: *gpu.RenderPipeline, - - const Uniform = extern struct { - position: Vec, - color: Vec, - }; - - fn init() Self { - const device = core.device; - const uniform = Uniform{ - .color = vec3u(1, 1, 1), - .position = vec3u(3, 7, 2), - }; - - const buffer = .{ - .buffer = initBuffer(device, .{ .uniform = true }, &@as([8]f32, @bitCast(uniform))), - .size = @sizeOf(@TypeOf(uniform)), - }; - - const layout = Self.bindGroupLayout(device); - const bind_group = device.createBindGroup(&gpu.BindGroup.Descriptor.init(.{ - .layout = layout, - .entries = &.{ - gpu.BindGroup.Entry.buffer(0, buffer.buffer, 0, buffer.size, buffer.size), - }, - })); - layout.release(); - - return Self{ - .buffer = buffer, - .uniform = uniform, - .bind_group = bind_group, - .pipeline = Self.pipeline(), - }; - } - - fn deinit(self: *Self) void { - self.buffer.release(); - self.bind_group.release(); - self.pipeline.release(); - } - - fn update(self: *Self, queue: *gpu.Queue, delta: f32) void { - const old = self.uniform; - const new = Light.Uniform{ - .position = zm.qmul(zm.quatFromAxisAngle(vec3u(0, 1, 0), delta), old.position), - .color = old.color, - }; - queue.writeBuffer(self.buffer.buffer, 0, &[_]Light.Uniform{new}); - self.uniform = new; - } - - inline fn bindGroupLayout(device: *gpu.Device) *gpu.BindGroupLayout { - const visibility = .{ .vertex = true, .fragment = true }; - const Entry = gpu.BindGroupLayout.Entry; - return device.createBindGroupLayout(&gpu.BindGroupLayout.Descriptor.init(.{ - .entries = &.{ - Entry.buffer(0, visibility, .uniform, false, 0), - }, - })); - } - - fn pipeline() *gpu.RenderPipeline { - const device = core.device; - - const camera_layout = Camera.bindGroupLayout(device); - const light_layout = Light.bindGroupLayout(device); - const layout_descriptor = gpu.PipelineLayout.Descriptor.init(.{ - .bind_group_layouts = &.{ - camera_layout, - light_layout, - }, - }); - defer camera_layout.release(); - defer light_layout.release(); - - const layout = device.createPipelineLayout(&layout_descriptor); - defer layout.release(); - - const shader = core.device.createShaderModuleWGSL("light.wgsl", @embedFile("light.wgsl")); - defer shader.release(); - - const blend = gpu.BlendState{}; - const color_target = gpu.ColorTargetState{ - .format = core.descriptor.format, - .blend = &blend, - }; - - const fragment = gpu.FragmentState.init(.{ - .module = shader, - .entry_point = "fs_main", - .targets = &.{color_target}, - }); - - const descriptor = gpu.RenderPipeline.Descriptor{ - .layout = layout, - .fragment = &fragment, - .vertex = gpu.VertexState.init(.{ - .module = shader, - .entry_point = "vs_main", - .buffers = &.{ - Cube.vertexBufferLayout(), - }, - }), - .depth_stencil = &.{ - .format = Texture.DEPTH_FORMAT, - .depth_write_enabled = .true, - .depth_compare = .less, - }, - .primitive = .{ - .cull_mode = .back, - .topology = .triangle_strip, - }, - }; - - return device.createRenderPipeline(&descriptor); - } -}; - -inline fn initBuffer(device: *gpu.Device, usage: gpu.Buffer.UsageFlags, data: anytype) *gpu.Buffer { - std.debug.assert(@typeInfo(@TypeOf(data)) == .Pointer); - const T = std.meta.Elem(@TypeOf(data)); - - var u = usage; - u.copy_dst = true; - const buffer = device.createBuffer(&.{ - .size = @sizeOf(T) * data.len, - .usage = u, - .mapped_at_creation = .true, - }); - - const mapped = buffer.getMappedRange(T, 0, data.len); - @memcpy(mapped.?, data); - buffer.unmap(); - return buffer; -} - -fn vec3i(x: isize, y: isize, z: isize) Vec { - return Vec{ @floatFromInt(x), @floatFromInt(y), @floatFromInt(z), 0.0 }; -} - -fn vec3u(x: usize, y: usize, z: usize) Vec { - return zm.Vec{ @floatFromInt(x), @floatFromInt(y), @floatFromInt(z), 0.0 }; -} - -// todo indside Cube -const Instance = struct { - const Self = @This(); - - position: Vec, - rotation: Mat, - - fn toMat(self: *const Self) Mat { - return zm.mul(self.rotation, zm.translationV(self.position)); - } -}; diff --git a/src/core/examples/sysgpu/image-blur/blur.wgsl b/src/core/examples/sysgpu/image-blur/blur.wgsl deleted file mode 100644 index f97449c1..00000000 --- a/src/core/examples/sysgpu/image-blur/blur.wgsl +++ /dev/null @@ -1,82 +0,0 @@ -struct Params { - filterDim : i32, - blockDim : u32, -} - -@group(0) @binding(0) var samp : sampler; -@group(0) @binding(1) var params : Params; -@group(1) @binding(1) var inputTex : texture_2d; -@group(1) @binding(2) var outputTex : texture_storage_2d; - -struct Flip { - value : u32, -} -@group(1) @binding(3) var flip : Flip; - -// This shader blurs the input texture in one direction, depending on whether -// |flip.value| is 0 or 1. -// It does so by running (128 / 4) threads per workgroup to load 128 -// texels into 4 rows of shared memory. Each thread loads a -// 4 x 4 block of texels to take advantage of the texture sampling -// hardware. -// Then, each thread computes the blur result by averaging the adjacent texel values -// in shared memory. -// Because we're operating on a subset of the texture, we cannot compute all of the -// results since not all of the neighbors are available in shared memory. -// Specifically, with 128 x 128 tiles, we can only compute and write out -// square blocks of size 128 - (filterSize - 1). We compute the number of blocks -// needed in Javascript and dispatch that amount. - -var tile : array, 128>, 4>; - -@compute @workgroup_size(32, 1, 1) -fn main( - @builtin(workgroup_id) WorkGroupID : vec3, - @builtin(local_invocation_id) LocalInvocationID : vec3 -) { - // TODO - mixed vector arithmetic (vec2 and vec2) - let filterOffset = (params.filterDim - 1) / 2; - let dims = vec2(textureDimensions(inputTex, 0)); - let baseIndex = vec2(WorkGroupID.xy * vec2(params.blockDim, 4) + - LocalInvocationID.xy * vec2(4, 1)) - - vec2(filterOffset, 0); - - for (var r = 0; r < 4; r++) { - for (var c = 0; c < 4; c++) { - var loadIndex = baseIndex + vec2(c, r); - if (flip.value != 0u) { - loadIndex = loadIndex.yx; - } - - tile[r][4 * LocalInvocationID.x + u32(c)] = textureSampleLevel( - inputTex, - samp, - (vec2(loadIndex) + vec2(0.25, 0.25)) / vec2(dims), - 0.0 - ).rgb; - } - } - - workgroupBarrier(); - - for (var r = 0; r < 4; r++) { - for (var c = 0; c < 4; c++) { - var writeIndex = baseIndex + vec2(c, r); - if (flip.value != 0) { - writeIndex = writeIndex.yx; - } - - let center = u32(4 * LocalInvocationID.x) + c; - if (center >= filterOffset && - center < 128 - filterOffset && - all(writeIndex < dims)) { - var acc = vec3(0.0, 0.0, 0.0); - for (var f = 0; f < params.filterDim; f++) { - var i = center + f - filterOffset; - acc = acc + (1.0 / f32(params.filterDim)) * tile[r][i]; - } - textureStore(outputTex, writeIndex, vec4(acc, 1.0)); - } - } - } -} diff --git a/src/core/examples/sysgpu/image-blur/fullscreen_textured_quad.wgsl b/src/core/examples/sysgpu/image-blur/fullscreen_textured_quad.wgsl deleted file mode 100644 index 61c461c0..00000000 --- a/src/core/examples/sysgpu/image-blur/fullscreen_textured_quad.wgsl +++ /dev/null @@ -1,38 +0,0 @@ -@group(0) @binding(0) var mySampler : sampler; -@group(0) @binding(1) var myTexture : texture_2d; - -struct VertexOutput { - @builtin(position) Position : vec4, - @location(0) fragUV : vec2, -} - -@vertex -fn vert_main(@builtin(vertex_index) VertexIndex : u32) -> VertexOutput { - var pos = array, 6>( - vec2( 1.0, 1.0), - vec2( 1.0, -1.0), - vec2(-1.0, -1.0), - vec2( 1.0, 1.0), - vec2(-1.0, -1.0), - vec2(-1.0, 1.0) - ); - - var uv = array, 6>( - vec2(1.0, 0.0), - vec2(1.0, 1.0), - vec2(0.0, 1.0), - vec2(1.0, 0.0), - vec2(0.0, 1.0), - vec2(0.0, 0.0) - ); - - var output : VertexOutput; - output.Position = vec4(pos[VertexIndex], 0.0, 1.0); - output.fragUV = uv[VertexIndex]; - return output; -} - -@fragment -fn frag_main(@location(0) fragUV : vec2) -> @location(0) vec4 { - return textureSample(myTexture, mySampler, fragUV); -} diff --git a/src/core/examples/sysgpu/image-blur/main.zig b/src/core/examples/sysgpu/image-blur/main.zig deleted file mode 100644 index 3a14d906..00000000 --- a/src/core/examples/sysgpu/image-blur/main.zig +++ /dev/null @@ -1,332 +0,0 @@ -const std = @import("std"); - -const mach = @import("mach"); -const core = mach.core; -const gpu = mach.gpu; - -const zigimg = @import("zigimg"); -const assets = @import("assets"); - -title_timer: core.Timer, -blur_pipeline: *gpu.ComputePipeline, -fullscreen_quad_pipeline: *gpu.RenderPipeline, -cube_texture: *gpu.Texture, -textures: [2]*gpu.Texture, -blur_params_buffer: *gpu.Buffer, -compute_constants: *gpu.BindGroup, -compute_bind_group_0: *gpu.BindGroup, -compute_bind_group_1: *gpu.BindGroup, -compute_bind_group_2: *gpu.BindGroup, -show_result_bind_group: *gpu.BindGroup, -img_size: gpu.Extent3D, - -pub const App = @This(); - -// Use experimental sysgpu graphics API -pub const use_sysgpu = true; - -// Constants from the blur.wgsl shader -const tile_dimension: u32 = 128; -const batch: [2]u32 = .{ 4, 4 }; - -// Currently hardcoded -const filter_size: u32 = 15; -const iterations: u32 = 2; -var block_dimension: u32 = tile_dimension - (filter_size - 1); -var gpa = std.heap.GeneralPurposeAllocator(.{}){}; - -pub fn init(app: *App) !void { - try core.init(.{}); - const allocator = gpa.allocator(); - - const queue = core.queue; - - const blur_shader_module = core.device.createShaderModuleWGSL("blur.wgsl", @embedFile("blur.wgsl")); - - const blur_pipeline_descriptor = gpu.ComputePipeline.Descriptor{ - .compute = gpu.ProgrammableStageDescriptor{ - .module = blur_shader_module, - .entry_point = "main", - }, - }; - - const blur_pipeline = core.device.createComputePipeline(&blur_pipeline_descriptor); - blur_shader_module.release(); - - const fullscreen_quad_vs_module = core.device.createShaderModuleWGSL( - "fullscreen_textured_quad.wgsl", - @embedFile("fullscreen_textured_quad.wgsl"), - ); - - const fullscreen_quad_fs_module = core.device.createShaderModuleWGSL( - "fullscreen_textured_quad.wgsl", - @embedFile("fullscreen_textured_quad.wgsl"), - ); - - const blend = gpu.BlendState{}; - const color_target = gpu.ColorTargetState{ - .format = core.descriptor.format, - .blend = &blend, - .write_mask = gpu.ColorWriteMaskFlags.all, - }; - - const fragment_state = gpu.FragmentState.init(.{ - .module = fullscreen_quad_fs_module, - .entry_point = "frag_main", - .targets = &.{color_target}, - }); - - const fullscreen_quad_pipeline_descriptor = gpu.RenderPipeline.Descriptor{ - .fragment = &fragment_state, - .vertex = .{ - .module = fullscreen_quad_vs_module, - .entry_point = "vert_main", - }, - }; - - const fullscreen_quad_pipeline = core.device.createRenderPipeline(&fullscreen_quad_pipeline_descriptor); - fullscreen_quad_vs_module.release(); - fullscreen_quad_fs_module.release(); - - const sampler = core.device.createSampler(&.{ - .mag_filter = .linear, - .min_filter = .linear, - }); - - var img = try zigimg.Image.fromMemory(allocator, assets.gotta_go_fast_png); - defer img.deinit(); - - const img_size = gpu.Extent3D{ .width = @as(u32, @intCast(img.width)), .height = @as(u32, @intCast(img.height)) }; - - const cube_texture = core.device.createTexture(&.{ - .size = img_size, - .format = .rgba8_unorm, - .usage = .{ - .texture_binding = true, - .copy_dst = true, - .render_attachment = true, - }, - }); - - const data_layout = gpu.Texture.DataLayout{ - .bytes_per_row = @as(u32, @intCast(img.width * 4)), - .rows_per_image = @as(u32, @intCast(img.height)), - }; - - switch (img.pixels) { - .rgba32 => |pixels| queue.writeTexture(&.{ .texture = cube_texture }, &data_layout, &img_size, pixels), - .rgb24 => |pixels| { - const data = try rgb24ToRgba32(allocator, pixels); - defer data.deinit(allocator); - queue.writeTexture(&.{ .texture = cube_texture }, &data_layout, &img_size, data.rgba32); - }, - else => @panic("unsupported image color format"), - } - - var textures: [2]*gpu.Texture = undefined; - for (textures, 0..) |_, i| { - textures[i] = core.device.createTexture(&.{ - .size = img_size, - .format = .rgba8_unorm, - .usage = .{ - .storage_binding = true, - .texture_binding = true, - .copy_dst = true, - }, - }); - } - - // the shader blurs the input texture in one direction, - // depending on whether flip value is 0 or 1 - var flip: [2]*gpu.Buffer = undefined; - for (flip, 0..) |_, i| { - const buffer = core.device.createBuffer(&.{ - .usage = .{ .uniform = true }, - .size = @sizeOf(u32), - .mapped_at_creation = .true, - }); - - const buffer_mapped = buffer.getMappedRange(u32, 0, 1); - buffer_mapped.?[0] = @as(u32, @intCast(i)); - buffer.unmap(); - - flip[i] = buffer; - } - - const blur_params_buffer = core.device.createBuffer(&.{ - .size = 8, - .usage = .{ .copy_dst = true, .uniform = true }, - }); - - const blur_bind_group_layout0 = blur_pipeline.getBindGroupLayout(0); - const blur_bind_group_layout1 = blur_pipeline.getBindGroupLayout(1); - const fullscreen_bind_group_layout = fullscreen_quad_pipeline.getBindGroupLayout(0); - const cube_texture_view = cube_texture.createView(&gpu.TextureView.Descriptor{}); - const texture0_view = textures[0].createView(&gpu.TextureView.Descriptor{}); - const texture1_view = textures[1].createView(&gpu.TextureView.Descriptor{}); - - const compute_constants = core.device.createBindGroup(&gpu.BindGroup.Descriptor.init(.{ - .layout = blur_bind_group_layout0, - .entries = &.{ - gpu.BindGroup.Entry.sampler(0, sampler), - gpu.BindGroup.Entry.buffer(1, blur_params_buffer, 0, 8, 8), - }, - })); - - const compute_bind_group_0 = core.device.createBindGroup(&gpu.BindGroup.Descriptor.init(.{ - .layout = blur_bind_group_layout1, - .entries = &.{ - gpu.BindGroup.Entry.textureView(1, cube_texture_view), - gpu.BindGroup.Entry.textureView(2, texture0_view), - gpu.BindGroup.Entry.buffer(3, flip[0], 0, 4, 4), - }, - })); - - const compute_bind_group_1 = core.device.createBindGroup(&gpu.BindGroup.Descriptor.init(.{ - .layout = blur_bind_group_layout1, - .entries = &.{ - gpu.BindGroup.Entry.textureView(1, texture0_view), - gpu.BindGroup.Entry.textureView(2, texture1_view), - gpu.BindGroup.Entry.buffer(3, flip[1], 0, 4, 4), - }, - })); - - const compute_bind_group_2 = core.device.createBindGroup(&gpu.BindGroup.Descriptor.init(.{ - .layout = blur_bind_group_layout1, - .entries = &.{ - gpu.BindGroup.Entry.textureView(1, texture1_view), - gpu.BindGroup.Entry.textureView(2, texture0_view), - gpu.BindGroup.Entry.buffer(3, flip[0], 0, 4, 4), - }, - })); - - const show_result_bind_group = core.device.createBindGroup(&gpu.BindGroup.Descriptor.init(.{ - .layout = fullscreen_bind_group_layout, - .entries = &.{ - gpu.BindGroup.Entry.sampler(0, sampler), - gpu.BindGroup.Entry.textureView(1, texture1_view), - }, - })); - - blur_bind_group_layout0.release(); - blur_bind_group_layout1.release(); - fullscreen_bind_group_layout.release(); - sampler.release(); - flip[0].release(); - flip[1].release(); - cube_texture_view.release(); - texture0_view.release(); - texture1_view.release(); - - const blur_params_buffer_data = [_]u32{ filter_size, block_dimension }; - queue.writeBuffer(blur_params_buffer, 0, &blur_params_buffer_data); - - app.title_timer = try core.Timer.start(); - app.blur_pipeline = blur_pipeline; - app.fullscreen_quad_pipeline = fullscreen_quad_pipeline; - app.cube_texture = cube_texture; - app.textures = textures; - app.blur_params_buffer = blur_params_buffer; - app.compute_constants = compute_constants; - app.compute_bind_group_0 = compute_bind_group_0; - app.compute_bind_group_1 = compute_bind_group_1; - app.compute_bind_group_2 = compute_bind_group_2; - app.show_result_bind_group = show_result_bind_group; - app.img_size = img_size; -} - -pub fn deinit(app: *App) void { - defer _ = gpa.deinit(); - defer core.deinit(); - - app.blur_pipeline.release(); - app.fullscreen_quad_pipeline.release(); - app.cube_texture.release(); - app.textures[0].release(); - app.textures[1].release(); - app.blur_params_buffer.release(); - app.compute_constants.release(); - app.compute_bind_group_0.release(); - app.compute_bind_group_1.release(); - app.compute_bind_group_2.release(); - app.show_result_bind_group.release(); -} - -pub fn update(app: *App) !bool { - var iter = core.pollEvents(); - while (iter.next()) |event| { - if (event == .close) return true; - } - - const back_buffer_view = core.swap_chain.getCurrentTextureView().?; - const encoder = core.device.createCommandEncoder(null); - - const compute_pass = encoder.beginComputePass(null); - compute_pass.setPipeline(app.blur_pipeline); - compute_pass.setBindGroup(0, app.compute_constants, &.{}); - - const width: u32 = @as(u32, @intCast(app.img_size.width)); - const height: u32 = @as(u32, @intCast(app.img_size.height)); - compute_pass.setBindGroup(1, app.compute_bind_group_0, &.{}); - compute_pass.dispatchWorkgroups(try std.math.divCeil(u32, width, block_dimension), try std.math.divCeil(u32, height, batch[1]), 1); - - compute_pass.setBindGroup(1, app.compute_bind_group_1, &.{}); - compute_pass.dispatchWorkgroups(try std.math.divCeil(u32, height, block_dimension), try std.math.divCeil(u32, width, batch[1]), 1); - - var i: u32 = 0; - while (i < iterations - 1) : (i += 1) { - compute_pass.setBindGroup(1, app.compute_bind_group_2, &.{}); - compute_pass.dispatchWorkgroups(try std.math.divCeil(u32, width, block_dimension), try std.math.divCeil(u32, height, batch[1]), 1); - - compute_pass.setBindGroup(1, app.compute_bind_group_1, &.{}); - compute_pass.dispatchWorkgroups(try std.math.divCeil(u32, height, block_dimension), try std.math.divCeil(u32, width, batch[1]), 1); - } - compute_pass.end(); - compute_pass.release(); - - const color_attachment = gpu.RenderPassColorAttachment{ - .view = back_buffer_view, - .clear_value = std.mem.zeroes(gpu.Color), - .load_op = .clear, - .store_op = .store, - }; - - const render_pass_descriptor = gpu.RenderPassDescriptor.init(.{ - .color_attachments = &.{color_attachment}, - }); - - const render_pass = encoder.beginRenderPass(&render_pass_descriptor); - render_pass.setPipeline(app.fullscreen_quad_pipeline); - render_pass.setBindGroup(0, app.show_result_bind_group, &.{}); - render_pass.draw(6, 1, 0, 0); - render_pass.end(); - render_pass.release(); - - var command = encoder.finish(null); - encoder.release(); - const queue = core.queue; - queue.submit(&[_]*gpu.CommandBuffer{command}); - command.release(); - core.swap_chain.present(); - back_buffer_view.release(); - - // update the window title every second - if (app.title_timer.read() >= 1.0) { - app.title_timer.reset(); - try core.printTitle("Image Blur [ {d}fps ] [ Input {d}hz ]", .{ - core.frameRate(), - core.inputRate(), - }); - } - - return false; -} - -fn rgb24ToRgba32(allocator: std.mem.Allocator, in: []zigimg.color.Rgb24) !zigimg.color.PixelStorage { - const out = try zigimg.color.PixelStorage.init(allocator, .rgba32, in.len); - var i: usize = 0; - while (i < in.len) : (i += 1) { - out.rgba32[i] = zigimg.color.Rgba32{ .r = in[i].r, .g = in[i].g, .b = in[i].b, .a = 255 }; - } - return out; -} diff --git a/src/core/examples/sysgpu/image/fullscreen_textured_quad.wgsl b/src/core/examples/sysgpu/image/fullscreen_textured_quad.wgsl deleted file mode 100644 index 3238e6a4..00000000 --- a/src/core/examples/sysgpu/image/fullscreen_textured_quad.wgsl +++ /dev/null @@ -1,39 +0,0 @@ -@group(0) @binding(0) var mySampler : sampler; -@group(0) @binding(1) var myTexture : texture_2d; - -struct VertexOutput { - @builtin(position) Position : vec4, - @location(0) fragUV : vec2, -} - -@vertex -fn vert_main(@builtin(vertex_index) VertexIndex : u32) -> VertexOutput { - // Draw a fullscreen quad using two triangles, with UV coordinates (normalized pixel coordinates) - // that would have the full texture be displayed. - var pos = array, 6>( - vec2( 1.0, 1.0), // right, top - vec2( 1.0, -1.0), // right, bottom - vec2(-1.0, -1.0), // left, bottom - vec2( 1.0, 1.0), // right, top - vec2(-1.0, -1.0), // left, bottom - vec2(-1.0, 1.0) // left, top - ); - var uv = array, 6>( - vec2(1.0, 0.0), - vec2(1.0, 1.0), - vec2(0.0, 1.0), - vec2(1.0, 0.0), - vec2(0.0, 1.0), - vec2(0.0, 0.0) - ); - - var output : VertexOutput; - output.Position = vec4(pos[VertexIndex], 0.0, 1.0); - output.fragUV = uv[VertexIndex]; - return output; -} - -@fragment -fn frag_main(@location(0) fragUV : vec2) -> @location(0) vec4 { - return textureSample(myTexture, mySampler, fragUV); -} diff --git a/src/core/examples/sysgpu/image/main.zig b/src/core/examples/sysgpu/image/main.zig deleted file mode 100644 index cdf2b734..00000000 --- a/src/core/examples/sysgpu/image/main.zig +++ /dev/null @@ -1,190 +0,0 @@ -const std = @import("std"); - -const mach = @import("mach"); -const core = mach.core; -const gpu = mach.gpu; - -const zigimg = @import("zigimg"); -const assets = @import("assets"); - -// Use experimental sysgpu graphics API -pub const use_sysgpu = true; - -title_timer: core.Timer, -pipeline: *gpu.RenderPipeline, -texture: *gpu.Texture, -bind_group: *gpu.BindGroup, -img_size: gpu.Extent3D, - -pub const App = @This(); - -var gpa = std.heap.GeneralPurposeAllocator(.{}){}; - -pub fn init(app: *App) !void { - try core.init(.{}); - const allocator = gpa.allocator(); - - // Load our shader that will render a fullscreen textured quad using two triangles, needed to - // get the image on screen. - const fullscreen_quad_vs_module = core.device.createShaderModuleWGSL( - "fullscreen_textured_quad.wgsl", - @embedFile("fullscreen_textured_quad.wgsl"), - ); - defer fullscreen_quad_vs_module.release(); - const fullscreen_quad_fs_module = core.device.createShaderModuleWGSL( - "fullscreen_textured_quad.wgsl", - @embedFile("fullscreen_textured_quad.wgsl"), - ); - defer fullscreen_quad_fs_module.release(); - - // Create our render pipeline - const blend = gpu.BlendState{}; - const color_target = gpu.ColorTargetState{ - .format = core.descriptor.format, - .blend = &blend, - .write_mask = gpu.ColorWriteMaskFlags.all, - }; - const fragment_state = gpu.FragmentState.init(.{ - .module = fullscreen_quad_fs_module, - .entry_point = "frag_main", - .targets = &.{color_target}, - }); - const pipeline_descriptor = gpu.RenderPipeline.Descriptor{ - .fragment = &fragment_state, - .vertex = .{ - .module = fullscreen_quad_vs_module, - .entry_point = "vert_main", - }, - }; - const pipeline = core.device.createRenderPipeline(&pipeline_descriptor); - - // Create a texture sampler. This determines what happens when the texture doesn't match the - // dimensions of the screen it's being displayed on. If the image needs to be magnified or - // minified to fit, it can be linearly interpolated (i.e. 'blurred', .linear) or the nearest - // pixel may be used (i.e. 'pixelated', .nearest) - const sampler = core.device.createSampler(&.{ - .mag_filter = .linear, - .min_filter = .linear, - }); - defer sampler.release(); - - // Load the pixels of the image - var img = try zigimg.Image.fromMemory(allocator, assets.gotta_go_fast_png); - defer img.deinit(); - const img_size = gpu.Extent3D{ .width = @as(u32, @intCast(img.width)), .height = @as(u32, @intCast(img.height)) }; - - // Create a texture - const texture = core.device.createTexture(&.{ - .size = img_size, - .format = .rgba8_unorm, - .usage = .{ - .texture_binding = true, - .copy_dst = true, - .render_attachment = true, - }, - }); - - // Upload the pixels (from the CPU) to the GPU. You could e.g. do this once per frame if you - // wanted the image to be updated dynamically. - const data_layout = gpu.Texture.DataLayout{ - .bytes_per_row = @as(u32, @intCast(img.width * 4)), - .rows_per_image = @as(u32, @intCast(img.height)), - }; - switch (img.pixels) { - .rgba32 => |pixels| core.queue.writeTexture(&.{ .texture = texture }, &data_layout, &img_size, pixels), - .rgb24 => |pixels| { - const data = try rgb24ToRgba32(allocator, pixels); - defer data.deinit(allocator); - core.queue.writeTexture(&.{ .texture = texture }, &data_layout, &img_size, data.rgba32); - }, - else => @panic("unsupported image color format"), - } - - // Describe which data we will pass to our shader (GPU program) - const bind_group_layout = pipeline.getBindGroupLayout(0); - defer bind_group_layout.release(); - const texture_view = texture.createView(&gpu.TextureView.Descriptor{}); - defer texture_view.release(); - const bind_group = core.device.createBindGroup(&gpu.BindGroup.Descriptor.init(.{ - .layout = bind_group_layout, - .entries = &.{ - gpu.BindGroup.Entry.sampler(0, sampler), - gpu.BindGroup.Entry.textureView(1, texture_view), - }, - })); - - app.* = .{ - .title_timer = try core.Timer.start(), - .pipeline = pipeline, - .texture = texture, - .bind_group = bind_group, - .img_size = img_size, - }; -} - -pub fn deinit(app: *App) void { - defer _ = gpa.deinit(); - defer core.deinit(); - app.pipeline.release(); - app.texture.release(); - app.bind_group.release(); -} - -pub fn update(app: *App) !bool { - const back_buffer_view = core.swap_chain.getCurrentTextureView().?; - defer back_buffer_view.release(); - - // Poll for events (keyboard input, etc.) - var iter = core.pollEvents(); - while (iter.next()) |event| { - if (event == .close) return true; - } - - const encoder = core.device.createCommandEncoder(null); - defer encoder.release(); - - // Begin our render pass by clearing the pixels that were on the screen from the previous frame. - const color_attachment = gpu.RenderPassColorAttachment{ - .view = back_buffer_view, - .clear_value = std.mem.zeroes(gpu.Color), - .load_op = .clear, - .store_op = .store, - }; - const render_pass_descriptor = gpu.RenderPassDescriptor.init(.{ - .color_attachments = &.{color_attachment}, - }); - const render_pass = encoder.beginRenderPass(&render_pass_descriptor); - defer render_pass.release(); - - // Render using our pipeline - render_pass.setPipeline(app.pipeline); - render_pass.setBindGroup(0, app.bind_group, &.{}); - render_pass.draw(6, 1, 0, 0); // Tell the GPU to draw 6 vertices, one object - render_pass.end(); - - // Submit all the commands to the GPU and render the frame. - var command = encoder.finish(null); - defer command.release(); - core.queue.submit(&[_]*gpu.CommandBuffer{command}); - core.swap_chain.present(); - - // update the window title every second to have the FPS - if (app.title_timer.read() >= 1.0) { - app.title_timer.reset(); - try core.printTitle("Image [ {d}fps ] [ Input {d}hz ]", .{ - core.frameRate(), - core.inputRate(), - }); - } - - return false; -} - -fn rgb24ToRgba32(allocator: std.mem.Allocator, in: []zigimg.color.Rgb24) !zigimg.color.PixelStorage { - const out = try zigimg.color.PixelStorage.init(allocator, .rgba32, in.len); - var i: usize = 0; - while (i < in.len) : (i += 1) { - out.rgba32[i] = zigimg.color.Rgba32{ .r = in[i].r, .g = in[i].g, .b = in[i].b, .a = 255 }; - } - return out; -} diff --git a/src/core/examples/sysgpu/instanced-cube/cube_mesh.zig b/src/core/examples/sysgpu/instanced-cube/cube_mesh.zig deleted file mode 100644 index f26c75ac..00000000 --- a/src/core/examples/sysgpu/instanced-cube/cube_mesh.zig +++ /dev/null @@ -1,49 +0,0 @@ -pub const Vertex = extern struct { - pos: @Vector(4, f32), - col: @Vector(4, f32), - uv: @Vector(2, f32), -}; - -pub const vertices = [_]Vertex{ - .{ .pos = .{ 1, -1, 1, 1 }, .col = .{ 1, 0, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, -1, -1, 1 }, .col = .{ 0, 0, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, -1, 1, 1 }, .col = .{ 1, 0, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, -1, -1, 1 }, .col = .{ 0, 0, 0, 1 }, .uv = .{ 0, 0 } }, - - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ 1, -1, 1, 1 }, .col = .{ 1, 0, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, 1, -1, 1 }, .col = .{ 1, 1, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 0, 0 } }, - - .{ .pos = .{ -1, 1, 1, 1 }, .col = .{ 0, 1, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ 1, 1, -1, 1 }, .col = .{ 1, 1, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ -1, 1, 1, 1 }, .col = .{ 0, 1, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ 1, 1, -1, 1 }, .col = .{ 1, 1, 0, 1 }, .uv = .{ 0, 0 } }, - - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, 1, 1, 1 }, .col = .{ 0, 1, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ -1, -1, -1, 1 }, .col = .{ 0, 0, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 0, 0 } }, - - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, 1, 1, 1 }, .col = .{ 0, 1, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, -1, 1, 1 }, .col = .{ 1, 0, 1, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 1, 1 } }, - - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, -1, -1, 1 }, .col = .{ 0, 0, 0, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, 1, -1, 1 }, .col = .{ 1, 1, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 0, 0 } }, -}; diff --git a/src/core/examples/sysgpu/instanced-cube/main.zig b/src/core/examples/sysgpu/instanced-cube/main.zig deleted file mode 100644 index 05e72c4e..00000000 --- a/src/core/examples/sysgpu/instanced-cube/main.zig +++ /dev/null @@ -1,211 +0,0 @@ -const std = @import("std"); - -const mach = @import("mach"); -const core = mach.core; -const gpu = mach.gpu; - -const zm = @import("zmath"); -const Vertex = @import("cube_mesh.zig").Vertex; -const vertices = @import("cube_mesh.zig").vertices; - -const UniformBufferObject = struct { - mat: zm.Mat, -}; - -var gpa = std.heap.GeneralPurposeAllocator(.{}){}; - -title_timer: core.Timer, - -timer: core.Timer, -pipeline: *gpu.RenderPipeline, -vertex_buffer: *gpu.Buffer, -uniform_buffer: *gpu.Buffer, -bind_group: *gpu.BindGroup, - -pub const App = @This(); - -// Use experimental sysgpu graphics API -pub const use_sysgpu = true; - -pub fn init(app: *App) !void { - try core.init(.{}); - app.timer = try core.Timer.start(); - - const shader_module = core.device.createShaderModuleWGSL("shader.wgsl", @embedFile("shader.wgsl")); - - const vertex_attributes = [_]gpu.VertexAttribute{ - .{ .format = .float32x4, .offset = @offsetOf(Vertex, "pos"), .shader_location = 0 }, - .{ .format = .float32x2, .offset = @offsetOf(Vertex, "uv"), .shader_location = 1 }, - }; - const vertex_buffer_layout = gpu.VertexBufferLayout.init(.{ - .array_stride = @sizeOf(Vertex), - .step_mode = .vertex, - .attributes = &vertex_attributes, - }); - - const color_target = gpu.ColorTargetState{ - .format = core.descriptor.format, - .write_mask = gpu.ColorWriteMaskFlags.all, - }; - const fragment = gpu.FragmentState.init(.{ - .module = shader_module, - .entry_point = "frag_main", - .targets = &.{color_target}, - }); - - const bgle = gpu.BindGroupLayout.Entry.buffer(0, .{ .vertex = true }, .uniform, true, 0); - const bgl = core.device.createBindGroupLayout( - &gpu.BindGroupLayout.Descriptor.init(.{ - .entries = &.{bgle}, - }), - ); - - const bind_group_layouts = [_]*gpu.BindGroupLayout{bgl}; - const pipeline_layout = core.device.createPipelineLayout(&gpu.PipelineLayout.Descriptor.init(.{ - .bind_group_layouts = &bind_group_layouts, - })); - - const pipeline_descriptor = gpu.RenderPipeline.Descriptor{ - .fragment = &fragment, - .layout = pipeline_layout, - .vertex = gpu.VertexState.init(.{ - .module = shader_module, - .entry_point = "vertex_main", - .buffers = &.{vertex_buffer_layout}, - }), - .primitive = .{ - .cull_mode = .back, - }, - }; - - const vertex_buffer = core.device.createBuffer(&.{ - .usage = .{ .vertex = true }, - .size = @sizeOf(Vertex) * vertices.len, - .mapped_at_creation = .true, - }); - const vertex_mapped = vertex_buffer.getMappedRange(Vertex, 0, vertices.len); - @memcpy(vertex_mapped.?, vertices[0..]); - vertex_buffer.unmap(); - - const x_count = 4; - const y_count = 4; - const num_instances = x_count * y_count; - - const uniform_buffer = core.device.createBuffer(&.{ - .usage = .{ .copy_dst = true, .uniform = true }, - .size = @sizeOf(UniformBufferObject) * num_instances, - .mapped_at_creation = .false, - }); - const bind_group = core.device.createBindGroup( - &gpu.BindGroup.Descriptor.init(.{ - .layout = bgl, - .entries = &.{ - gpu.BindGroup.Entry.buffer(0, uniform_buffer, 0, @sizeOf(UniformBufferObject) * num_instances, @sizeOf(UniformBufferObject)), - }, - }), - ); - - app.title_timer = try core.Timer.start(); - app.pipeline = core.device.createRenderPipeline(&pipeline_descriptor); - app.vertex_buffer = vertex_buffer; - app.uniform_buffer = uniform_buffer; - app.bind_group = bind_group; - - shader_module.release(); - pipeline_layout.release(); - bgl.release(); -} - -pub fn deinit(app: *App) void { - defer _ = gpa.deinit(); - defer core.deinit(); - - app.pipeline.release(); - app.vertex_buffer.release(); - app.bind_group.release(); - app.uniform_buffer.release(); -} - -pub fn update(app: *App) !bool { - var iter = core.pollEvents(); - while (iter.next()) |event| { - switch (event) { - .key_press => |ev| { - if (ev.key == .space) return true; - }, - .close => return true, - else => {}, - } - } - - const back_buffer_view = core.swap_chain.getCurrentTextureView().?; - const color_attachment = gpu.RenderPassColorAttachment{ - .view = back_buffer_view, - .clear_value = std.mem.zeroes(gpu.Color), - .load_op = .clear, - .store_op = .store, - }; - - const encoder = core.device.createCommandEncoder(null); - const render_pass_info = gpu.RenderPassDescriptor.init(.{ - .color_attachments = &.{color_attachment}, - }); - - { - const proj = zm.perspectiveFovRh( - (std.math.pi / 3.0), - @as(f32, @floatFromInt(core.descriptor.width)) / @as(f32, @floatFromInt(core.descriptor.height)), - 10, - 30, - ); - - var ubos: [16]UniformBufferObject = undefined; - const time = app.timer.read(); - const step: f32 = 4.0; - var m: u8 = 0; - var x: u8 = 0; - while (x < 4) : (x += 1) { - var y: u8 = 0; - while (y < 4) : (y += 1) { - const trans = zm.translation(step * (@as(f32, @floatFromInt(x)) - 2.0 + 0.5), step * (@as(f32, @floatFromInt(y)) - 2.0 + 0.5), -20); - const localTime = time + @as(f32, @floatFromInt(m)) * 0.5; - const model = zm.mul(zm.mul(zm.mul(zm.rotationX(localTime * (std.math.pi / 2.1)), zm.rotationY(localTime * (std.math.pi / 0.9))), zm.rotationZ(localTime * (std.math.pi / 1.3))), trans); - const mvp = zm.mul(model, proj); - const ubo = UniformBufferObject{ - .mat = mvp, - }; - ubos[m] = ubo; - m += 1; - } - } - encoder.writeBuffer(app.uniform_buffer, 0, &ubos); - } - - const pass = encoder.beginRenderPass(&render_pass_info); - pass.setPipeline(app.pipeline); - pass.setVertexBuffer(0, app.vertex_buffer, 0, @sizeOf(Vertex) * vertices.len); - pass.setBindGroup(0, app.bind_group, &.{0}); - pass.draw(vertices.len, 16, 0, 0); - pass.end(); - pass.release(); - - var command = encoder.finish(null); - encoder.release(); - - const queue = core.queue; - queue.submit(&[_]*gpu.CommandBuffer{command}); - command.release(); - core.swap_chain.present(); - back_buffer_view.release(); - - // update the window title every second - if (app.title_timer.read() >= 1.0) { - app.title_timer.reset(); - try core.printTitle("Instanced Cube [ {d}fps ] [ Input {d}hz ]", .{ - core.frameRate(), - core.inputRate(), - }); - } - - return false; -} diff --git a/src/core/examples/sysgpu/instanced-cube/shader.wgsl b/src/core/examples/sysgpu/instanced-cube/shader.wgsl deleted file mode 100644 index 1e279d8d..00000000 --- a/src/core/examples/sysgpu/instanced-cube/shader.wgsl +++ /dev/null @@ -1,25 +0,0 @@ -@binding(0) @group(0) var ubos : array, 16>; - -struct VertexOutput { - @builtin(position) position_clip : vec4, - @location(0) fragUV : vec2, - @location(1) fragPosition: vec4, -}; - -@vertex -fn vertex_main(@builtin(instance_index) instanceIdx : u32, - @location(0) position : vec4, - @location(1) uv : vec2) -> VertexOutput { - var output : VertexOutput; - output.position_clip = ubos[instanceIdx] * position; - output.fragUV = uv; - output.fragPosition = 0.5 * (position + vec4(1.0, 1.0, 1.0, 1.0)); - return output; -} - -@fragment fn frag_main( - @location(0) fragUV: vec2, - @location(1) fragPosition: vec4 -) -> @location(0) vec4 { - return fragPosition; -} \ No newline at end of file diff --git a/src/core/examples/sysgpu/map-async/main.wgsl b/src/core/examples/sysgpu/map-async/main.wgsl deleted file mode 100644 index a4270992..00000000 --- a/src/core/examples/sysgpu/map-async/main.wgsl +++ /dev/null @@ -1,16 +0,0 @@ -@group(0) @binding(0) var output: array; - -@compute @workgroup_size(64, 1, 1) -fn main( - @builtin(global_invocation_id) - global_id : vec3, - - @builtin(local_invocation_id) - local_id : vec3, -) { - if (global_id.x >= arrayLength(&output)) { - return; - } - output[global_id.x] = - f32(global_id.x) * 1000. + f32(local_id.x); -} diff --git a/src/core/examples/sysgpu/map-async/main.zig b/src/core/examples/sysgpu/map-async/main.zig deleted file mode 100644 index a450d859..00000000 --- a/src/core/examples/sysgpu/map-async/main.zig +++ /dev/null @@ -1,106 +0,0 @@ -const std = @import("std"); - -const mach = @import("mach"); -const core = mach.core; -const gpu = mach.gpu; - -pub const App = @This(); - -// Use experimental sysgpu graphics API -pub const use_sysgpu = true; - -var gpa = std.heap.GeneralPurposeAllocator(.{}){}; - -const workgroup_size = 64; -const buffer_size = 1000; - -pub fn init(app: *App) !void { - try core.init(.{}); - app.* = .{}; - - const output = core.device.createBuffer(&.{ - .usage = .{ .storage = true, .copy_src = true }, - .size = buffer_size * @sizeOf(f32), - .mapped_at_creation = .false, - }); - defer output.release(); - - const staging = core.device.createBuffer(&.{ - .usage = .{ .map_read = true, .copy_dst = true }, - .size = buffer_size * @sizeOf(f32), - .mapped_at_creation = .false, - }); - defer staging.release(); - - const compute_module = core.device.createShaderModuleWGSL("main.wgsl", @embedFile("main.wgsl")); - - const compute_pipeline = core.device.createComputePipeline(&gpu.ComputePipeline.Descriptor{ .compute = gpu.ProgrammableStageDescriptor{ - .module = compute_module, - .entry_point = "main", - } }); - defer compute_pipeline.release(); - - const layout = compute_pipeline.getBindGroupLayout(0); - defer layout.release(); - - const compute_bind_group = core.device.createBindGroup(&gpu.BindGroup.Descriptor.init(.{ - .layout = layout, - .entries = &.{ - gpu.BindGroup.Entry.buffer(0, output, 0, buffer_size * @sizeOf(f32), @sizeOf(f32)), - }, - })); - defer compute_bind_group.release(); - - compute_module.release(); - - const encoder = core.device.createCommandEncoder(null); - - const compute_pass = encoder.beginComputePass(null); - compute_pass.setPipeline(compute_pipeline); - compute_pass.setBindGroup(0, compute_bind_group, &.{}); - compute_pass.dispatchWorkgroups(try std.math.divCeil(u32, buffer_size, workgroup_size), 1, 1); - compute_pass.end(); - compute_pass.release(); - - encoder.copyBufferToBuffer(output, 0, staging, 0, buffer_size * @sizeOf(f32)); - - var command = encoder.finish(null); - encoder.release(); - - var response: gpu.Buffer.MapAsyncStatus = undefined; - const callback = (struct { - pub inline fn callback(ctx: *gpu.Buffer.MapAsyncStatus, status: gpu.Buffer.MapAsyncStatus) void { - ctx.* = status; - } - }).callback; - - var queue = core.queue; - queue.submit(&[_]*gpu.CommandBuffer{command}); - command.release(); - - staging.mapAsync(.{ .read = true }, 0, buffer_size * @sizeOf(f32), &response, callback); - while (true) { - if (response == gpu.Buffer.MapAsyncStatus.success) { - break; - } else { - core.device.tick(); - } - } - - const staging_mapped = staging.getConstMappedRange(f32, 0, buffer_size); - for (staging_mapped.?) |v| { - std.debug.print("{d} ", .{v}); - } - std.debug.print("\n", .{}); - staging.unmap(); -} - -pub fn deinit(app: *App) void { - _ = app; - defer _ = gpa.deinit(); - core.deinit(); -} - -pub fn update(_: *App) !bool { - return true; -} diff --git a/src/core/examples/sysgpu/pixel-post-process/cube_mesh.zig b/src/core/examples/sysgpu/pixel-post-process/cube_mesh.zig deleted file mode 100644 index edf25840..00000000 --- a/src/core/examples/sysgpu/pixel-post-process/cube_mesh.zig +++ /dev/null @@ -1,49 +0,0 @@ -pub const Vertex = extern struct { - pos: @Vector(3, f32), - normal: @Vector(3, f32), - uv: @Vector(2, f32), -}; - -pub const vertices = [_]Vertex{ - .{ .pos = .{ 1, -1, 1 }, .normal = .{ 0, -1, 0 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, -1, 1 }, .normal = .{ 0, -1, 0 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, -1, -1 }, .normal = .{ 0, -1, 0 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, -1, -1 }, .normal = .{ 0, -1, 0 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, -1, 1 }, .normal = .{ 0, -1, 0 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, -1, -1 }, .normal = .{ 0, -1, 0 }, .uv = .{ 0, 0 } }, - - .{ .pos = .{ 1, 1, 1 }, .normal = .{ 1, 0, 0 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ 1, -1, 1 }, .normal = .{ 1, 0, 0 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ 1, -1, -1 }, .normal = .{ 1, 0, 0 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, 1, -1 }, .normal = .{ 1, 0, 0 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, 1, 1 }, .normal = .{ 1, 0, 0 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ 1, -1, -1 }, .normal = .{ 1, 0, 0 }, .uv = .{ 0, 0 } }, - - .{ .pos = .{ -1, 1, 1 }, .normal = .{ 0, 1, 0 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ 1, 1, 1 }, .normal = .{ 0, 1, 0 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ 1, 1, -1 }, .normal = .{ 0, 1, 0 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ -1, 1, -1 }, .normal = .{ 0, 1, 0 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ -1, 1, 1 }, .normal = .{ 0, 1, 0 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ 1, 1, -1 }, .normal = .{ 0, 1, 0 }, .uv = .{ 0, 0 } }, - - .{ .pos = .{ -1, -1, 1 }, .normal = .{ -1, 0, 0 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, 1, 1 }, .normal = .{ -1, 0, 0 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, 1, -1 }, .normal = .{ -1, 0, 0 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ -1, -1, -1 }, .normal = .{ -1, 0, 0 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ -1, -1, 1 }, .normal = .{ -1, 0, 0 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, 1, -1 }, .normal = .{ -1, 0, 0 }, .uv = .{ 0, 0 } }, - - .{ .pos = .{ 1, 1, 1 }, .normal = .{ 0, 0, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, 1, 1 }, .normal = .{ 0, 0, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, -1, 1 }, .normal = .{ 0, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ -1, -1, 1 }, .normal = .{ 0, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, -1, 1 }, .normal = .{ 0, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, 1, 1 }, .normal = .{ 0, 0, 1 }, .uv = .{ 1, 1 } }, - - .{ .pos = .{ 1, -1, -1 }, .normal = .{ 0, 0, -1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, -1, -1 }, .normal = .{ 0, 0, -1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, 1, -1 }, .normal = .{ 0, 0, -1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, 1, -1 }, .normal = .{ 0, 0, -1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, -1, -1 }, .normal = .{ 0, 0, -1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, 1, -1 }, .normal = .{ 0, 0, -1 }, .uv = .{ 0, 0 } }, -}; diff --git a/src/core/examples/sysgpu/pixel-post-process/main.zig b/src/core/examples/sysgpu/pixel-post-process/main.zig deleted file mode 100644 index ccead043..00000000 --- a/src/core/examples/sysgpu/pixel-post-process/main.zig +++ /dev/null @@ -1,467 +0,0 @@ -const std = @import("std"); - -const mach = @import("mach"); -const core = mach.core; -const gpu = mach.gpu; - -const zm = @import("zmath"); - -const Vertex = @import("cube_mesh.zig").Vertex; -const vertices = @import("cube_mesh.zig").vertices; -const Quad = @import("quad_mesh.zig").Quad; -const quad = @import("quad_mesh.zig").quad; - -pub const App = @This(); - -// Use experimental sysgpu graphics API -pub const use_sysgpu = true; - -const pixel_size = 8; - -const UniformBufferObject = struct { - mat: zm.Mat, -}; -const PostUniformBufferObject = extern struct { - width: u32, - height: u32, - pixel_size: u32 = pixel_size, -}; -var gpa = std.heap.GeneralPurposeAllocator(.{}){}; - -title_timer: core.Timer, -timer: core.Timer, - -pipeline: *gpu.RenderPipeline, -normal_pipeline: *gpu.RenderPipeline, -vertex_buffer: *gpu.Buffer, -uniform_buffer: *gpu.Buffer, -bind_group: *gpu.BindGroup, - -post_pipeline: *gpu.RenderPipeline, -post_vertex_buffer: *gpu.Buffer, -post_uniform_buffer: *gpu.Buffer, -post_bind_group: *gpu.BindGroup, - -draw_texture_view: *gpu.TextureView, -depth_texture_view: *gpu.TextureView, -normal_texture_view: *gpu.TextureView, - -pub fn init(app: *App) !void { - try core.init(.{}); - app.title_timer = try core.Timer.start(); - app.timer = try core.Timer.start(); - - try app.createRenderTextures(); - app.createDrawPipeline(); - app.createPostPipeline(); -} - -pub fn deinit(app: *App) void { - defer _ = gpa.deinit(); - defer core.deinit(); - - app.cleanup(); -} - -pub fn update(app: *App) !bool { - var iter = core.pollEvents(); - while (iter.next()) |event| { - switch (event) { - .key_press => |ev| { - if (ev.key == .space) return true; - }, - .close => return true, - .framebuffer_resize => { - app.cleanup(); - try app.createRenderTextures(); - app.createDrawPipeline(); - app.createPostPipeline(); - }, - else => {}, - } - } - - const size = core.size(); - const encoder = core.device.createCommandEncoder(null); - encoder.writeBuffer(app.post_uniform_buffer, 0, &[_]PostUniformBufferObject{ - PostUniformBufferObject{ - .width = size.width, - .height = size.height, - }, - }); - - { - const time = app.timer.read() * 0.5; - const model = zm.mul(zm.rotationX(time * (std.math.pi / 2.0)), zm.rotationZ(time * (std.math.pi / 2.0))); - const view = zm.lookAtRh( - zm.Vec{ 0, 5, 2, 1 }, - zm.Vec{ 0, 0, 0, 1 }, - zm.Vec{ 0, 0, 1, 0 }, - ); - const proj = zm.perspectiveFovRh( - (std.math.pi / 4.0), - @as(f32, @floatFromInt(core.descriptor.width)) / @as(f32, @floatFromInt(core.descriptor.height)), - 0.1, - 10, - ); - const mvp = zm.mul(zm.mul(model, view), proj); - const ubo = UniformBufferObject{ - .mat = zm.transpose(mvp), - }; - encoder.writeBuffer(app.uniform_buffer, 0, &[_]UniformBufferObject{ubo}); - } - - { - // render scene to downscaled texture - const color_attachment = gpu.RenderPassColorAttachment{ - .view = app.draw_texture_view, - .clear_value = std.mem.zeroes(gpu.Color), - .load_op = .clear, - .store_op = .store, - }; - const render_pass_info = gpu.RenderPassDescriptor.init(.{ - .color_attachments = &.{color_attachment}, - .depth_stencil_attachment = &gpu.RenderPassDepthStencilAttachment{ - .view = app.depth_texture_view, - .depth_load_op = .clear, - .depth_store_op = .store, - .depth_clear_value = 1.0, - }, - }); - - const pass = encoder.beginRenderPass(&render_pass_info); - pass.setPipeline(app.pipeline); - pass.setVertexBuffer(0, app.vertex_buffer, 0, @sizeOf(Vertex) * vertices.len); - pass.setBindGroup(0, app.bind_group, &.{0}); - pass.draw(vertices.len, 1, 0, 0); - pass.end(); - pass.release(); - } - - { - // render scene normals to texture - const normal_color_attachment = gpu.RenderPassColorAttachment{ - .view = app.normal_texture_view, - .clear_value = .{ .r = 0.5, .b = 0.5, .g = 0.5, .a = 1.0 }, - .load_op = .clear, - .store_op = .store, - }; - const normal_render_pass_info = gpu.RenderPassDescriptor.init(.{ - .color_attachments = &.{normal_color_attachment}, - }); - - const normal_pass = encoder.beginRenderPass(&normal_render_pass_info); - normal_pass.setPipeline(app.normal_pipeline); - normal_pass.setVertexBuffer(0, app.vertex_buffer, 0, @sizeOf(Vertex) * vertices.len); - normal_pass.setBindGroup(0, app.bind_group, &.{0}); - normal_pass.draw(vertices.len, 1, 0, 0); - normal_pass.end(); - normal_pass.release(); - } - - const back_buffer_view = core.swap_chain.getCurrentTextureView().?; - { - // render to swap chain using previous passes - const post_color_attachment = gpu.RenderPassColorAttachment{ - .view = back_buffer_view, - .clear_value = std.mem.zeroes(gpu.Color), - .load_op = .clear, - .store_op = .store, - }; - const post_render_pass_info = gpu.RenderPassDescriptor.init(.{ - .color_attachments = &.{post_color_attachment}, - }); - - const draw_pass = encoder.beginRenderPass(&post_render_pass_info); - draw_pass.setPipeline(app.post_pipeline); - draw_pass.setVertexBuffer(0, app.post_vertex_buffer, 0, @sizeOf(Quad) * quad.len); - draw_pass.setBindGroup(0, app.post_bind_group, &.{0}); - draw_pass.draw(quad.len, 1, 0, 0); - draw_pass.end(); - draw_pass.release(); - } - - var command = encoder.finish(null); - encoder.release(); - - const queue = core.queue; - queue.submit(&[_]*gpu.CommandBuffer{command}); - command.release(); - core.swap_chain.present(); - back_buffer_view.release(); - - // update the window title every second - if (app.title_timer.read() >= 1.0) { - app.title_timer.reset(); - try core.printTitle("Pixel Post Process [ {d}fps ] [ Input {d}hz ]", .{ - core.frameRate(), - core.inputRate(), - }); - } - - return false; -} - -fn cleanup(app: *App) void { - app.pipeline.release(); - app.normal_pipeline.release(); - app.vertex_buffer.release(); - app.uniform_buffer.release(); - app.bind_group.release(); - - app.post_pipeline.release(); - app.post_vertex_buffer.release(); - app.post_uniform_buffer.release(); - app.post_bind_group.release(); - - app.draw_texture_view.release(); - app.depth_texture_view.release(); - app.normal_texture_view.release(); -} - -fn createRenderTextures(app: *App) !void { - const size = core.size(); - - const draw_texture_desc = gpu.Texture.Descriptor.init(.{ - .size = .{ .width = size.width / pixel_size, .height = size.height / pixel_size }, - .format = .bgra8_unorm, - .usage = .{ .texture_binding = true, .copy_dst = true, .render_attachment = true }, - }); - const draw_texture = core.device.createTexture(&draw_texture_desc); - app.draw_texture_view = draw_texture.createView(null); - draw_texture.release(); - - const depth_texture_desc = gpu.Texture.Descriptor.init(.{ - .size = .{ .width = size.width / pixel_size, .height = size.height / pixel_size }, - .format = .depth32_float, - .usage = .{ .texture_binding = true, .copy_dst = true, .render_attachment = true }, - }); - const depth_texture = core.device.createTexture(&depth_texture_desc); - app.depth_texture_view = depth_texture.createView(null); - depth_texture.release(); - - const normal_texture_desc = gpu.Texture.Descriptor.init(.{ - .size = .{ .width = size.width / pixel_size, .height = size.height / pixel_size }, - .format = .bgra8_unorm, - .usage = .{ .texture_binding = true, .copy_dst = true, .render_attachment = true }, - }); - const normal_texture = core.device.createTexture(&normal_texture_desc); - app.normal_texture_view = normal_texture.createView(null); - normal_texture.release(); -} - -fn createDrawPipeline(app: *App) void { - const shader_module = core.device.createShaderModuleWGSL("shader.wgsl", @embedFile("shader.wgsl")); - const vertex_attributes = [_]gpu.VertexAttribute{ - .{ .format = .float32x3, .offset = @offsetOf(Vertex, "pos"), .shader_location = 0 }, - .{ .format = .float32x3, .offset = @offsetOf(Vertex, "normal"), .shader_location = 1 }, - .{ .format = .float32x2, .offset = @offsetOf(Vertex, "uv"), .shader_location = 2 }, - }; - const vertex_buffer_layout = gpu.VertexBufferLayout.init(.{ - .array_stride = @sizeOf(Vertex), - .step_mode = .vertex, - .attributes = &vertex_attributes, - }); - const vertex = gpu.VertexState.init(.{ - .module = shader_module, - .entry_point = "vertex_main", - .buffers = &.{vertex_buffer_layout}, - }); - - const blend = gpu.BlendState{}; - const color_target = gpu.ColorTargetState{ - .format = core.descriptor.format, - .blend = &blend, - .write_mask = gpu.ColorWriteMaskFlags.all, - }; - const fragment = gpu.FragmentState.init(.{ - .module = shader_module, - .entry_point = "frag_main", - .targets = &.{color_target}, - }); - - const bgle = gpu.BindGroupLayout.Entry.buffer(0, .{ .vertex = true }, .uniform, true, 0); - const bgl = core.device.createBindGroupLayout( - &gpu.BindGroupLayout.Descriptor.init(.{ - .entries = &.{bgle}, - }), - ); - - const bind_group_layouts = [_]*gpu.BindGroupLayout{bgl}; - const pipeline_layout = core.device.createPipelineLayout( - &gpu.PipelineLayout.Descriptor.init(.{ - .bind_group_layouts = &bind_group_layouts, - }), - ); - - const vertex_buffer = core.device.createBuffer(&.{ - .usage = .{ .vertex = true }, - .size = @sizeOf(Vertex) * vertices.len, - .mapped_at_creation = .true, - }); - const vertex_mapped = vertex_buffer.getMappedRange(Vertex, 0, vertices.len); - @memcpy(vertex_mapped.?, vertices[0..]); - vertex_buffer.unmap(); - - const uniform_buffer = core.device.createBuffer(&.{ - .usage = .{ .copy_dst = true, .uniform = true }, - .size = @sizeOf(UniformBufferObject), - .mapped_at_creation = .false, - }); - const bind_group = core.device.createBindGroup( - &gpu.BindGroup.Descriptor.init(.{ - .layout = bgl, - .entries = &.{ - gpu.BindGroup.Entry.buffer(0, uniform_buffer, 0, @sizeOf(UniformBufferObject), @sizeOf(UniformBufferObject)), - }, - }), - ); - - const pipeline_descriptor = gpu.RenderPipeline.Descriptor{ - .fragment = &fragment, - .layout = pipeline_layout, - .vertex = vertex, - .primitive = .{ - .cull_mode = .back, - }, - .depth_stencil = &gpu.DepthStencilState{ - .format = .depth32_float, - .depth_write_enabled = .true, - .depth_compare = .less, - }, - }; - - { - // "same" pipeline, different fragment shader to create a texture with normal information - const normal_fs_module = core.device.createShaderModuleWGSL("normal_frag.wgsl", @embedFile("normal_frag.wgsl")); - const normal_fragment = gpu.FragmentState.init(.{ - .module = normal_fs_module, - .entry_point = "main", - .targets = &.{color_target}, - }); - const normal_pipeline_descriptor = gpu.RenderPipeline.Descriptor{ - .fragment = &normal_fragment, - .layout = pipeline_layout, - .vertex = vertex, - .primitive = .{ - .cull_mode = .back, - }, - }; - app.normal_pipeline = core.device.createRenderPipeline(&normal_pipeline_descriptor); - - normal_fs_module.release(); - } - - app.pipeline = core.device.createRenderPipeline(&pipeline_descriptor); - app.vertex_buffer = vertex_buffer; - app.uniform_buffer = uniform_buffer; - app.bind_group = bind_group; - - shader_module.release(); - pipeline_layout.release(); - bgl.release(); -} - -fn createPostPipeline(app: *App) void { - const vs_module = core.device.createShaderModuleWGSL("pixel_vert.wgsl", @embedFile("pixel_vert.wgsl")); - const vertex_attributes = [_]gpu.VertexAttribute{ - .{ .format = .float32x3, .offset = @offsetOf(Quad, "pos"), .shader_location = 0 }, - .{ .format = .float32x2, .offset = @offsetOf(Quad, "uv"), .shader_location = 1 }, - }; - const vertex_buffer_layout = gpu.VertexBufferLayout.init(.{ - .array_stride = @sizeOf(Quad), - .step_mode = .vertex, - .attributes = &vertex_attributes, - }); - const vertex = gpu.VertexState.init(.{ - .module = vs_module, - .entry_point = "main", - .buffers = &.{vertex_buffer_layout}, - }); - - const fs_module = core.device.createShaderModuleWGSL("pixel_frag.wgsl", @embedFile("pixel_frag.wgsl")); - const blend = gpu.BlendState{}; - const color_target = gpu.ColorTargetState{ - .format = core.descriptor.format, - .blend = &blend, - .write_mask = gpu.ColorWriteMaskFlags.all, - }; - const fragment = gpu.FragmentState.init(.{ - .module = fs_module, - .entry_point = "main", - .targets = &.{color_target}, - }); - - const bgl = core.device.createBindGroupLayout( - &gpu.BindGroupLayout.Descriptor.init(.{ - .entries = &.{ - gpu.BindGroupLayout.Entry.texture(0, .{ .fragment = true }, .float, .dimension_2d, false), - gpu.BindGroupLayout.Entry.sampler(1, .{ .fragment = true }, .filtering), - gpu.BindGroupLayout.Entry.texture(2, .{ .fragment = true }, .depth, .dimension_2d, false), - gpu.BindGroupLayout.Entry.sampler(3, .{ .fragment = true }, .filtering), - gpu.BindGroupLayout.Entry.texture(4, .{ .fragment = true }, .float, .dimension_2d, false), - gpu.BindGroupLayout.Entry.sampler(5, .{ .fragment = true }, .filtering), - gpu.BindGroupLayout.Entry.buffer(6, .{ .fragment = true }, .uniform, true, 0), - }, - }), - ); - - const bind_group_layouts = [_]*gpu.BindGroupLayout{bgl}; - const pipeline_layout = core.device.createPipelineLayout(&gpu.PipelineLayout.Descriptor.init(.{ - .bind_group_layouts = &bind_group_layouts, - })); - - const vertex_buffer = core.device.createBuffer(&.{ - .usage = .{ .vertex = true }, - .size = @sizeOf(Quad) * quad.len, - .mapped_at_creation = .true, - }); - const vertex_mapped = vertex_buffer.getMappedRange(Quad, 0, quad.len); - @memcpy(vertex_mapped.?, quad[0..]); - vertex_buffer.unmap(); - - const draw_sampler = core.device.createSampler(null); - const depth_sampler = core.device.createSampler(null); - const normal_sampler = core.device.createSampler(null); - const uniform_buffer = core.device.createBuffer(&.{ - .usage = .{ .copy_dst = true, .uniform = true }, - .size = @sizeOf(PostUniformBufferObject), - .mapped_at_creation = .false, - }); - const bind_group = core.device.createBindGroup( - &gpu.BindGroup.Descriptor.init(.{ - .layout = bgl, - .entries = &[_]gpu.BindGroup.Entry{ - gpu.BindGroup.Entry.textureView(0, app.draw_texture_view), - gpu.BindGroup.Entry.sampler(1, draw_sampler), - gpu.BindGroup.Entry.textureView(2, app.depth_texture_view), - gpu.BindGroup.Entry.sampler(3, depth_sampler), - gpu.BindGroup.Entry.textureView(4, app.normal_texture_view), - gpu.BindGroup.Entry.sampler(5, normal_sampler), - gpu.BindGroup.Entry.buffer(6, uniform_buffer, 0, @sizeOf(PostUniformBufferObject), @sizeOf(PostUniformBufferObject)), - }, - }), - ); - draw_sampler.release(); - depth_sampler.release(); - normal_sampler.release(); - - const pipeline_descriptor = gpu.RenderPipeline.Descriptor{ - .fragment = &fragment, - .layout = pipeline_layout, - .vertex = vertex, - .primitive = .{ - .cull_mode = .back, - }, - }; - - app.post_pipeline = core.device.createRenderPipeline(&pipeline_descriptor); - app.post_vertex_buffer = vertex_buffer; - app.post_uniform_buffer = uniform_buffer; - app.post_bind_group = bind_group; - - vs_module.release(); - fs_module.release(); - pipeline_layout.release(); - bgl.release(); -} diff --git a/src/core/examples/sysgpu/pixel-post-process/normal_frag.wgsl b/src/core/examples/sysgpu/pixel-post-process/normal_frag.wgsl deleted file mode 100644 index 28f7407c..00000000 --- a/src/core/examples/sysgpu/pixel-post-process/normal_frag.wgsl +++ /dev/null @@ -1,6 +0,0 @@ -@fragment fn main( - @location(0) normal: vec3, - @location(1) uv: vec2, -) -> @location(0) vec4 { - return vec4(normal / 2 + 0.5, 1.0); -} diff --git a/src/core/examples/sysgpu/pixel-post-process/pixel_frag.wgsl b/src/core/examples/sysgpu/pixel-post-process/pixel_frag.wgsl deleted file mode 100644 index 9f125273..00000000 --- a/src/core/examples/sysgpu/pixel-post-process/pixel_frag.wgsl +++ /dev/null @@ -1,77 +0,0 @@ -@group(0) @binding(0) -var draw_texture: texture_2d; -@group(0) @binding(1) -var draw_texture_sampler: sampler; - -@group(0) @binding(2) -var depth_texture: texture_depth_2d; -@group(0) @binding(3) -var depth_texture_sampler: sampler; - -@group(0) @binding(4) -var normal_texture: texture_2d; -@group(0) @binding(5) -var normal_texture_sampler: sampler; - -struct View { - @location(0) width: u32, - @location(1) height: u32, - @location(2) pixel_size: u32, -} -@group(0) @binding(6) -var view: View; - -fn sample_depth(uv: vec2, x: f32, y: f32) -> f32 { - return textureSample( - depth_texture, - depth_texture_sampler, - uv + vec2(x * f32(view.pixel_size) / f32(view.width), y * f32(view.pixel_size) / f32(view.height)) - ); -} - -fn sample_normal(uv: vec2, x: f32, y: f32) -> vec3 { - return textureSample( - normal_texture, - normal_texture_sampler, - uv + vec2(x * f32(view.pixel_size) / f32(view.width), y * f32(view.pixel_size) / f32(view.height)) - ).xyz; -} - -fn normal_indicator(uv: vec2, x: f32, y: f32) -> f32 { - // TODO - integer promotion to float argument - var depth_diff = sample_depth(uv, 0.0, 0.0) - sample_depth(uv, x, y); - var dx = sample_normal(uv, 0.0, 0.0); - var dy = sample_normal(uv, x, y); - if (depth_diff > 0) { - // only sample normals from closest pixel - return 0; - } - return distance(dx, dy); -} - -@fragment fn main( - // TODO - vertex/fragment linkage - @location(0) uv: vec2, - @builtin(position) position: vec4 -) -> @location(0) vec4 { - // TODO - integer promotion to float argument - var depth = sample_depth(uv, 0.0, 0.0); - var depth_diff: f32 = 0; - depth_diff += abs(depth - sample_depth(uv, -1.0, 0.0)); - depth_diff += abs(depth - sample_depth(uv, 1.0, 0.0)); - depth_diff += abs(depth - sample_depth(uv, 0.0, -1.0)); - depth_diff += abs(depth - sample_depth(uv, 0.0, 1.0)); - - var normal_diff: f32 = 0; - normal_diff += normal_indicator(uv, -1.0, 0.0); - normal_diff += normal_indicator(uv, 1.0, 0.0); - normal_diff += normal_indicator(uv, 0.0, -1.0); - normal_diff += normal_indicator(uv, 0.0, 1.0); - - var color = textureSample(draw_texture, draw_texture_sampler, uv); - if (depth_diff > 0.007) { // magic number from testing - return color * 0.7; - } - // add instead of multiply so really dark pixels get brighter - return color + (vec4(1) * step(0.1, normal_diff) * 0.7); -} diff --git a/src/core/examples/sysgpu/pixel-post-process/pixel_vert.wgsl b/src/core/examples/sysgpu/pixel-post-process/pixel_vert.wgsl deleted file mode 100644 index 734f629e..00000000 --- a/src/core/examples/sysgpu/pixel-post-process/pixel_vert.wgsl +++ /dev/null @@ -1,14 +0,0 @@ -struct VertexOut { - @builtin(position) position_clip: vec4, - @location(0) uv: vec2 -} - -@vertex fn main( - @location(0) position: vec3, - @location(1) uv: vec2 -) -> VertexOut { - var output : VertexOut; - output.position_clip = vec4(position.xy, 0.0, 1.0); - output.uv = uv; - return output; -} diff --git a/src/core/examples/sysgpu/pixel-post-process/quad_mesh.zig b/src/core/examples/sysgpu/pixel-post-process/quad_mesh.zig deleted file mode 100644 index 57db212f..00000000 --- a/src/core/examples/sysgpu/pixel-post-process/quad_mesh.zig +++ /dev/null @@ -1,13 +0,0 @@ -pub const Quad = extern struct { - pos: @Vector(3, f32), - uv: @Vector(2, f32), -}; - -pub const quad = [_]Quad{ - .{ .pos = .{ -1.0, 1.0, 0.0 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1.0, -1.0, 0.0 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1.0, 1.0, 0.0 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ 1.0, 1.0, 0.0 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1.0, -1.0, 0.0 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1.0, -1.0, 0.0 }, .uv = .{ 1, 0 } }, -}; diff --git a/src/core/examples/sysgpu/pixel-post-process/shader.wgsl b/src/core/examples/sysgpu/pixel-post-process/shader.wgsl deleted file mode 100644 index 325391cd..00000000 --- a/src/core/examples/sysgpu/pixel-post-process/shader.wgsl +++ /dev/null @@ -1,27 +0,0 @@ -@group(0) @binding(0) var ubo: mat4x4; - -struct VertexOut { - @builtin(position) position_clip: vec4, - @location(0) normal: vec3, - @location(1) uv: vec2, -} - -@vertex fn vertex_main( - @location(0) position: vec3, - @location(1) normal: vec3, - @location(2) uv: vec2 -) -> VertexOut { - var output: VertexOut; - output.position_clip = vec4(position, 1) * ubo; - output.normal = (vec4(normal, 0) * ubo).xyz; - output.uv = uv; - return output; -} - -@fragment fn frag_main( - @location(0) normal: vec3, - @location(1) uv: vec2, -) -> @location(0) vec4 { - var color = floor((uv * 0.5 + 0.25) * 32) / 32; - return vec4(color, 1, 1); -} \ No newline at end of file diff --git a/src/core/examples/sysgpu/procedural-primitives/main.zig b/src/core/examples/sysgpu/procedural-primitives/main.zig deleted file mode 100644 index 8f20785d..00000000 --- a/src/core/examples/sysgpu/procedural-primitives/main.zig +++ /dev/null @@ -1,68 +0,0 @@ -const std = @import("std"); - -const mach = @import("mach"); -const core = mach.core; -const gpu = mach.gpu; - -const renderer = @import("renderer.zig"); - -pub const App = @This(); - -// Use experimental sysgpu graphics API -pub const use_sysgpu = true; - -var gpa = std.heap.GeneralPurposeAllocator(.{}){}; - -title_timer: core.Timer, - -pub fn init(app: *App) !void { - try core.init(.{ .required_limits = gpu.Limits{ - .max_vertex_buffers = 1, - .max_vertex_attributes = 2, - .max_bind_groups = 1, - .max_uniform_buffers_per_shader_stage = 1, - .max_uniform_buffer_binding_size = 16 * 1 * @sizeOf(f32), - } }); - - const allocator = gpa.allocator(); - const timer = try core.Timer.start(); - try renderer.init(allocator, timer); - app.* = .{ .title_timer = try core.Timer.start() }; -} - -pub fn deinit(app: *App) void { - _ = app; - defer _ = gpa.deinit(); - defer core.deinit(); - defer renderer.deinit(); -} - -pub fn update(app: *App) !bool { - var iter = core.pollEvents(); - while (iter.next()) |event| { - switch (event) { - .key_press => |ev| { - if (ev.key == .space) return true; - if (ev.key == .right) { - renderer.curr_primitive_index += 1; - renderer.curr_primitive_index %= 7; - } - }, - .close => return true, - else => {}, - } - } - - renderer.update(); - - // update the window title every second - if (app.title_timer.read() >= 1.0) { - app.title_timer.reset(); - try core.printTitle("Procedural Primitives [ {d}fps ] [ Input {d}hz ]", .{ - core.frameRate(), - core.inputRate(), - }); - } - - return false; -} diff --git a/src/core/examples/sysgpu/procedural-primitives/procedural-primitives.zig b/src/core/examples/sysgpu/procedural-primitives/procedural-primitives.zig deleted file mode 100644 index ae1c74ab..00000000 --- a/src/core/examples/sysgpu/procedural-primitives/procedural-primitives.zig +++ /dev/null @@ -1,336 +0,0 @@ -const std = @import("std"); -const zmath = @import("zmath"); - -const PI = 3.1415927410125732421875; - -pub const F32x3 = @Vector(3, f32); -pub const F32x4 = @Vector(4, f32); -pub const VertexData = struct { - position: F32x3, - normal: F32x3, -}; - -pub const PrimitiveType = enum(u4) { none, triangle, quad, plane, circle, uv_sphere, ico_sphere, cylinder, cone, torus }; - -pub const Primitive = struct { - vertex_data: std.ArrayList(VertexData), - vertex_count: u32, - index_data: std.ArrayList(u32), - index_count: u32, - type: PrimitiveType = .none, -}; - -// 2D Primitives -pub fn createTrianglePrimitive(allocator: std.mem.Allocator, size: f32) !Primitive { - const vertex_count = 3; - const index_count = 3; - var vertex_data = try std.ArrayList(VertexData).initCapacity(allocator, vertex_count); - - const edge = size / 2.0; - - vertex_data.appendSliceAssumeCapacity(&[vertex_count]VertexData{ - VertexData{ .position = F32x3{ -edge, -edge, 0.0 }, .normal = F32x3{ -edge, -edge, 0.0 } }, - VertexData{ .position = F32x3{ edge, -edge, 0.0 }, .normal = F32x3{ edge, -edge, 0.0 } }, - VertexData{ .position = F32x3{ 0.0, edge, 0.0 }, .normal = F32x3{ 0.0, edge, 0.0 } }, - }); - - var index_data = try std.ArrayList(u32).initCapacity(allocator, index_count); - index_data.appendSliceAssumeCapacity(&[index_count]u32{ 0, 1, 2 }); - - return Primitive{ .vertex_data = vertex_data, .vertex_count = 3, .index_data = index_data, .index_count = 3, .type = .triangle }; -} - -pub fn createQuadPrimitive(allocator: std.mem.Allocator, size: f32) !Primitive { - const vertex_count = 4; - const index_count = 6; - var vertex_data = try std.ArrayList(VertexData).initCapacity(allocator, vertex_count); - - const edge = size / 2.0; - - vertex_data.appendSliceAssumeCapacity(&[vertex_count]VertexData{ - VertexData{ .position = F32x3{ -edge, -edge, 0.0 }, .normal = F32x3{ -edge, -edge, 0.0 } }, - VertexData{ .position = F32x3{ edge, -edge, 0.0 }, .normal = F32x3{ edge, -edge, 0.0 } }, - VertexData{ .position = F32x3{ -edge, edge, 0.0 }, .normal = F32x3{ -edge, edge, 0.0 } }, - VertexData{ .position = F32x3{ edge, edge, 0.0 }, .normal = F32x3{ edge, edge, 0.0 } }, - }); - - var index_data = try std.ArrayList(u32).initCapacity(allocator, index_count); - index_data.appendSliceAssumeCapacity(&[index_count]u32{ - 0, 1, 2, - 1, 3, 2, - }); - - return Primitive{ .vertex_data = vertex_data, .vertex_count = 4, .index_data = index_data, .index_count = 6, .type = .quad }; -} - -pub fn createPlanePrimitive(allocator: std.mem.Allocator, x_subdivision: u32, y_subdivision: u32, size: f32) !Primitive { - const x_num_vertices = x_subdivision + 1; - const y_num_vertices = y_subdivision + 1; - const vertex_count = x_num_vertices * y_num_vertices; - var vertex_data = try std.ArrayList(VertexData).initCapacity(allocator, vertex_count); - - const vertices_distance_y = (size / @as(f32, @floatFromInt(y_subdivision))); - const vertices_distance_x = (size / @as(f32, @floatFromInt(x_subdivision))); - var y: u32 = 0; - while (y < y_num_vertices) : (y += 1) { - var x: u32 = 0; - const pos_y = (-size / 2.0) + @as(f32, @floatFromInt(y)) * vertices_distance_y; - while (x < x_num_vertices) : (x += 1) { - const pos_x = (-size / 2.0) + @as(f32, @floatFromInt(x)) * vertices_distance_x; - vertex_data.appendAssumeCapacity(VertexData{ .position = F32x3{ pos_x, pos_y, 0.0 }, .normal = F32x3{ pos_x, pos_y, 0.0 } }); - } - } - - const index_count = x_subdivision * y_subdivision * 2 * 3; - var index_data = try std.ArrayList(u32).initCapacity(allocator, index_count); - - y = 0; - while (y < y_subdivision) : (y += 1) { - var x: u32 = 0; - while (x < x_subdivision) : (x += 1) { - // First Triangle of Quad - index_data.appendAssumeCapacity(x + y * y_num_vertices); - index_data.appendAssumeCapacity(x + 1 + y * y_num_vertices); - index_data.appendAssumeCapacity(x + (y + 1) * y_num_vertices); - - // Second Triangle of Quad - index_data.appendAssumeCapacity(x + 1 + y * y_num_vertices); - index_data.appendAssumeCapacity(x + (y + 1) * y_num_vertices + 1); - index_data.appendAssumeCapacity(x + (y + 1) * y_num_vertices); - } - } - - return Primitive{ .vertex_data = vertex_data, .vertex_count = vertex_count, .index_data = index_data, .index_count = index_count, .type = .plane }; -} - -pub fn createCirclePrimitive(allocator: std.mem.Allocator, vertices: u32, radius: f32) !Primitive { - const vertex_count = vertices + 1; - var vertex_data = try std.ArrayList(VertexData).initCapacity(allocator, vertex_count); - - // Mid point of circle - vertex_data.appendAssumeCapacity(VertexData{ .position = F32x3{ 0, 0, 0.0 }, .normal = F32x3{ 0, 0, 0.0 } }); - - var x: u32 = 0; - const angle = 2 * PI / @as(f32, @floatFromInt(vertices)); - while (x < vertices) : (x += 1) { - const x_f = @as(f32, @floatFromInt(x)); - const pos_x = radius * zmath.cos(angle * x_f); - const pos_y = radius * zmath.sin(angle * x_f); - - vertex_data.appendAssumeCapacity(VertexData{ .position = F32x3{ pos_x, pos_y, 0.0 }, .normal = F32x3{ pos_x, pos_y, 0.0 } }); - } - - const index_count = (vertices + 1) * 3; - var index_data = try std.ArrayList(u32).initCapacity(allocator, index_count); - - x = 1; - while (x <= vertices) : (x += 1) { - index_data.appendAssumeCapacity(0); - index_data.appendAssumeCapacity(x); - index_data.appendAssumeCapacity(x + 1); - } - - index_data.appendAssumeCapacity(0); - index_data.appendAssumeCapacity(vertices); - index_data.appendAssumeCapacity(1); - - return Primitive{ .vertex_data = vertex_data, .vertex_count = vertex_count, .index_data = index_data, .index_count = index_count, .type = .plane }; -} - -// 3D Primitives -pub fn createCubePrimitive(allocator: std.mem.Allocator, size: f32) !Primitive { - const vertex_count = 8; - const index_count = 36; - var vertex_data = try std.ArrayList(VertexData).initCapacity(allocator, vertex_count); - - const edge = size / 2.0; - - vertex_data.appendSliceAssumeCapacity(&[vertex_count]VertexData{ - // Front positions - VertexData{ .position = F32x3{ -edge, -edge, edge }, .normal = F32x3{ -edge, -edge, edge } }, - VertexData{ .position = F32x3{ edge, -edge, edge }, .normal = F32x3{ edge, -edge, edge } }, - VertexData{ .position = F32x3{ edge, edge, edge }, .normal = F32x3{ edge, edge, edge } }, - VertexData{ .position = F32x3{ -edge, edge, edge }, .normal = F32x3{ -edge, edge, edge } }, - // Back positions - VertexData{ .position = F32x3{ -edge, -edge, -edge }, .normal = F32x3{ -edge, -edge, -edge } }, - VertexData{ .position = F32x3{ edge, -edge, -edge }, .normal = F32x3{ edge, -edge, -edge } }, - VertexData{ .position = F32x3{ edge, edge, -edge }, .normal = F32x3{ edge, edge, -edge } }, - VertexData{ .position = F32x3{ -edge, edge, -edge }, .normal = F32x3{ -edge, edge, -edge } }, - }); - - var index_data = try std.ArrayList(u32).initCapacity(allocator, index_count); - - index_data.appendSliceAssumeCapacity(&[index_count]u32{ - // front quad - 0, 1, 2, - 2, 3, 0, - // right quad - 1, 5, 6, - 6, 2, 1, - // back quad - 7, 6, 5, - 5, 4, 7, - // left quad - 4, 0, 3, - 3, 7, 4, - // bottom quad - 4, 5, 1, - 1, 0, 4, - // top quad - 3, 2, 6, - 6, 7, 3, - }); - - return Primitive{ .vertex_data = vertex_data, .vertex_count = vertex_count, .index_data = index_data, .index_count = index_count, .type = .quad }; -} - -const VertexDataMAL = std.MultiArrayList(VertexData); - -pub fn createCylinderPrimitive(allocator: std.mem.Allocator, radius: f32, height: f32, num_sides: u32) !Primitive { - const alloc_amt_vert: u32 = num_sides * 2 + 2; - const alloc_amt_idx: u32 = num_sides * 12; - - var vertex_data = VertexDataMAL{}; - try vertex_data.ensureTotalCapacity(allocator, alloc_amt_vert); - defer vertex_data.deinit(allocator); - - var out_vertex_data = try std.ArrayList(VertexData).initCapacity(allocator, alloc_amt_vert); - var index_data = try std.ArrayList(u32).initCapacity(allocator, alloc_amt_idx); - - vertex_data.appendAssumeCapacity(VertexData{ .position = F32x3{ 0.0, (height / 2.0), 0.0 }, .normal = undefined }); - vertex_data.appendAssumeCapacity(VertexData{ .position = F32x3{ 0.0, -(height / 2.0), 0.0 }, .normal = undefined }); - - const angle = 2.0 * PI / @as(f32, @floatFromInt(num_sides)); - - for (1..num_sides + 1) |i| { - const float_i = @as(f32, @floatFromInt(i)); - - const x: f32 = radius * zmath.sin(angle * float_i); - const y: f32 = radius * zmath.cos(angle * float_i); - - vertex_data.appendAssumeCapacity(VertexData{ .position = F32x3{ x, (height / 2.0), y }, .normal = undefined }); - vertex_data.appendAssumeCapacity(VertexData{ .position = F32x3{ x, -(height / 2.0), y }, .normal = undefined }); - } - - var group1: u32 = 1; - var group2: u32 = 3; - - for (0..num_sides) |_| { - if (group2 >= num_sides * 2) group2 = 1; - index_data.appendSliceAssumeCapacity(&[_]u32{ - 0, group1 + 1, group2 + 1, - group1 + 1, group1 + 2, group2 + 1, - group1 + 2, group2 + 2, group2 + 1, - group2 + 2, group1 + 2, 1, - }); - group1 += 2; - group2 += 2; - } - - { - var i: u32 = 0; - while (i < alloc_amt_idx) : (i += 3) { - const indexA: u32 = index_data.items[i]; - const indexB: u32 = index_data.items[i + 1]; - const indexC: u32 = index_data.items[i + 2]; - - const vert1: F32x4 = F32x4{ vertex_data.get(indexA).position[0], vertex_data.get(indexA).position[1], vertex_data.get(indexA).position[2], 1.0 }; - const vert2: F32x4 = F32x4{ vertex_data.get(indexB).position[0], vertex_data.get(indexB).position[1], vertex_data.get(indexB).position[2], 1.0 }; - const vert3: F32x4 = F32x4{ vertex_data.get(indexC).position[0], vertex_data.get(indexC).position[1], vertex_data.get(indexC).position[2], 1.0 }; - - const edgeAB: F32x4 = vert2 - vert1; - const edgeAC: F32x4 = vert3 - vert1; - - const cross = zmath.cross3(edgeAB, edgeAC); - - vertex_data.items(.normal)[indexA][0] += cross[0]; - vertex_data.items(.normal)[indexA][1] += cross[1]; - vertex_data.items(.normal)[indexA][2] += cross[2]; - vertex_data.items(.normal)[indexB][0] += cross[0]; - vertex_data.items(.normal)[indexB][1] += cross[1]; - vertex_data.items(.normal)[indexB][2] += cross[2]; - vertex_data.items(.normal)[indexC][0] += cross[0]; - vertex_data.items(.normal)[indexC][1] += cross[1]; - vertex_data.items(.normal)[indexC][2] += cross[2]; - } - } - - for (vertex_data.items(.position), vertex_data.items(.normal)) |pos, nor| { - out_vertex_data.appendAssumeCapacity(VertexData{ .position = pos, .normal = nor }); - } - - return Primitive{ .vertex_data = out_vertex_data, .vertex_count = alloc_amt_vert, .index_data = index_data, .index_count = alloc_amt_idx, .type = .cylinder }; -} - -pub fn createConePrimitive(allocator: std.mem.Allocator, radius: f32, height: f32, num_sides: u32) !Primitive { - const alloc_amt_vert: u32 = num_sides + 2; - const alloc_amt_idx: u32 = num_sides * 6; - - var vertex_data = VertexDataMAL{}; - try vertex_data.ensureTotalCapacity(allocator, alloc_amt_vert); - defer vertex_data.deinit(allocator); - - var out_vertex_data = try std.ArrayList(VertexData).initCapacity(allocator, alloc_amt_vert); - var index_data = try std.ArrayList(u32).initCapacity(allocator, alloc_amt_idx); - - vertex_data.appendAssumeCapacity(VertexData{ .position = F32x3{ 0.0, (height / 2.0), 0.0 }, .normal = undefined }); - vertex_data.appendAssumeCapacity(VertexData{ .position = F32x3{ 0.0, -(height / 2.0), 0.0 }, .normal = undefined }); - - const angle = 2.0 * PI / @as(f32, @floatFromInt(num_sides)); - - for (1..num_sides + 1) |i| { - const float_i = @as(f32, @floatFromInt(i)); - - const x: f32 = radius * zmath.sin(angle * float_i); - const y: f32 = radius * zmath.cos(angle * float_i); - - vertex_data.appendAssumeCapacity(VertexData{ .position = F32x3{ x, -(height / 2.0), y }, .normal = undefined }); - } - - var group1: u32 = 1; - var group2: u32 = 2; - - for (0..num_sides) |_| { - if (group2 >= num_sides + 1) group2 = 1; - index_data.appendSliceAssumeCapacity(&[_]u32{ - 0, group1 + 1, group2 + 1, - group2 + 1, group1 + 1, 1, - }); - group1 += 1; - group2 += 1; - } - - { - var i: u32 = 0; - while (i < alloc_amt_idx) : (i += 3) { - const indexA: u32 = index_data.items[i]; - const indexB: u32 = index_data.items[i + 1]; - const indexC: u32 = index_data.items[i + 2]; - - const vert1: F32x4 = F32x4{ vertex_data.get(indexA).position[0], vertex_data.get(indexA).position[1], vertex_data.get(indexA).position[2], 1.0 }; - const vert2: F32x4 = F32x4{ vertex_data.get(indexB).position[0], vertex_data.get(indexB).position[1], vertex_data.get(indexB).position[2], 1.0 }; - const vert3: F32x4 = F32x4{ vertex_data.get(indexC).position[0], vertex_data.get(indexC).position[1], vertex_data.get(indexC).position[2], 1.0 }; - - const edgeAB: F32x4 = vert2 - vert1; - const edgeAC: F32x4 = vert3 - vert1; - - const cross = zmath.cross3(edgeAB, edgeAC); - - vertex_data.items(.normal)[indexA][0] += cross[0]; - vertex_data.items(.normal)[indexA][1] += cross[1]; - vertex_data.items(.normal)[indexA][2] += cross[2]; - vertex_data.items(.normal)[indexB][0] += cross[0]; - vertex_data.items(.normal)[indexB][1] += cross[1]; - vertex_data.items(.normal)[indexB][2] += cross[2]; - vertex_data.items(.normal)[indexC][0] += cross[0]; - vertex_data.items(.normal)[indexC][1] += cross[1]; - vertex_data.items(.normal)[indexC][2] += cross[2]; - } - } - - for (vertex_data.items(.position), vertex_data.items(.normal)) |pos, nor| { - out_vertex_data.appendAssumeCapacity(VertexData{ .position = pos, .normal = nor }); - } - - return Primitive{ .vertex_data = out_vertex_data, .vertex_count = alloc_amt_vert, .index_data = index_data, .index_count = alloc_amt_idx, .type = .cone }; -} diff --git a/src/core/examples/sysgpu/procedural-primitives/renderer.zig b/src/core/examples/sysgpu/procedural-primitives/renderer.zig deleted file mode 100644 index dc45faea..00000000 --- a/src/core/examples/sysgpu/procedural-primitives/renderer.zig +++ /dev/null @@ -1,328 +0,0 @@ -const std = @import("std"); - -const mach = @import("mach"); -const core = mach.core; -const gpu = mach.gpu; - -const zm = @import("zmath"); -const primitives = @import("procedural-primitives.zig"); -const Primitive = primitives.Primitive; -const VertexData = primitives.VertexData; - -pub const Renderer = @This(); - -var queue: *gpu.Queue = undefined; -var pipeline: *gpu.RenderPipeline = undefined; -var app_timer: core.Timer = undefined; -var depth_texture: *gpu.Texture = undefined; -var depth_texture_view: *gpu.TextureView = undefined; - -const PrimitiveRenderData = struct { - vertex_buffer: *gpu.Buffer, - index_buffer: *gpu.Buffer, - vertex_count: u32, - index_count: u32, -}; - -const UniformBufferObject = struct { - mvp_matrix: zm.Mat, -}; -var uniform_buffer: *gpu.Buffer = undefined; -var bind_group: *gpu.BindGroup = undefined; - -var primitives_data: [7]PrimitiveRenderData = undefined; - -pub var curr_primitive_index: u4 = 0; - -pub fn init(allocator: std.mem.Allocator, timer: core.Timer) !void { - queue = core.queue; - app_timer = timer; - - { - const triangle_primitive = try primitives.createTrianglePrimitive(allocator, 1); - primitives_data[0] = PrimitiveRenderData{ .vertex_buffer = createVertexBuffer(triangle_primitive), .index_buffer = createIndexBuffer(triangle_primitive), .vertex_count = triangle_primitive.vertex_count, .index_count = triangle_primitive.index_count }; - defer triangle_primitive.vertex_data.deinit(); - defer triangle_primitive.index_data.deinit(); - } - - { - const quad_primitive = try primitives.createQuadPrimitive(allocator, 1.4); - primitives_data[1] = PrimitiveRenderData{ .vertex_buffer = createVertexBuffer(quad_primitive), .index_buffer = createIndexBuffer(quad_primitive), .vertex_count = quad_primitive.vertex_count, .index_count = quad_primitive.index_count }; - defer quad_primitive.vertex_data.deinit(); - defer quad_primitive.index_data.deinit(); - } - - { - const plane_primitive = try primitives.createPlanePrimitive(allocator, 1000, 1000, 1.5); - primitives_data[2] = PrimitiveRenderData{ .vertex_buffer = createVertexBuffer(plane_primitive), .index_buffer = createIndexBuffer(plane_primitive), .vertex_count = plane_primitive.vertex_count, .index_count = plane_primitive.index_count }; - defer plane_primitive.vertex_data.deinit(); - defer plane_primitive.index_data.deinit(); - } - - { - const circle_primitive = try primitives.createCirclePrimitive(allocator, 64, 1); - primitives_data[3] = PrimitiveRenderData{ .vertex_buffer = createVertexBuffer(circle_primitive), .index_buffer = createIndexBuffer(circle_primitive), .vertex_count = circle_primitive.vertex_count, .index_count = circle_primitive.index_count }; - defer circle_primitive.vertex_data.deinit(); - defer circle_primitive.index_data.deinit(); - } - - { - const cube_primitive = try primitives.createCubePrimitive(allocator, 0.5); - primitives_data[4] = PrimitiveRenderData{ .vertex_buffer = createVertexBuffer(cube_primitive), .index_buffer = createIndexBuffer(cube_primitive), .vertex_count = cube_primitive.vertex_count, .index_count = cube_primitive.index_count }; - defer cube_primitive.vertex_data.deinit(); - defer cube_primitive.index_data.deinit(); - } - - { - const cylinder_primitive = try primitives.createCylinderPrimitive(allocator, 1.0, 1.0, 6); - primitives_data[5] = PrimitiveRenderData{ .vertex_buffer = createVertexBuffer(cylinder_primitive), .index_buffer = createIndexBuffer(cylinder_primitive), .vertex_count = cylinder_primitive.vertex_count, .index_count = cylinder_primitive.index_count }; - defer cylinder_primitive.vertex_data.deinit(); - defer cylinder_primitive.index_data.deinit(); - } - - { - const cone_primitive = try primitives.createConePrimitive(allocator, 0.7, 1.0, 15); - primitives_data[6] = PrimitiveRenderData{ .vertex_buffer = createVertexBuffer(cone_primitive), .index_buffer = createIndexBuffer(cone_primitive), .vertex_count = cone_primitive.vertex_count, .index_count = cone_primitive.index_count }; - defer cone_primitive.vertex_data.deinit(); - defer cone_primitive.index_data.deinit(); - } - var bind_group_layout = createBindGroupLayout(); - defer bind_group_layout.release(); - - createBindBuffer(bind_group_layout); - - createDepthTexture(); - - var shader = core.device.createShaderModuleWGSL("shader.wgsl", @embedFile("shader.wgsl")); - defer shader.release(); - - pipeline = createPipeline(shader, bind_group_layout); -} - -fn createVertexBuffer(primitive: Primitive) *gpu.Buffer { - const vertex_buffer_descriptor = gpu.Buffer.Descriptor{ - .size = primitive.vertex_count * @sizeOf(VertexData), - .usage = .{ .vertex = true, .copy_dst = true }, - .mapped_at_creation = .false, - }; - - const vertex_buffer = core.device.createBuffer(&vertex_buffer_descriptor); - queue.writeBuffer(vertex_buffer, 0, primitive.vertex_data.items[0..]); - - return vertex_buffer; -} - -fn createIndexBuffer(primitive: Primitive) *gpu.Buffer { - const index_buffer_descriptor = gpu.Buffer.Descriptor{ - .size = primitive.index_count * @sizeOf(u32), - .usage = .{ .index = true, .copy_dst = true }, - .mapped_at_creation = .false, - }; - const index_buffer = core.device.createBuffer(&index_buffer_descriptor); - queue.writeBuffer(index_buffer, 0, primitive.index_data.items[0..]); - - return index_buffer; -} - -fn createBindGroupLayout() *gpu.BindGroupLayout { - const bgle = gpu.BindGroupLayout.Entry.buffer(0, .{ .vertex = true, .fragment = false }, .uniform, true, 0); - return core.device.createBindGroupLayout( - &gpu.BindGroupLayout.Descriptor.init(.{ - .entries = &.{bgle}, - }), - ); -} - -fn createBindBuffer(bind_group_layout: *gpu.BindGroupLayout) void { - uniform_buffer = core.device.createBuffer(&.{ - .usage = .{ .copy_dst = true, .uniform = true }, - .size = @sizeOf(UniformBufferObject), - .mapped_at_creation = .false, - }); - - bind_group = core.device.createBindGroup( - &gpu.BindGroup.Descriptor.init(.{ - .layout = bind_group_layout, - .entries = &.{ - gpu.BindGroup.Entry.buffer(0, uniform_buffer, 0, @sizeOf(UniformBufferObject), @sizeOf(UniformBufferObject)), - }, - }), - ); -} - -fn createDepthTexture() void { - depth_texture = core.device.createTexture(&gpu.Texture.Descriptor{ - .usage = .{ .render_attachment = true }, - .size = .{ .width = core.descriptor.width, .height = core.descriptor.height }, - .format = .depth24_plus, - }); - - depth_texture_view = depth_texture.createView(&gpu.TextureView.Descriptor{ - .format = .depth24_plus, - .dimension = .dimension_2d, - .array_layer_count = 1, - .mip_level_count = 1, - }); -} - -fn createPipeline(shader_module: *gpu.ShaderModule, bind_group_layout: *gpu.BindGroupLayout) *gpu.RenderPipeline { - const vertex_attributes = [_]gpu.VertexAttribute{ - .{ .format = .float32x3, .shader_location = 0, .offset = 0 }, - .{ .format = .float32x3, .shader_location = 1, .offset = @sizeOf(primitives.F32x3) }, - }; - - const vertex_buffer_layout = gpu.VertexBufferLayout.init(.{ - .array_stride = @sizeOf(VertexData), - .step_mode = .vertex, - .attributes = &vertex_attributes, - }); - - const vertex_pipeline_state = gpu.VertexState.init(.{ .module = shader_module, .entry_point = "vertex_main", .buffers = &.{vertex_buffer_layout} }); - - const primitive_pipeline_state = gpu.PrimitiveState{ - .topology = .triangle_list, - .front_face = .ccw, - .cull_mode = .back, - }; - - // Fragment Pipeline State - const blend = gpu.BlendState{ - .color = gpu.BlendComponent{ .operation = .add, .src_factor = .src_alpha, .dst_factor = .one_minus_src_alpha }, - .alpha = gpu.BlendComponent{ .operation = .add, .src_factor = .zero, .dst_factor = .one }, - }; - const color_target = gpu.ColorTargetState{ - .format = core.descriptor.format, - .blend = &blend, - .write_mask = gpu.ColorWriteMaskFlags.all, - }; - const fragment_pipeline_state = gpu.FragmentState.init(.{ - .module = shader_module, - .entry_point = "frag_main", - .targets = &.{color_target}, - }); - - const depth_stencil_state = gpu.DepthStencilState{ - .format = .depth24_plus, - .depth_write_enabled = .true, - .depth_compare = .less, - }; - - const multi_sample_state = gpu.MultisampleState{ - .count = 1, - .mask = 0xFFFFFFFF, - .alpha_to_coverage_enabled = .false, - }; - - const bind_group_layouts = [_]*gpu.BindGroupLayout{bind_group_layout}; - // Pipeline Layout - const pipeline_layout_descriptor = gpu.PipelineLayout.Descriptor.init(.{ - .bind_group_layouts = &bind_group_layouts, - }); - const pipeline_layout = core.device.createPipelineLayout(&pipeline_layout_descriptor); - defer pipeline_layout.release(); - - const pipeline_descriptor = gpu.RenderPipeline.Descriptor{ - .label = "Main Pipeline", - .layout = pipeline_layout, - .vertex = vertex_pipeline_state, - .primitive = primitive_pipeline_state, - .depth_stencil = &depth_stencil_state, - .multisample = multi_sample_state, - .fragment = &fragment_pipeline_state, - }; - - return core.device.createRenderPipeline(&pipeline_descriptor); -} - -pub const F32x1 = @Vector(1, f32); - -pub fn update() void { - const back_buffer_view = core.swap_chain.getCurrentTextureView().?; - const color_attachment = gpu.RenderPassColorAttachment{ - .view = back_buffer_view, - .clear_value = gpu.Color{ .r = 0.2, .g = 0.2, .b = 0.2, .a = 1.0 }, - .load_op = .clear, - .store_op = .store, - }; - - const depth_stencil_attachment = gpu.RenderPassDepthStencilAttachment{ - .view = depth_texture_view, - .depth_load_op = .clear, - .depth_store_op = .store, - .depth_clear_value = 1.0, - }; - - const encoder = core.device.createCommandEncoder(null); - const render_pass_info = gpu.RenderPassDescriptor.init(.{ - .color_attachments = &.{color_attachment}, - .depth_stencil_attachment = &depth_stencil_attachment, - }); - - if (curr_primitive_index >= 4) { - const time = app_timer.read() / 5; - const model = zm.mul(zm.rotationX(time * (std.math.pi / 2.0)), zm.rotationZ(time * (std.math.pi / 2.0))); - const view = zm.lookAtRh( - zm.Vec{ 0, 4, 2, 1 }, - zm.Vec{ 0, 0, 0, 1 }, - zm.Vec{ 0, 0, 1, 0 }, - ); - const proj = zm.perspectiveFovRh( - (std.math.pi / 4.0), - @as(f32, @floatFromInt(core.descriptor.width)) / @as(f32, @floatFromInt(core.descriptor.height)), - 0.1, - 10, - ); - - const mvp = zm.mul(zm.mul(model, view), proj); - - const ubo = UniformBufferObject{ - .mvp_matrix = zm.transpose(mvp), - }; - encoder.writeBuffer(uniform_buffer, 0, &[_]UniformBufferObject{ubo}); - } else { - const ubo = UniformBufferObject{ - .mvp_matrix = zm.identity(), - }; - encoder.writeBuffer(uniform_buffer, 0, &[_]UniformBufferObject{ubo}); - } - - const pass = encoder.beginRenderPass(&render_pass_info); - - pass.setPipeline(pipeline); - - const vertex_buffer = primitives_data[curr_primitive_index].vertex_buffer; - const vertex_count = primitives_data[curr_primitive_index].vertex_count; - pass.setVertexBuffer(0, vertex_buffer, 0, @sizeOf(VertexData) * vertex_count); - - pass.setBindGroup(0, bind_group, &.{0}); - - const index_buffer = primitives_data[curr_primitive_index].index_buffer; - const index_count = primitives_data[curr_primitive_index].index_count; - pass.setIndexBuffer(index_buffer, .uint32, 0, @sizeOf(u32) * index_count); - pass.drawIndexed(index_count, 1, 0, 0, 0); - - pass.end(); - pass.release(); - - var command = encoder.finish(null); - encoder.release(); - - queue.submit(&[_]*gpu.CommandBuffer{command}); - command.release(); - core.swap_chain.present(); - back_buffer_view.release(); -} - -pub fn deinit() void { - var i: u4 = 0; - while (i < 7) : (i += 1) { - primitives_data[i].vertex_buffer.release(); - primitives_data[i].index_buffer.release(); - } - - bind_group.release(); - uniform_buffer.release(); - depth_texture.release(); - depth_texture_view.release(); - pipeline.release(); -} diff --git a/src/core/examples/sysgpu/procedural-primitives/shader.wgsl b/src/core/examples/sysgpu/procedural-primitives/shader.wgsl deleted file mode 100644 index 18606b69..00000000 --- a/src/core/examples/sysgpu/procedural-primitives/shader.wgsl +++ /dev/null @@ -1,32 +0,0 @@ -struct Uniforms { - mvp_matrix : mat4x4, -}; - -@binding(0) @group(0) var ubo : Uniforms; - -struct VertexOutput { - @builtin(position) position: vec4, - @location(0) normal: vec3, -}; - -@vertex fn vertex_main( - // TODO - struct input - @location(0) position: vec3, - @location(1) normal: vec3, -) -> VertexOutput { - var out: VertexOutput; - out.position = vec4(position, 1.0) * ubo.mvp_matrix; - out.normal = normal; - return out; -} - -struct FragmentOutput { - @location(0) pixel_color: vec4 -}; - -@fragment fn frag_main(in: VertexOutput) -> FragmentOutput { - var out : FragmentOutput; - - out.pixel_color = vec4((in.normal + 1) / 2, 1.0); - return out; -} \ No newline at end of file diff --git a/src/core/examples/sysgpu/rgb-quad/main.zig b/src/core/examples/sysgpu/rgb-quad/main.zig deleted file mode 100644 index 2f8ed683..00000000 --- a/src/core/examples/sysgpu/rgb-quad/main.zig +++ /dev/null @@ -1,143 +0,0 @@ -const std = @import("std"); - -const mach = @import("mach"); -const core = mach.core; -const gpu = mach.gpu; - -const Vertex = extern struct { - pos: @Vector(2, f32), - col: @Vector(3, f32), -}; -const vertices = [_]Vertex{ - .{ .pos = .{ -0.5, -0.5 }, .col = .{ 1, 0, 0 } }, - .{ .pos = .{ 0.5, -0.5 }, .col = .{ 0, 1, 0 } }, - .{ .pos = .{ 0.5, 0.5 }, .col = .{ 0, 0, 1 } }, - .{ .pos = .{ -0.5, 0.5 }, .col = .{ 1, 1, 1 } }, -}; -const index_data = [_]u32{ 0, 1, 2, 2, 3, 0 }; - -// Use experimental sysgpu graphics API -pub const use_sysgpu = true; - -pub const App = @This(); - -var gpa = std.heap.GeneralPurposeAllocator(.{}){}; - -title_timer: core.Timer, -pipeline: *gpu.RenderPipeline, -vertex_buffer: *gpu.Buffer, -index_buffer: *gpu.Buffer, - -pub fn init(app: *App) !void { - try core.init(.{}); - - const shader_module = core.device.createShaderModuleWGSL("shader.wgsl", @embedFile("shader.wgsl")); - defer shader_module.release(); - - const vertex_attributes = [_]gpu.VertexAttribute{ - .{ .format = .float32x2, .offset = @offsetOf(Vertex, "pos"), .shader_location = 0 }, - .{ .format = .float32x3, .offset = @offsetOf(Vertex, "col"), .shader_location = 1 }, - }; - const vertex_buffer_layout = gpu.VertexBufferLayout.init(.{ - .array_stride = @sizeOf(Vertex), - .step_mode = .vertex, - .attributes = &vertex_attributes, - }); - - const color_target = gpu.ColorTargetState{ - .format = core.descriptor.format, - .blend = &.{}, - .write_mask = gpu.ColorWriteMaskFlags.all, - }; - const fragment = gpu.FragmentState.init(.{ - .module = shader_module, - .entry_point = "frag_main", - .targets = &.{color_target}, - }); - - const pipeline_layout = core.device.createPipelineLayout(&gpu.PipelineLayout.Descriptor.init(.{})); - defer pipeline_layout.release(); - - const pipeline_descriptor = gpu.RenderPipeline.Descriptor{ - .fragment = &fragment, - .layout = pipeline_layout, - .vertex = gpu.VertexState.init(.{ - .module = shader_module, - .entry_point = "vertex_main", - .buffers = &.{vertex_buffer_layout}, - }), - .primitive = .{ .cull_mode = .back }, - }; - - const vertex_buffer = core.device.createBuffer(&.{ - .usage = .{ .vertex = true }, - .size = @sizeOf(Vertex) * vertices.len, - .mapped_at_creation = .true, - }); - const vertex_mapped = vertex_buffer.getMappedRange(Vertex, 0, vertices.len); - @memcpy(vertex_mapped.?, vertices[0..]); - vertex_buffer.unmap(); - - const index_buffer = core.device.createBuffer(&.{ - .usage = .{ .index = true }, - .size = @sizeOf(u32) * index_data.len, - .mapped_at_creation = .true, - }); - const index_mapped = index_buffer.getMappedRange(u32, 0, index_data.len); - @memcpy(index_mapped.?, index_data[0..]); - index_buffer.unmap(); - - app.title_timer = try core.Timer.start(); - app.pipeline = core.device.createRenderPipeline(&pipeline_descriptor); - app.vertex_buffer = vertex_buffer; - app.index_buffer = index_buffer; -} - -pub fn deinit(app: *App) void { - app.vertex_buffer.release(); - app.index_buffer.release(); - app.pipeline.release(); - core.deinit(); - _ = gpa.deinit(); -} - -pub fn update(app: *App) !bool { - var iter = core.pollEvents(); - while (iter.next()) |event| if (event == .close) return true; - - const back_buffer_view = core.swap_chain.getCurrentTextureView().?; - const encoder = core.device.createCommandEncoder(null); - const color_attachment = gpu.RenderPassColorAttachment{ - .view = back_buffer_view, - .clear_value = .{ .r = 0, .g = 0, .b = 0, .a = 1 }, - .load_op = .clear, - .store_op = .store, - }; - const render_pass_info = gpu.RenderPassDescriptor.init(.{ .color_attachments = &.{color_attachment} }); - - const pass = encoder.beginRenderPass(&render_pass_info); - pass.setPipeline(app.pipeline); - pass.setVertexBuffer(0, app.vertex_buffer, 0, @sizeOf(Vertex) * vertices.len); - pass.setIndexBuffer(app.index_buffer, .uint32, 0, @sizeOf(u32) * index_data.len); - pass.drawIndexed(index_data.len, 1, 0, 0, 0); - pass.end(); - pass.release(); - - var command = encoder.finish(null); - encoder.release(); - core.queue.submit(&.{command}); - command.release(); - core.swap_chain.present(); - back_buffer_view.release(); - - // update the window title every second - if (app.title_timer.read() >= 1.0) { - app.title_timer.reset(); - try core.printTitle("RGB Quad [ {d}fps ] [ Input {d}hz ]", .{ - core.frameRate(), - core.inputRate(), - }); - } - - return false; -} diff --git a/src/core/examples/sysgpu/rgb-quad/shader.wgsl b/src/core/examples/sysgpu/rgb-quad/shader.wgsl deleted file mode 100644 index 85f687bc..00000000 --- a/src/core/examples/sysgpu/rgb-quad/shader.wgsl +++ /dev/null @@ -1,15 +0,0 @@ -struct Output { - @builtin(position) pos: vec4, - @location(0) color: vec3, -}; - -@vertex fn vertex_main(@location(0) pos: vec2, @location(1) color: vec3) -> Output { - var output: Output; - output.pos = vec4(pos, 0, 1); - output.color = color; - return output; -} - -@fragment fn frag_main(@location(0) color: vec3) -> @location(0) vec4 { - return vec4(color, 1); -} \ No newline at end of file diff --git a/src/core/examples/sysgpu/rotating-cube/cube_mesh.zig b/src/core/examples/sysgpu/rotating-cube/cube_mesh.zig deleted file mode 100644 index f26c75ac..00000000 --- a/src/core/examples/sysgpu/rotating-cube/cube_mesh.zig +++ /dev/null @@ -1,49 +0,0 @@ -pub const Vertex = extern struct { - pos: @Vector(4, f32), - col: @Vector(4, f32), - uv: @Vector(2, f32), -}; - -pub const vertices = [_]Vertex{ - .{ .pos = .{ 1, -1, 1, 1 }, .col = .{ 1, 0, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, -1, -1, 1 }, .col = .{ 0, 0, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, -1, 1, 1 }, .col = .{ 1, 0, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, -1, -1, 1 }, .col = .{ 0, 0, 0, 1 }, .uv = .{ 0, 0 } }, - - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ 1, -1, 1, 1 }, .col = .{ 1, 0, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, 1, -1, 1 }, .col = .{ 1, 1, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 0, 0 } }, - - .{ .pos = .{ -1, 1, 1, 1 }, .col = .{ 0, 1, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ 1, 1, -1, 1 }, .col = .{ 1, 1, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ -1, 1, 1, 1 }, .col = .{ 0, 1, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ 1, 1, -1, 1 }, .col = .{ 1, 1, 0, 1 }, .uv = .{ 0, 0 } }, - - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, 1, 1, 1 }, .col = .{ 0, 1, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ -1, -1, -1, 1 }, .col = .{ 0, 0, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 0, 0 } }, - - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, 1, 1, 1 }, .col = .{ 0, 1, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, -1, 1, 1 }, .col = .{ 1, 0, 1, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 1, 1 } }, - - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, -1, -1, 1 }, .col = .{ 0, 0, 0, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, 1, -1, 1 }, .col = .{ 1, 1, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 0, 0 } }, -}; diff --git a/src/core/examples/sysgpu/rotating-cube/main.zig b/src/core/examples/sysgpu/rotating-cube/main.zig deleted file mode 100644 index 0555c8ff..00000000 --- a/src/core/examples/sysgpu/rotating-cube/main.zig +++ /dev/null @@ -1,198 +0,0 @@ -const std = @import("std"); - -const mach = @import("mach"); -const core = mach.core; -const gpu = mach.gpu; - -const zm = @import("zmath"); -const Vertex = @import("cube_mesh.zig").Vertex; -const vertices = @import("cube_mesh.zig").vertices; - -pub const App = @This(); - -// Use experimental sysgpu graphics API -pub const use_sysgpu = true; - -var gpa = std.heap.GeneralPurposeAllocator(.{}){}; -const UniformBufferObject = struct { - mat: zm.Mat, -}; - -title_timer: core.Timer, -timer: core.Timer, -pipeline: *gpu.RenderPipeline, -vertex_buffer: *gpu.Buffer, -uniform_buffer: *gpu.Buffer, -bind_group: *gpu.BindGroup, - -pub fn init(app: *App) !void { - try core.init(.{}); - - const shader_module = core.device.createShaderModuleWGSL("shader.wgsl", @embedFile("shader.wgsl")); - - const vertex_attributes = [_]gpu.VertexAttribute{ - .{ .format = .float32x4, .offset = @offsetOf(Vertex, "pos"), .shader_location = 0 }, - .{ .format = .float32x2, .offset = @offsetOf(Vertex, "uv"), .shader_location = 1 }, - }; - const vertex_buffer_layout = gpu.VertexBufferLayout.init(.{ - .array_stride = @sizeOf(Vertex), - .step_mode = .vertex, - .attributes = &vertex_attributes, - }); - - const blend = gpu.BlendState{}; - const color_target = gpu.ColorTargetState{ - .format = core.descriptor.format, - .blend = &blend, - .write_mask = gpu.ColorWriteMaskFlags.all, - }; - const fragment = gpu.FragmentState.init(.{ - .module = shader_module, - .entry_point = "frag_main", - .targets = &.{color_target}, - }); - - const bgle = gpu.BindGroupLayout.Entry.buffer(0, .{ .vertex = true }, .uniform, true, 0); - const bgl = core.device.createBindGroupLayout( - &gpu.BindGroupLayout.Descriptor.init(.{ - .entries = &.{bgle}, - }), - ); - - const bind_group_layouts = [_]*gpu.BindGroupLayout{bgl}; - const pipeline_layout = core.device.createPipelineLayout(&gpu.PipelineLayout.Descriptor.init(.{ - .bind_group_layouts = &bind_group_layouts, - })); - - const pipeline_descriptor = gpu.RenderPipeline.Descriptor{ - .fragment = &fragment, - .layout = pipeline_layout, - .vertex = gpu.VertexState.init(.{ - .module = shader_module, - .entry_point = "vertex_main", - .buffers = &.{vertex_buffer_layout}, - }), - .primitive = .{ - .cull_mode = .back, - }, - }; - - const vertex_buffer = core.device.createBuffer(&.{ - .usage = .{ .vertex = true }, - .size = @sizeOf(Vertex) * vertices.len, - .mapped_at_creation = .true, - }); - const vertex_mapped = vertex_buffer.getMappedRange(Vertex, 0, vertices.len); - @memcpy(vertex_mapped.?, vertices[0..]); - vertex_buffer.unmap(); - - const uniform_buffer = core.device.createBuffer(&.{ - .usage = .{ .copy_dst = true, .uniform = true }, - .size = @sizeOf(UniformBufferObject), - .mapped_at_creation = .false, - }); - const bind_group = core.device.createBindGroup( - &gpu.BindGroup.Descriptor.init(.{ - .layout = bgl, - .entries = &.{ - gpu.BindGroup.Entry.buffer(0, uniform_buffer, 0, @sizeOf(UniformBufferObject), @sizeOf(UniformBufferObject)), - }, - }), - ); - - app.title_timer = try core.Timer.start(); - app.timer = try core.Timer.start(); - app.pipeline = core.device.createRenderPipeline(&pipeline_descriptor); - app.vertex_buffer = vertex_buffer; - app.uniform_buffer = uniform_buffer; - app.bind_group = bind_group; - - shader_module.release(); - pipeline_layout.release(); - bgl.release(); -} - -pub fn deinit(app: *App) void { - defer _ = gpa.deinit(); - defer core.deinit(); - - app.vertex_buffer.release(); - app.uniform_buffer.release(); - app.bind_group.release(); - app.pipeline.release(); -} - -pub fn update(app: *App) !bool { - var iter = core.pollEvents(); - while (iter.next()) |event| { - switch (event) { - .key_press => |ev| { - if (ev.key == .space) return true; - }, - .close => return true, - else => {}, - } - } - - const back_buffer_view = core.swap_chain.getCurrentTextureView().?; - const color_attachment = gpu.RenderPassColorAttachment{ - .view = back_buffer_view, - .clear_value = std.mem.zeroes(gpu.Color), - .load_op = .clear, - .store_op = .store, - }; - - const queue = core.queue; - const encoder = core.device.createCommandEncoder(null); - const render_pass_info = gpu.RenderPassDescriptor.init(.{ - .color_attachments = &.{color_attachment}, - }); - - { - const time = app.timer.read(); - const model = zm.mul(zm.rotationX(time * (std.math.pi / 2.0)), zm.rotationZ(time * (std.math.pi / 2.0))); - const view = zm.lookAtRh( - zm.Vec{ 0, 4, 2, 1 }, - zm.Vec{ 0, 0, 0, 1 }, - zm.Vec{ 0, 0, 1, 0 }, - ); - const proj = zm.perspectiveFovRh( - (std.math.pi / 4.0), - @as(f32, @floatFromInt(core.descriptor.width)) / @as(f32, @floatFromInt(core.descriptor.height)), - 0.1, - 10, - ); - const mvp = zm.mul(zm.mul(model, view), proj); - const ubo = UniformBufferObject{ - .mat = zm.transpose(mvp), - }; - queue.writeBuffer(app.uniform_buffer, 0, &[_]UniformBufferObject{ubo}); - } - - const pass = encoder.beginRenderPass(&render_pass_info); - pass.setPipeline(app.pipeline); - pass.setVertexBuffer(0, app.vertex_buffer, 0, @sizeOf(Vertex) * vertices.len); - pass.setBindGroup(0, app.bind_group, &.{0}); - pass.draw(vertices.len, 1, 0, 0); - pass.end(); - pass.release(); - - var command = encoder.finish(null); - encoder.release(); - - queue.submit(&[_]*gpu.CommandBuffer{command}); - command.release(); - core.swap_chain.present(); - back_buffer_view.release(); - - // update the window title every second - if (app.title_timer.read() >= 1.0) { - app.title_timer.reset(); - try core.printTitle("Rotating Cube [ {d}fps ] [ Input {d}hz ]", .{ - core.frameRate(), - core.inputRate(), - }); - } - - return false; -} diff --git a/src/core/examples/sysgpu/rotating-cube/shader.wgsl b/src/core/examples/sysgpu/rotating-cube/shader.wgsl deleted file mode 100644 index 6b7291ee..00000000 --- a/src/core/examples/sysgpu/rotating-cube/shader.wgsl +++ /dev/null @@ -1,24 +0,0 @@ -@group(0) @binding(0) var ubo : mat4x4; -struct VertexOut { - @builtin(position) position_clip : vec4, - @location(0) fragUV : vec2, - @location(1) fragPosition: vec4, -} - -@vertex fn vertex_main( - @location(0) position : vec4, - @location(1) uv: vec2 -) -> VertexOut { - var output : VertexOut; - output.position_clip = position * ubo; - output.fragUV = uv; - output.fragPosition = 0.5 * (position + vec4(1.0, 1.0, 1.0, 1.0)); - return output; -} - -@fragment fn frag_main( - @location(0) fragUV: vec2, - @location(1) fragPosition: vec4 -) -> @location(0) vec4 { - return fragPosition; -} \ No newline at end of file diff --git a/src/core/examples/sysgpu/sprite2d/main.zig b/src/core/examples/sysgpu/sprite2d/main.zig deleted file mode 100644 index 5a89b0b9..00000000 --- a/src/core/examples/sysgpu/sprite2d/main.zig +++ /dev/null @@ -1,360 +0,0 @@ -const std = @import("std"); - -const mach = @import("mach"); -const core = mach.core; -const gpu = mach.gpu; - -const zm = @import("zmath"); -const zigimg = @import("zigimg"); -const assets = @import("assets"); -const json = std.json; - -pub const App = @This(); - -// Use experimental sysgpu graphics API -pub const use_sysgpu = true; - -const speed = 2.0 * 100.0; // pixels per second - -const Vec2 = @Vector(2, f32); - -const UniformBufferObject = struct { - mat: zm.Mat, -}; -const Sprite = extern struct { - pos: Vec2, - size: Vec2, - world_pos: Vec2, - sheet_size: Vec2, -}; -const SpriteFrames = extern struct { - up: Vec2, - down: Vec2, - left: Vec2, - right: Vec2, -}; -const JSONFrames = struct { - up: []f32, - down: []f32, - left: []f32, - right: []f32, -}; -const JSONSprite = struct { - pos: []f32, - size: []f32, - world_pos: []f32, - is_player: bool = false, - frames: JSONFrames, -}; -const SpriteSheet = struct { - width: f32, - height: f32, -}; -const JSONData = struct { - sheet: SpriteSheet, - sprites: []JSONSprite, -}; -var gpa = std.heap.GeneralPurposeAllocator(.{}){}; - -title_timer: core.Timer, -timer: core.Timer, -fps_timer: core.Timer, -pipeline: *gpu.RenderPipeline, -uniform_buffer: *gpu.Buffer, -bind_group: *gpu.BindGroup, -sheet: SpriteSheet, -sprites_buffer: *gpu.Buffer, -sprites: std.ArrayList(Sprite), -sprites_frames: std.ArrayList(SpriteFrames), -player_pos: Vec2, -direction: Vec2, -player_sprite_index: usize, - -pub fn init(app: *App) !void { - try core.init(.{}); - - const allocator = gpa.allocator(); - - const sprites_file = try std.fs.cwd().openFile("../../examples/sprite2d/sprites.json", .{ .mode = .read_only }); - defer sprites_file.close(); - const file_size = (try sprites_file.stat()).size; - const buffer = try allocator.alloc(u8, file_size); - defer allocator.free(buffer); - try sprites_file.reader().readNoEof(buffer); - const root = try std.json.parseFromSlice(JSONData, allocator, buffer, .{}); - defer root.deinit(); - - app.player_pos = Vec2{ 0, 0 }; - app.direction = Vec2{ 0, 0 }; - app.sheet = root.value.sheet; - std.log.info("Sheet Dimensions: {} {}", .{ app.sheet.width, app.sheet.height }); - app.sprites = std.ArrayList(Sprite).init(allocator); - app.sprites_frames = std.ArrayList(SpriteFrames).init(allocator); - for (root.value.sprites) |sprite| { - std.log.info("Sprite World Position: {} {}", .{ sprite.world_pos[0], sprite.world_pos[1] }); - std.log.info("Sprite Texture Position: {} {}", .{ sprite.pos[0], sprite.pos[1] }); - std.log.info("Sprite Dimensions: {} {}", .{ sprite.size[0], sprite.size[1] }); - if (sprite.is_player) { - app.player_sprite_index = app.sprites.items.len; - } - try app.sprites.append(.{ - .pos = Vec2{ sprite.pos[0], sprite.pos[1] }, - .size = Vec2{ sprite.size[0], sprite.size[1] }, - .world_pos = Vec2{ sprite.world_pos[0], sprite.world_pos[1] }, - .sheet_size = Vec2{ app.sheet.width, app.sheet.height }, - }); - try app.sprites_frames.append(.{ .up = Vec2{ sprite.frames.up[0], sprite.frames.up[1] }, .down = Vec2{ sprite.frames.down[0], sprite.frames.down[1] }, .left = Vec2{ sprite.frames.left[0], sprite.frames.left[1] }, .right = Vec2{ sprite.frames.right[0], sprite.frames.right[1] } }); - } - std.log.info("Number of sprites: {}", .{app.sprites.items.len}); - - const shader_module = core.device.createShaderModuleWGSL("sprite-shader.wgsl", @embedFile("sprite-shader.wgsl")); - - const blend = gpu.BlendState{ - .color = .{ - .operation = .add, - .src_factor = .src_alpha, - .dst_factor = .one_minus_src_alpha, - }, - .alpha = .{ - .operation = .add, - .src_factor = .one, - .dst_factor = .zero, - }, - }; - const color_target = gpu.ColorTargetState{ - .format = core.descriptor.format, - .blend = &blend, - .write_mask = gpu.ColorWriteMaskFlags.all, - }; - const fragment = gpu.FragmentState.init(.{ - .module = shader_module, - .entry_point = "frag_main", - .targets = &.{color_target}, - }); - - const pipeline_descriptor = gpu.RenderPipeline.Descriptor{ - .fragment = &fragment, - .vertex = gpu.VertexState.init(.{ - .module = shader_module, - .entry_point = "vertex_main", - }), - }; - const pipeline = core.device.createRenderPipeline(&pipeline_descriptor); - - const sprites_buffer = core.device.createBuffer(&.{ - .usage = .{ .storage = true, .copy_dst = true }, - .size = @sizeOf(Sprite) * app.sprites.items.len, - .mapped_at_creation = .true, - }); - const sprites_mapped = sprites_buffer.getMappedRange(Sprite, 0, app.sprites.items.len); - @memcpy(sprites_mapped.?, app.sprites.items[0..]); - sprites_buffer.unmap(); - - // Create a sampler with linear filtering for smooth interpolation. - const sampler = core.device.createSampler(&.{ - .mag_filter = .linear, - .min_filter = .linear, - }); - const queue = core.queue; - var img = try zigimg.Image.fromMemory(allocator, assets.sprites_sheet_png); - defer img.deinit(); - const img_size = gpu.Extent3D{ .width = @as(u32, @intCast(img.width)), .height = @as(u32, @intCast(img.height)) }; - std.log.info("Image Dimensions: {} {}", .{ img.width, img.height }); - const texture = core.device.createTexture(&.{ - .size = img_size, - .format = .rgba8_unorm, - .usage = .{ - .texture_binding = true, - .copy_dst = true, - .render_attachment = true, - }, - }); - const data_layout = gpu.Texture.DataLayout{ - .bytes_per_row = @as(u32, @intCast(img.width * 4)), - .rows_per_image = @as(u32, @intCast(img.height)), - }; - switch (img.pixels) { - .rgba32 => |pixels| queue.writeTexture(&.{ .texture = texture }, &data_layout, &img_size, pixels), - .rgb24 => |pixels| { - const data = try rgb24ToRgba32(allocator, pixels); - defer data.deinit(allocator); - queue.writeTexture(&.{ .texture = texture }, &data_layout, &img_size, data.rgba32); - }, - else => @panic("unsupported image color format"), - } - - const uniform_buffer = core.device.createBuffer(&.{ - .usage = .{ .copy_dst = true, .uniform = true }, - .size = @sizeOf(UniformBufferObject), - .mapped_at_creation = .false, - }); - - const texture_view = texture.createView(&gpu.TextureView.Descriptor{}); - texture.release(); - - const bind_group_layout = pipeline.getBindGroupLayout(0); - const bind_group = core.device.createBindGroup( - &gpu.BindGroup.Descriptor.init(.{ - .layout = bind_group_layout, - .entries = &.{ - gpu.BindGroup.Entry.buffer(0, uniform_buffer, 0, @sizeOf(UniformBufferObject), @sizeOf(UniformBufferObject)), - gpu.BindGroup.Entry.sampler(1, sampler), - gpu.BindGroup.Entry.textureView(2, texture_view), - gpu.BindGroup.Entry.buffer(3, sprites_buffer, 0, @sizeOf(Sprite) * app.sprites.items.len, @sizeOf(Sprite)), - }, - }), - ); - texture_view.release(); - sampler.release(); - bind_group_layout.release(); - - app.title_timer = try core.Timer.start(); - app.timer = try core.Timer.start(); - app.fps_timer = try core.Timer.start(); - app.pipeline = pipeline; - app.uniform_buffer = uniform_buffer; - app.bind_group = bind_group; - app.sprites_buffer = sprites_buffer; - - shader_module.release(); -} - -pub fn deinit(app: *App) void { - defer _ = gpa.deinit(); - defer core.deinit(); - - app.pipeline.release(); - app.sprites.deinit(); - app.sprites_frames.deinit(); - app.uniform_buffer.release(); - app.bind_group.release(); - app.sprites_buffer.release(); -} - -pub fn update(app: *App) !bool { - // Handle input by determining the direction the player wants to go. - var iter = core.pollEvents(); - while (iter.next()) |event| { - switch (event) { - .key_press => |ev| { - switch (ev.key) { - .space => return true, - .left => app.direction[0] += 1, - .right => app.direction[0] -= 1, - .up => app.direction[1] += 1, - .down => app.direction[1] -= 1, - else => {}, - } - }, - .key_release => |ev| { - switch (ev.key) { - .left => app.direction[0] -= 1, - .right => app.direction[0] += 1, - .up => app.direction[1] -= 1, - .down => app.direction[1] += 1, - else => {}, - } - }, - .close => return true, - else => {}, - } - } - - // Calculate the player position, by moving in the direction the player wants to go - // by the speed amount. Multiply by delta_time to ensure that movement is the same speed - // regardless of the frame rate. - const delta_time = app.fps_timer.lap(); - app.player_pos += app.direction * Vec2{ speed, speed } * Vec2{ delta_time, delta_time }; - - // Render the frame - try app.render(); - - // update the window title every second - if (app.title_timer.read() >= 1.0) { - app.title_timer.reset(); - try core.printTitle("Sprite2D [ {d}fps ] [ Input {d}hz ]", .{ - core.frameRate(), - core.inputRate(), - }); - } - - return false; -} - -fn render(app: *App) !void { - const back_buffer_view = core.swap_chain.getCurrentTextureView().?; - const color_attachment = gpu.RenderPassColorAttachment{ - .view = back_buffer_view, - // sky blue background color: - .clear_value = .{ .r = 0.52, .g = 0.8, .b = 0.92, .a = 1.0 }, - .load_op = .clear, - .store_op = .store, - }; - - const encoder = core.device.createCommandEncoder(null); - const render_pass_info = gpu.RenderPassDescriptor.init(.{ - .color_attachments = &.{color_attachment}, - }); - - const player_sprite = &app.sprites.items[app.player_sprite_index]; - const player_sprite_frame = &app.sprites_frames.items[app.player_sprite_index]; - if (app.direction[0] == -1.0) { - player_sprite.pos = player_sprite_frame.left; - } else if (app.direction[0] == 1.0) { - player_sprite.pos = player_sprite_frame.right; - } else if (app.direction[1] == -1.0) { - player_sprite.pos = player_sprite_frame.down; - } else if (app.direction[1] == 1.0) { - player_sprite.pos = player_sprite_frame.up; - } - player_sprite.world_pos = app.player_pos; - - // One pixel in our scene will equal one window pixel (i.e. be roughly the same size - // irrespective of whether the user has a Retina/HDPI display.) - const proj = zm.orthographicRh( - @as(f32, @floatFromInt(core.size().width)), - @as(f32, @floatFromInt(core.size().height)), - 0.1, - 1000, - ); - const view = zm.lookAtRh( - zm.Vec{ 0, 1000, 0, 1 }, - zm.Vec{ 0, 0, 0, 1 }, - zm.Vec{ 0, 0, 1, 0 }, - ); - const mvp = zm.mul(view, proj); - const ubo = UniformBufferObject{ - .mat = zm.transpose(mvp), - }; - - // Pass the latest uniform values & sprite values to the shader program. - encoder.writeBuffer(app.uniform_buffer, 0, &[_]UniformBufferObject{ubo}); - encoder.writeBuffer(app.sprites_buffer, 0, app.sprites.items); - - // Draw the sprite batch - const total_vertices = @as(u32, @intCast(app.sprites.items.len * 6)); - const pass = encoder.beginRenderPass(&render_pass_info); - pass.setPipeline(app.pipeline); - pass.setBindGroup(0, app.bind_group, &.{}); - pass.draw(total_vertices, 1, 0, 0); - pass.end(); - pass.release(); - - // Submit the frame. - var command = encoder.finish(null); - encoder.release(); - const queue = core.queue; - queue.submit(&[_]*gpu.CommandBuffer{command}); - command.release(); - core.swap_chain.present(); - back_buffer_view.release(); -} - -fn rgb24ToRgba32(allocator: std.mem.Allocator, in: []zigimg.color.Rgb24) !zigimg.color.PixelStorage { - const out = try zigimg.color.PixelStorage.init(allocator, .rgba32, in.len); - var i: usize = 0; - while (i < in.len) : (i += 1) { - out.rgba32[i] = zigimg.color.Rgba32{ .r = in[i].r, .g = in[i].g, .b = in[i].b, .a = 255 }; - } - return out; -} diff --git a/src/core/examples/sysgpu/sprite2d/sprite-shader.wgsl b/src/core/examples/sysgpu/sprite2d/sprite-shader.wgsl deleted file mode 100644 index 979c14de..00000000 --- a/src/core/examples/sysgpu/sprite2d/sprite-shader.wgsl +++ /dev/null @@ -1,82 +0,0 @@ -struct Uniforms { - modelViewProjectionMatrix : mat4x4, -}; -@binding(0) @group(0) var uniforms : Uniforms; - -struct VertexOutput { - @builtin(position) Position : vec4, - @location(0) fragUV : vec2, - @location(1) spriteIndex : f32, -}; - -struct Sprite { - pos: vec2, - size: vec2, - world_pos: vec2, - sheet_size: vec2, -}; -@binding(3) @group(0) var sprites: array; - -@vertex -fn vertex_main( - @builtin(vertex_index) VertexIndex : u32 -) -> VertexOutput { - var sprite = sprites[VertexIndex / 6]; - - // Calculate the vertex position - var positions = array, 6>( - vec2(0.0, 0.0), // bottom-left - vec2(0.0, 1.0), // top-left - vec2(1.0, 0.0), // bottom-right - vec2(1.0, 0.0), // bottom-right - vec2(0.0, 1.0), // top-left - vec2(1.0, 1.0), // top-right - ); - var pos = positions[VertexIndex % 6]; - pos.x *= sprite.size.x; - pos.y *= sprite.size.y; - pos.x += sprite.world_pos.x; - pos.y += sprite.world_pos.y; - - // Calculate the UV coordinate - var uvs = array, 6>( - vec2(0.0, 1.0), // bottom-left - vec2(0.0, 0.0), // top-left - vec2(1.0, 1.0), // bottom-right - vec2(1.0, 1.0), // bottom-right - vec2(0.0, 0.0), // top-left - vec2(1.0, 0.0), // top-right - ); - var uv = uvs[VertexIndex % 6]; - uv.x *= sprite.size.x / sprite.sheet_size.x; - uv.y *= sprite.size.y / sprite.sheet_size.y; - uv.x += sprite.pos.x / sprite.sheet_size.x; - uv.y += sprite.pos.y / sprite.sheet_size.y; - - var output : VertexOutput; - output.Position = vec4(pos.x, 0.0, pos.y, 1.0) * uniforms.modelViewProjectionMatrix; - output.fragUV = uv; - output.spriteIndex = f32(VertexIndex / 6); - return output; -} - -@group(0) @binding(1) var spriteSampler: sampler; -@group(0) @binding(2) var spriteTexture: texture_2d; - -@fragment -fn frag_main( - @location(0) fragUV: vec2, - @location(1) spriteIndex: f32 -) -> @location(0) vec4 { - var color = textureSample(spriteTexture, spriteSampler, fragUV); - if (spriteIndex == 0.0) { - if (color[3] > 0.0) { - color[0] = 0.3; - color[1] = 0.2; - color[2] = 0.5; - color[3] = 1.0; - } - } - - return color; -} \ No newline at end of file diff --git a/src/core/examples/sysgpu/sprite2d/sprites.json b/src/core/examples/sysgpu/sprite2d/sprites.json deleted file mode 100644 index 37d5ab13..00000000 --- a/src/core/examples/sysgpu/sprite2d/sprites.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "sheet": { - "width": 352.0, - "height": 32.0 - }, - "sprites": [ - { - "pos": [ 0.0, 0.0 ], - "size": [ 32.0, 32.0 ], - "world_pos": [ 0.0, 0.0 ], - "is_player": true, - "frames": { - "down": [ 0.0, 0.0 ], - "left": [ 32.0, 0.0 ], - "right": [ 64.0, 0.0 ], - "up": [ 96.0, 0.0 ] - } - }, - { - "pos": [ 128.0, 0.0 ], - "size": [ 32.0, 32.0 ], - "world_pos": [ 32.0, 32.0 ], - "frames": { - "down": [ 128.0, 0.0 ], - "left": [ 160.0, 0.0 ], - "right": [ 192.0, 0.0 ], - "up": [ 224.0, 0.0 ] - } - }, - { - "pos": [ 128.0, 0.0 ], - "size": [ 32.0, 32.0 ], - "world_pos": [ 64.0, 64.0 ], - "frames": { - "down": [ 0.0, 0.0 ], - "left": [ 0.0, 0.0 ], - "right": [ 0.0, 0.0 ], - "up": [ 0.0, 0.0 ] - } - }, - { - "pos": [ 256.0, 0.0 ], - "size": [ 32.0, 32.0 ], - "world_pos": [ 96.0, 96.0 ], - "frames": { - "down": [ 0.0, 0.0 ], - "left": [ 0.0, 0.0 ], - "right": [ 0.0, 0.0 ], - "up": [ 0.0, 0.0 ] - } - } - ] -} \ No newline at end of file diff --git a/src/core/examples/sysgpu/textured-cube/cube_mesh.zig b/src/core/examples/sysgpu/textured-cube/cube_mesh.zig deleted file mode 100644 index ae5b2912..00000000 --- a/src/core/examples/sysgpu/textured-cube/cube_mesh.zig +++ /dev/null @@ -1,49 +0,0 @@ -pub const Vertex = extern struct { - pos: @Vector(4, f32), - col: @Vector(4, f32), - uv: @Vector(2, f32), -}; - -pub const vertices = [_]Vertex{ - .{ .pos = .{ 1, -1, 1, 1 }, .col = .{ 1, 0, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, -1, -1, 1 }, .col = .{ 0, 0, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, -1, 1, 1 }, .col = .{ 1, 0, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, -1, -1, 1 }, .col = .{ 0, 0, 0, 1 }, .uv = .{ 1, 0 } }, - - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ 1, -1, 1, 1 }, .col = .{ 1, 0, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, 1, -1, 1 }, .col = .{ 1, 1, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 1, 0 } }, - - .{ .pos = .{ -1, 1, 1, 1 }, .col = .{ 0, 1, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ 1, 1, -1, 1 }, .col = .{ 1, 1, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ -1, 1, 1, 1 }, .col = .{ 0, 1, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ 1, 1, -1, 1 }, .col = .{ 1, 1, 0, 1 }, .uv = .{ 1, 0 } }, - - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, 1, 1, 1 }, .col = .{ 0, 1, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ -1, -1, -1, 1 }, .col = .{ 0, 0, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 1, 0 } }, - - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, 1, 1, 1 }, .col = .{ 0, 1, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, -1, 1, 1 }, .col = .{ 1, 0, 1, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 0, 1 } }, - - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, -1, -1, 1 }, .col = .{ 0, 0, 0, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, 1, -1, 1 }, .col = .{ 1, 1, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 1, 0 } }, -}; diff --git a/src/core/examples/sysgpu/textured-cube/main.zig b/src/core/examples/sysgpu/textured-cube/main.zig deleted file mode 100644 index 34785439..00000000 --- a/src/core/examples/sysgpu/textured-cube/main.zig +++ /dev/null @@ -1,319 +0,0 @@ -const std = @import("std"); - -const mach = @import("mach"); -const core = mach.core; -const gpu = mach.gpu; - -const zm = @import("zmath"); -const zigimg = @import("zigimg"); -const Vertex = @import("cube_mesh.zig").Vertex; -const vertices = @import("cube_mesh.zig").vertices; -const assets = @import("assets"); - -pub const App = @This(); - -// Use experimental sysgpu graphics API -pub const use_sysgpu = true; - -const UniformBufferObject = struct { - mat: zm.Mat, -}; -var gpa = std.heap.GeneralPurposeAllocator(.{}){}; - -title_timer: core.Timer, -timer: core.Timer, -pipeline: *gpu.RenderPipeline, -vertex_buffer: *gpu.Buffer, -uniform_buffer: *gpu.Buffer, -bind_group: *gpu.BindGroup, -depth_texture: *gpu.Texture, -depth_texture_view: *gpu.TextureView, - -pub fn init(app: *App) !void { - try core.init(.{}); - const allocator = gpa.allocator(); - - const shader_module = core.device.createShaderModuleWGSL("shader.wgsl", @embedFile("shader.wgsl")); - - const vertex_attributes = [_]gpu.VertexAttribute{ - .{ .format = .float32x4, .offset = @offsetOf(Vertex, "pos"), .shader_location = 0 }, - .{ .format = .float32x2, .offset = @offsetOf(Vertex, "uv"), .shader_location = 1 }, - }; - const vertex_buffer_layout = gpu.VertexBufferLayout.init(.{ - .array_stride = @sizeOf(Vertex), - .step_mode = .vertex, - .attributes = &vertex_attributes, - }); - - const blend = gpu.BlendState{ - .color = .{ - .operation = .add, - .src_factor = .src_alpha, - .dst_factor = .one_minus_src_alpha, - }, - .alpha = .{ - .operation = .add, - .src_factor = .one, - .dst_factor = .zero, - }, - }; - const color_target = gpu.ColorTargetState{ - .format = core.descriptor.format, - .blend = &blend, - .write_mask = gpu.ColorWriteMaskFlags.all, - }; - const fragment = gpu.FragmentState.init(.{ - .module = shader_module, - .entry_point = "frag_main", - .targets = &.{color_target}, - }); - - const pipeline_descriptor = gpu.RenderPipeline.Descriptor{ - .fragment = &fragment, - // Enable depth testing so that the fragment closest to the camera - // is rendered in front. - .depth_stencil = &.{ - .format = .depth24_plus, - .depth_write_enabled = .true, - .depth_compare = .less, - }, - .vertex = gpu.VertexState.init(.{ - .module = shader_module, - .entry_point = "vertex_main", - .buffers = &.{vertex_buffer_layout}, - }), - .primitive = .{ - // Backface culling since the cube is solid piece of geometry. - // Faces pointing away from the camera will be occluded by faces - // pointing toward the camera. - .cull_mode = .back, - }, - }; - const pipeline = core.device.createRenderPipeline(&pipeline_descriptor); - shader_module.release(); - - const vertex_buffer = core.device.createBuffer(&.{ - .usage = .{ .vertex = true }, - .size = @sizeOf(Vertex) * vertices.len, - .mapped_at_creation = .true, - }); - const vertex_mapped = vertex_buffer.getMappedRange(Vertex, 0, vertices.len); - @memcpy(vertex_mapped.?, vertices[0..]); - vertex_buffer.unmap(); - - // Create a sampler with linear filtering for smooth interpolation. - const sampler = core.device.createSampler(&.{ - .mag_filter = .linear, - .min_filter = .linear, - }); - const queue = core.queue; - var img = try zigimg.Image.fromMemory(allocator, assets.gotta_go_fast_png); - defer img.deinit(); - const img_size = gpu.Extent3D{ .width = @as(u32, @intCast(img.width)), .height = @as(u32, @intCast(img.height)) }; - const cube_texture = core.device.createTexture(&.{ - .size = img_size, - .format = .rgba8_unorm, - .usage = .{ - .texture_binding = true, - .copy_dst = true, - .render_attachment = true, - }, - }); - const data_layout = gpu.Texture.DataLayout{ - .bytes_per_row = @as(u32, @intCast(img.width * 4)), - .rows_per_image = @as(u32, @intCast(img.height)), - }; - switch (img.pixels) { - .rgba32 => |pixels| queue.writeTexture(&.{ .texture = cube_texture }, &data_layout, &img_size, pixels), - .rgb24 => |pixels| { - const data = try rgb24ToRgba32(allocator, pixels); - defer data.deinit(allocator); - queue.writeTexture(&.{ .texture = cube_texture }, &data_layout, &img_size, data.rgba32); - }, - else => @panic("unsupported image color format"), - } - - const uniform_buffer = core.device.createBuffer(&.{ - .usage = .{ .copy_dst = true, .uniform = true }, - .size = @sizeOf(UniformBufferObject), - .mapped_at_creation = .false, - }); - - const texture_view = cube_texture.createView(&gpu.TextureView.Descriptor{}); - cube_texture.release(); - - const bind_group_layout = pipeline.getBindGroupLayout(0); - const bind_group = core.device.createBindGroup( - &gpu.BindGroup.Descriptor.init(.{ - .layout = bind_group_layout, - .entries = &.{ - gpu.BindGroup.Entry.buffer(0, uniform_buffer, 0, @sizeOf(UniformBufferObject), @sizeOf(UniformBufferObject)), - gpu.BindGroup.Entry.sampler(1, sampler), - gpu.BindGroup.Entry.textureView(2, texture_view), - }, - }), - ); - sampler.release(); - texture_view.release(); - bind_group_layout.release(); - - const depth_texture = core.device.createTexture(&gpu.Texture.Descriptor{ - .size = gpu.Extent3D{ - .width = core.descriptor.width, - .height = core.descriptor.height, - }, - .format = .depth24_plus, - .usage = .{ - .render_attachment = true, - .texture_binding = true, - }, - }); - - const depth_texture_view = depth_texture.createView(&gpu.TextureView.Descriptor{ - .format = .depth24_plus, - .dimension = .dimension_2d, - .array_layer_count = 1, - .mip_level_count = 1, - }); - - app.timer = try core.Timer.start(); - app.title_timer = try core.Timer.start(); - app.pipeline = pipeline; - app.vertex_buffer = vertex_buffer; - app.uniform_buffer = uniform_buffer; - app.bind_group = bind_group; - app.depth_texture = depth_texture; - app.depth_texture_view = depth_texture_view; -} - -pub fn deinit(app: *App) void { - defer _ = gpa.deinit(); - defer core.deinit(); - - app.pipeline.release(); - app.vertex_buffer.release(); - app.uniform_buffer.release(); - app.bind_group.release(); - app.depth_texture.release(); - app.depth_texture_view.release(); -} - -pub fn update(app: *App) !bool { - var iter = core.pollEvents(); - while (iter.next()) |event| { - switch (event) { - .key_press => |ev| { - switch (ev.key) { - .space => return true, - .one => core.setVSync(.none), - .two => core.setVSync(.double), - .three => core.setVSync(.triple), - else => {}, - } - std.debug.print("vsync mode changed to {s}\n", .{@tagName(core.vsync())}); - }, - .framebuffer_resize => |ev| { - // If window is resized, recreate depth buffer otherwise we cannot use it. - app.depth_texture.release(); - - app.depth_texture = core.device.createTexture(&gpu.Texture.Descriptor{ - .size = gpu.Extent3D{ - .width = ev.width, - .height = ev.height, - }, - .format = .depth24_plus, - .usage = .{ - .render_attachment = true, - .texture_binding = true, - }, - }); - - app.depth_texture_view.release(); - app.depth_texture_view = app.depth_texture.createView(&gpu.TextureView.Descriptor{ - .format = .depth24_plus, - .dimension = .dimension_2d, - .array_layer_count = 1, - .mip_level_count = 1, - }); - }, - .close => return true, - else => {}, - } - } - - const back_buffer_view = core.swap_chain.getCurrentTextureView().?; - const color_attachment = gpu.RenderPassColorAttachment{ - .view = back_buffer_view, - .clear_value = .{ .r = 0.5, .g = 0.5, .b = 0.5, .a = 0.0 }, - .load_op = .clear, - .store_op = .store, - }; - - const encoder = core.device.createCommandEncoder(null); - const render_pass_info = gpu.RenderPassDescriptor.init(.{ - .color_attachments = &.{color_attachment}, - .depth_stencil_attachment = &.{ - .view = app.depth_texture_view, - .depth_clear_value = 1.0, - .depth_load_op = .clear, - .depth_store_op = .store, - }, - }); - - { - const time = app.timer.read(); - const model = zm.mul(zm.rotationX(time * (std.math.pi / 2.0)), zm.rotationZ(time * (std.math.pi / 2.0))); - const view = zm.lookAtRh( - zm.Vec{ 0, 4, 2, 1 }, - zm.Vec{ 0, 0, 0, 1 }, - zm.Vec{ 0, 0, 1, 0 }, - ); - const proj = zm.perspectiveFovRh( - (std.math.pi / 4.0), - @as(f32, @floatFromInt(core.descriptor.width)) / @as(f32, @floatFromInt(core.descriptor.height)), - 0.1, - 10, - ); - const mvp = zm.mul(zm.mul(model, view), proj); - const ubo = UniformBufferObject{ - .mat = zm.transpose(mvp), - }; - encoder.writeBuffer(app.uniform_buffer, 0, &[_]UniformBufferObject{ubo}); - } - - const pass = encoder.beginRenderPass(&render_pass_info); - pass.setPipeline(app.pipeline); - pass.setVertexBuffer(0, app.vertex_buffer, 0, @sizeOf(Vertex) * vertices.len); - pass.setBindGroup(0, app.bind_group, &.{}); - pass.draw(vertices.len, 1, 0, 0); - pass.end(); - pass.release(); - - var command = encoder.finish(null); - encoder.release(); - - const queue = core.queue; - queue.submit(&[_]*gpu.CommandBuffer{command}); - command.release(); - core.swap_chain.present(); - back_buffer_view.release(); - - // update the window title every second - if (app.title_timer.read() >= 1.0) { - app.title_timer.reset(); - try core.printTitle("Textured cube [ {d}fps ] [ Input {d}hz ]", .{ - core.frameRate(), - core.inputRate(), - }); - } - return false; -} - -fn rgb24ToRgba32(allocator: std.mem.Allocator, in: []zigimg.color.Rgb24) !zigimg.color.PixelStorage { - const out = try zigimg.color.PixelStorage.init(allocator, .rgba32, in.len); - var i: usize = 0; - while (i < in.len) : (i += 1) { - out.rgba32[i] = zigimg.color.Rgba32{ .r = in[i].r, .g = in[i].g, .b = in[i].b, .a = 255 }; - } - return out; -} diff --git a/src/core/examples/sysgpu/textured-cube/shader.wgsl b/src/core/examples/sysgpu/textured-cube/shader.wgsl deleted file mode 100644 index 7e8b5422..00000000 --- a/src/core/examples/sysgpu/textured-cube/shader.wgsl +++ /dev/null @@ -1,29 +0,0 @@ -struct Uniforms { - modelViewProjectionMatrix : mat4x4, -}; -@binding(0) @group(0) var uniforms : Uniforms; - -struct VertexOutput { - @builtin(position) Position : vec4, - @location(0) fragUV : vec2, - @location(1) fragPosition: vec4, -}; - -@vertex -fn vertex_main(@location(0) position : vec4, - @location(1) uv : vec2) -> VertexOutput { - var output : VertexOutput; - output.Position = position * uniforms.modelViewProjectionMatrix; - output.fragUV = uv; - output.fragPosition = 0.5 * (position + vec4(1.0, 1.0, 1.0, 1.0)); - return output; -} - -@group(0) @binding(1) var mySampler: sampler; -@group(0) @binding(2) var myTexture: texture_2d; - -@fragment -fn frag_main(@location(0) fragUV: vec2, - @location(1) fragPosition: vec4) -> @location(0) vec4 { - return textureSample(myTexture, mySampler, fragUV); -} \ No newline at end of file diff --git a/src/core/examples/sysgpu/textured-quad/main.zig b/src/core/examples/sysgpu/textured-quad/main.zig deleted file mode 100644 index 7b26d6ad..00000000 --- a/src/core/examples/sysgpu/textured-quad/main.zig +++ /dev/null @@ -1,210 +0,0 @@ -const std = @import("std"); - -const mach = @import("mach"); -const core = mach.core; -const gpu = mach.gpu; - -const zigimg = @import("zigimg"); -const assets = @import("assets"); - -pub const App = @This(); - -const Vertex = extern struct { - pos: @Vector(2, f32), - uv: @Vector(2, f32), -}; - -const vertices = [_]Vertex{ - .{ .pos = .{ -0.5, -0.5 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ 0.5, -0.5 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ 0.5, 0.5 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ -0.5, 0.5 }, .uv = .{ 1, 0 } }, -}; -const index_data = [_]u32{ 0, 1, 2, 2, 3, 0 }; - -// Use experimental sysgpu graphics API -pub const use_sysgpu = true; - -var gpa = std.heap.GeneralPurposeAllocator(.{}){}; - -title_timer: core.Timer, -timer: core.Timer, -pipeline: *gpu.RenderPipeline, -vertex_buffer: *gpu.Buffer, -index_buffer: *gpu.Buffer, -bind_group: *gpu.BindGroup, - -pub fn init(app: *App) !void { - try core.init(.{}); - const allocator = gpa.allocator(); - - const shader_module = core.device.createShaderModuleWGSL("shader.wgsl", @embedFile("shader.wgsl")); - - const vertex_attributes = [_]gpu.VertexAttribute{ - .{ .format = .float32x4, .offset = @offsetOf(Vertex, "pos"), .shader_location = 0 }, - .{ .format = .float32x2, .offset = @offsetOf(Vertex, "uv"), .shader_location = 1 }, - }; - const vertex_buffer_layout = gpu.VertexBufferLayout.init(.{ - .array_stride = @sizeOf(Vertex), - .step_mode = .vertex, - .attributes = &vertex_attributes, - }); - - const blend = gpu.BlendState{}; - const color_target = gpu.ColorTargetState{ - .format = core.descriptor.format, - .blend = &blend, - .write_mask = gpu.ColorWriteMaskFlags.all, - }; - const fragment = gpu.FragmentState.init(.{ - .module = shader_module, - .entry_point = "frag_main", - .targets = &.{color_target}, - }); - const pipeline_descriptor = gpu.RenderPipeline.Descriptor{ - .fragment = &fragment, - .vertex = gpu.VertexState.init(.{ - .module = shader_module, - .entry_point = "vertex_main", - .buffers = &.{vertex_buffer_layout}, - }), - .primitive = .{ .cull_mode = .back }, - }; - const pipeline = core.device.createRenderPipeline(&pipeline_descriptor); - shader_module.release(); - - const vertex_buffer = core.device.createBuffer(&.{ - .usage = .{ .vertex = true }, - .size = @sizeOf(Vertex) * vertices.len, - .mapped_at_creation = .true, - }); - const vertex_mapped = vertex_buffer.getMappedRange(Vertex, 0, vertices.len); - @memcpy(vertex_mapped.?, vertices[0..]); - vertex_buffer.unmap(); - - const index_buffer = core.device.createBuffer(&.{ - .usage = .{ .index = true }, - .size = @sizeOf(u32) * index_data.len, - .mapped_at_creation = .true, - }); - const index_mapped = index_buffer.getMappedRange(u32, 0, index_data.len); - @memcpy(index_mapped.?, index_data[0..]); - index_buffer.unmap(); - - const sampler = core.device.createSampler(&.{ .mag_filter = .linear, .min_filter = .linear }); - const queue = core.queue; - var img = try zigimg.Image.fromMemory(allocator, assets.gotta_go_fast_png); - defer img.deinit(); - const img_size = gpu.Extent3D{ - .width = @as(u32, @intCast(img.width)), - .height = @as(u32, @intCast(img.height)), - }; - const texture = core.device.createTexture(&.{ - .size = img_size, - .format = .rgba8_unorm, - .usage = .{ - .texture_binding = true, - .copy_dst = true, - .render_attachment = true, - }, - }); - const data_layout = gpu.Texture.DataLayout{ - .bytes_per_row = @as(u32, @intCast(img.width * 4)), - .rows_per_image = @as(u32, @intCast(img.height)), - }; - switch (img.pixels) { - .rgba32 => |pixels| queue.writeTexture(&.{ .texture = texture }, &data_layout, &img_size, pixels), - .rgb24 => |pixels| { - const data = try rgb24ToRgba32(allocator, pixels); - defer data.deinit(allocator); - queue.writeTexture(&.{ .texture = texture }, &data_layout, &img_size, data.rgba32); - }, - else => @panic("unsupported image color format"), - } - - const texture_view = texture.createView(&gpu.TextureView.Descriptor{}); - texture.release(); - - const bind_group_layout = pipeline.getBindGroupLayout(0); - const bind_group = core.device.createBindGroup( - &gpu.BindGroup.Descriptor.init(.{ - .layout = bind_group_layout, - .entries = &.{ - gpu.BindGroup.Entry.sampler(0, sampler), - gpu.BindGroup.Entry.textureView(1, texture_view), - }, - }), - ); - sampler.release(); - texture_view.release(); - bind_group_layout.release(); - - app.timer = try core.Timer.start(); - app.title_timer = try core.Timer.start(); - app.pipeline = pipeline; - app.vertex_buffer = vertex_buffer; - app.index_buffer = index_buffer; - app.bind_group = bind_group; -} - -pub fn deinit(app: *App) void { - app.pipeline.release(); - app.vertex_buffer.release(); - app.index_buffer.release(); - app.bind_group.release(); - core.deinit(); - _ = gpa.deinit(); -} - -pub fn update(app: *App) !bool { - var iter = core.pollEvents(); - while (iter.next()) |event| if (event == .close) return true; - - const back_buffer_view = core.swap_chain.getCurrentTextureView().?; - const color_attachment = gpu.RenderPassColorAttachment{ - .view = back_buffer_view, - .clear_value = .{ .r = 0, .g = 0, .b = 0, .a = 0.0 }, - .load_op = .clear, - .store_op = .store, - }; - - const encoder = core.device.createCommandEncoder(null); - const render_pass_info = gpu.RenderPassDescriptor.init(.{ .color_attachments = &.{color_attachment} }); - - const pass = encoder.beginRenderPass(&render_pass_info); - pass.setPipeline(app.pipeline); - pass.setVertexBuffer(0, app.vertex_buffer, 0, @sizeOf(Vertex) * vertices.len); - pass.setIndexBuffer(app.index_buffer, .uint32, 0, @sizeOf(u32) * index_data.len); - pass.setBindGroup(0, app.bind_group, &.{}); - pass.drawIndexed(index_data.len, 1, 0, 0, 0); - pass.end(); - pass.release(); - - var command = encoder.finish(null); - encoder.release(); - - const queue = core.queue; - queue.submit(&[_]*gpu.CommandBuffer{command}); - command.release(); - core.swap_chain.present(); - back_buffer_view.release(); - - // update the window title every second - if (app.title_timer.read() >= 1.0) { - app.title_timer.reset(); - try core.printTitle("Textured Quad [ {d}fps ] [ Input {d}hz ]", .{ - core.frameRate(), - core.inputRate(), - }); - } - return false; -} - -fn rgb24ToRgba32(allocator: std.mem.Allocator, in: []zigimg.color.Rgb24) !zigimg.color.PixelStorage { - const out = try zigimg.color.PixelStorage.init(allocator, .rgba32, in.len); - var i: usize = 0; - while (i < in.len) : (i += 1) { - out.rgba32[i] = zigimg.color.Rgba32{ .r = in[i].r, .g = in[i].g, .b = in[i].b, .a = 255 }; - } - return out; -} diff --git a/src/core/examples/sysgpu/textured-quad/shader.wgsl b/src/core/examples/sysgpu/textured-quad/shader.wgsl deleted file mode 100644 index 3328340b..00000000 --- a/src/core/examples/sysgpu/textured-quad/shader.wgsl +++ /dev/null @@ -1,21 +0,0 @@ -struct VertexOutput { - @builtin(position) Position : vec4, - @location(0) fragUV : vec2, -}; - -@vertex -fn vertex_main(@location(0) position : vec2, - @location(1) uv : vec2) -> VertexOutput { - var output : VertexOutput; - output.Position = vec4(position, 0, 1); - output.fragUV = uv; - return output; -} - -@group(0) @binding(0) var mySampler: sampler; -@group(0) @binding(1) var myTexture: texture_2d; - -@fragment -fn frag_main(@location(0) fragUV: vec2) -> @location(0) vec4 { - return textureSample(myTexture, mySampler, fragUV); -} \ No newline at end of file diff --git a/src/core/examples/sysgpu/triangle-msaa/main.zig b/src/core/examples/sysgpu/triangle-msaa/main.zig deleted file mode 100644 index 60d7d844..00000000 --- a/src/core/examples/sysgpu/triangle-msaa/main.zig +++ /dev/null @@ -1,133 +0,0 @@ -const std = @import("std"); - -const mach = @import("mach"); -const core = mach.core; -const gpu = mach.gpu; - -pub const App = @This(); - -// Use experimental sysgpu graphics API -pub const use_sysgpu = true; - -title_timer: core.Timer, -pipeline: *gpu.RenderPipeline, -texture: *gpu.Texture, -texture_view: *gpu.TextureView, - -const sample_count = 4; - -pub fn init(app: *App) !void { - try core.init(.{}); - app.title_timer = try core.Timer.start(); - - const shader_module = core.device.createShaderModuleWGSL("shader.wgsl", @embedFile("shader.wgsl")); - defer shader_module.release(); - - // Fragment state - const blend = gpu.BlendState{}; - const color_target = gpu.ColorTargetState{ - .format = core.descriptor.format, - .blend = &blend, - .write_mask = gpu.ColorWriteMaskFlags.all, - }; - const fragment = gpu.FragmentState.init(.{ - .module = shader_module, - .entry_point = "frag_main", - .targets = &.{color_target}, - }); - const pipeline_descriptor = gpu.RenderPipeline.Descriptor{ - .fragment = &fragment, - .vertex = gpu.VertexState{ - .module = shader_module, - .entry_point = "vertex_main", - }, - .multisample = gpu.MultisampleState{ - .count = sample_count, - }, - }; - - app.pipeline = core.device.createRenderPipeline(&pipeline_descriptor); - - app.texture = core.device.createTexture(&gpu.Texture.Descriptor{ - .size = gpu.Extent3D{ - .width = core.descriptor.width, - .height = core.descriptor.height, - }, - .sample_count = sample_count, - .format = core.descriptor.format, - .usage = .{ .render_attachment = true }, - }); - app.texture_view = app.texture.createView(null); -} - -pub fn deinit(app: *App) void { - defer core.deinit(); - - app.pipeline.release(); - app.texture.release(); - app.texture_view.release(); -} - -pub fn update(app: *App) !bool { - var iter = core.pollEvents(); - while (iter.next()) |event| { - switch (event) { - .framebuffer_resize => |size| { - app.texture.release(); - app.texture = core.device.createTexture(&gpu.Texture.Descriptor{ - .size = gpu.Extent3D{ - .width = size.width, - .height = size.height, - }, - .sample_count = sample_count, - .format = core.descriptor.format, - .usage = .{ .render_attachment = true }, - }); - - app.texture_view.release(); - app.texture_view = app.texture.createView(null); - }, - .close => return true, - else => {}, - } - } - - const back_buffer_view = core.swap_chain.getCurrentTextureView().?; - const color_attachment = gpu.RenderPassColorAttachment{ - .view = app.texture_view, - .resolve_target = back_buffer_view, - .clear_value = std.mem.zeroes(gpu.Color), - .load_op = .clear, - .store_op = .discard, - }; - - const encoder = core.device.createCommandEncoder(null); - const render_pass_info = gpu.RenderPassDescriptor.init(.{ - .color_attachments = &.{color_attachment}, - }); - const pass = encoder.beginRenderPass(&render_pass_info); - pass.setPipeline(app.pipeline); - pass.draw(3, 1, 0, 0); - pass.end(); - pass.release(); - - var command = encoder.finish(null); - encoder.release(); - - const queue = core.queue; - queue.submit(&[_]*gpu.CommandBuffer{command}); - command.release(); - core.swap_chain.present(); - back_buffer_view.release(); - - // update the window title every second - if (app.title_timer.read() >= 1.0) { - app.title_timer.reset(); - try core.printTitle("Triangle MSAA [ {d}fps ] [ Input {d}hz ]", .{ - core.frameRate(), - core.inputRate(), - }); - } - - return false; -} diff --git a/src/core/examples/sysgpu/triangle-msaa/shader.wgsl b/src/core/examples/sysgpu/triangle-msaa/shader.wgsl deleted file mode 100644 index 429d87e0..00000000 --- a/src/core/examples/sysgpu/triangle-msaa/shader.wgsl +++ /dev/null @@ -1,14 +0,0 @@ -@vertex fn vertex_main( - @builtin(vertex_index) VertexIndex : u32 -) -> @builtin(position) vec4 { - var pos = array, 3>( - vec2( 0.0, 0.5), - vec2(-0.5, -0.5), - vec2( 0.5, -0.5) - ); - return vec4(pos[VertexIndex], 0.0, 1.0); -} - -@fragment fn frag_main() -> @location(0) vec4 { - return vec4(1.0, 0.0, 0.0, 1.0); -} diff --git a/src/core/examples/sysgpu/triangle/main.zig b/src/core/examples/sysgpu/triangle/main.zig deleted file mode 100644 index a52e4d53..00000000 --- a/src/core/examples/sysgpu/triangle/main.zig +++ /dev/null @@ -1,96 +0,0 @@ -const std = @import("std"); - -const mach = @import("mach"); -const core = mach.core; -const gpu = mach.gpu; - -pub const App = @This(); - -// Use experimental sysgpu graphics API -pub const use_sysgpu = true; - -title_timer: core.Timer, -pipeline: *gpu.RenderPipeline, - -pub fn init(app: *App) !void { - try core.init(.{}); - - const shader_module = core.device.createShaderModuleWGSL("shader.wgsl", @embedFile("shader.wgsl")); - defer shader_module.release(); - - // Fragment state - const blend = gpu.BlendState{}; - const color_target = gpu.ColorTargetState{ - .format = core.descriptor.format, - .blend = &blend, - .write_mask = gpu.ColorWriteMaskFlags.all, - }; - const fragment = gpu.FragmentState.init(.{ - .module = shader_module, - .entry_point = "frag_main", - .targets = &.{color_target}, - }); - const pipeline_descriptor = gpu.RenderPipeline.Descriptor{ - .fragment = &fragment, - .vertex = gpu.VertexState{ - .module = shader_module, - .entry_point = "vertex_main", - }, - }; - const pipeline = core.device.createRenderPipeline(&pipeline_descriptor); - - app.* = .{ .title_timer = try core.Timer.start(), .pipeline = pipeline }; -} - -pub fn deinit(app: *App) void { - defer core.deinit(); - app.pipeline.release(); -} - -pub fn update(app: *App) !bool { - var iter = core.pollEvents(); - while (iter.next()) |event| { - switch (event) { - .close => return true, - else => {}, - } - } - - const queue = core.queue; - const back_buffer_view = core.swap_chain.getCurrentTextureView().?; - const color_attachment = gpu.RenderPassColorAttachment{ - .view = back_buffer_view, - .clear_value = std.mem.zeroes(gpu.Color), - .load_op = .clear, - .store_op = .store, - }; - - const encoder = core.device.createCommandEncoder(null); - const render_pass_info = gpu.RenderPassDescriptor.init(.{ - .color_attachments = &.{color_attachment}, - }); - const pass = encoder.beginRenderPass(&render_pass_info); - pass.setPipeline(app.pipeline); - pass.draw(3, 1, 0, 0); - pass.end(); - pass.release(); - - var command = encoder.finish(null); - encoder.release(); - - queue.submit(&[_]*gpu.CommandBuffer{command}); - command.release(); - core.swap_chain.present(); - back_buffer_view.release(); - - // update the window title every second - if (app.title_timer.read() >= 1.0) { - app.title_timer.reset(); - try core.printTitle("Triangle [ {d}fps ] [ Input {d}hz ]", .{ - core.frameRate(), - core.inputRate(), - }); - } - - return false; -} diff --git a/src/core/examples/sysgpu/triangle/shader.wgsl b/src/core/examples/sysgpu/triangle/shader.wgsl deleted file mode 100644 index 429d87e0..00000000 --- a/src/core/examples/sysgpu/triangle/shader.wgsl +++ /dev/null @@ -1,14 +0,0 @@ -@vertex fn vertex_main( - @builtin(vertex_index) VertexIndex : u32 -) -> @builtin(position) vec4 { - var pos = array, 3>( - vec2( 0.0, 0.5), - vec2(-0.5, -0.5), - vec2( 0.5, -0.5) - ); - return vec4(pos[VertexIndex], 0.0, 1.0); -} - -@fragment fn frag_main() -> @location(0) vec4 { - return vec4(1.0, 0.0, 0.0, 1.0); -} diff --git a/src/core/examples/sysgpu/two-cubes/cube_mesh.zig b/src/core/examples/sysgpu/two-cubes/cube_mesh.zig deleted file mode 100644 index f26c75ac..00000000 --- a/src/core/examples/sysgpu/two-cubes/cube_mesh.zig +++ /dev/null @@ -1,49 +0,0 @@ -pub const Vertex = extern struct { - pos: @Vector(4, f32), - col: @Vector(4, f32), - uv: @Vector(2, f32), -}; - -pub const vertices = [_]Vertex{ - .{ .pos = .{ 1, -1, 1, 1 }, .col = .{ 1, 0, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, -1, -1, 1 }, .col = .{ 0, 0, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, -1, 1, 1 }, .col = .{ 1, 0, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, -1, -1, 1 }, .col = .{ 0, 0, 0, 1 }, .uv = .{ 0, 0 } }, - - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ 1, -1, 1, 1 }, .col = .{ 1, 0, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, 1, -1, 1 }, .col = .{ 1, 1, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 0, 0 } }, - - .{ .pos = .{ -1, 1, 1, 1 }, .col = .{ 0, 1, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ 1, 1, -1, 1 }, .col = .{ 1, 1, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ -1, 1, 1, 1 }, .col = .{ 0, 1, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ 1, 1, -1, 1 }, .col = .{ 1, 1, 0, 1 }, .uv = .{ 0, 0 } }, - - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, 1, 1, 1 }, .col = .{ 0, 1, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ -1, -1, -1, 1 }, .col = .{ 0, 0, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 0, 0 } }, - - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, 1, 1, 1 }, .col = .{ 0, 1, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, -1, 1, 1 }, .col = .{ 1, 0, 1, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 1, 1 } }, - - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, -1, -1, 1 }, .col = .{ 0, 0, 0, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, 1, -1, 1 }, .col = .{ 1, 1, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 0, 0 } }, -}; diff --git a/src/core/examples/sysgpu/two-cubes/main.zig b/src/core/examples/sysgpu/two-cubes/main.zig deleted file mode 100644 index 9acdea56..00000000 --- a/src/core/examples/sysgpu/two-cubes/main.zig +++ /dev/null @@ -1,229 +0,0 @@ -const std = @import("std"); - -const mach = @import("mach"); -const core = mach.core; -const gpu = mach.gpu; - -const zm = @import("zmath"); -const Vertex = @import("cube_mesh.zig").Vertex; -const vertices = @import("cube_mesh.zig").vertices; - -const UniformBufferObject = struct { - mat: zm.Mat, -}; - -var gpa = std.heap.GeneralPurposeAllocator(.{}){}; - -title_timer: core.Timer, -timer: core.Timer, -pipeline: *gpu.RenderPipeline, -vertex_buffer: *gpu.Buffer, -uniform_buffer: *gpu.Buffer, -bind_group1: *gpu.BindGroup, -bind_group2: *gpu.BindGroup, - -pub const App = @This(); - -// Use experimental sysgpu graphics API -pub const use_sysgpu = true; - -pub fn init(app: *App) !void { - try core.init(.{}); - app.title_timer = try core.Timer.start(); - app.timer = try core.Timer.start(); - - const shader_module = core.device.createShaderModuleWGSL("shader.wgsl", @embedFile("shader.wgsl")); - - const vertex_attributes = [_]gpu.VertexAttribute{ - .{ .format = .float32x4, .offset = @offsetOf(Vertex, "pos"), .shader_location = 0 }, - .{ .format = .float32x2, .offset = @offsetOf(Vertex, "uv"), .shader_location = 1 }, - }; - const vertex_buffer_layout = gpu.VertexBufferLayout.init(.{ - .array_stride = @sizeOf(Vertex), - .step_mode = .vertex, - .attributes = &vertex_attributes, - }); - - const blend = gpu.BlendState{}; - const color_target = gpu.ColorTargetState{ - .format = core.descriptor.format, - .blend = &blend, - .write_mask = gpu.ColorWriteMaskFlags.all, - }; - const fragment = gpu.FragmentState.init(.{ - .module = shader_module, - .entry_point = "frag_main", - .targets = &.{color_target}, - }); - - const bgle = gpu.BindGroupLayout.Entry.buffer(0, .{ .vertex = true }, .uniform, true, 0); - const bgl = core.device.createBindGroupLayout( - &gpu.BindGroupLayout.Descriptor.init(.{ - .entries = &.{bgle}, - }), - ); - - const bind_group_layouts = [_]*gpu.BindGroupLayout{bgl}; - const pipeline_layout = core.device.createPipelineLayout(&gpu.PipelineLayout.Descriptor.init(.{ - .bind_group_layouts = &bind_group_layouts, - })); - - const pipeline_descriptor = gpu.RenderPipeline.Descriptor{ - .fragment = &fragment, - .layout = pipeline_layout, - .vertex = gpu.VertexState.init(.{ - .module = shader_module, - .entry_point = "vertex_main", - .buffers = &.{vertex_buffer_layout}, - }), - .primitive = .{ - .cull_mode = .back, - }, - }; - - const vertex_buffer = core.device.createBuffer(&.{ - .usage = .{ .vertex = true }, - .size = @sizeOf(Vertex) * vertices.len, - .mapped_at_creation = .true, - }); - const vertex_mapped = vertex_buffer.getMappedRange(Vertex, 0, vertices.len); - @memcpy(vertex_mapped.?, vertices[0..]); - vertex_buffer.unmap(); - - // uniformBindGroup offset must be 256-byte aligned - const uniform_offset = 256; - const uniform_buffer = core.device.createBuffer(&.{ - .usage = .{ .uniform = true, .copy_dst = true }, - .size = @sizeOf(UniformBufferObject) + uniform_offset, - .mapped_at_creation = .false, - }); - - const bind_group1 = core.device.createBindGroup( - &gpu.BindGroup.Descriptor.init(.{ - .layout = bgl, - .entries = &.{ - gpu.BindGroup.Entry.buffer(0, uniform_buffer, 0, @sizeOf(UniformBufferObject), @sizeOf(UniformBufferObject)), - }, - }), - ); - - const bind_group2 = core.device.createBindGroup( - &gpu.BindGroup.Descriptor.init(.{ - .layout = bgl, - .entries = &.{ - gpu.BindGroup.Entry.buffer(0, uniform_buffer, uniform_offset, @sizeOf(UniformBufferObject), @sizeOf(UniformBufferObject)), - }, - }), - ); - - app.pipeline = core.device.createRenderPipeline(&pipeline_descriptor); - app.vertex_buffer = vertex_buffer; - app.uniform_buffer = uniform_buffer; - app.bind_group1 = bind_group1; - app.bind_group2 = bind_group2; - - shader_module.release(); - pipeline_layout.release(); - bgl.release(); -} - -pub fn deinit(app: *App) void { - defer _ = gpa.deinit(); - defer core.deinit(); - - app.pipeline.release(); - app.vertex_buffer.release(); - app.uniform_buffer.release(); - app.bind_group1.release(); - app.bind_group2.release(); -} - -pub fn update(app: *App) !bool { - var iter = core.pollEvents(); - while (iter.next()) |event| { - switch (event) { - .key_press => |ev| { - if (ev.key == .space) return true; - }, - .close => return true, - else => {}, - } - } - - const back_buffer_view = core.swap_chain.getCurrentTextureView().?; - const color_attachment = gpu.RenderPassColorAttachment{ - .view = back_buffer_view, - .clear_value = std.mem.zeroes(gpu.Color), - .load_op = .clear, - .store_op = .store, - }; - - const encoder = core.device.createCommandEncoder(null); - const render_pass_info = gpu.RenderPassDescriptor.init(.{ - .color_attachments = &.{color_attachment}, - }); - - { - const time = app.timer.read(); - const rotation1 = zm.mul(zm.rotationX(time * (std.math.pi / 2.0)), zm.rotationZ(time * (std.math.pi / 2.0))); - const rotation2 = zm.mul(zm.rotationZ(time * (std.math.pi / 2.0)), zm.rotationX(time * (std.math.pi / 2.0))); - const model1 = zm.mul(rotation1, zm.translation(-2, 0, 0)); - const model2 = zm.mul(rotation2, zm.translation(2, 0, 0)); - const view = zm.lookAtRh( - zm.Vec{ 0, -4, 2, 1 }, - zm.Vec{ 0, 0, 0, 1 }, - zm.Vec{ 0, 0, 1, 0 }, - ); - const proj = zm.perspectiveFovRh( - (2.0 * std.math.pi / 5.0), - @as(f32, @floatFromInt(core.descriptor.width)) / @as(f32, @floatFromInt(core.descriptor.height)), - 1, - 100, - ); - const mvp1 = zm.mul(zm.mul(model1, view), proj); - const mvp2 = zm.mul(zm.mul(model2, view), proj); - const ubo1 = UniformBufferObject{ - .mat = zm.transpose(mvp1), - }; - const ubo2 = UniformBufferObject{ - .mat = zm.transpose(mvp2), - }; - - core.queue.writeBuffer(app.uniform_buffer, 0, &[_]UniformBufferObject{ubo1}); - - // bind_group2 offset - core.queue.writeBuffer(app.uniform_buffer, 256, &[_]UniformBufferObject{ubo2}); - } - - const pass = encoder.beginRenderPass(&render_pass_info); - pass.setPipeline(app.pipeline); - pass.setVertexBuffer(0, app.vertex_buffer, 0, @sizeOf(Vertex) * vertices.len); - - pass.setBindGroup(0, app.bind_group1, &.{0}); - pass.draw(vertices.len, 1, 0, 0); - pass.setBindGroup(0, app.bind_group2, &.{0}); - pass.draw(vertices.len, 1, 0, 0); - - pass.end(); - pass.release(); - - var command = encoder.finish(null); - encoder.release(); - - const queue = core.queue; - queue.submit(&[_]*gpu.CommandBuffer{command}); - command.release(); - core.swap_chain.present(); - back_buffer_view.release(); - - // update the window title every second - if (app.title_timer.read() >= 1.0) { - app.title_timer.reset(); - try core.printTitle("Two Cubes [ {d}fps ] [ Input {d}hz ]", .{ - core.frameRate(), - core.inputRate(), - }); - } - - return false; -} diff --git a/src/core/examples/sysgpu/two-cubes/shader.wgsl b/src/core/examples/sysgpu/two-cubes/shader.wgsl deleted file mode 100644 index 05384f41..00000000 --- a/src/core/examples/sysgpu/two-cubes/shader.wgsl +++ /dev/null @@ -1,24 +0,0 @@ -@group(0) @binding(0) var ubo : mat4x4; -struct VertexOut { - @builtin(position) position_clip : vec4, - @location(0) fragUV : vec2, - @location(1) fragPosition: vec4, -} - -@vertex fn vertex_main( - @location(0) position : vec4, - @location(1) uv: vec2 -) -> VertexOut { - var output : VertexOut; - output.position_clip = position * ubo; - output.fragUV = uv; - output.fragPosition = 0.5 * (position + vec4(1.0, 1.0, 1.0, 1.0)); - return output; -} - -@fragment fn frag_main( - @location(0) fragUV: vec2, - @location(1) fragPosition: vec4 -) -> @location(0) vec4 { - return fragPosition; -} diff --git a/src/core/examples/textured-cube/cube_mesh.zig b/src/core/examples/textured-cube/cube_mesh.zig deleted file mode 100644 index ae5b2912..00000000 --- a/src/core/examples/textured-cube/cube_mesh.zig +++ /dev/null @@ -1,49 +0,0 @@ -pub const Vertex = extern struct { - pos: @Vector(4, f32), - col: @Vector(4, f32), - uv: @Vector(2, f32), -}; - -pub const vertices = [_]Vertex{ - .{ .pos = .{ 1, -1, 1, 1 }, .col = .{ 1, 0, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, -1, -1, 1 }, .col = .{ 0, 0, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, -1, 1, 1 }, .col = .{ 1, 0, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, -1, -1, 1 }, .col = .{ 0, 0, 0, 1 }, .uv = .{ 1, 0 } }, - - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ 1, -1, 1, 1 }, .col = .{ 1, 0, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, 1, -1, 1 }, .col = .{ 1, 1, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 1, 0 } }, - - .{ .pos = .{ -1, 1, 1, 1 }, .col = .{ 0, 1, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ 1, 1, -1, 1 }, .col = .{ 1, 1, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ -1, 1, 1, 1 }, .col = .{ 0, 1, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ 1, 1, -1, 1 }, .col = .{ 1, 1, 0, 1 }, .uv = .{ 1, 0 } }, - - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, 1, 1, 1 }, .col = .{ 0, 1, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ -1, -1, -1, 1 }, .col = .{ 0, 0, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 1, 0 } }, - - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, 1, 1, 1 }, .col = .{ 0, 1, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, -1, 1, 1 }, .col = .{ 1, 0, 1, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 0, 1 } }, - - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, -1, -1, 1 }, .col = .{ 0, 0, 0, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, 1, -1, 1 }, .col = .{ 1, 1, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 1, 0 } }, -}; diff --git a/src/core/examples/textured-cube/main.zig b/src/core/examples/textured-cube/main.zig deleted file mode 100644 index 0c6a1251..00000000 --- a/src/core/examples/textured-cube/main.zig +++ /dev/null @@ -1,316 +0,0 @@ -const std = @import("std"); - -const mach = @import("mach"); -const core = mach.core; -const gpu = mach.gpu; - -const zm = @import("zmath"); -const zigimg = @import("zigimg"); -const Vertex = @import("cube_mesh.zig").Vertex; -const vertices = @import("cube_mesh.zig").vertices; -const assets = @import("assets"); - -pub const App = @This(); - -const UniformBufferObject = struct { - mat: zm.Mat, -}; -var gpa = std.heap.GeneralPurposeAllocator(.{}){}; - -title_timer: core.Timer, -timer: core.Timer, -pipeline: *gpu.RenderPipeline, -vertex_buffer: *gpu.Buffer, -uniform_buffer: *gpu.Buffer, -bind_group: *gpu.BindGroup, -depth_texture: *gpu.Texture, -depth_texture_view: *gpu.TextureView, - -pub fn init(app: *App) !void { - try core.init(.{}); - const allocator = gpa.allocator(); - - const shader_module = core.device.createShaderModuleWGSL("shader.wgsl", @embedFile("shader.wgsl")); - - const vertex_attributes = [_]gpu.VertexAttribute{ - .{ .format = .float32x4, .offset = @offsetOf(Vertex, "pos"), .shader_location = 0 }, - .{ .format = .float32x2, .offset = @offsetOf(Vertex, "uv"), .shader_location = 1 }, - }; - const vertex_buffer_layout = gpu.VertexBufferLayout.init(.{ - .array_stride = @sizeOf(Vertex), - .step_mode = .vertex, - .attributes = &vertex_attributes, - }); - - const blend = gpu.BlendState{ - .color = .{ - .operation = .add, - .src_factor = .src_alpha, - .dst_factor = .one_minus_src_alpha, - }, - .alpha = .{ - .operation = .add, - .src_factor = .one, - .dst_factor = .zero, - }, - }; - const color_target = gpu.ColorTargetState{ - .format = core.descriptor.format, - .blend = &blend, - .write_mask = gpu.ColorWriteMaskFlags.all, - }; - const fragment = gpu.FragmentState.init(.{ - .module = shader_module, - .entry_point = "frag_main", - .targets = &.{color_target}, - }); - - const pipeline_descriptor = gpu.RenderPipeline.Descriptor{ - .fragment = &fragment, - // Enable depth testing so that the fragment closest to the camera - // is rendered in front. - .depth_stencil = &.{ - .format = .depth24_plus, - .depth_write_enabled = .true, - .depth_compare = .less, - }, - .vertex = gpu.VertexState.init(.{ - .module = shader_module, - .entry_point = "vertex_main", - .buffers = &.{vertex_buffer_layout}, - }), - .primitive = .{ - // Backface culling since the cube is solid piece of geometry. - // Faces pointing away from the camera will be occluded by faces - // pointing toward the camera. - .cull_mode = .back, - }, - }; - const pipeline = core.device.createRenderPipeline(&pipeline_descriptor); - shader_module.release(); - - const vertex_buffer = core.device.createBuffer(&.{ - .usage = .{ .vertex = true }, - .size = @sizeOf(Vertex) * vertices.len, - .mapped_at_creation = .true, - }); - const vertex_mapped = vertex_buffer.getMappedRange(Vertex, 0, vertices.len); - @memcpy(vertex_mapped.?, vertices[0..]); - vertex_buffer.unmap(); - - // Create a sampler with linear filtering for smooth interpolation. - const sampler = core.device.createSampler(&.{ - .mag_filter = .linear, - .min_filter = .linear, - }); - const queue = core.queue; - var img = try zigimg.Image.fromMemory(allocator, assets.gotta_go_fast_png); - defer img.deinit(); - const img_size = gpu.Extent3D{ .width = @as(u32, @intCast(img.width)), .height = @as(u32, @intCast(img.height)) }; - const cube_texture = core.device.createTexture(&.{ - .size = img_size, - .format = .rgba8_unorm, - .usage = .{ - .texture_binding = true, - .copy_dst = true, - .render_attachment = true, - }, - }); - const data_layout = gpu.Texture.DataLayout{ - .bytes_per_row = @as(u32, @intCast(img.width * 4)), - .rows_per_image = @as(u32, @intCast(img.height)), - }; - switch (img.pixels) { - .rgba32 => |pixels| queue.writeTexture(&.{ .texture = cube_texture }, &data_layout, &img_size, pixels), - .rgb24 => |pixels| { - const data = try rgb24ToRgba32(allocator, pixels); - defer data.deinit(allocator); - queue.writeTexture(&.{ .texture = cube_texture }, &data_layout, &img_size, data.rgba32); - }, - else => @panic("unsupported image color format"), - } - - const uniform_buffer = core.device.createBuffer(&.{ - .usage = .{ .copy_dst = true, .uniform = true }, - .size = @sizeOf(UniformBufferObject), - .mapped_at_creation = .false, - }); - - const texture_view = cube_texture.createView(&gpu.TextureView.Descriptor{}); - cube_texture.release(); - - const bind_group_layout = pipeline.getBindGroupLayout(0); - const bind_group = core.device.createBindGroup( - &gpu.BindGroup.Descriptor.init(.{ - .layout = bind_group_layout, - .entries = &.{ - gpu.BindGroup.Entry.buffer(0, uniform_buffer, 0, @sizeOf(UniformBufferObject)), - gpu.BindGroup.Entry.sampler(1, sampler), - gpu.BindGroup.Entry.textureView(2, texture_view), - }, - }), - ); - sampler.release(); - texture_view.release(); - bind_group_layout.release(); - - const depth_texture = core.device.createTexture(&gpu.Texture.Descriptor{ - .size = gpu.Extent3D{ - .width = core.descriptor.width, - .height = core.descriptor.height, - }, - .format = .depth24_plus, - .usage = .{ - .render_attachment = true, - .texture_binding = true, - }, - }); - - const depth_texture_view = depth_texture.createView(&gpu.TextureView.Descriptor{ - .format = .depth24_plus, - .dimension = .dimension_2d, - .array_layer_count = 1, - .mip_level_count = 1, - }); - - app.timer = try core.Timer.start(); - app.title_timer = try core.Timer.start(); - app.pipeline = pipeline; - app.vertex_buffer = vertex_buffer; - app.uniform_buffer = uniform_buffer; - app.bind_group = bind_group; - app.depth_texture = depth_texture; - app.depth_texture_view = depth_texture_view; -} - -pub fn deinit(app: *App) void { - defer _ = gpa.deinit(); - defer core.deinit(); - - app.pipeline.release(); - app.vertex_buffer.release(); - app.uniform_buffer.release(); - app.bind_group.release(); - app.depth_texture.release(); - app.depth_texture_view.release(); -} - -pub fn update(app: *App) !bool { - var iter = core.pollEvents(); - while (iter.next()) |event| { - switch (event) { - .key_press => |ev| { - switch (ev.key) { - .space => return true, - .one => core.setVSync(.none), - .two => core.setVSync(.double), - .three => core.setVSync(.triple), - else => {}, - } - std.debug.print("vsync mode changed to {s}\n", .{@tagName(core.vsync())}); - }, - .framebuffer_resize => |ev| { - // If window is resized, recreate depth buffer otherwise we cannot use it. - app.depth_texture.release(); - - app.depth_texture = core.device.createTexture(&gpu.Texture.Descriptor{ - .size = gpu.Extent3D{ - .width = ev.width, - .height = ev.height, - }, - .format = .depth24_plus, - .usage = .{ - .render_attachment = true, - .texture_binding = true, - }, - }); - - app.depth_texture_view.release(); - app.depth_texture_view = app.depth_texture.createView(&gpu.TextureView.Descriptor{ - .format = .depth24_plus, - .dimension = .dimension_2d, - .array_layer_count = 1, - .mip_level_count = 1, - }); - }, - .close => return true, - else => {}, - } - } - - const back_buffer_view = core.swap_chain.getCurrentTextureView().?; - const color_attachment = gpu.RenderPassColorAttachment{ - .view = back_buffer_view, - .clear_value = .{ .r = 0.5, .g = 0.5, .b = 0.5, .a = 0.0 }, - .load_op = .clear, - .store_op = .store, - }; - - const encoder = core.device.createCommandEncoder(null); - const render_pass_info = gpu.RenderPassDescriptor.init(.{ - .color_attachments = &.{color_attachment}, - .depth_stencil_attachment = &.{ - .view = app.depth_texture_view, - .depth_clear_value = 1.0, - .depth_load_op = .clear, - .depth_store_op = .store, - }, - }); - - { - const time = app.timer.read(); - const model = zm.mul(zm.rotationX(time * (std.math.pi / 2.0)), zm.rotationZ(time * (std.math.pi / 2.0))); - const view = zm.lookAtRh( - zm.Vec{ 0, 4, 2, 1 }, - zm.Vec{ 0, 0, 0, 1 }, - zm.Vec{ 0, 0, 1, 0 }, - ); - const proj = zm.perspectiveFovRh( - (std.math.pi / 4.0), - @as(f32, @floatFromInt(core.descriptor.width)) / @as(f32, @floatFromInt(core.descriptor.height)), - 0.1, - 10, - ); - const mvp = zm.mul(zm.mul(model, view), proj); - const ubo = UniformBufferObject{ - .mat = zm.transpose(mvp), - }; - encoder.writeBuffer(app.uniform_buffer, 0, &[_]UniformBufferObject{ubo}); - } - - const pass = encoder.beginRenderPass(&render_pass_info); - pass.setPipeline(app.pipeline); - pass.setVertexBuffer(0, app.vertex_buffer, 0, @sizeOf(Vertex) * vertices.len); - pass.setBindGroup(0, app.bind_group, &.{}); - pass.draw(vertices.len, 1, 0, 0); - pass.end(); - pass.release(); - - var command = encoder.finish(null); - encoder.release(); - - const queue = core.queue; - queue.submit(&[_]*gpu.CommandBuffer{command}); - command.release(); - core.swap_chain.present(); - back_buffer_view.release(); - - // update the window title every second - if (app.title_timer.read() >= 1.0) { - app.title_timer.reset(); - try core.printTitle("Textured cube [ {d}fps ] [ Input {d}hz ]", .{ - core.frameRate(), - core.inputRate(), - }); - } - return false; -} - -fn rgb24ToRgba32(allocator: std.mem.Allocator, in: []zigimg.color.Rgb24) !zigimg.color.PixelStorage { - const out = try zigimg.color.PixelStorage.init(allocator, .rgba32, in.len); - var i: usize = 0; - while (i < in.len) : (i += 1) { - out.rgba32[i] = zigimg.color.Rgba32{ .r = in[i].r, .g = in[i].g, .b = in[i].b, .a = 255 }; - } - return out; -} diff --git a/src/core/examples/textured-cube/shader.wgsl b/src/core/examples/textured-cube/shader.wgsl deleted file mode 100644 index 7e8b5422..00000000 --- a/src/core/examples/textured-cube/shader.wgsl +++ /dev/null @@ -1,29 +0,0 @@ -struct Uniforms { - modelViewProjectionMatrix : mat4x4, -}; -@binding(0) @group(0) var uniforms : Uniforms; - -struct VertexOutput { - @builtin(position) Position : vec4, - @location(0) fragUV : vec2, - @location(1) fragPosition: vec4, -}; - -@vertex -fn vertex_main(@location(0) position : vec4, - @location(1) uv : vec2) -> VertexOutput { - var output : VertexOutput; - output.Position = position * uniforms.modelViewProjectionMatrix; - output.fragUV = uv; - output.fragPosition = 0.5 * (position + vec4(1.0, 1.0, 1.0, 1.0)); - return output; -} - -@group(0) @binding(1) var mySampler: sampler; -@group(0) @binding(2) var myTexture: texture_2d; - -@fragment -fn frag_main(@location(0) fragUV: vec2, - @location(1) fragPosition: vec4) -> @location(0) vec4 { - return textureSample(myTexture, mySampler, fragUV); -} \ No newline at end of file diff --git a/src/core/examples/textured-quad/main.zig b/src/core/examples/textured-quad/main.zig deleted file mode 100644 index dc1cfa4e..00000000 --- a/src/core/examples/textured-quad/main.zig +++ /dev/null @@ -1,207 +0,0 @@ -const std = @import("std"); - -const mach = @import("mach"); -const core = mach.core; -const gpu = mach.gpu; - -const zigimg = @import("zigimg"); -const assets = @import("assets"); - -pub const App = @This(); - -const Vertex = extern struct { - pos: @Vector(2, f32), - uv: @Vector(2, f32), -}; - -const vertices = [_]Vertex{ - .{ .pos = .{ -0.5, -0.5 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ 0.5, -0.5 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ 0.5, 0.5 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ -0.5, 0.5 }, .uv = .{ 1, 0 } }, -}; -const index_data = [_]u32{ 0, 1, 2, 2, 3, 0 }; - -var gpa = std.heap.GeneralPurposeAllocator(.{}){}; - -title_timer: core.Timer, -timer: core.Timer, -pipeline: *gpu.RenderPipeline, -vertex_buffer: *gpu.Buffer, -index_buffer: *gpu.Buffer, -bind_group: *gpu.BindGroup, - -pub fn init(app: *App) !void { - try core.init(.{}); - const allocator = gpa.allocator(); - - const shader_module = core.device.createShaderModuleWGSL("shader.wgsl", @embedFile("shader.wgsl")); - - const vertex_attributes = [_]gpu.VertexAttribute{ - .{ .format = .float32x4, .offset = @offsetOf(Vertex, "pos"), .shader_location = 0 }, - .{ .format = .float32x2, .offset = @offsetOf(Vertex, "uv"), .shader_location = 1 }, - }; - const vertex_buffer_layout = gpu.VertexBufferLayout.init(.{ - .array_stride = @sizeOf(Vertex), - .step_mode = .vertex, - .attributes = &vertex_attributes, - }); - - const blend = gpu.BlendState{}; - const color_target = gpu.ColorTargetState{ - .format = core.descriptor.format, - .blend = &blend, - .write_mask = gpu.ColorWriteMaskFlags.all, - }; - const fragment = gpu.FragmentState.init(.{ - .module = shader_module, - .entry_point = "frag_main", - .targets = &.{color_target}, - }); - const pipeline_descriptor = gpu.RenderPipeline.Descriptor{ - .fragment = &fragment, - .vertex = gpu.VertexState.init(.{ - .module = shader_module, - .entry_point = "vertex_main", - .buffers = &.{vertex_buffer_layout}, - }), - .primitive = .{ .cull_mode = .back }, - }; - const pipeline = core.device.createRenderPipeline(&pipeline_descriptor); - shader_module.release(); - - const vertex_buffer = core.device.createBuffer(&.{ - .usage = .{ .vertex = true }, - .size = @sizeOf(Vertex) * vertices.len, - .mapped_at_creation = .true, - }); - const vertex_mapped = vertex_buffer.getMappedRange(Vertex, 0, vertices.len); - @memcpy(vertex_mapped.?, vertices[0..]); - vertex_buffer.unmap(); - - const index_buffer = core.device.createBuffer(&.{ - .usage = .{ .index = true }, - .size = @sizeOf(u32) * index_data.len, - .mapped_at_creation = .true, - }); - const index_mapped = index_buffer.getMappedRange(u32, 0, index_data.len); - @memcpy(index_mapped.?, index_data[0..]); - index_buffer.unmap(); - - const sampler = core.device.createSampler(&.{ .mag_filter = .linear, .min_filter = .linear }); - const queue = core.queue; - var img = try zigimg.Image.fromMemory(allocator, assets.gotta_go_fast_png); - defer img.deinit(); - const img_size = gpu.Extent3D{ - .width = @as(u32, @intCast(img.width)), - .height = @as(u32, @intCast(img.height)), - }; - const texture = core.device.createTexture(&.{ - .size = img_size, - .format = .rgba8_unorm, - .usage = .{ - .texture_binding = true, - .copy_dst = true, - .render_attachment = true, - }, - }); - const data_layout = gpu.Texture.DataLayout{ - .bytes_per_row = @as(u32, @intCast(img.width * 4)), - .rows_per_image = @as(u32, @intCast(img.height)), - }; - switch (img.pixels) { - .rgba32 => |pixels| queue.writeTexture(&.{ .texture = texture }, &data_layout, &img_size, pixels), - .rgb24 => |pixels| { - const data = try rgb24ToRgba32(allocator, pixels); - defer data.deinit(allocator); - queue.writeTexture(&.{ .texture = texture }, &data_layout, &img_size, data.rgba32); - }, - else => @panic("unsupported image color format"), - } - - const texture_view = texture.createView(&gpu.TextureView.Descriptor{}); - texture.release(); - - const bind_group_layout = pipeline.getBindGroupLayout(0); - const bind_group = core.device.createBindGroup( - &gpu.BindGroup.Descriptor.init(.{ - .layout = bind_group_layout, - .entries = &.{ - gpu.BindGroup.Entry.sampler(0, sampler), - gpu.BindGroup.Entry.textureView(1, texture_view), - }, - }), - ); - sampler.release(); - texture_view.release(); - bind_group_layout.release(); - - app.timer = try core.Timer.start(); - app.title_timer = try core.Timer.start(); - app.pipeline = pipeline; - app.vertex_buffer = vertex_buffer; - app.index_buffer = index_buffer; - app.bind_group = bind_group; -} - -pub fn deinit(app: *App) void { - app.pipeline.release(); - app.vertex_buffer.release(); - app.index_buffer.release(); - app.bind_group.release(); - core.deinit(); - _ = gpa.deinit(); -} - -pub fn update(app: *App) !bool { - var iter = core.pollEvents(); - while (iter.next()) |event| if (event == .close) return true; - - const back_buffer_view = core.swap_chain.getCurrentTextureView().?; - const color_attachment = gpu.RenderPassColorAttachment{ - .view = back_buffer_view, - .clear_value = .{ .r = 0, .g = 0, .b = 0, .a = 0.0 }, - .load_op = .clear, - .store_op = .store, - }; - - const encoder = core.device.createCommandEncoder(null); - const render_pass_info = gpu.RenderPassDescriptor.init(.{ .color_attachments = &.{color_attachment} }); - - const pass = encoder.beginRenderPass(&render_pass_info); - pass.setPipeline(app.pipeline); - pass.setVertexBuffer(0, app.vertex_buffer, 0, @sizeOf(Vertex) * vertices.len); - pass.setIndexBuffer(app.index_buffer, .uint32, 0, @sizeOf(u32) * index_data.len); - pass.setBindGroup(0, app.bind_group, &.{}); - pass.drawIndexed(index_data.len, 1, 0, 0, 0); - pass.end(); - pass.release(); - - var command = encoder.finish(null); - encoder.release(); - - const queue = core.queue; - queue.submit(&[_]*gpu.CommandBuffer{command}); - command.release(); - core.swap_chain.present(); - back_buffer_view.release(); - - // update the window title every second - if (app.title_timer.read() >= 1.0) { - app.title_timer.reset(); - try core.printTitle("Textured Quad [ {d}fps ] [ Input {d}hz ]", .{ - core.frameRate(), - core.inputRate(), - }); - } - return false; -} - -fn rgb24ToRgba32(allocator: std.mem.Allocator, in: []zigimg.color.Rgb24) !zigimg.color.PixelStorage { - const out = try zigimg.color.PixelStorage.init(allocator, .rgba32, in.len); - var i: usize = 0; - while (i < in.len) : (i += 1) { - out.rgba32[i] = zigimg.color.Rgba32{ .r = in[i].r, .g = in[i].g, .b = in[i].b, .a = 255 }; - } - return out; -} diff --git a/src/core/examples/textured-quad/shader.wgsl b/src/core/examples/textured-quad/shader.wgsl deleted file mode 100644 index 3328340b..00000000 --- a/src/core/examples/textured-quad/shader.wgsl +++ /dev/null @@ -1,21 +0,0 @@ -struct VertexOutput { - @builtin(position) Position : vec4, - @location(0) fragUV : vec2, -}; - -@vertex -fn vertex_main(@location(0) position : vec2, - @location(1) uv : vec2) -> VertexOutput { - var output : VertexOutput; - output.Position = vec4(position, 0, 1); - output.fragUV = uv; - return output; -} - -@group(0) @binding(0) var mySampler: sampler; -@group(0) @binding(1) var myTexture: texture_2d; - -@fragment -fn frag_main(@location(0) fragUV: vec2) -> @location(0) vec4 { - return textureSample(myTexture, mySampler, fragUV); -} \ No newline at end of file diff --git a/src/core/examples/triangle-msaa/main.zig b/src/core/examples/triangle-msaa/main.zig deleted file mode 100644 index 7c0e837e..00000000 --- a/src/core/examples/triangle-msaa/main.zig +++ /dev/null @@ -1,130 +0,0 @@ -const std = @import("std"); - -const mach = @import("mach"); -const core = mach.core; -const gpu = mach.gpu; - -pub const App = @This(); - -title_timer: core.Timer, -pipeline: *gpu.RenderPipeline, -texture: *gpu.Texture, -texture_view: *gpu.TextureView, - -const sample_count = 4; - -pub fn init(app: *App) !void { - try core.init(.{}); - app.title_timer = try core.Timer.start(); - - const shader_module = core.device.createShaderModuleWGSL("shader.wgsl", @embedFile("shader.wgsl")); - defer shader_module.release(); - - // Fragment state - const blend = gpu.BlendState{}; - const color_target = gpu.ColorTargetState{ - .format = core.descriptor.format, - .blend = &blend, - .write_mask = gpu.ColorWriteMaskFlags.all, - }; - const fragment = gpu.FragmentState.init(.{ - .module = shader_module, - .entry_point = "frag_main", - .targets = &.{color_target}, - }); - const pipeline_descriptor = gpu.RenderPipeline.Descriptor{ - .fragment = &fragment, - .vertex = gpu.VertexState{ - .module = shader_module, - .entry_point = "vertex_main", - }, - .multisample = gpu.MultisampleState{ - .count = sample_count, - }, - }; - - app.pipeline = core.device.createRenderPipeline(&pipeline_descriptor); - - app.texture = core.device.createTexture(&gpu.Texture.Descriptor{ - .size = gpu.Extent3D{ - .width = core.descriptor.width, - .height = core.descriptor.height, - }, - .sample_count = sample_count, - .format = core.descriptor.format, - .usage = .{ .render_attachment = true }, - }); - app.texture_view = app.texture.createView(null); -} - -pub fn deinit(app: *App) void { - defer core.deinit(); - - app.pipeline.release(); - app.texture.release(); - app.texture_view.release(); -} - -pub fn update(app: *App) !bool { - var iter = core.pollEvents(); - while (iter.next()) |event| { - switch (event) { - .framebuffer_resize => |size| { - app.texture.release(); - app.texture = core.device.createTexture(&gpu.Texture.Descriptor{ - .size = gpu.Extent3D{ - .width = size.width, - .height = size.height, - }, - .sample_count = sample_count, - .format = core.descriptor.format, - .usage = .{ .render_attachment = true }, - }); - - app.texture_view.release(); - app.texture_view = app.texture.createView(null); - }, - .close => return true, - else => {}, - } - } - - const back_buffer_view = core.swap_chain.getCurrentTextureView().?; - const color_attachment = gpu.RenderPassColorAttachment{ - .view = app.texture_view, - .resolve_target = back_buffer_view, - .clear_value = std.mem.zeroes(gpu.Color), - .load_op = .clear, - .store_op = .discard, - }; - - const encoder = core.device.createCommandEncoder(null); - const render_pass_info = gpu.RenderPassDescriptor.init(.{ - .color_attachments = &.{color_attachment}, - }); - const pass = encoder.beginRenderPass(&render_pass_info); - pass.setPipeline(app.pipeline); - pass.draw(3, 1, 0, 0); - pass.end(); - pass.release(); - - var command = encoder.finish(null); - encoder.release(); - - const queue = core.queue; - queue.submit(&[_]*gpu.CommandBuffer{command}); - command.release(); - core.swap_chain.present(); - back_buffer_view.release(); - - // update the window title every second - if (app.title_timer.read() >= 1.0) { - app.title_timer.reset(); - try core.printTitle("Triangle MSAA [ {d}fps ] [ Input {d}hz ]", .{ - core.frameRate(), - core.inputRate(), - }); - } - - return false; -} diff --git a/src/core/examples/triangle-msaa/shader.wgsl b/src/core/examples/triangle-msaa/shader.wgsl deleted file mode 100644 index 429d87e0..00000000 --- a/src/core/examples/triangle-msaa/shader.wgsl +++ /dev/null @@ -1,14 +0,0 @@ -@vertex fn vertex_main( - @builtin(vertex_index) VertexIndex : u32 -) -> @builtin(position) vec4 { - var pos = array, 3>( - vec2( 0.0, 0.5), - vec2(-0.5, -0.5), - vec2( 0.5, -0.5) - ); - return vec4(pos[VertexIndex], 0.0, 1.0); -} - -@fragment fn frag_main() -> @location(0) vec4 { - return vec4(1.0, 0.0, 0.0, 1.0); -} diff --git a/src/core/examples/triangle/main.zig b/src/core/examples/triangle/main.zig deleted file mode 100644 index f86bb47b..00000000 --- a/src/core/examples/triangle/main.zig +++ /dev/null @@ -1,93 +0,0 @@ -const std = @import("std"); - -const mach = @import("mach"); -const core = mach.core; -const gpu = mach.gpu; - -pub const App = @This(); - -title_timer: core.Timer, -pipeline: *gpu.RenderPipeline, - -pub fn init(app: *App) !void { - try core.init(.{}); - - const shader_module = core.device.createShaderModuleWGSL("shader.wgsl", @embedFile("shader.wgsl")); - defer shader_module.release(); - - // Fragment state - const blend = gpu.BlendState{}; - const color_target = gpu.ColorTargetState{ - .format = core.descriptor.format, - .blend = &blend, - .write_mask = gpu.ColorWriteMaskFlags.all, - }; - const fragment = gpu.FragmentState.init(.{ - .module = shader_module, - .entry_point = "frag_main", - .targets = &.{color_target}, - }); - const pipeline_descriptor = gpu.RenderPipeline.Descriptor{ - .fragment = &fragment, - .vertex = gpu.VertexState{ - .module = shader_module, - .entry_point = "vertex_main", - }, - }; - const pipeline = core.device.createRenderPipeline(&pipeline_descriptor); - - app.* = .{ .title_timer = try core.Timer.start(), .pipeline = pipeline }; -} - -pub fn deinit(app: *App) void { - defer core.deinit(); - app.pipeline.release(); -} - -pub fn update(app: *App) !bool { - var iter = core.pollEvents(); - while (iter.next()) |event| { - switch (event) { - .close => return true, - else => {}, - } - } - - const queue = core.queue; - const back_buffer_view = core.swap_chain.getCurrentTextureView().?; - const color_attachment = gpu.RenderPassColorAttachment{ - .view = back_buffer_view, - .clear_value = std.mem.zeroes(gpu.Color), - .load_op = .clear, - .store_op = .store, - }; - - const encoder = core.device.createCommandEncoder(null); - const render_pass_info = gpu.RenderPassDescriptor.init(.{ - .color_attachments = &.{color_attachment}, - }); - const pass = encoder.beginRenderPass(&render_pass_info); - pass.setPipeline(app.pipeline); - pass.draw(3, 1, 0, 0); - pass.end(); - pass.release(); - - var command = encoder.finish(null); - encoder.release(); - - queue.submit(&[_]*gpu.CommandBuffer{command}); - command.release(); - core.swap_chain.present(); - back_buffer_view.release(); - - // update the window title every second - if (app.title_timer.read() >= 1.0) { - app.title_timer.reset(); - try core.printTitle("Triangle [ {d}fps ] [ Input {d}hz ]", .{ - core.frameRate(), - core.inputRate(), - }); - } - - return false; -} diff --git a/src/core/examples/triangle/shader.wgsl b/src/core/examples/triangle/shader.wgsl deleted file mode 100644 index 429d87e0..00000000 --- a/src/core/examples/triangle/shader.wgsl +++ /dev/null @@ -1,14 +0,0 @@ -@vertex fn vertex_main( - @builtin(vertex_index) VertexIndex : u32 -) -> @builtin(position) vec4 { - var pos = array, 3>( - vec2( 0.0, 0.5), - vec2(-0.5, -0.5), - vec2( 0.5, -0.5) - ); - return vec4(pos[VertexIndex], 0.0, 1.0); -} - -@fragment fn frag_main() -> @location(0) vec4 { - return vec4(1.0, 0.0, 0.0, 1.0); -} diff --git a/src/core/examples/two-cubes/cube_mesh.zig b/src/core/examples/two-cubes/cube_mesh.zig deleted file mode 100644 index f26c75ac..00000000 --- a/src/core/examples/two-cubes/cube_mesh.zig +++ /dev/null @@ -1,49 +0,0 @@ -pub const Vertex = extern struct { - pos: @Vector(4, f32), - col: @Vector(4, f32), - uv: @Vector(2, f32), -}; - -pub const vertices = [_]Vertex{ - .{ .pos = .{ 1, -1, 1, 1 }, .col = .{ 1, 0, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, -1, -1, 1 }, .col = .{ 0, 0, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, -1, 1, 1 }, .col = .{ 1, 0, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, -1, -1, 1 }, .col = .{ 0, 0, 0, 1 }, .uv = .{ 0, 0 } }, - - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ 1, -1, 1, 1 }, .col = .{ 1, 0, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, 1, -1, 1 }, .col = .{ 1, 1, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 0, 0 } }, - - .{ .pos = .{ -1, 1, 1, 1 }, .col = .{ 0, 1, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ 1, 1, -1, 1 }, .col = .{ 1, 1, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ -1, 1, 1, 1 }, .col = .{ 0, 1, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ 1, 1, -1, 1 }, .col = .{ 1, 1, 0, 1 }, .uv = .{ 0, 0 } }, - - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, 1, 1, 1 }, .col = .{ 0, 1, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ -1, -1, -1, 1 }, .col = .{ 0, 0, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 0, 0 } }, - - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, 1, 1, 1 }, .col = .{ 0, 1, 1, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ -1, -1, 1, 1 }, .col = .{ 0, 0, 1, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, -1, 1, 1 }, .col = .{ 1, 0, 1, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, 1, 1, 1 }, .col = .{ 1, 1, 1, 1 }, .uv = .{ 1, 1 } }, - - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, -1, -1, 1 }, .col = .{ 0, 0, 0, 1 }, .uv = .{ 0, 1 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 0, 0 } }, - .{ .pos = .{ 1, 1, -1, 1 }, .col = .{ 1, 1, 0, 1 }, .uv = .{ 1, 0 } }, - .{ .pos = .{ 1, -1, -1, 1 }, .col = .{ 1, 0, 0, 1 }, .uv = .{ 1, 1 } }, - .{ .pos = .{ -1, 1, -1, 1 }, .col = .{ 0, 1, 0, 1 }, .uv = .{ 0, 0 } }, -}; diff --git a/src/core/examples/two-cubes/main.zig b/src/core/examples/two-cubes/main.zig deleted file mode 100755 index 7a1df3aa..00000000 --- a/src/core/examples/two-cubes/main.zig +++ /dev/null @@ -1,226 +0,0 @@ -const std = @import("std"); - -const mach = @import("mach"); -const core = mach.core; -const gpu = mach.gpu; - -const zm = @import("zmath"); -const Vertex = @import("cube_mesh.zig").Vertex; -const vertices = @import("cube_mesh.zig").vertices; - -const UniformBufferObject = struct { - mat: zm.Mat, -}; - -var gpa = std.heap.GeneralPurposeAllocator(.{}){}; - -title_timer: core.Timer, -timer: core.Timer, -pipeline: *gpu.RenderPipeline, -vertex_buffer: *gpu.Buffer, -uniform_buffer: *gpu.Buffer, -bind_group1: *gpu.BindGroup, -bind_group2: *gpu.BindGroup, - -pub const App = @This(); - -pub fn init(app: *App) !void { - try core.init(.{}); - app.title_timer = try core.Timer.start(); - app.timer = try core.Timer.start(); - - const shader_module = core.device.createShaderModuleWGSL("shader.wgsl", @embedFile("shader.wgsl")); - - const vertex_attributes = [_]gpu.VertexAttribute{ - .{ .format = .float32x4, .offset = @offsetOf(Vertex, "pos"), .shader_location = 0 }, - .{ .format = .float32x2, .offset = @offsetOf(Vertex, "uv"), .shader_location = 1 }, - }; - const vertex_buffer_layout = gpu.VertexBufferLayout.init(.{ - .array_stride = @sizeOf(Vertex), - .step_mode = .vertex, - .attributes = &vertex_attributes, - }); - - const blend = gpu.BlendState{}; - const color_target = gpu.ColorTargetState{ - .format = core.descriptor.format, - .blend = &blend, - .write_mask = gpu.ColorWriteMaskFlags.all, - }; - const fragment = gpu.FragmentState.init(.{ - .module = shader_module, - .entry_point = "frag_main", - .targets = &.{color_target}, - }); - - const bgle = gpu.BindGroupLayout.Entry.buffer(0, .{ .vertex = true }, .uniform, true, 0); - const bgl = core.device.createBindGroupLayout( - &gpu.BindGroupLayout.Descriptor.init(.{ - .entries = &.{bgle}, - }), - ); - - const bind_group_layouts = [_]*gpu.BindGroupLayout{bgl}; - const pipeline_layout = core.device.createPipelineLayout(&gpu.PipelineLayout.Descriptor.init(.{ - .bind_group_layouts = &bind_group_layouts, - })); - - const pipeline_descriptor = gpu.RenderPipeline.Descriptor{ - .fragment = &fragment, - .layout = pipeline_layout, - .vertex = gpu.VertexState.init(.{ - .module = shader_module, - .entry_point = "vertex_main", - .buffers = &.{vertex_buffer_layout}, - }), - .primitive = .{ - .cull_mode = .back, - }, - }; - - const vertex_buffer = core.device.createBuffer(&.{ - .usage = .{ .vertex = true }, - .size = @sizeOf(Vertex) * vertices.len, - .mapped_at_creation = .true, - }); - const vertex_mapped = vertex_buffer.getMappedRange(Vertex, 0, vertices.len); - @memcpy(vertex_mapped.?, vertices[0..]); - vertex_buffer.unmap(); - - // uniformBindGroup offset must be 256-byte aligned - const uniform_offset = 256; - const uniform_buffer = core.device.createBuffer(&.{ - .usage = .{ .uniform = true, .copy_dst = true }, - .size = @sizeOf(UniformBufferObject) + uniform_offset, - .mapped_at_creation = .false, - }); - - const bind_group1 = core.device.createBindGroup( - &gpu.BindGroup.Descriptor.init(.{ - .layout = bgl, - .entries = &.{ - gpu.BindGroup.Entry.buffer(0, uniform_buffer, 0, @sizeOf(UniformBufferObject)), - }, - }), - ); - - const bind_group2 = core.device.createBindGroup( - &gpu.BindGroup.Descriptor.init(.{ - .layout = bgl, - .entries = &.{ - gpu.BindGroup.Entry.buffer(0, uniform_buffer, uniform_offset, @sizeOf(UniformBufferObject)), - }, - }), - ); - - app.pipeline = core.device.createRenderPipeline(&pipeline_descriptor); - app.vertex_buffer = vertex_buffer; - app.uniform_buffer = uniform_buffer; - app.bind_group1 = bind_group1; - app.bind_group2 = bind_group2; - - shader_module.release(); - pipeline_layout.release(); - bgl.release(); -} - -pub fn deinit(app: *App) void { - defer _ = gpa.deinit(); - defer core.deinit(); - - app.pipeline.release(); - app.vertex_buffer.release(); - app.uniform_buffer.release(); - app.bind_group1.release(); - app.bind_group2.release(); -} - -pub fn update(app: *App) !bool { - var iter = core.pollEvents(); - while (iter.next()) |event| { - switch (event) { - .key_press => |ev| { - if (ev.key == .space) return true; - }, - .close => return true, - else => {}, - } - } - - const back_buffer_view = core.swap_chain.getCurrentTextureView().?; - const color_attachment = gpu.RenderPassColorAttachment{ - .view = back_buffer_view, - .clear_value = std.mem.zeroes(gpu.Color), - .load_op = .clear, - .store_op = .store, - }; - - const encoder = core.device.createCommandEncoder(null); - const render_pass_info = gpu.RenderPassDescriptor.init(.{ - .color_attachments = &.{color_attachment}, - }); - - { - const time = app.timer.read(); - const rotation1 = zm.mul(zm.rotationX(time * (std.math.pi / 2.0)), zm.rotationZ(time * (std.math.pi / 2.0))); - const rotation2 = zm.mul(zm.rotationZ(time * (std.math.pi / 2.0)), zm.rotationX(time * (std.math.pi / 2.0))); - const model1 = zm.mul(rotation1, zm.translation(-2, 0, 0)); - const model2 = zm.mul(rotation2, zm.translation(2, 0, 0)); - const view = zm.lookAtRh( - zm.Vec{ 0, -4, 2, 1 }, - zm.Vec{ 0, 0, 0, 1 }, - zm.Vec{ 0, 0, 1, 0 }, - ); - const proj = zm.perspectiveFovRh( - (2.0 * std.math.pi / 5.0), - @as(f32, @floatFromInt(core.descriptor.width)) / @as(f32, @floatFromInt(core.descriptor.height)), - 1, - 100, - ); - const mvp1 = zm.mul(zm.mul(model1, view), proj); - const mvp2 = zm.mul(zm.mul(model2, view), proj); - const ubo1 = UniformBufferObject{ - .mat = zm.transpose(mvp1), - }; - const ubo2 = UniformBufferObject{ - .mat = zm.transpose(mvp2), - }; - - encoder.writeBuffer(app.uniform_buffer, 0, &[_]UniformBufferObject{ubo1}); - - // bind_group2 offset - encoder.writeBuffer(app.uniform_buffer, 256, &[_]UniformBufferObject{ubo2}); - } - - const pass = encoder.beginRenderPass(&render_pass_info); - pass.setPipeline(app.pipeline); - pass.setVertexBuffer(0, app.vertex_buffer, 0, @sizeOf(Vertex) * vertices.len); - - pass.setBindGroup(0, app.bind_group1, &.{0}); - pass.draw(vertices.len, 1, 0, 0); - pass.setBindGroup(0, app.bind_group2, &.{0}); - pass.draw(vertices.len, 1, 0, 0); - - pass.end(); - pass.release(); - - var command = encoder.finish(null); - encoder.release(); - - const queue = core.queue; - queue.submit(&[_]*gpu.CommandBuffer{command}); - command.release(); - core.swap_chain.present(); - back_buffer_view.release(); - - // update the window title every second - if (app.title_timer.read() >= 1.0) { - app.title_timer.reset(); - try core.printTitle("Two Cubes [ {d}fps ] [ Input {d}hz ]", .{ - core.frameRate(), - core.inputRate(), - }); - } - - return false; -} diff --git a/src/core/examples/two-cubes/shader.wgsl b/src/core/examples/two-cubes/shader.wgsl deleted file mode 100644 index 05384f41..00000000 --- a/src/core/examples/two-cubes/shader.wgsl +++ /dev/null @@ -1,24 +0,0 @@ -@group(0) @binding(0) var ubo : mat4x4; -struct VertexOut { - @builtin(position) position_clip : vec4, - @location(0) fragUV : vec2, - @location(1) fragPosition: vec4, -} - -@vertex fn vertex_main( - @location(0) position : vec4, - @location(1) uv: vec2 -) -> VertexOut { - var output : VertexOut; - output.position_clip = position * ubo; - output.fragUV = uv; - output.fragPosition = 0.5 * (position + vec4(1.0, 1.0, 1.0, 1.0)); - return output; -} - -@fragment fn frag_main( - @location(0) fragUV: vec2, - @location(1) fragPosition: vec4 -) -> @location(0) vec4 { - return fragPosition; -} diff --git a/src/core/examples/wasm-test/main.zig b/src/core/examples/wasm-test/main.zig deleted file mode 100644 index c23c3d89..00000000 --- a/src/core/examples/wasm-test/main.zig +++ /dev/null @@ -1,37 +0,0 @@ -const std = @import("std"); - -const mach = @import("mach"); -const core = mach.core; -const gpu = mach.gpu; - -pub const App = @This(); - -pub fn init(app: *App) !void { - try core.init(.{}); - app.* = App{}; -} - -pub fn deinit(app: *App) void { - defer core.deinit(); - _ = app; -} - -pub fn update(app: *App) !bool { - _ = app; - var iter = core.pollEvents(); - while (iter.next()) |event| { - std.log.debug("event: {}\n", .{event}); - switch (event) { - .close => return true, - .key_press => |ev| { - if (ev.key == .p) @panic("p pressed, panic triggered"); - if (ev.key == .q) { - std.log.err("q pressed, exiting app", .{}); - return true; - } - }, - else => {}, - } - } - return false; -} diff --git a/src/core/examples/zmath.zig b/src/core/examples/zmath.zig deleted file mode 100644 index 7aa6bf54..00000000 --- a/src/core/examples/zmath.zig +++ /dev/null @@ -1,996 +0,0 @@ -//! Heavily stripped down zmath version. -//! -//! In your own projects, you should bring your own math library. This file is just for example -//! purposes. -//! - -const builtin = @import("builtin"); -const std = @import("std"); -const math = std.math; -const assert = std.debug.assert; -const expect = std.testing.expect; - -pub const Vec = @Vector(4, f32); -pub const Mat = [4]@Vector(4, f32); -pub const Quat = @Vector(4, f32); - -pub inline fn abs(v: anytype) @TypeOf(v) { - return @abs(v); -} - -inline fn dot3(v0: Vec, v1: Vec) Vec { - const dot = v0 * v1; - return @splat(dot[0] + dot[1] + dot[2]); -} - -pub inline fn normalize3(v: Vec) Vec { - return v * @as(Vec, @splat(1.0)) / @sqrt(dot3(v, v)); -} - -pub fn scaling(x: f32, y: f32, z: f32) Mat { - return .{ - .{ x, 0.0, 0.0, 0.0 }, - .{ 0.0, y, 0.0, 0.0 }, - .{ 0.0, 0.0, z, 0.0 }, - .{ 0.0, 0.0, 0.0, 1.0 }, - }; -} - -pub inline fn cross3(a: Vec, b: Vec) Vec { - const v1 = Vec{ a[1], a[2], a[0], 1.0 }; - const v2 = Vec{ b[2], b[0], b[1], 1.0 }; - const sub1 = v1 * v2; - - const _v1 = Vec{ a[2], a[0], a[1], 1.0 }; - const _v2 = Vec{ b[1], b[2], b[0], 1.0 }; - const sub2 = _v1 * _v2; - - return sub1 - sub2; -} - -pub fn orthographicRh(w: f32, h: f32, near: f32, far: f32) Mat { - assert(!math.approxEqAbs(f32, w, 0.0, 0.001)); - assert(!math.approxEqAbs(f32, h, 0.0, 0.001)); - assert(!math.approxEqAbs(f32, far, near, 0.001)); - - const r = 1 / (near - far); - return .{ - .{ 2 / w, 0.0, 0.0, 0.0 }, - .{ 0.0, 2 / h, 0.0, 0.0 }, - .{ 0.0, 0.0, r, 0.0 }, - .{ 0.0, 0.0, r * near, 1.0 }, - }; -} - -//--- -// Public APIs used by examples that we should reduce to their minimal counterparts -//--- -pub fn lookAtRh(eyepos: Vec, focuspos: Vec, updir: Vec) Mat { - return lookToLh(eyepos, eyepos - focuspos, updir); -} -pub inline fn storeMat(mem: []f32, m: Mat) void { - store(mem[0..4], m[0], 0); - store(mem[4..8], m[1], 0); - store(mem[8..12], m[2], 0); - store(mem[12..16], m[3], 0); -} -pub fn quatFromAxisAngle(axis: Vec, angle: f32) Quat { - assert(!all(axis == splat(F32x4, 0.0), 3)); - assert(!all(isInf(axis), 3)); - const normal = normalize3(axis); - return quatFromNormAxisAngle(normal, angle); -} -pub fn perspectiveFovRh(fovy: f32, aspect: f32, near: f32, far: f32) Mat { - const scfov = sincos(0.5 * fovy); - - assert(near > 0.0 and far > 0.0); - assert(!math.approxEqAbs(f32, scfov[0], 0.0, 0.001)); - assert(!math.approxEqAbs(f32, far, near, 0.001)); - assert(!math.approxEqAbs(f32, aspect, 0.0, 0.01)); - - const h = scfov[1] / scfov[0]; - const w = h / aspect; - const r = far / (near - far); - return .{ - f32x4(w, 0.0, 0.0, 0.0), - f32x4(0.0, h, 0.0, 0.0), - f32x4(0.0, 0.0, r, -1.0), - f32x4(0.0, 0.0, r * near, 0.0), - }; -} -pub fn qmul(q0: Quat, q1: Quat) Quat { - var result = swizzle(q1, .w, .w, .w, .w); - var q1x = swizzle(q1, .x, .x, .x, .x); - var q1y = swizzle(q1, .y, .y, .y, .y); - var q1z = swizzle(q1, .z, .z, .z, .z); - result = result * q0; - var q0_shuf = swizzle(q0, .w, .z, .y, .x); - q1x = q1x * q0_shuf; - q0_shuf = swizzle(q0_shuf, .y, .x, .w, .z); - result = mulAdd(q1x, f32x4(1.0, -1.0, 1.0, -1.0), result); - q1y = q1y * q0_shuf; - q0_shuf = swizzle(q0_shuf, .w, .z, .y, .x); - q1y = q1y * f32x4(1.0, 1.0, -1.0, -1.0); - q1z = q1z * q0_shuf; - q1y = mulAdd(q1z, f32x4(-1.0, 1.0, 1.0, -1.0), q1y); - return result + q1y; -} -pub fn mul(a: anytype, b: anytype) mulRetType(@TypeOf(a), @TypeOf(b)) { - const Ta = @TypeOf(a); - const Tb = @TypeOf(b); - if (Ta == Mat and Tb == Mat) { - return mulMat(a, b); - } else if (Ta == f32 and Tb == Mat) { - const va = splat(F32x4, a); - return Mat{ va * b[0], va * b[1], va * b[2], va * b[3] }; - } else if (Ta == Mat and Tb == f32) { - const vb = splat(F32x4, b); - return Mat{ a[0] * vb, a[1] * vb, a[2] * vb, a[3] * vb }; - } else if (Ta == Vec and Tb == Mat) { - return vecMulMat(a, b); - } else if (Ta == Mat and Tb == Vec) { - return matMulVec(a, b); - } else { - @compileError("zmath.mul() not implemented for types: " ++ @typeName(Ta) ++ ", " ++ @typeName(Tb)); - } -} -pub fn translationV(v: Vec) Mat { - return translation(v[0], v[1], v[2]); -} -pub fn transpose(m: Mat) Mat { - const temp1 = @shuffle(f32, m[0], m[1], [4]i32{ 0, 1, ~@as(i32, 0), ~@as(i32, 1) }); - const temp3 = @shuffle(f32, m[0], m[1], [4]i32{ 2, 3, ~@as(i32, 2), ~@as(i32, 3) }); - const temp2 = @shuffle(f32, m[2], m[3], [4]i32{ 0, 1, ~@as(i32, 0), ~@as(i32, 1) }); - const temp4 = @shuffle(f32, m[2], m[3], [4]i32{ 2, 3, ~@as(i32, 2), ~@as(i32, 3) }); - return .{ - @shuffle(f32, temp1, temp2, [4]i32{ 0, 2, ~@as(i32, 0), ~@as(i32, 2) }), - @shuffle(f32, temp1, temp2, [4]i32{ 1, 3, ~@as(i32, 1), ~@as(i32, 3) }), - @shuffle(f32, temp3, temp4, [4]i32{ 0, 2, ~@as(i32, 0), ~@as(i32, 2) }), - @shuffle(f32, temp3, temp4, [4]i32{ 1, 3, ~@as(i32, 1), ~@as(i32, 3) }), - }; -} -pub fn rotationX(angle: f32) Mat { - const sc = sincos(angle); - return .{ - f32x4(1.0, 0.0, 0.0, 0.0), - f32x4(0.0, sc[1], sc[0], 0.0), - f32x4(0.0, -sc[0], sc[1], 0.0), - f32x4(0.0, 0.0, 0.0, 1.0), - }; -} -pub fn rotationY(angle: f32) Mat { - const sc = sincos(angle); - return .{ - f32x4(sc[1], 0.0, -sc[0], 0.0), - f32x4(0.0, 1.0, 0.0, 0.0), - f32x4(sc[0], 0.0, sc[1], 0.0), - f32x4(0.0, 0.0, 0.0, 1.0), - }; -} -pub fn rotationZ(angle: f32) Mat { - const sc = sincos(angle); - return .{ - f32x4(sc[1], sc[0], 0.0, 0.0), - f32x4(-sc[0], sc[1], 0.0, 0.0), - f32x4(0.0, 0.0, 1.0, 0.0), - f32x4(0.0, 0.0, 0.0, 1.0), - }; -} -pub fn cos(v: anytype) @TypeOf(v) { - const T = @TypeOf(v); - return switch (T) { - f32 => cos32(v), - F32x4 => cos32xN(v), - else => @compileError("zmath.cos() not implemented for " ++ @typeName(T)), - }; -} -pub fn sin(v: anytype) @TypeOf(v) { - const T = @TypeOf(v); - return switch (T) { - f32 => sin32(v), - F32x4 => sin32xN(v), - else => @compileError("zmath.sin() not implemented for " ++ @typeName(T)), - }; -} -// Produces Z values in [-1.0, 1.0] range (OpenGL defaults) -pub fn perspectiveFovRhGl(fovy: f32, aspect: f32, near: f32, far: f32) Mat { - const scfov = sincos(0.5 * fovy); - - assert(near > 0.0 and far > 0.0); - assert(!math.approxEqAbs(f32, scfov[0], 0.0, 0.001)); - assert(!math.approxEqAbs(f32, far, near, 0.001)); - assert(!math.approxEqAbs(f32, aspect, 0.0, 0.01)); - - const h = scfov[1] / scfov[0]; - const w = h / aspect; - const r = near - far; - return .{ - f32x4(w, 0.0, 0.0, 0.0), - f32x4(0.0, h, 0.0, 0.0), - f32x4(0.0, 0.0, (near + far) / r, -1.0), - f32x4(0.0, 0.0, 2.0 * near * far / r, 0.0), - }; -} -pub inline fn clamp(v: anytype, vmin: anytype, vmax: anytype) @TypeOf(v, vmin, vmax) { - var result = @max(vmin, v); - result = min(vmax, result); - return result; -} -pub fn inverse(a: anytype) @TypeOf(a) { - const T = @TypeOf(a); - return switch (T) { - Mat => inverseMat(a), - else => @compileError("zmath.inverse() not implemented for " ++ @typeName(T)), - }; -} -pub fn identity() Mat { - const static = struct { - const identity = Mat{ - f32x4(1.0, 0.0, 0.0, 0.0), - f32x4(0.0, 1.0, 0.0, 0.0), - f32x4(0.0, 0.0, 1.0, 0.0), - f32x4(0.0, 0.0, 0.0, 1.0), - }; - }; - return static.identity; -} -pub fn translation(x: f32, y: f32, z: f32) Mat { - return .{ - f32x4(1.0, 0.0, 0.0, 0.0), - f32x4(0.0, 1.0, 0.0, 0.0), - f32x4(0.0, 0.0, 1.0, 0.0), - f32x4(x, y, z, 1.0), - }; -} - -//--- -// Internal APIs -//--- - -inline fn f32x4(e0: f32, e1: f32, e2: f32, e3: f32) F32x4 { - return .{ e0, e1, e2, e3 }; -} - -const F32x4 = @Vector(4, f32); - -inline fn veclen(comptime T: type) comptime_int { - return @typeInfo(T).Vector.len; -} - -inline fn splat(comptime T: type, value: f32) T { - return @splat(value); -} -inline fn splatInt(comptime T: type, value: u32) T { - return @splat(@bitCast(value)); -} - -fn load(mem: []const f32, comptime T: type, comptime len: u32) T { - var v = splat(T, 0.0); - const loop_len = if (len == 0) veclen(T) else len; - comptime var i: u32 = 0; - inline while (i < loop_len) : (i += 1) { - v[i] = mem[i]; - } - return v; -} - -fn store(mem: []f32, v: anytype, comptime len: u32) void { - const T = @TypeOf(v); - const loop_len = if (len == 0) veclen(T) else len; - comptime var i: u32 = 0; - inline while (i < loop_len) : (i += 1) { - mem[i] = v[i]; - } -} - -inline fn loadArr2(arr: [2]f32) F32x4 { - return f32x4(arr[0], arr[1], 0.0, 0.0); -} -inline fn loadArr2zw(arr: [2]f32, z: f32, w: f32) F32x4 { - return f32x4(arr[0], arr[1], z, w); -} -inline fn loadArr3(arr: [3]f32) F32x4 { - return f32x4(arr[0], arr[1], arr[2], 0.0); -} -inline fn loadArr3w(arr: [3]f32, w: f32) F32x4 { - return f32x4(arr[0], arr[1], arr[2], w); -} -inline fn loadArr4(arr: [4]f32) F32x4 { - return f32x4(arr[0], arr[1], arr[2], arr[3]); -} - -inline fn storeArr2(arr: *[2]f32, v: F32x4) void { - arr.* = .{ v[0], v[1] }; -} -inline fn storeArr3(arr: *[3]f32, v: F32x4) void { - arr.* = .{ v[0], v[1], v[2] }; -} - -inline fn arr3Ptr(ptr: anytype) *const [3]f32 { - comptime assert(@typeInfo(@TypeOf(ptr)) == .Pointer); - const T = std.meta.Child(@TypeOf(ptr)); - comptime assert(T == F32x4); - return @as(*const [3]f32, @ptrCast(ptr)); -} - -inline fn arrNPtr(ptr: anytype) [*]const f32 { - comptime assert(@typeInfo(@TypeOf(ptr)) == .Pointer); - const T = std.meta.Child(@TypeOf(ptr)); - comptime assert(T == Mat or T == F32x4); - return @as([*]const f32, @ptrCast(ptr)); -} - -inline fn vecToArr2(v: Vec) [2]f32 { - return .{ v[0], v[1] }; -} -inline fn vecToArr3(v: Vec) [3]f32 { - return .{ v[0], v[1], v[2] }; -} -inline fn vecToArr4(v: Vec) [4]f32 { - return .{ v[0], v[1], v[2], v[3] }; -} - -fn all(vb: anytype, comptime len: u32) bool { - const T = @TypeOf(vb); - if (len > veclen(T)) { - @compileError("zmath.all(): 'len' is greater than vector len of type " ++ @typeName(T)); - } - const loop_len = if (len == 0) veclen(T) else len; - const ab: [veclen(T)]bool = vb; - comptime var i: u32 = 0; - var result = true; - inline while (i < loop_len) : (i += 1) { - result = result and ab[i]; - } - return result; -} - -fn any(vb: anytype, comptime len: u32) bool { - const T = @TypeOf(vb); - if (len > veclen(T)) { - @compileError("zmath.any(): 'len' is greater than vector len of type " ++ @typeName(T)); - } - const loop_len = if (len == 0) veclen(T) else len; - const ab: [veclen(T)]bool = vb; - comptime var i: u32 = 0; - var result = false; - inline while (i < loop_len) : (i += 1) { - result = result or ab[i]; - } - return result; -} - -inline fn isNearEqual( - v0: anytype, - v1: anytype, - epsilon: anytype, -) @Vector(veclen(@TypeOf(v0)), bool) { - const T = @TypeOf(v0, v1, epsilon); - const delta = v0 - v1; - const temp = maxFast(delta, splat(T, 0.0) - delta); - return temp <= epsilon; -} - -inline fn isNan( - v: anytype, -) @Vector(veclen(@TypeOf(v)), bool) { - return v != v; -} - -inline fn isInf( - v: anytype, -) @Vector(veclen(@TypeOf(v)), bool) { - const T = @TypeOf(v); - return abs(v) == splat(T, math.inf(f32)); -} - -inline fn isInBounds( - v: anytype, - bounds: anytype, -) @Vector(veclen(@TypeOf(v)), bool) { - const T = @TypeOf(v, bounds); - const Tu = @Vector(veclen(T), u1); - const Tr = @Vector(veclen(T), bool); - - // 2 x cmpleps, xorps, load, andps - const b0 = v <= bounds; - const b1 = (bounds * splat(T, -1.0)) <= v; - const b0u = @as(Tu, @bitCast(b0)); - const b1u = @as(Tu, @bitCast(b1)); - return @as(Tr, @bitCast(b0u & b1u)); -} - -inline fn andInt(v0: anytype, v1: anytype) @TypeOf(v0, v1) { - const T = @TypeOf(v0, v1); - const Tu = @Vector(veclen(T), u32); - const v0u = @as(Tu, @bitCast(v0)); - const v1u = @as(Tu, @bitCast(v1)); - return @as(T, @bitCast(v0u & v1u)); // andps -} - -inline fn andNotInt(v0: anytype, v1: anytype) @TypeOf(v0, v1) { - const T = @TypeOf(v0, v1); - const Tu = @Vector(veclen(T), u32); - const v0u = @as(Tu, @bitCast(v0)); - const v1u = @as(Tu, @bitCast(v1)); - return @as(T, @bitCast(~v0u & v1u)); // andnps -} - -inline fn orInt(v0: anytype, v1: anytype) @TypeOf(v0, v1) { - const T = @TypeOf(v0, v1); - const Tu = @Vector(veclen(T), u32); - const v0u = @as(Tu, @bitCast(v0)); - const v1u = @as(Tu, @bitCast(v1)); - return @as(T, @bitCast(v0u | v1u)); // orps -} - -inline fn norInt(v0: anytype, v1: anytype) @TypeOf(v0, v1) { - const T = @TypeOf(v0, v1); - const Tu = @Vector(veclen(T), u32); - const v0u = @as(Tu, @bitCast(v0)); - const v1u = @as(Tu, @bitCast(v1)); - return @as(T, @bitCast(~(v0u | v1u))); // por, pcmpeqd, pxor -} - -inline fn xorInt(v0: anytype, v1: anytype) @TypeOf(v0, v1) { - const T = @TypeOf(v0, v1); - const Tu = @Vector(veclen(T), u32); - const v0u = @as(Tu, @bitCast(v0)); - const v1u = @as(Tu, @bitCast(v1)); - return @as(T, @bitCast(v0u ^ v1u)); // xorps -} - -inline fn minFast(v0: anytype, v1: anytype) @TypeOf(v0, v1) { - return select(v0 < v1, v0, v1); // minps -} - -inline fn maxFast(v0: anytype, v1: anytype) @TypeOf(v0, v1) { - return select(v0 > v1, v0, v1); // maxps -} - -inline fn min(v0: anytype, v1: anytype) @TypeOf(v0, v1) { - // This will handle inf & nan - return @min(v0, v1); // minps, cmpunordps, andps, andnps, orps -} - -fn round(v: anytype) @TypeOf(v) { - const T = @TypeOf(v); - const sign = andInt(v, splatNegativeZero(T)); - const magic = orInt(splatNoFraction(T), sign); - var r1 = v + magic; - r1 = r1 - magic; - const r2 = abs(v); - const mask = r2 <= splatNoFraction(T); - return select(mask, r1, v); -} - -fn trunc(v: anytype) @TypeOf(v) { - const T = @TypeOf(v); - const mask = abs(v) < splatNoFraction(T); - const result = floatToIntAndBack(v); - return select(mask, result, v); -} - -fn floor(v: anytype) @TypeOf(v) { - const T = @TypeOf(v); - const mask = abs(v) < splatNoFraction(T); - var result = floatToIntAndBack(v); - const larger_mask = result > v; - const larger = select(larger_mask, splat(T, -1.0), splat(T, 0.0)); - result = result + larger; - return select(mask, result, v); -} - -fn ceil(v: anytype) @TypeOf(v) { - const T = @TypeOf(v); - const mask = abs(v) < splatNoFraction(T); - var result = floatToIntAndBack(v); - const smaller_mask = result < v; - const smaller = select(smaller_mask, splat(T, -1.0), splat(T, 0.0)); - result = result - smaller; - return select(mask, result, v); -} - -inline fn clampFast(v: anytype, vmin: anytype, vmax: anytype) @TypeOf(v, vmin, vmax) { - var result = maxFast(vmin, v); - result = minFast(vmax, result); - return result; -} - -inline fn saturate(v: anytype) @TypeOf(v) { - const T = @TypeOf(v); - var result = @max(v, splat(T, 0.0)); - result = min(result, splat(T, 1.0)); - return result; -} - -inline fn saturateFast(v: anytype) @TypeOf(v) { - const T = @TypeOf(v); - var result = maxFast(v, splat(T, 0.0)); - result = minFast(result, splat(T, 1.0)); - return result; -} - -inline fn select(mask: anytype, v0: anytype, v1: anytype) @TypeOf(v0, v1) { - return @select(f32, mask, v0, v1); -} - -inline fn lerp(v0: anytype, v1: anytype, t: f32) @TypeOf(v0, v1) { - const T = @TypeOf(v0, v1); - return v0 + (v1 - v0) * splat(T, t); // subps, shufps, addps, mulps -} - -inline fn lerpV(v0: anytype, v1: anytype, t: anytype) @TypeOf(v0, v1, t) { - return v0 + (v1 - v0) * t; // subps, addps, mulps -} - -inline fn lerpInverse(v0: anytype, v1: anytype, t: anytype) @TypeOf(v0, v1) { - const T = @TypeOf(v0, v1); - return (splat(T, t) - v0) / (v1 - v0); -} - -inline fn lerpInverseV(v0: anytype, v1: anytype, t: anytype) @TypeOf(v0, v1, t) { - return (t - v0) / (v1 - v0); -} - -// Frame rate independent lerp (or "damp"), for approaching things over time. -// Reference: https://www.gamedeveloper.com/programming/improved-lerp-smoothing- -inline fn lerpOverTime(v0: anytype, v1: anytype, rate: anytype, dt: anytype) @TypeOf(v0, v1) { - const t = std.math.exp2(-rate * dt); - return lerp(v0, v1, t); -} - -inline fn lerpVOverTime(v0: anytype, v1: anytype, rate: anytype, dt: anytype) @TypeOf(v0, v1, rate, dt) { - const t = std.math.exp2(-rate * dt); - return lerpV(v0, v1, t); -} - -/// To transform a vector of values from one range to another. -inline fn mapLinear(v: anytype, min1: anytype, max1: anytype, min2: anytype, max2: anytype) @TypeOf(v) { - const T = @TypeOf(v); - const min1V = splat(T, min1); - const max1V = splat(T, max1); - const min2V = splat(T, min2); - const max2V = splat(T, max2); - const dV = max1V - min1V; - return min2V + (v - min1V) * (max2V - min2V) / dV; -} - -inline fn mapLinearV(v: anytype, min1: anytype, max1: anytype, min2: anytype, max2: anytype) @TypeOf(v, min1, max1, min2, max2) { - const d = max1 - min1; - return min2 + (v - min1) * (max2 - min2) / d; -} - -const F32x4Component = enum { x, y, z, w }; - -inline fn swizzle( - v: F32x4, - comptime x: F32x4Component, - comptime y: F32x4Component, - comptime z: F32x4Component, - comptime w: F32x4Component, -) F32x4 { - return @shuffle(f32, v, undefined, [4]i32{ @intFromEnum(x), @intFromEnum(y), @intFromEnum(z), @intFromEnum(w) }); -} - -inline fn mod(v0: anytype, v1: anytype) @TypeOf(v0, v1) { - // vdivps, vroundps, vmulps, vsubps - return v0 - v1 * trunc(v0 / v1); -} - -fn modAngle(v: anytype) @TypeOf(v) { - const T = @TypeOf(v); - return switch (T) { - f32 => modAngle32(v), - F32x4 => modAngle32xN(v), - else => @compileError("zmath.modAngle() not implemented for " ++ @typeName(T)), - }; -} - -inline fn modAngle32xN(v: anytype) @TypeOf(v) { - const T = @TypeOf(v); - return v - splat(T, math.tau) * round(v * splat(T, 1.0 / math.tau)); // 2 x vmulps, 2 x load, vroundps, vaddps -} - -inline fn mulAdd(v0: anytype, v1: anytype, v2: anytype) @TypeOf(v0, v1, v2) { - return v0 * v1 + v2; // Compiler will generate mul, add sequence (no fma even if the target supports it). -} - -fn sin32xN(v: anytype) @TypeOf(v) { - // 11-degree minimax approximation - const T = @TypeOf(v); - - var x = modAngle(v); - const sign = andInt(x, splatNegativeZero(T)); - const c = orInt(sign, splat(T, math.pi)); - const absx = andNotInt(sign, x); - const rflx = c - x; - const comp = absx <= splat(T, 0.5 * math.pi); - x = select(comp, x, rflx); - const x2 = x * x; - - var result = mulAdd(splat(T, -2.3889859e-08), x2, splat(T, 2.7525562e-06)); - result = mulAdd(result, x2, splat(T, -0.00019840874)); - result = mulAdd(result, x2, splat(T, 0.0083333310)); - result = mulAdd(result, x2, splat(T, -0.16666667)); - result = mulAdd(result, x2, splat(T, 1.0)); - return x * result; -} - -fn cos32xN(v: anytype) @TypeOf(v) { - // 10-degree minimax approximation - const T = @TypeOf(v); - - var x = modAngle(v); - var sign = andInt(x, splatNegativeZero(T)); - const c = orInt(sign, splat(T, math.pi)); - const absx = andNotInt(sign, x); - const rflx = c - x; - const comp = absx <= splat(T, 0.5 * math.pi); - x = select(comp, x, rflx); - sign = select(comp, splat(T, 1.0), splat(T, -1.0)); - const x2 = x * x; - - var result = mulAdd(splat(T, -2.6051615e-07), x2, splat(T, 2.4760495e-05)); - result = mulAdd(result, x2, splat(T, -0.0013888378)); - result = mulAdd(result, x2, splat(T, 0.041666638)); - result = mulAdd(result, x2, splat(T, -0.5)); - result = mulAdd(result, x2, splat(T, 1.0)); - return sign * result; -} - -fn sincos(v: anytype) [2]@TypeOf(v) { - const T = @TypeOf(v); - return switch (T) { - f32 => sincos32(v), - else => @compileError("zmath.sincos() not implemented for " ++ @typeName(T)), - }; -} - -inline fn dot2(v0: Vec, v1: Vec) F32x4 { - var xmm0 = v0 * v1; // | x0*x1 | y0*y1 | -- | -- | - const xmm1 = swizzle(xmm0, .y, .x, .x, .x); // | y0*y1 | -- | -- | -- | - xmm0 = f32x4(xmm0[0] + xmm1[0], xmm0[1], xmm0[2], xmm0[3]); // | x0*x1 + y0*y1 | -- | -- | -- | - return swizzle(xmm0, .x, .x, .x, .x); -} - -inline fn dot4(v0: Vec, v1: Vec) F32x4 { - var xmm0 = v0 * v1; // | x0*x1 | y0*y1 | z0*z1 | w0*w1 | - var xmm1 = swizzle(xmm0, .y, .x, .w, .x); // | y0*y1 | -- | w0*w1 | -- | - xmm1 = xmm0 + xmm1; // | x0*x1 + y0*y1 | -- | z0*z1 + w0*w1 | -- | - xmm0 = swizzle(xmm1, .z, .x, .x, .x); // | z0*z1 + w0*w1 | -- | -- | -- | - xmm0 = f32x4(xmm0[0] + xmm1[0], xmm0[1], xmm0[2], xmm0[2]); // addss - return swizzle(xmm0, .x, .x, .x, .x); -} - -inline fn lengthSq2(v: Vec) F32x4 { - return dot2(v, v); -} -inline fn lengthSq3(v: Vec) F32x4 { - return dot3(v, v); -} - -inline fn length2(v: Vec) F32x4 { - return @sqrt(dot2(v, v)); -} -inline fn length3(v: Vec) F32x4 { - return @sqrt(dot3(v, v)); -} -inline fn length4(v: Vec) F32x4 { - return @sqrt(dot4(v, v)); -} - -inline fn normalize2(v: Vec) Vec { - return v * splat(F32x4, 1.0) / @sqrt(dot2(v, v)); -} -inline fn normalize4(v: Vec) Vec { - return v * splat(F32x4, 1.0) / @sqrt(dot4(v, v)); -} - -fn vecMulMat(v: Vec, m: Mat) Vec { - const vx = @shuffle(f32, v, undefined, [4]i32{ 0, 0, 0, 0 }); - const vy = @shuffle(f32, v, undefined, [4]i32{ 1, 1, 1, 1 }); - const vz = @shuffle(f32, v, undefined, [4]i32{ 2, 2, 2, 2 }); - const vw = @shuffle(f32, v, undefined, [4]i32{ 3, 3, 3, 3 }); - return vx * m[0] + vy * m[1] + vz * m[2] + vw * m[3]; -} -fn matMulVec(m: Mat, v: Vec) Vec { - return .{ dot4(m[0], v)[0], dot4(m[1], v)[0], dot4(m[2], v)[0], dot4(m[3], v)[0] }; -} - -fn matFromArr(arr: [16]f32) Mat { - return Mat{ - f32x4(arr[0], arr[1], arr[2], arr[3]), - f32x4(arr[4], arr[5], arr[6], arr[7]), - f32x4(arr[8], arr[9], arr[10], arr[11]), - f32x4(arr[12], arr[13], arr[14], arr[15]), - }; -} - -fn mulRetType(comptime Ta: type, comptime Tb: type) type { - if (Ta == Mat and Tb == Mat) { - return Mat; - } else if ((Ta == f32 and Tb == Mat) or (Ta == Mat and Tb == f32)) { - return Mat; - } else if ((Ta == Vec and Tb == Mat) or (Ta == Mat and Tb == Vec)) { - return Vec; - } - @compileError("zmath.mul() not implemented for types: " ++ @typeName(Ta) ++ @typeName(Tb)); -} - -fn mulMat(m0: Mat, m1: Mat) Mat { - var result: Mat = undefined; - comptime var row: u32 = 0; - inline while (row < 4) : (row += 1) { - const vx = swizzle(m0[row], .x, .x, .x, .x); - const vy = swizzle(m0[row], .y, .y, .y, .y); - const vz = swizzle(m0[row], .z, .z, .z, .z); - const vw = swizzle(m0[row], .w, .w, .w, .w); - result[row] = mulAdd(vx, m1[0], vz * m1[2]) + mulAdd(vy, m1[1], vw * m1[3]); - } - return result; -} -fn lookToLh(eyepos: Vec, eyedir: Vec, updir: Vec) Mat { - const az = normalize3(eyedir); - const ax = normalize3(cross3(updir, az)); - const ay = normalize3(cross3(az, ax)); - return transpose(.{ - f32x4(ax[0], ax[1], ax[2], -dot3(ax, eyepos)[0]), - f32x4(ay[0], ay[1], ay[2], -dot3(ay, eyepos)[0]), - f32x4(az[0], az[1], az[2], -dot3(az, eyepos)[0]), - f32x4(0.0, 0.0, 0.0, 1.0), - }); -} - -fn inverseMat(m: Mat) Mat { - return inverseDet(m, null); -} - -fn inverseDet(m: Mat, out_det: ?*F32x4) Mat { - const mt = transpose(m); - var v0: [4]F32x4 = undefined; - var v1: [4]F32x4 = undefined; - - v0[0] = swizzle(mt[2], .x, .x, .y, .y); - v1[0] = swizzle(mt[3], .z, .w, .z, .w); - v0[1] = swizzle(mt[0], .x, .x, .y, .y); - v1[1] = swizzle(mt[1], .z, .w, .z, .w); - v0[2] = @shuffle(f32, mt[2], mt[0], [4]i32{ 0, 2, ~@as(i32, 0), ~@as(i32, 2) }); - v1[2] = @shuffle(f32, mt[3], mt[1], [4]i32{ 1, 3, ~@as(i32, 1), ~@as(i32, 3) }); - - var d0 = v0[0] * v1[0]; - var d1 = v0[1] * v1[1]; - var d2 = v0[2] * v1[2]; - - v0[0] = swizzle(mt[2], .z, .w, .z, .w); - v1[0] = swizzle(mt[3], .x, .x, .y, .y); - v0[1] = swizzle(mt[0], .z, .w, .z, .w); - v1[1] = swizzle(mt[1], .x, .x, .y, .y); - v0[2] = @shuffle(f32, mt[2], mt[0], [4]i32{ 1, 3, ~@as(i32, 1), ~@as(i32, 3) }); - v1[2] = @shuffle(f32, mt[3], mt[1], [4]i32{ 0, 2, ~@as(i32, 0), ~@as(i32, 2) }); - - d0 = mulAdd(-v0[0], v1[0], d0); - d1 = mulAdd(-v0[1], v1[1], d1); - d2 = mulAdd(-v0[2], v1[2], d2); - - v0[0] = swizzle(mt[1], .y, .z, .x, .y); - v1[0] = @shuffle(f32, d0, d2, [4]i32{ ~@as(i32, 1), 1, 3, 0 }); - v0[1] = swizzle(mt[0], .z, .x, .y, .x); - v1[1] = @shuffle(f32, d0, d2, [4]i32{ 3, ~@as(i32, 1), 1, 2 }); - v0[2] = swizzle(mt[3], .y, .z, .x, .y); - v1[2] = @shuffle(f32, d1, d2, [4]i32{ ~@as(i32, 3), 1, 3, 0 }); - v0[3] = swizzle(mt[2], .z, .x, .y, .x); - v1[3] = @shuffle(f32, d1, d2, [4]i32{ 3, ~@as(i32, 3), 1, 2 }); - - var c0 = v0[0] * v1[0]; - var c2 = v0[1] * v1[1]; - var c4 = v0[2] * v1[2]; - var c6 = v0[3] * v1[3]; - - v0[0] = swizzle(mt[1], .z, .w, .y, .z); - v1[0] = @shuffle(f32, d0, d2, [4]i32{ 3, 0, 1, ~@as(i32, 0) }); - v0[1] = swizzle(mt[0], .w, .z, .w, .y); - v1[1] = @shuffle(f32, d0, d2, [4]i32{ 2, 1, ~@as(i32, 0), 0 }); - v0[2] = swizzle(mt[3], .z, .w, .y, .z); - v1[2] = @shuffle(f32, d1, d2, [4]i32{ 3, 0, 1, ~@as(i32, 2) }); - v0[3] = swizzle(mt[2], .w, .z, .w, .y); - v1[3] = @shuffle(f32, d1, d2, [4]i32{ 2, 1, ~@as(i32, 2), 0 }); - - c0 = mulAdd(-v0[0], v1[0], c0); - c2 = mulAdd(-v0[1], v1[1], c2); - c4 = mulAdd(-v0[2], v1[2], c4); - c6 = mulAdd(-v0[3], v1[3], c6); - - v0[0] = swizzle(mt[1], .w, .x, .w, .x); - v1[0] = @shuffle(f32, d0, d2, [4]i32{ 2, ~@as(i32, 1), ~@as(i32, 0), 2 }); - v0[1] = swizzle(mt[0], .y, .w, .x, .z); - v1[1] = @shuffle(f32, d0, d2, [4]i32{ ~@as(i32, 1), 0, 3, ~@as(i32, 0) }); - v0[2] = swizzle(mt[3], .w, .x, .w, .x); - v1[2] = @shuffle(f32, d1, d2, [4]i32{ 2, ~@as(i32, 3), ~@as(i32, 2), 2 }); - v0[3] = swizzle(mt[2], .y, .w, .x, .z); - v1[3] = @shuffle(f32, d1, d2, [4]i32{ ~@as(i32, 3), 0, 3, ~@as(i32, 2) }); - - const c1 = mulAdd(-v0[0], v1[0], c0); - const c3 = mulAdd(v0[1], v1[1], c2); - const c5 = mulAdd(-v0[2], v1[2], c4); - const c7 = mulAdd(v0[3], v1[3], c6); - - c0 = mulAdd(v0[0], v1[0], c0); - c2 = mulAdd(-v0[1], v1[1], c2); - c4 = mulAdd(v0[2], v1[2], c4); - c6 = mulAdd(-v0[3], v1[3], c6); - - var mr = Mat{ - f32x4(c0[0], c1[1], c0[2], c1[3]), - f32x4(c2[0], c3[1], c2[2], c3[3]), - f32x4(c4[0], c5[1], c4[2], c5[3]), - f32x4(c6[0], c7[1], c6[2], c7[3]), - }; - - const det = dot4(mr[0], mt[0]); - if (out_det != null) { - out_det.?.* = det; - } - - if (math.approxEqAbs(f32, det[0], 0.0, math.floatEps(f32))) { - return .{ - f32x4(0.0, 0.0, 0.0, 0.0), - f32x4(0.0, 0.0, 0.0, 0.0), - f32x4(0.0, 0.0, 0.0, 0.0), - f32x4(0.0, 0.0, 0.0, 0.0), - }; - } - - const scale = splat(F32x4, 1.0) / det; - mr[0] *= scale; - mr[1] *= scale; - mr[2] *= scale; - mr[3] *= scale; - return mr; -} - -fn quatFromNormAxisAngle(axis: Vec, angle: f32) Quat { - const n = f32x4(axis[0], axis[1], axis[2], 1.0); - const sc = sincos(0.5 * angle); - return n * f32x4(sc[0], sc[0], sc[0], sc[1]); -} - -fn sin32(v: f32) f32 { - var y = v - math.tau * @round(v * 1.0 / math.tau); - - if (y > 0.5 * math.pi) { - y = math.pi - y; - } else if (y < -math.pi * 0.5) { - y = -math.pi - y; - } - const y2 = y * y; - - // 11-degree minimax approximation - var sinv = mulAdd(@as(f32, -2.3889859e-08), y2, 2.7525562e-06); - sinv = mulAdd(sinv, y2, -0.00019840874); - sinv = mulAdd(sinv, y2, 0.0083333310); - sinv = mulAdd(sinv, y2, -0.16666667); - return y * mulAdd(sinv, y2, 1.0); -} -fn cos32(v: f32) f32 { - var y = v - math.tau * @round(v * 1.0 / math.tau); - - const sign = blk: { - if (y > 0.5 * math.pi) { - y = math.pi - y; - break :blk @as(f32, -1.0); - } else if (y < -math.pi * 0.5) { - y = -math.pi - y; - break :blk @as(f32, -1.0); - } else { - break :blk @as(f32, 1.0); - } - }; - const y2 = y * y; - - // 10-degree minimax approximation - var cosv = mulAdd(@as(f32, -2.6051615e-07), y2, 2.4760495e-05); - cosv = mulAdd(cosv, y2, -0.0013888378); - cosv = mulAdd(cosv, y2, 0.041666638); - cosv = mulAdd(cosv, y2, -0.5); - return sign * mulAdd(cosv, y2, 1.0); -} -fn sincos32(v: f32) [2]f32 { - var y = v - math.tau * @round(v * 1.0 / math.tau); - - const sign = blk: { - if (y > 0.5 * math.pi) { - y = math.pi - y; - break :blk @as(f32, -1.0); - } else if (y < -math.pi * 0.5) { - y = -math.pi - y; - break :blk @as(f32, -1.0); - } else { - break :blk @as(f32, 1.0); - } - }; - const y2 = y * y; - - // 11-degree minimax approximation - var sinv = mulAdd(@as(f32, -2.3889859e-08), y2, 2.7525562e-06); - sinv = mulAdd(sinv, y2, -0.00019840874); - sinv = mulAdd(sinv, y2, 0.0083333310); - sinv = mulAdd(sinv, y2, -0.16666667); - sinv = y * mulAdd(sinv, y2, 1.0); - - // 10-degree minimax approximation - var cosv = mulAdd(@as(f32, -2.6051615e-07), y2, 2.4760495e-05); - cosv = mulAdd(cosv, y2, -0.0013888378); - cosv = mulAdd(cosv, y2, 0.041666638); - cosv = mulAdd(cosv, y2, -0.5); - cosv = sign * mulAdd(cosv, y2, 1.0); - - return .{ sinv, cosv }; -} - -fn modAngle32(in_angle: f32) f32 { - const angle = in_angle + math.pi; - var temp: f32 = @abs(angle); - temp = temp - (2.0 * math.pi * @as(f32, @floatFromInt(@as(i32, @intFromFloat(temp / math.pi))))); - temp = temp - math.pi; - if (angle < 0.0) { - temp = -temp; - } - return temp; -} - -const f32x4_sign_mask1: F32x4 = F32x4{ @as(f32, @bitCast(@as(u32, 0x8000_0000))), 0, 0, 0 }; -const f32x4_mask2: F32x4 = F32x4{ - @as(f32, @bitCast(@as(u32, 0xffff_ffff))), - @as(f32, @bitCast(@as(u32, 0xffff_ffff))), - 0, - 0, -}; -const f32x4_mask3: F32x4 = F32x4{ - @as(f32, @bitCast(@as(u32, 0xffff_ffff))), - @as(f32, @bitCast(@as(u32, 0xffff_ffff))), - @as(f32, @bitCast(@as(u32, 0xffff_ffff))), - 0, -}; - -inline fn splatNegativeZero(comptime T: type) T { - return @splat(@as(f32, @bitCast(@as(u32, 0x8000_0000)))); -} -inline fn splatNoFraction(comptime T: type) T { - return @splat(@as(f32, 8_388_608.0)); -} - -fn floatToIntAndBack(v: anytype) @TypeOf(v) { - // This routine won't handle nan, inf and numbers greater than 8_388_608.0 (will generate undefined values). - @setRuntimeSafety(false); - - const T = @TypeOf(v); - const len = veclen(T); - - var vi32: [len]i32 = undefined; - comptime var i: u32 = 0; - // vcvttps2dq - inline while (i < len) : (i += 1) { - vi32[i] = @as(i32, @intFromFloat(v[i])); - } - - var vf32: [len]f32 = undefined; - i = 0; - // vcvtdq2ps - inline while (i < len) : (i += 1) { - vf32[i] = @as(f32, @floatFromInt(vi32[i])); - } - - return vf32; -} - -fn approxEqAbs(v0: anytype, v1: anytype, eps: f32) bool { - const T = @TypeOf(v0, v1); - comptime var i: comptime_int = 0; - inline while (i < veclen(T)) : (i += 1) { - if (!math.approxEqAbs(f32, v0[i], v1[i], eps)) { - return false; - } - } - return true; -}