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; -}