More wrappers, more cleanup
This commit is contained in:
34
src/Game.zig
34
src/Game.zig
@@ -1,30 +1,28 @@
|
||||
const Game = @This();
|
||||
const std = @import("std");
|
||||
|
||||
const math = @import("math.zig");
|
||||
const glfw = @import("zglfw");
|
||||
const vk = @import("vulkan");
|
||||
|
||||
const math = @import("math.zig");
|
||||
const worldgen = @import("worldgen.zig");
|
||||
|
||||
const Blocks = @import("assets/Blocks.zig");
|
||||
const Chunk = @import("assets/Chunk.zig");
|
||||
const Materials = @import("assets/Materials.zig");
|
||||
const Textures = @import("assets/Textures.zig");
|
||||
const CommandBuffer = @import("engine/CommandBuffer.zig").CommandBuffer;
|
||||
const CommandBuffer = @import("engine/CommandBuffer.zig");
|
||||
const Engine = @import("engine/Engine.zig");
|
||||
const GenericBuffer = @import("engine/GenericBuffer.zig").GenericBuffer;
|
||||
const Iterator2 = math.Iterator2;
|
||||
const Materials = @import("assets/Materials.zig");
|
||||
const Matrix4x4 = math.Matrix4x4;
|
||||
const Player = @import("Player.zig");
|
||||
const Quaternion = math.Quaternion;
|
||||
const StagingBuffer = @import("engine/StagingBuffer.zig");
|
||||
const Swapchain = @import("engine/Swapchain.zig");
|
||||
const Player = @import("Player.zig");
|
||||
const Interator2 = math.Interator2;
|
||||
const Matrix4x4 = math.Matrix4x4;
|
||||
const Quaternion = math.Quaternion;
|
||||
const Textures = @import("assets/Textures.zig");
|
||||
const Vector2 = math.Vector2;
|
||||
const Vector2x8 = math.Vector2x8;
|
||||
const Vector3 = math.Vector3;
|
||||
const Vector4 = math.Vector4;
|
||||
const ps = math.ps;
|
||||
|
||||
const PointLight = extern struct {
|
||||
positionWS: [3]f32,
|
||||
@@ -121,7 +119,7 @@ index_buffer: IndexBuffer,
|
||||
|
||||
global_uniforms: GlobalUniformsBuffer,
|
||||
global_uniforms_staging_buffer: StagingBuffer,
|
||||
global_uniforms_transfer_command_buffer: CommandBuffer(.transfer, .persistent),
|
||||
global_uniforms_transfer_command_buffer: CommandBuffer,
|
||||
global_uniforms_transfer_semaphores: []vk.Semaphore,
|
||||
point_lights: PointLightBuffer,
|
||||
directional_lights: DirectionalLightBuffer,
|
||||
@@ -305,10 +303,10 @@ pub fn init(allocator: std.mem.Allocator, engine: *Engine, swapchain: *Swapchain
|
||||
});
|
||||
errdefer global_uniforms_staging_buffer.deinit(engine);
|
||||
|
||||
var global_uniforms_transfer_command_buffer: CommandBuffer(.transfer, .persistent) = try .init(engine);
|
||||
var global_uniforms_transfer_command_buffer: CommandBuffer = try .init(engine, .transfer, .persistent);
|
||||
errdefer global_uniforms_transfer_command_buffer.deinit(engine);
|
||||
|
||||
try global_uniforms_transfer_command_buffer.beginCommandBuffer(.{});
|
||||
try global_uniforms_transfer_command_buffer.beginCommandBuffer();
|
||||
global_uniforms_transfer_command_buffer.copyBuffer(
|
||||
global_uniforms_staging_buffer.buffer,
|
||||
global_uniforms.buffer,
|
||||
@@ -608,8 +606,10 @@ pub fn init(allocator: std.mem.Allocator, engine: *Engine, swapchain: *Swapchain
|
||||
|
||||
const world_seed = engine.random.int(u64);
|
||||
std.log.info("Using world seed 0x{x:0<16}", .{world_seed});
|
||||
var it = Interator2(i16).init(-8, -8, 7, 7);
|
||||
|
||||
var it = Iterator2(i16).init(.{
|
||||
.min = .{ -8, -8 },
|
||||
.max = .{ 7, 7 },
|
||||
});
|
||||
while (it.next()) |chunk_coords2| {
|
||||
const chunk_coords3 = chunk_coords2 ++ [_]i16{0};
|
||||
|
||||
@@ -852,10 +852,10 @@ fn render(self: *Game) !void {
|
||||
|
||||
const extent = self.swapchain.extent;
|
||||
|
||||
const command_buffer: CommandBuffer(.graphics, .transient) = try .init(self.engine);
|
||||
const command_buffer: CommandBuffer = try .init(self.engine, .graphics, .transient);
|
||||
// NOTE Do not free command buffer yet
|
||||
|
||||
try command_buffer.beginCommandBuffer(.{});
|
||||
try command_buffer.beginCommandBuffer();
|
||||
{
|
||||
command_buffer.beginRenderPass(.{
|
||||
.render_pass = self.swapchain.render_pass,
|
||||
|
||||
@@ -6,7 +6,7 @@ const vk = @import("vulkan");
|
||||
const math = @import("../math.zig");
|
||||
|
||||
const Blocks = @import("Blocks.zig");
|
||||
const CommandBuffer = @import("../engine/CommandBuffer.zig").CommandBuffer;
|
||||
const CommandBuffer = @import("../engine/CommandBuffer.zig");
|
||||
const Engine = @import("../engine/Engine.zig");
|
||||
const Game = @import("../Game.zig");
|
||||
const GenericBuffer = @import("../engine/GenericBuffer.zig").GenericBuffer;
|
||||
@@ -235,7 +235,7 @@ pub fn refresh(self: *Chunk, engine: *Engine, blocks: *const Blocks, neighbors:
|
||||
self.object_count = object_count;
|
||||
}
|
||||
|
||||
pub fn draw(self: *const Chunk, layout: vk.PipelineLayout, command_buffer: CommandBuffer(.graphics, .transient)) void {
|
||||
pub fn draw(self: *const Chunk, layout: vk.PipelineLayout, command_buffer: CommandBuffer) void {
|
||||
command_buffer.bindDescriptorSets(.graphics, layout, 1, &.{self.descriptor_set}, &.{});
|
||||
command_buffer.drawIndexed(.{ .index_count = 6, .instance_count = self.object_count });
|
||||
}
|
||||
|
||||
@@ -1,3 +1,12 @@
|
||||
//! A thin wrapper around `@import("vk").CommandBufferProxy` that ziggifies
|
||||
//! arguments by turning pointer-length pairs into slices and integrates with
|
||||
//! different queues from `Engine` struct.
|
||||
//!
|
||||
//! The wrapper retains information about the queue type and whether its
|
||||
//! transient, such that it can submit to the correct queue preallocated in the
|
||||
//! `Engine` struct when calling `CommandBuffer.submit`.
|
||||
|
||||
const CommandBuffer = @This();
|
||||
const std = @import("std");
|
||||
|
||||
const vk = @import("vulkan");
|
||||
@@ -7,6 +16,42 @@ const QueueType = @import("QueueType.zig").QueueType;
|
||||
const Transient = @import("Transient.zig").Transient;
|
||||
const WaitSemaphore = @import("WaitSemaphore.zig");
|
||||
|
||||
proxy: vk.CommandBufferProxy,
|
||||
allocator: std.mem.Allocator,
|
||||
queue_type: QueueType,
|
||||
transient: Transient,
|
||||
|
||||
pub fn init(engine: *Engine, queue_type: QueueType, transient: Transient) !CommandBuffer {
|
||||
const handle = try engine.allocateCommandBuffer(.{
|
||||
.queue_type = queue_type,
|
||||
.transient = transient,
|
||||
.level = .primary,
|
||||
});
|
||||
const proxy: vk.CommandBufferProxy = .init(handle, engine.device.wrapper);
|
||||
const allocator = engine.vk_allocator.allocator;
|
||||
return .{
|
||||
.proxy = proxy,
|
||||
.allocator = allocator,
|
||||
.queue_type = queue_type,
|
||||
.transient = transient,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn deinit(self: *CommandBuffer, engine: *Engine) void {
|
||||
engine.freeCommandBuffer(.{
|
||||
.queue_type = self.queue_type,
|
||||
.transient = self.transient,
|
||||
.command_buffer = self.proxy.handle,
|
||||
});
|
||||
self.* = undefined;
|
||||
}
|
||||
|
||||
pub fn submit(self: CommandBuffer, engine: *Engine, submit_info: SubmitInfo) !void {
|
||||
try submitCommandBuffer(engine, self.queue_type, self.proxy.handle, submit_info);
|
||||
}
|
||||
|
||||
// --- VULKAN WRAPPERS ---------------------------------------------------------
|
||||
|
||||
pub const DrawIndexed = struct {
|
||||
index_count: u32,
|
||||
instance_count: u32 = 1,
|
||||
@@ -42,218 +87,152 @@ pub const VertexBufferBinding = struct {
|
||||
offset: usize,
|
||||
};
|
||||
|
||||
pub fn CommandBuffer(comptime queue_type: QueueType, comptime transient: Transient) type {
|
||||
return struct {
|
||||
const Self = @This();
|
||||
|
||||
proxy: vk.CommandBufferProxy,
|
||||
allocator: std.mem.Allocator,
|
||||
|
||||
pub fn init(engine: *const Engine) !Self {
|
||||
const handle = try allocateCommandBuffer(engine, queue_type, transient);
|
||||
const proxy: vk.CommandBufferProxy = .init(handle, engine.device.wrapper);
|
||||
const allocator = engine.vk_allocator.allocator;
|
||||
return .{ .proxy = proxy, .allocator = allocator };
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Self, engine: *const Engine) void {
|
||||
freeCommandBuffer(engine, queue_type, transient, self.proxy.handle);
|
||||
self.* = undefined;
|
||||
}
|
||||
|
||||
pub fn submit(self: Self, engine: *const Engine, submit_info: SubmitInfo) !void {
|
||||
try submitCommandBuffer(engine, queue_type, self.proxy.handle, submit_info);
|
||||
}
|
||||
|
||||
pub const CommandBufferBeginInfo = struct {
|
||||
flags: vk.CommandBufferUsageFlags = .{
|
||||
.one_time_submit_bit = switch (transient) {
|
||||
.persistent => false,
|
||||
.transient => true,
|
||||
},
|
||||
pub fn beginCommandBuffer(self: CommandBuffer) !void {
|
||||
try self.proxy.beginCommandBuffer(&.{
|
||||
.flags = .{
|
||||
.one_time_submit_bit = switch (self.transient) {
|
||||
.persistent => true,
|
||||
.transient => false,
|
||||
},
|
||||
inheritance_info: ?vk.CommandBufferInheritanceInfo = null,
|
||||
};
|
||||
|
||||
pub fn beginCommandBuffer(self: Self, begin_info: CommandBufferBeginInfo) !void {
|
||||
try self.proxy.beginCommandBuffer(&.{
|
||||
.flags = begin_info.flags,
|
||||
.p_inheritance_info = if (begin_info.inheritance_info) |*x| x else null,
|
||||
});
|
||||
}
|
||||
|
||||
pub inline fn beginRenderPass(self: Self, render_pass_begin: RenderPassBeginInfo, contents: vk.SubpassContents) void {
|
||||
self.proxy.beginRenderPass(&.{
|
||||
.render_pass = render_pass_begin.render_pass,
|
||||
.framebuffer = render_pass_begin.framebuffer,
|
||||
.render_area = render_pass_begin.render_area,
|
||||
.clear_value_count = @intCast(render_pass_begin.clear_values.len),
|
||||
.p_clear_values = render_pass_begin.clear_values.ptr,
|
||||
}, contents);
|
||||
}
|
||||
|
||||
pub inline fn bindDescriptorSet(
|
||||
self: Self,
|
||||
pipeline_bind_point: vk.PipelineBindPoint,
|
||||
layout: vk.PipelineLayout,
|
||||
set: u32,
|
||||
descriptor_set: vk.DescriptorSet,
|
||||
dynamic_offset: ?u32,
|
||||
) void {
|
||||
self.bindDescriptorSets(
|
||||
pipeline_bind_point,
|
||||
layout,
|
||||
set,
|
||||
&.{descriptor_set},
|
||||
if (dynamic_offset) |x| &.{x} else &.{},
|
||||
);
|
||||
}
|
||||
|
||||
pub inline fn bindDescriptorSets(
|
||||
self: Self,
|
||||
pipeline_bind_point: vk.PipelineBindPoint,
|
||||
layout: vk.PipelineLayout,
|
||||
first_set: u32,
|
||||
descriptor_sets: []const vk.DescriptorSet,
|
||||
dynamic_offsets: []const u32,
|
||||
) void {
|
||||
self.proxy.bindDescriptorSets(
|
||||
pipeline_bind_point,
|
||||
layout,
|
||||
first_set,
|
||||
@intCast(descriptor_sets.len),
|
||||
descriptor_sets.ptr,
|
||||
@intCast(dynamic_offsets.len),
|
||||
dynamic_offsets.ptr,
|
||||
);
|
||||
}
|
||||
|
||||
pub inline fn bindPipeline(self: Self, pipeline_bind_point: vk.PipelineBindPoint, pipeline: vk.Pipeline) void {
|
||||
self.proxy.bindPipeline(pipeline_bind_point, pipeline);
|
||||
}
|
||||
|
||||
pub inline fn bindIndexBuffer(self: Self, buffer: vk.Buffer, offset: u64, index_type: vk.IndexType) void {
|
||||
self.proxy.bindIndexBuffer(buffer, offset, index_type);
|
||||
}
|
||||
|
||||
pub inline fn bindVertexBuffers(self: Self, first_binding: u32, bindings: []const VertexBufferBinding) !void {
|
||||
var vertex_buffer_bindings = std.MultiArrayList(VertexBufferBinding){};
|
||||
defer vertex_buffer_bindings.deinit(self.allocator);
|
||||
try vertex_buffer_bindings.ensureTotalCapacity(self.allocator, bindings.len);
|
||||
|
||||
for (bindings) |binding| {
|
||||
vertex_buffer_bindings.appendAssumeCapacity(binding);
|
||||
}
|
||||
|
||||
self.proxy.bindVertexBuffers(
|
||||
first_binding,
|
||||
@intCast(vertex_buffer_bindings.len),
|
||||
vertex_buffer_bindings.items(.buffer).ptr,
|
||||
vertex_buffer_bindings.items(.offset).ptr,
|
||||
);
|
||||
}
|
||||
|
||||
pub inline fn drawIndexed(self: Self, draw_indexed: DrawIndexed) void {
|
||||
self.proxy.drawIndexed(
|
||||
draw_indexed.index_count,
|
||||
draw_indexed.instance_count,
|
||||
draw_indexed.first_index,
|
||||
draw_indexed.vertex_offset,
|
||||
draw_indexed.first_instance,
|
||||
);
|
||||
}
|
||||
|
||||
pub inline fn endCommandBuffer(self: Self) !void {
|
||||
try self.proxy.endCommandBuffer();
|
||||
}
|
||||
|
||||
pub inline fn endRenderPass(self: Self) void {
|
||||
self.proxy.endRenderPass();
|
||||
}
|
||||
|
||||
pub inline fn copyBuffer(
|
||||
self: Self,
|
||||
src_buffer: vk.Buffer,
|
||||
dst_buffer: vk.Buffer,
|
||||
regions: []const vk.BufferCopy,
|
||||
) void {
|
||||
self.proxy.copyBuffer(src_buffer, dst_buffer, @intCast(regions.len), regions.ptr);
|
||||
}
|
||||
|
||||
pub inline fn copyBufferToImage(
|
||||
self: Self,
|
||||
src_buffer: vk.Buffer,
|
||||
dst_image: vk.Image,
|
||||
dst_image_layout: vk.ImageLayout,
|
||||
regions: []const vk.BufferImageCopy,
|
||||
) void {
|
||||
self.proxy.copyBufferToImage(src_buffer, dst_image, dst_image_layout, @intCast(regions.len), regions.ptr);
|
||||
}
|
||||
|
||||
pub inline fn pipelineBarrier(self: Self, barrier: PipelineBarrier) void {
|
||||
self.proxy.pipelineBarrier(
|
||||
barrier.src_stage_mask,
|
||||
barrier.dst_stage_mask,
|
||||
barrier.dependency_flags,
|
||||
@intCast(barrier.memory_barriers.len),
|
||||
barrier.memory_barriers.ptr,
|
||||
@intCast(barrier.buffer_memory_barriers.len),
|
||||
barrier.buffer_memory_barriers.ptr,
|
||||
@intCast(barrier.image_memory_barriers.len),
|
||||
barrier.image_memory_barriers.ptr,
|
||||
);
|
||||
}
|
||||
|
||||
pub inline fn setScissor(self: Self, first_scissor: u32, scissors: []const vk.Rect2D) void {
|
||||
self.proxy.setScissor(first_scissor, @intCast(scissors.len), scissors.ptr);
|
||||
}
|
||||
|
||||
pub inline fn setViewport(self: Self, first_viewport: u32, viewports: []const vk.Viewport) void {
|
||||
self.proxy.setViewport(first_viewport, @intCast(viewports.len), viewports.ptr);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
inline fn resolveCommandPool(self: *const Engine, comptime queue_type: QueueType, comptime transient: Transient) vk.CommandPool {
|
||||
return switch (queue_type) {
|
||||
.graphics => switch (transient) {
|
||||
.persistent => self.graphics_command_pool,
|
||||
.transient => self.transient_graphics_command_pool,
|
||||
},
|
||||
.compute => switch (transient) {
|
||||
.persistent => self.compute_command_pool,
|
||||
.transient => self.transient_compute_command_pool,
|
||||
},
|
||||
.transfer => switch (transient) {
|
||||
.persistent => self.transfer_command_pool,
|
||||
.transient => self.transient_transfer_command_pool,
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
fn allocateCommandBuffer(engine: *const Engine, comptime queue_type: QueueType, comptime transient: Transient) !vk.CommandBuffer {
|
||||
const command_pool = resolveCommandPool(engine, queue_type, transient);
|
||||
|
||||
var command_buffers: [1]vk.CommandBuffer = undefined;
|
||||
try engine.device.allocateCommandBuffers(&.{
|
||||
.command_pool = command_pool,
|
||||
.level = .primary,
|
||||
.command_buffer_count = command_buffers.len,
|
||||
}, &command_buffers);
|
||||
|
||||
return command_buffers[0];
|
||||
pub fn beginRenderPass(self: CommandBuffer, render_pass_begin: RenderPassBeginInfo, contents: vk.SubpassContents) void {
|
||||
self.proxy.beginRenderPass(&.{
|
||||
.render_pass = render_pass_begin.render_pass,
|
||||
.framebuffer = render_pass_begin.framebuffer,
|
||||
.render_area = render_pass_begin.render_area,
|
||||
.clear_value_count = @intCast(render_pass_begin.clear_values.len),
|
||||
.p_clear_values = render_pass_begin.clear_values.ptr,
|
||||
}, contents);
|
||||
}
|
||||
|
||||
fn freeCommandBuffer(engine: *const Engine, comptime queue_type: QueueType, comptime transient: Transient, command_buffer: vk.CommandBuffer) void {
|
||||
const command_pool = resolveCommandPool(engine, queue_type, transient);
|
||||
const command_buffers = [_]vk.CommandBuffer{command_buffer};
|
||||
|
||||
engine.device.freeCommandBuffers(command_pool, command_buffers.len, &command_buffers);
|
||||
pub fn bindDescriptorSet(
|
||||
self: CommandBuffer,
|
||||
pipeline_bind_point: vk.PipelineBindPoint,
|
||||
layout: vk.PipelineLayout,
|
||||
set: u32,
|
||||
descriptor_set: vk.DescriptorSet,
|
||||
dynamic_offset: ?u32,
|
||||
) void {
|
||||
self.bindDescriptorSets(
|
||||
pipeline_bind_point,
|
||||
layout,
|
||||
set,
|
||||
&.{descriptor_set},
|
||||
if (dynamic_offset) |x| &.{x} else &.{},
|
||||
);
|
||||
}
|
||||
|
||||
pub fn bindDescriptorSets(
|
||||
self: CommandBuffer,
|
||||
pipeline_bind_point: vk.PipelineBindPoint,
|
||||
layout: vk.PipelineLayout,
|
||||
first_set: u32,
|
||||
descriptor_sets: []const vk.DescriptorSet,
|
||||
dynamic_offsets: []const u32,
|
||||
) void {
|
||||
self.proxy.bindDescriptorSets(
|
||||
pipeline_bind_point,
|
||||
layout,
|
||||
first_set,
|
||||
@intCast(descriptor_sets.len),
|
||||
descriptor_sets.ptr,
|
||||
@intCast(dynamic_offsets.len),
|
||||
dynamic_offsets.ptr,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn bindPipeline(self: CommandBuffer, pipeline_bind_point: vk.PipelineBindPoint, pipeline: vk.Pipeline) void {
|
||||
self.proxy.bindPipeline(pipeline_bind_point, pipeline);
|
||||
}
|
||||
|
||||
pub fn bindIndexBuffer(self: CommandBuffer, buffer: vk.Buffer, offset: u64, index_type: vk.IndexType) void {
|
||||
self.proxy.bindIndexBuffer(buffer, offset, index_type);
|
||||
}
|
||||
|
||||
pub fn bindVertexBuffers(self: CommandBuffer, first_binding: u32, bindings: []const VertexBufferBinding) !void {
|
||||
var vertex_buffer_bindings = std.MultiArrayList(VertexBufferBinding){};
|
||||
defer vertex_buffer_bindings.deinit(self.allocator);
|
||||
try vertex_buffer_bindings.ensureTotalCapacity(self.allocator, bindings.len);
|
||||
|
||||
for (bindings) |binding| {
|
||||
vertex_buffer_bindings.appendAssumeCapacity(binding);
|
||||
}
|
||||
|
||||
self.proxy.bindVertexBuffers(
|
||||
first_binding,
|
||||
@intCast(vertex_buffer_bindings.len),
|
||||
vertex_buffer_bindings.items(.buffer).ptr,
|
||||
vertex_buffer_bindings.items(.offset).ptr,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn drawIndexed(self: CommandBuffer, draw_indexed: DrawIndexed) void {
|
||||
self.proxy.drawIndexed(
|
||||
draw_indexed.index_count,
|
||||
draw_indexed.instance_count,
|
||||
draw_indexed.first_index,
|
||||
draw_indexed.vertex_offset,
|
||||
draw_indexed.first_instance,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn endCommandBuffer(self: CommandBuffer) !void {
|
||||
try self.proxy.endCommandBuffer();
|
||||
}
|
||||
|
||||
pub fn endRenderPass(self: CommandBuffer) void {
|
||||
self.proxy.endRenderPass();
|
||||
}
|
||||
|
||||
pub fn copyBuffer(
|
||||
self: CommandBuffer,
|
||||
src_buffer: vk.Buffer,
|
||||
dst_buffer: vk.Buffer,
|
||||
regions: []const vk.BufferCopy,
|
||||
) void {
|
||||
self.proxy.copyBuffer(src_buffer, dst_buffer, @intCast(regions.len), regions.ptr);
|
||||
}
|
||||
|
||||
pub fn copyBufferToImage(
|
||||
self: CommandBuffer,
|
||||
src_buffer: vk.Buffer,
|
||||
dst_image: vk.Image,
|
||||
dst_image_layout: vk.ImageLayout,
|
||||
regions: []const vk.BufferImageCopy,
|
||||
) void {
|
||||
self.proxy.copyBufferToImage(src_buffer, dst_image, dst_image_layout, @intCast(regions.len), regions.ptr);
|
||||
}
|
||||
|
||||
pub fn pipelineBarrier(self: CommandBuffer, barrier: PipelineBarrier) void {
|
||||
self.proxy.pipelineBarrier(
|
||||
barrier.src_stage_mask,
|
||||
barrier.dst_stage_mask,
|
||||
barrier.dependency_flags,
|
||||
@intCast(barrier.memory_barriers.len),
|
||||
barrier.memory_barriers.ptr,
|
||||
@intCast(barrier.buffer_memory_barriers.len),
|
||||
barrier.buffer_memory_barriers.ptr,
|
||||
@intCast(barrier.image_memory_barriers.len),
|
||||
barrier.image_memory_barriers.ptr,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn setScissor(self: CommandBuffer, first_scissor: u32, scissors: []const vk.Rect2D) void {
|
||||
self.proxy.setScissor(first_scissor, @intCast(scissors.len), scissors.ptr);
|
||||
}
|
||||
|
||||
pub fn setViewport(self: CommandBuffer, first_viewport: u32, viewports: []const vk.Viewport) void {
|
||||
self.proxy.setViewport(first_viewport, @intCast(viewports.len), viewports.ptr);
|
||||
}
|
||||
|
||||
// --- HELPER FUNCTIONS --------------------------------------------------------
|
||||
|
||||
fn submitCommandBuffer(
|
||||
engine: *const Engine,
|
||||
comptime queue_type: QueueType,
|
||||
engine: *Engine,
|
||||
queue_type: QueueType,
|
||||
command_buffer: vk.CommandBuffer,
|
||||
submit_info: SubmitInfo,
|
||||
) !void {
|
||||
|
||||
@@ -7,6 +7,7 @@ const vk = @import("vulkan");
|
||||
|
||||
const Queue = @import("Queue.zig");
|
||||
const QueueType = @import("QueueType.zig").QueueType;
|
||||
const Transient = @import("Transient.zig").Transient;
|
||||
const VkAllocator = @import("VkAllocator.zig");
|
||||
|
||||
pub const Mode = union(enum) {
|
||||
@@ -347,10 +348,34 @@ pub fn init(allocator: std.mem.Allocator, maybe_window: ?*glfw.Window) !Engine {
|
||||
}, &vk_allocator.interface);
|
||||
errdefer device.destroyCommandPool(transient_transfer_command_pool, &vk_allocator.interface);
|
||||
|
||||
const graphics_queue: Queue = .initAllocation(device, queue_allocations.graphics_queue);
|
||||
const compute_queue: Queue = .initAllocation(device, queue_allocations.compute_queue);
|
||||
const transfer_queue: Queue = .initAllocation(device, queue_allocations.transfer_queue);
|
||||
const presentation_queue: Queue = if (maybe_window != null) .initAllocation(device, queue_allocations.presentation_queue) else undefined;
|
||||
const graphics_queue: Queue = .init(
|
||||
device.getDeviceQueue(
|
||||
queue_allocations.graphics_queue.family,
|
||||
queue_allocations.graphics_queue.index,
|
||||
),
|
||||
queue_allocations.graphics_queue,
|
||||
);
|
||||
const compute_queue: Queue = .init(
|
||||
device.getDeviceQueue(
|
||||
queue_allocations.compute_queue.family,
|
||||
queue_allocations.compute_queue.index,
|
||||
),
|
||||
queue_allocations.compute_queue,
|
||||
);
|
||||
const transfer_queue: Queue = .init(
|
||||
device.getDeviceQueue(
|
||||
queue_allocations.transfer_queue.family,
|
||||
queue_allocations.transfer_queue.index,
|
||||
),
|
||||
queue_allocations.transfer_queue,
|
||||
);
|
||||
const presentation_queue: Queue = if (maybe_window != null) .init(
|
||||
device.getDeviceQueue(
|
||||
queue_allocations.presentation_queue.family,
|
||||
queue_allocations.presentation_queue.index,
|
||||
),
|
||||
queue_allocations.presentation_queue,
|
||||
) else undefined;
|
||||
|
||||
// --- CREATE AND SEED RNG -------------------------------------------------
|
||||
|
||||
@@ -613,6 +638,23 @@ fn findPresentationQueueFamily(queue_families_properties: []const vk.QueueFamily
|
||||
return null;
|
||||
}
|
||||
|
||||
fn resolveCommandPool(self: *const Engine, queue_type: QueueType, transient: Transient) vk.CommandPool {
|
||||
return switch (queue_type) {
|
||||
.graphics => switch (transient) {
|
||||
.persistent => self.graphics_command_pool,
|
||||
.transient => self.transient_graphics_command_pool,
|
||||
},
|
||||
.compute => switch (transient) {
|
||||
.persistent => self.compute_command_pool,
|
||||
.transient => self.transient_compute_command_pool,
|
||||
},
|
||||
.transfer => switch (transient) {
|
||||
.persistent => self.transfer_command_pool,
|
||||
.transient => self.transient_transfer_command_pool,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// --- VULKAN WRAPPERS ---------------------------------------------------------
|
||||
|
||||
pub const BufferCreateInfo = struct {
|
||||
@@ -622,6 +664,18 @@ pub const BufferCreateInfo = struct {
|
||||
queue_family_indices: []const u32 = &.{},
|
||||
};
|
||||
|
||||
pub const CommandBufferAllocateInfo = struct {
|
||||
queue_type: QueueType,
|
||||
transient: Transient,
|
||||
level: vk.CommandBufferLevel,
|
||||
};
|
||||
|
||||
pub const CommandBufferFreeInfo = struct {
|
||||
queue_type: QueueType,
|
||||
transient: Transient,
|
||||
command_buffer: vk.CommandBuffer,
|
||||
};
|
||||
|
||||
pub const DescriptorPoolCreateInfo = struct {
|
||||
flags: vk.DescriptorPoolCreateFlags = .{},
|
||||
max_sets: u32,
|
||||
@@ -798,6 +852,17 @@ pub fn createBuffer(self: *Engine, create_info: BufferCreateInfo) !vk.Buffer {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
pub fn allocateCommandBuffer(self: *Engine, allocate_info: CommandBufferAllocateInfo) !vk.CommandBuffer {
|
||||
const command_pool = self.resolveCommandPool(allocate_info.queue_type, allocate_info.transient);
|
||||
var command_buffers: [1]vk.CommandBuffer = undefined;
|
||||
try self.device.allocateCommandBuffers(&.{
|
||||
.command_pool = command_pool,
|
||||
.level = allocate_info.level,
|
||||
.command_buffer_count = command_buffers.len,
|
||||
}, &command_buffers);
|
||||
return command_buffers[0];
|
||||
}
|
||||
|
||||
pub fn allocateDescriptorSet(self: *Engine, allocate_info: DescriptorSetAllocateInfo) !vk.DescriptorSet {
|
||||
var descriptor_sets: [1]vk.DescriptorSet = undefined;
|
||||
try self.allocateDescriptorSets(.{
|
||||
@@ -831,6 +896,14 @@ pub fn allocateDescriptorSets(self: *Engine, allocate_info: DescriptorSetsAlloca
|
||||
}, descriptor_sets.ptr);
|
||||
}
|
||||
|
||||
pub fn bindBufferMemory(self: *Engine, buffer: vk.Buffer, memory: vk.DeviceMemory, memory_offset: vk.DeviceSize) !void {
|
||||
try self.device.bindBufferMemory(buffer, memory, memory_offset);
|
||||
}
|
||||
|
||||
pub fn bindImageMemory(self: *Engine, image: vk.Image, memory: vk.DeviceMemory, memory_offset: vk.DeviceSize) !void {
|
||||
try self.device.bindImageMemory(image, memory, memory_offset);
|
||||
}
|
||||
|
||||
pub fn createDescriptorSetLayout(self: *Engine, create_info: DescriptorSetLayoutCreateInfo) !vk.DescriptorSetLayout {
|
||||
var arena: std.heap.ArenaAllocator = .init(self.vk_allocator.allocator);
|
||||
defer arena.deinit();
|
||||
@@ -1106,6 +1179,16 @@ pub fn destroyShaderModule(self: *Engine, shader_module: vk.ShaderModule) void {
|
||||
self.device.destroyShaderModule(shader_module, &self.vk_allocator.interface);
|
||||
}
|
||||
|
||||
pub fn deviceWaitIdle(self: *Engine) !void {
|
||||
try self.device.deviceWaitIdle();
|
||||
}
|
||||
|
||||
pub fn freeCommandBuffer(self: *Engine, free_info: CommandBufferFreeInfo) void {
|
||||
const command_pool = self.resolveCommandPool(free_info.queue_type, free_info.transient);
|
||||
const command_buffers = [_]vk.CommandBuffer{free_info.command_buffer};
|
||||
self.device.freeCommandBuffers(command_pool, command_buffers.len, &command_buffers);
|
||||
}
|
||||
|
||||
pub fn freeDescriptorSet(self: *Engine, descriptor_pool: vk.DescriptorPool, descriptor_set: vk.DescriptorSet) void {
|
||||
const descriptor_sets = [_]vk.DescriptorSet{descriptor_set};
|
||||
self.device.freeDescriptorSets(descriptor_pool, descriptor_sets.len, &descriptor_sets) catch unreachable;
|
||||
@@ -1115,10 +1198,27 @@ pub fn freeMemory(self: *Engine, device_memory: vk.DeviceMemory) void {
|
||||
self.device.freeMemory(device_memory, &self.vk_allocator.interface);
|
||||
}
|
||||
|
||||
pub fn getBufferMemoryRequirements(self: *Engine, buffer: vk.Buffer) vk.MemoryRequirements {
|
||||
return self.device.getBufferMemoryRequirements(buffer);
|
||||
}
|
||||
|
||||
pub fn getImageMemoryRequirements(self: *Engine, image: vk.Image) vk.MemoryRequirements {
|
||||
return self.device.getImageMemoryRequirements(image);
|
||||
}
|
||||
|
||||
pub fn mapMemory(self: *Engine, memory: vk.DeviceMemory, offset: vk.DeviceSize, size: vk.DeviceSize, flags: vk.MemoryMapFlags) ![]u8 {
|
||||
const mapped_memory = try self.device.mapMemory(memory, offset, size, flags);
|
||||
return @as([*]u8, @ptrCast(mapped_memory))[0..size];
|
||||
}
|
||||
|
||||
pub fn resetFence(self: *Engine, fence: vk.Fence) !void {
|
||||
try self.device.resetFences(1, @ptrCast(&fence));
|
||||
}
|
||||
|
||||
pub fn unmapMemory(self: *Engine, memory: vk.DeviceMemory) void {
|
||||
self.device.unmapMemory(memory);
|
||||
}
|
||||
|
||||
pub fn updateDescriptorSets(self: *Engine, update_info: DescriptorSetsUpdateInfo) !void {
|
||||
var arena: std.heap.ArenaAllocator = .init(self.vk_allocator.allocator);
|
||||
defer arena.deinit();
|
||||
|
||||
@@ -2,7 +2,7 @@ const std = @import("std");
|
||||
|
||||
const vk = @import("vulkan");
|
||||
|
||||
const CommandBuffer = @import("CommandBuffer.zig").CommandBuffer;
|
||||
const CommandBuffer = @import("CommandBuffer.zig");
|
||||
const Engine = @import("Engine.zig");
|
||||
const StagingBuffer = @import("StagingBuffer.zig");
|
||||
const TargetQueue = @import("TargetQueue.zig").TargetQueue;
|
||||
@@ -71,14 +71,14 @@ pub fn GenericBuffer(comptime Header: type, comptime Element: type) type {
|
||||
engine.setObjectName(buffer, "B {s} [{s}, {s}]", .{ name, @typeName(Header), @typeName(Element) });
|
||||
}
|
||||
|
||||
const memory_requirements = engine.device.getBufferMemoryRequirements(buffer);
|
||||
const memory_requirements = engine.getBufferMemoryRequirements(buffer);
|
||||
const device_memory = try engine.allocate(memory_requirements, .{ .device_local_bit = true });
|
||||
errdefer engine.freeMemory(device_memory);
|
||||
if (init_info.name) |name| {
|
||||
engine.setObjectName(device_memory, "DM {s} [{s}, {s}]", .{ name, @typeName(Header), @typeName(Element) });
|
||||
}
|
||||
|
||||
try engine.device.bindBufferMemory(buffer, device_memory, 0);
|
||||
try engine.bindBufferMemory(buffer, device_memory, 0);
|
||||
|
||||
return .{
|
||||
.buffer = buffer,
|
||||
@@ -154,10 +154,10 @@ pub fn GenericBuffer(comptime Header: type, comptime Element: type) type {
|
||||
@memcpy(staging_memory[array_write_offset..write_size], std.mem.sliceAsBytes(write_info.elements));
|
||||
staging_buffer.unmap(engine);
|
||||
|
||||
var command_buffer: CommandBuffer(.transfer, .transient) = try .init(engine);
|
||||
var command_buffer: CommandBuffer = try .init(engine, .transfer, .transient);
|
||||
defer command_buffer.deinit(engine);
|
||||
|
||||
try command_buffer.beginCommandBuffer(.{});
|
||||
try command_buffer.beginCommandBuffer();
|
||||
command_buffer.copyBuffer(staging_buffer.buffer, self.buffer, regions.items);
|
||||
try command_buffer.endCommandBuffer();
|
||||
|
||||
|
||||
@@ -11,9 +11,9 @@ pub const Allocation = struct {
|
||||
handle: vk.Queue,
|
||||
allocation: Allocation,
|
||||
|
||||
pub fn initAllocation(device: vk.DeviceProxy, allocation: Allocation) Queue {
|
||||
pub fn init(handle: vk.Queue, allocation: Allocation) Queue {
|
||||
return .{
|
||||
.handle = device.getDeviceQueue(allocation.family, allocation.index),
|
||||
.handle = handle,
|
||||
.allocation = allocation,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ pub fn init(engine: *Engine, init_info: InitInfo) !StagingBuffer {
|
||||
});
|
||||
errdefer engine.destroyBuffer(buffer);
|
||||
|
||||
const memory_requirements = engine.device.getBufferMemoryRequirements(buffer);
|
||||
const memory_requirements = engine.getBufferMemoryRequirements(buffer);
|
||||
const device_memory = try engine.allocate(
|
||||
memory_requirements,
|
||||
.{
|
||||
@@ -41,7 +41,7 @@ pub fn init(engine: *Engine, init_info: InitInfo) !StagingBuffer {
|
||||
);
|
||||
errdefer engine.freeMemory(device_memory);
|
||||
|
||||
try engine.device.bindBufferMemory(buffer, device_memory, 0);
|
||||
try engine.bindBufferMemory(buffer, device_memory, 0);
|
||||
|
||||
return .{
|
||||
.buffer = buffer,
|
||||
@@ -65,10 +65,10 @@ pub fn map(self: StagingBuffer, engine: *Engine) ![]u8 {
|
||||
}
|
||||
|
||||
pub fn mapPartial(self: StagingBuffer, engine: *Engine, offset: u32, len: u32) ![]u8 {
|
||||
const mapped_memory = try engine.device.mapMemory(self.device_memory, offset, len, .{});
|
||||
return @as([*]u8, @ptrCast(mapped_memory))[0..len];
|
||||
const mapped_memory = try engine.mapMemory(self.device_memory, offset, len, .{});
|
||||
return mapped_memory;
|
||||
}
|
||||
|
||||
pub fn unmap(self: StagingBuffer, engine: *Engine) void {
|
||||
engine.device.unmapMemory(self.device_memory);
|
||||
engine.unmapMemory(self.device_memory);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ const std = @import("std");
|
||||
|
||||
const vk = @import("vulkan");
|
||||
|
||||
const CommandBuffer = @import("CommandBuffer.zig").CommandBuffer;
|
||||
const CommandBuffer = @import("CommandBuffer.zig");
|
||||
const Engine = @import("Engine.zig");
|
||||
const QSM = @import("QueueSharingMode.zig");
|
||||
const Texture = @import("Texture.zig");
|
||||
@@ -271,7 +271,7 @@ pub fn recreate(self: *Swapchain, engine: *Engine) !void {
|
||||
}
|
||||
|
||||
pub const PresentInfo = struct {
|
||||
command_buffer: CommandBuffer(.graphics, .transient),
|
||||
command_buffer: CommandBuffer,
|
||||
wait_semaphores: []const WaitSemaphore = &.{},
|
||||
};
|
||||
|
||||
@@ -411,7 +411,7 @@ const SwapchainImage = struct {
|
||||
semaphore_render_finished: vk.Semaphore,
|
||||
fence: vk.Fence,
|
||||
framebuffer: vk.Framebuffer,
|
||||
command_buffer: ?CommandBuffer(.graphics, .transient),
|
||||
command_buffer: ?CommandBuffer,
|
||||
|
||||
const InitProps = struct {
|
||||
image: vk.Image,
|
||||
|
||||
@@ -3,7 +3,7 @@ const std = @import("std");
|
||||
|
||||
const vk = @import("vulkan");
|
||||
|
||||
const CommandBuffer = @import("CommandBuffer.zig").CommandBuffer;
|
||||
const CommandBuffer = @import("CommandBuffer.zig");
|
||||
const Engine = @import("Engine.zig");
|
||||
const StagingBuffer = @import("StagingBuffer.zig");
|
||||
const TargetQueue = @import("TargetQueue.zig").TargetQueue;
|
||||
@@ -116,14 +116,14 @@ pub fn init(engine: *Engine, init_info: InitInfo) !Texture {
|
||||
engine.setObjectName(image, "I {s} [{s}]", .{ name, @tagName(init_info.usage) });
|
||||
}
|
||||
|
||||
const memory_requirements = engine.device.getImageMemoryRequirements(image);
|
||||
const memory_requirements = engine.getImageMemoryRequirements(image);
|
||||
const device_memory = try engine.allocate(memory_requirements, .{ .device_local_bit = true });
|
||||
errdefer engine.freeMemory(device_memory);
|
||||
if (init_info.name) |name| {
|
||||
engine.setObjectName(device_memory, "DM {s} [{s}]", .{ name, @tagName(init_info.usage) });
|
||||
}
|
||||
|
||||
try engine.device.bindImageMemory(image, device_memory, 0);
|
||||
try engine.bindImageMemory(image, device_memory, 0);
|
||||
|
||||
const image_view = try engine.createImageView(.{
|
||||
.image = image,
|
||||
@@ -205,10 +205,10 @@ pub fn writeRaw(self: Texture, engine: *Engine, data: []const u8) !void {
|
||||
|
||||
// --- TRANSITION TO TRANSFER_DST_OPTIMAL AND COPY -----------------
|
||||
|
||||
var transfer_command_buffer: CommandBuffer(.transfer, .transient) = try .init(engine);
|
||||
var transfer_command_buffer: CommandBuffer = try .init(engine, .transfer, .transient);
|
||||
defer transfer_command_buffer.deinit(engine);
|
||||
|
||||
try transfer_command_buffer.beginCommandBuffer(.{});
|
||||
try transfer_command_buffer.beginCommandBuffer();
|
||||
|
||||
transfer_command_buffer.pipelineBarrier(.{
|
||||
.src_stage_mask = .{ .top_of_pipe_bit = true },
|
||||
@@ -265,10 +265,10 @@ pub fn writeRaw(self: Texture, engine: *Engine, data: []const u8) !void {
|
||||
|
||||
// --- TRANSITION TO SHADER_READ_ONLY_OPTIMAL ----------------------
|
||||
|
||||
var graphics_command_buffer: CommandBuffer(.graphics, .transient) = try .init(engine);
|
||||
var graphics_command_buffer: CommandBuffer = try .init(engine, .graphics, .transient);
|
||||
defer graphics_command_buffer.deinit(engine);
|
||||
|
||||
try graphics_command_buffer.beginCommandBuffer(.{});
|
||||
try graphics_command_buffer.beginCommandBuffer();
|
||||
|
||||
graphics_command_buffer.pipelineBarrier(.{
|
||||
.src_stage_mask = .{ .transfer_bit = true },
|
||||
|
||||
@@ -101,7 +101,7 @@ pub fn main() !void {
|
||||
std.log.debug("Exitted the game loop", .{});
|
||||
|
||||
for (swapchain.swapchain_images) |x| engine.waitForFence(x.fence) catch {};
|
||||
engine.device.deviceWaitIdle() catch {};
|
||||
engine.deviceWaitIdle() catch {};
|
||||
}
|
||||
|
||||
const CallbackContext = struct {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
pub const Interator2 = @import("math/Interator2.zig").Interator2;
|
||||
pub const Interator3 = @import("math/Interator3.zig").Interator3;
|
||||
pub const Iterator3 = @import("math/Iterator3.zig");
|
||||
pub const Iterator2 = @import("math/Iterator2.zig").Iterator2;
|
||||
pub const Iterator3 = @import("math/Iterator3.zig").Iterator3;
|
||||
pub const Matrix4x4 = @import("math/Matrix4x4.zig").Matrix4x4;
|
||||
pub const Quaternion = @import("math/Quaternion.zig").Quaternion;
|
||||
pub const Vector2 = @import("math/Vector2.zig").Vector2;
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
pub fn Interator2(comptime T: type) type {
|
||||
return struct {
|
||||
const Self = @This();
|
||||
const Vector = @Vector(2, T);
|
||||
|
||||
min: Vector,
|
||||
max: Vector,
|
||||
current: ?Vector,
|
||||
|
||||
pub fn init(min_x: T, min_y: T, max_x: T, max_y: T) Self {
|
||||
const min: Vector = .{ min_x, min_y };
|
||||
const max: Vector = .{ max_x, max_y };
|
||||
return .{
|
||||
.min = min,
|
||||
.max = max,
|
||||
.current = min,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn next(self: *Self) ?[2]T {
|
||||
const current = self.current orelse return null;
|
||||
var next_current = current;
|
||||
|
||||
next_current[0] = next_current[0] + 1;
|
||||
if (next_current[0] > self.max[0]) {
|
||||
next_current[0] = self.min[0];
|
||||
next_current[1] = next_current[1] + 1;
|
||||
if (next_current[1] > self.max[1]) {
|
||||
self.current = null;
|
||||
return current;
|
||||
}
|
||||
}
|
||||
|
||||
self.current = next_current;
|
||||
return current;
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
pub fn Interator3(comptime T: type) type {
|
||||
return struct {
|
||||
const Self = @This();
|
||||
const Vector = @Vector(3, T);
|
||||
|
||||
min: Vector,
|
||||
max: Vector,
|
||||
current: ?Vector,
|
||||
|
||||
pub fn init(min_x: T, min_y: T, min_z: T, max_x: T, max_y: T, max_z: T) Self {
|
||||
const min: Vector = .{ min_x, min_y, min_z };
|
||||
const max: Vector = .{ max_x, max_y, max_z };
|
||||
return .{
|
||||
.min = min,
|
||||
.max = max,
|
||||
.current = min,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn next(self: *Self) ?[3]T {
|
||||
const current = self.current orelse return null;
|
||||
var next_current = current;
|
||||
|
||||
next_current[0] = next_current[0] + 1;
|
||||
if (next_current[0] > self.max[0]) {
|
||||
next_current[0] = self.min[0];
|
||||
next_current[1] = next_current[1] + 1;
|
||||
if (next_current[1] > self.max[1]) {
|
||||
next_current[1] = self.min[1];
|
||||
next_current[2] = next_current[2] + 1;
|
||||
if (next_current[2] > self.max[2]) {
|
||||
self.current = null;
|
||||
return current;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.current = next_current;
|
||||
return current;
|
||||
}
|
||||
};
|
||||
}
|
||||
44
src/math/Iterator2.zig
Normal file
44
src/math/Iterator2.zig
Normal file
@@ -0,0 +1,44 @@
|
||||
pub fn Iterator2(comptime T: type) type {
|
||||
return struct {
|
||||
const Self = @This();
|
||||
const Array = [2]T;
|
||||
|
||||
min: Array,
|
||||
max: Array,
|
||||
step: Array,
|
||||
current: ?Array,
|
||||
|
||||
pub const InitInfo = struct {
|
||||
min: Array,
|
||||
max: Array,
|
||||
step: Array = .{ 1, 1 },
|
||||
};
|
||||
|
||||
pub fn init(init_info: InitInfo) Self {
|
||||
return .{
|
||||
.min = init_info.min,
|
||||
.max = init_info.max,
|
||||
.step = init_info.step,
|
||||
.current = init_info.min,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn next(self: *Self) ?Array {
|
||||
const current = self.current orelse return null;
|
||||
var next_current = current;
|
||||
|
||||
next_current[0] = next_current[0] + self.step[0];
|
||||
if (next_current[0] > self.max[0]) {
|
||||
next_current[0] = self.min[0];
|
||||
next_current[1] = next_current[1] + self.step[1];
|
||||
if (next_current[1] > self.max[1]) {
|
||||
self.current = null;
|
||||
return current;
|
||||
}
|
||||
}
|
||||
|
||||
self.current = next_current;
|
||||
return current;
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1,38 +1,48 @@
|
||||
const Vector3 = @import("Vector3.zig").Vector3;
|
||||
pub fn Iterator3(comptime T: type) type {
|
||||
return struct {
|
||||
const Self = @This();
|
||||
const Array = [3]T;
|
||||
|
||||
min: Vector3,
|
||||
max: Vector3,
|
||||
step: Vector3,
|
||||
current: ?Vector3,
|
||||
min: Array,
|
||||
max: Array,
|
||||
step: Array,
|
||||
current: ?Array,
|
||||
|
||||
pub fn init(min: Vector3, max: Vector3, step: Vector3) @This() {
|
||||
return .{
|
||||
.min = min,
|
||||
.max = max,
|
||||
.step = step,
|
||||
.current = min,
|
||||
pub const InitInfo = struct {
|
||||
min: Array,
|
||||
max: Array,
|
||||
step: Array = .{ 1, 1, 1 },
|
||||
};
|
||||
|
||||
pub fn init(init_info: InitInfo) Self {
|
||||
return .{
|
||||
.min = init_info.min,
|
||||
.max = init_info.max,
|
||||
.step = init_info.step,
|
||||
.current = init_info.min,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn next(self: *Self) ?Array {
|
||||
const current = self.current orelse return null;
|
||||
var next_current = current;
|
||||
|
||||
next_current[0] = next_current[0] + self.step[0];
|
||||
if (next_current[0] > self.max[0]) {
|
||||
next_current[0] = self.min[0];
|
||||
next_current[1] = next_current[1] + self.step[1];
|
||||
if (next_current[1] > self.max[1]) {
|
||||
next_current[1] = self.min[1];
|
||||
next_current[2] = next_current[2] + self.step[2];
|
||||
if (next_current[2] > self.max[2]) {
|
||||
self.current = null;
|
||||
return current;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.current = next_current;
|
||||
return current;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub fn next(self: *@This()) ?Vector3 {
|
||||
const current = self.current orelse return null;
|
||||
|
||||
var next_current = current;
|
||||
|
||||
next_current = next_current.setX(next_current.getX() + self.step.getX());
|
||||
if (next_current.getX() > self.max.getX()) {
|
||||
next_current = next_current.setX(self.min.getX());
|
||||
next_current = next_current.setY(next_current.getY() + self.step.getY());
|
||||
if (next_current.getY() > self.max.getY()) {
|
||||
next_current = next_current.setY(self.min.getY());
|
||||
next_current = next_current.setZ(next_current.getZ() + self.step.getZ());
|
||||
if (next_current.getZ() > self.max.getZ()) {
|
||||
self.current = null;
|
||||
return current;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.current = next_current;
|
||||
return current;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
const std = @import("std");
|
||||
const math = @import("../math.zig");
|
||||
|
||||
const Vector2 = math.Vector2;
|
||||
const Vector2 = @import("Vector2.zig").Vector2;
|
||||
|
||||
const f32x8 = math.f32x8;
|
||||
|
||||
const ps = math.ps;
|
||||
|
||||
pub const Vector2x8 = extern struct {
|
||||
|
||||
Reference in New Issue
Block a user