refactor stub
This commit is contained in:
16
src/App.zig
Normal file
16
src/App.zig
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const nu = @import("nu.zig");
|
||||||
|
|
||||||
|
const Self = @This();
|
||||||
|
|
||||||
|
pub fn init(alloc: std.mem.Allocator, render: *nu.Render, imgui: *nu.ImGui) !Self {
|
||||||
|
_ = alloc;
|
||||||
|
_ = render;
|
||||||
|
_ = imgui;
|
||||||
|
|
||||||
|
return .{};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: *Self) void {
|
||||||
|
_ = self;
|
||||||
|
}
|
@@ -105,6 +105,7 @@ fn init_glfw() !void {
|
|||||||
return error.glfwInitFailed;
|
return error.glfwInitFailed;
|
||||||
errdefer c.glfwTerminate();
|
errdefer c.glfwTerminate();
|
||||||
|
|
||||||
|
// todo move to render
|
||||||
if (c.glfwVulkanSupported() != c.GLFW_TRUE)
|
if (c.glfwVulkanSupported() != c.GLFW_TRUE)
|
||||||
return error.glfwNoVulkan;
|
return error.glfwNoVulkan;
|
||||||
}
|
}
|
||||||
|
294
src/main.zig
294
src/main.zig
@@ -1,287 +1,29 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const vk = @import("vk");
|
|
||||||
const c = @import("c.zig");
|
|
||||||
const shaders = @import("shaders");
|
|
||||||
const Allocator = std.mem.Allocator;
|
|
||||||
|
|
||||||
const au = @import("au.zig");
|
const nu = @import("nu.zig");
|
||||||
const Uber = @import("Uber.zig");
|
|
||||||
|
|
||||||
const ui = @import("au/ui.zig");
|
const App = @import("App.zig");
|
||||||
|
|
||||||
const vertices = [_]Uber.Vertex{
|
|
||||||
// Vulkan depth range is 0, 1 instead of OpenGL -1, 1
|
|
||||||
.{ .pos = .{ -0.5, -0.5, -0.5, 1.0 }, .color = .{ 1, 0, 0 } },
|
|
||||||
.{ .pos = .{ -0.5, 0.5, -0.5, 1.0 }, .color = .{ 0, 1, 0 } },
|
|
||||||
.{ .pos = .{ 0.5, -0.5, -0.5, 1.0 }, .color = .{ 0, 0, 1 } },
|
|
||||||
.{ .pos = .{ 0.5, 0.5, -0.5, 1.0 }, .color = .{ 1, 1, 0 } },
|
|
||||||
.{ .pos = .{ -0.5, -0.5, 0.5, 1.0 }, .color = .{ 1, 0, 0 } },
|
|
||||||
.{ .pos = .{ -0.5, 0.5, 0.5, 1.0 }, .color = .{ 0, 1, 0 } },
|
|
||||||
.{ .pos = .{ 0.5, -0.5, 0.5, 1.0 }, .color = .{ 0, 0, 1 } },
|
|
||||||
.{ .pos = .{ 0.5, 0.5, 0.5, 1.0 }, .color = .{ 1, 1, 0 } },
|
|
||||||
};
|
|
||||||
|
|
||||||
const indices = [_]Uber.Index{ 4, 5, 6, 6, 5, 7 };
|
|
||||||
|
|
||||||
const uniform = Uber.Uniform{
|
|
||||||
.mat = .{
|
|
||||||
0.5, 0.0, 0.0, 0.0,
|
|
||||||
0.0, 1.0, 0.0, 0.0,
|
|
||||||
0.0, 0.0, 1.0, 0.0,
|
|
||||||
0.0, 0.0, 0.0, 1.0,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
fn record_render(
|
|
||||||
cmd: au.CommandBufferProxy,
|
|
||||||
uber: Uber,
|
|
||||||
area: vk.Rect2D, // render area, scissor, and viewport.
|
|
||||||
vertex_buffer: vk.Buffer,
|
|
||||||
index_buffer: vk.Buffer,
|
|
||||||
descriptor_set: vk.DescriptorSet,
|
|
||||||
) void {
|
|
||||||
cmd.setViewport(0, 1, &.{.{
|
|
||||||
.x = @floatFromInt(area.offset.x),
|
|
||||||
.y = @floatFromInt(area.offset.y),
|
|
||||||
.width = @floatFromInt(area.extent.width),
|
|
||||||
.height = @floatFromInt(area.extent.height),
|
|
||||||
.min_depth = 0,
|
|
||||||
.max_depth = 1,
|
|
||||||
}});
|
|
||||||
cmd.setScissor(0, 1, &.{area});
|
|
||||||
|
|
||||||
cmd.bindPipeline(.graphics, uber.pipeline);
|
|
||||||
cmd.bindDescriptorSets(.graphics, uber.layout, 0, 1, &.{descriptor_set}, 0, null);
|
|
||||||
cmd.bindVertexBuffers(0, 1, &.{vertex_buffer}, &.{0});
|
|
||||||
cmd.bindIndexBuffer(index_buffer, 0, .uint16);
|
|
||||||
cmd.drawIndexed(indices.len, 1, 0, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn main() !void {
|
pub fn main() !void {
|
||||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||||
defer _ = gpa.detectLeaks();
|
defer _ = gpa.detectLeaks();
|
||||||
const alloc = gpa.allocator();
|
const alloc = gpa.allocator();
|
||||||
|
|
||||||
try au.init(alloc);
|
var window = try nu.Window.init(alloc, .{ .title = "Hello World" });
|
||||||
defer au.deinit();
|
defer window.deinit();
|
||||||
|
|
||||||
{
|
var render = try nu.Render.init(alloc, &window);
|
||||||
const pdev_prop = au.I.getPhysicalDeviceProperties(au.device_config.pdev);
|
defer render.deinit();
|
||||||
std.debug.print("Selected '{s}' in mode '{any}'\n", .{ pdev_prop.device_name, au.device_config.mode });
|
|
||||||
}
|
var imgui = try nu.ImGui.init(alloc, &window, &render);
|
||||||
|
defer imgui.deinit();
|
||||||
var sc = try au.SwapChain.init(alloc);
|
|
||||||
defer sc.deinit();
|
var app = try App.init(alloc, &render, &imgui);
|
||||||
|
defer app.deinit();
|
||||||
var flights = try au.Flights.init(alloc, 3); // FRAMES IN FLIGHT
|
|
||||||
defer flights.deinit();
|
try nu.run(&window, .{
|
||||||
|
&app,
|
||||||
const ctx = try ui.init(flights.flights.len);
|
&imgui,
|
||||||
defer ui.deinit(ctx);
|
&render,
|
||||||
|
});
|
||||||
const descriptorPool = try au.D.createDescriptorPool(&vk.DescriptorPoolCreateInfo{
|
|
||||||
.flags = .{ .free_descriptor_set_bit = true },
|
|
||||||
.pool_size_count = 1,
|
|
||||||
.p_pool_sizes = &.{
|
|
||||||
vk.DescriptorPoolSize{ .descriptor_count = 32, .type = .combined_image_sampler },
|
|
||||||
},
|
|
||||||
.max_sets = 32,
|
|
||||||
}, null);
|
|
||||||
defer au.D.destroyDescriptorPool(descriptorPool, null);
|
|
||||||
|
|
||||||
_ = try sc.rebuild();
|
|
||||||
|
|
||||||
const cache = try au.D.createPipelineCache(&vk.PipelineCacheCreateInfo{}, null);
|
|
||||||
defer au.D.destroyPipelineCache(cache, null);
|
|
||||||
|
|
||||||
const uber = try Uber.init(cache);
|
|
||||||
defer uber.deinit();
|
|
||||||
|
|
||||||
const vkalloc = au.VkAllocator.init();
|
|
||||||
|
|
||||||
const vertex_buffer = try au.D.createBuffer(&vk.BufferCreateInfo{
|
|
||||||
.size = @sizeOf(@TypeOf(vertices)),
|
|
||||||
.usage = .{ .vertex_buffer_bit = true },
|
|
||||||
.sharing_mode = .exclusive,
|
|
||||||
}, null);
|
|
||||||
defer au.D.destroyBuffer(vertex_buffer, null);
|
|
||||||
const vertex_memory = try vkalloc.alloc(
|
|
||||||
au.D.getBufferMemoryRequirements(vertex_buffer),
|
|
||||||
.{ .host_visible_bit = true, .host_coherent_bit = true },
|
|
||||||
);
|
|
||||||
defer vkalloc.free(vertex_memory);
|
|
||||||
try au.D.bindBufferMemory(vertex_buffer, vertex_memory, 0);
|
|
||||||
const vertex_data: *align(1) @TypeOf(vertices) =
|
|
||||||
@ptrCast(try au.D.mapMemory(vertex_memory, 0, vk.WHOLE_SIZE, .{}));
|
|
||||||
defer au.D.unmapMemory(vertex_memory);
|
|
||||||
vertex_data.* = vertices;
|
|
||||||
|
|
||||||
const index_buffer = try au.D.createBuffer(&vk.BufferCreateInfo{
|
|
||||||
.size = @sizeOf(@TypeOf(indices)),
|
|
||||||
.usage = .{ .index_buffer_bit = true },
|
|
||||||
.sharing_mode = .exclusive,
|
|
||||||
}, null);
|
|
||||||
defer au.D.destroyBuffer(index_buffer, null);
|
|
||||||
const index_memory = try vkalloc.alloc(
|
|
||||||
au.D.getBufferMemoryRequirements(index_buffer),
|
|
||||||
.{ .host_visible_bit = true, .host_coherent_bit = true },
|
|
||||||
);
|
|
||||||
defer vkalloc.free(index_memory);
|
|
||||||
try au.D.bindBufferMemory(index_buffer, index_memory, 0);
|
|
||||||
const index_data: *align(1) @TypeOf(indices) =
|
|
||||||
@ptrCast(try au.D.mapMemory(index_memory, 0, vk.WHOLE_SIZE, .{}));
|
|
||||||
defer au.D.unmapMemory(index_memory);
|
|
||||||
index_data.* = indices;
|
|
||||||
|
|
||||||
// todo ring buffer for frames in flight. need to use an offset when binding
|
|
||||||
// use dynamic offset - descriptor type VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC
|
|
||||||
const uniform_buffer = try au.D.createBuffer(&vk.BufferCreateInfo{
|
|
||||||
.size = @sizeOf(@TypeOf(uniform)),
|
|
||||||
.usage = .{ .uniform_buffer_bit = true },
|
|
||||||
.sharing_mode = .exclusive,
|
|
||||||
}, null);
|
|
||||||
defer au.D.destroyBuffer(uniform_buffer, null);
|
|
||||||
const uniform_memory = try vkalloc.alloc(
|
|
||||||
au.D.getBufferMemoryRequirements(uniform_buffer),
|
|
||||||
.{ .host_visible_bit = true, .host_coherent_bit = true },
|
|
||||||
);
|
|
||||||
defer vkalloc.free(uniform_memory);
|
|
||||||
try au.D.bindBufferMemory(uniform_buffer, uniform_memory, 0);
|
|
||||||
const uniform_data: *align(1) @TypeOf(uniform) =
|
|
||||||
@ptrCast(try au.D.mapMemory(uniform_memory, 0, vk.WHOLE_SIZE, .{}));
|
|
||||||
defer au.D.unmapMemory(uniform_memory);
|
|
||||||
uniform_data.* = uniform;
|
|
||||||
|
|
||||||
var descriptorSet: vk.DescriptorSet = undefined;
|
|
||||||
try au.D.allocateDescriptorSets(&vk.DescriptorSetAllocateInfo{
|
|
||||||
.descriptor_pool = descriptorPool,
|
|
||||||
.descriptor_set_count = 1,
|
|
||||||
.p_set_layouts = &.{uber.set_layout},
|
|
||||||
}, @ptrCast(&descriptorSet));
|
|
||||||
defer au.D.freeDescriptorSets(descriptorPool, 1, &.{descriptorSet}) catch unreachable; // todo handle this?
|
|
||||||
|
|
||||||
au.D.updateDescriptorSets(
|
|
||||||
1,
|
|
||||||
&.{
|
|
||||||
vk.WriteDescriptorSet{
|
|
||||||
.dst_set = descriptorSet,
|
|
||||||
.dst_binding = 0,
|
|
||||||
.dst_array_element = 0,
|
|
||||||
.descriptor_type = .uniform_buffer,
|
|
||||||
.descriptor_count = 1,
|
|
||||||
.p_image_info = undefined,
|
|
||||||
.p_texel_buffer_view = undefined,
|
|
||||||
.p_buffer_info = &.{
|
|
||||||
vk.DescriptorBufferInfo{
|
|
||||||
.buffer = uniform_buffer,
|
|
||||||
.offset = 0,
|
|
||||||
.range = vk.WHOLE_SIZE,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
0,
|
|
||||||
null,
|
|
||||||
);
|
|
||||||
|
|
||||||
var prng = std.Random.Sfc64.init(std.crypto.random.int(u64));
|
|
||||||
const rand = prng.random();
|
|
||||||
|
|
||||||
while (!au.W.should_close()) {
|
|
||||||
ui.NewFrame();
|
|
||||||
ui.igShowMetricsWindow(null);
|
|
||||||
ui.EndFrame();
|
|
||||||
|
|
||||||
const flight = flights.next();
|
|
||||||
|
|
||||||
const events = if (au.W.focused())
|
|
||||||
au.poll_events()
|
|
||||||
else
|
|
||||||
au.wait_events_timeout(0.5);
|
|
||||||
|
|
||||||
for (events) |u| {
|
|
||||||
switch (u) {
|
|
||||||
.framebufferSize => sc.mark(),
|
|
||||||
.cursorPos, .windowPos, .windowSize, .windowRefresh => {},
|
|
||||||
else => |e| std.debug.print("{any}\n", .{e}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_ = try au.D.waitForFences(1, &.{flight.fence}, vk.TRUE, std.math.maxInt(u64));
|
|
||||||
try au.D.resetFences(1, &.{flight.fence});
|
|
||||||
|
|
||||||
// TODO need to check the standard to see what happens to a fence or semaphore on OutOfDateKHR error.
|
|
||||||
// acquire, submit, and present.
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
_ = try sc.rebuild();
|
|
||||||
|
|
||||||
const target = sc.acquire(flight.acquire, .null_handle) catch |err| switch (err) {
|
|
||||||
error.OutOfDateKHR => {
|
|
||||||
sc.mark();
|
|
||||||
continue;
|
|
||||||
},
|
|
||||||
else => return err,
|
|
||||||
};
|
|
||||||
|
|
||||||
try au.D.resetCommandPool(flight.pool, .{});
|
|
||||||
var cmd = au.CommandBufferProxy.init(flight.cmd, au.D.wrapper);
|
|
||||||
try cmd.beginCommandBuffer(&.{ .flags = .{ .one_time_submit_bit = true } });
|
|
||||||
|
|
||||||
const render_area: vk.Rect2D = .{
|
|
||||||
.offset = .{ .x = 0, .y = 0 },
|
|
||||||
.extent = sc.cinfo.image_extent,
|
|
||||||
};
|
|
||||||
|
|
||||||
target.begin_rendering(cmd, render_area);
|
|
||||||
record_render(
|
|
||||||
cmd,
|
|
||||||
uber,
|
|
||||||
render_area,
|
|
||||||
vertex_buffer,
|
|
||||||
index_buffer,
|
|
||||||
descriptorSet,
|
|
||||||
);
|
|
||||||
ui.Draw(cmd);
|
|
||||||
target.end_rendering(cmd);
|
|
||||||
|
|
||||||
for (vertex_data) |*v| {
|
|
||||||
for (v.pos[0..2]) |*f| {
|
|
||||||
f.* += (rand.float(f32) - 0.5) * 0.001;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try cmd.endCommandBuffer();
|
|
||||||
|
|
||||||
try au.Q.submit(
|
|
||||||
1,
|
|
||||||
&.{
|
|
||||||
vk.SubmitInfo{
|
|
||||||
.wait_semaphore_count = 1,
|
|
||||||
.p_wait_semaphores = @ptrCast(&flight.acquire),
|
|
||||||
.p_wait_dst_stage_mask = @ptrCast(&vk.PipelineStageFlags{ .color_attachment_output_bit = true }),
|
|
||||||
.command_buffer_count = 1,
|
|
||||||
.p_command_buffers = @ptrCast(&cmd.handle),
|
|
||||||
.signal_semaphore_count = 1,
|
|
||||||
.p_signal_semaphores = @ptrCast(&flight.complete),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
flight.fence,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (sc.present(&.{flight.complete}, target)) |_| {
|
|
||||||
break;
|
|
||||||
} else |err| switch (err) {
|
|
||||||
error.OutOfDateKHR => {
|
|
||||||
_ = try au.D.waitForFences(1, &.{flight.fence}, vk.TRUE, std.math.maxInt(u64));
|
|
||||||
try au.D.resetFences(1, &.{flight.fence});
|
|
||||||
sc.mark();
|
|
||||||
continue;
|
|
||||||
},
|
|
||||||
else => return err,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try au.D.deviceWaitIdle();
|
|
||||||
}
|
}
|
||||||
|
22
src/nu.zig
Normal file
22
src/nu.zig
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
pub const Window = @import("nu/Window.zig");
|
||||||
|
pub const Render = @import("nu/Render.zig");
|
||||||
|
pub const ImGui = @import("nu/ImGui.zig");
|
||||||
|
|
||||||
|
pub fn run(
|
||||||
|
driver: anytype,
|
||||||
|
modules: anytype,
|
||||||
|
) !void {
|
||||||
|
while (driver.next()) |events| {
|
||||||
|
// todo event handler
|
||||||
|
_ = events;
|
||||||
|
|
||||||
|
inline for (modules) |module| {
|
||||||
|
if (std.meta.hasMethod(@TypeOf(module), "frame"))
|
||||||
|
module.frame();
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo fixed timestep
|
||||||
|
}
|
||||||
|
}
|
294
src/nu/Bus.zig
Normal file
294
src/nu/Bus.zig
Normal file
@@ -0,0 +1,294 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
// const vk = @import("vk");
|
||||||
|
// const c = @import("../c.zig");
|
||||||
|
// const Window = @import("../au.zig").Window;
|
||||||
|
const Self = @This();
|
||||||
|
|
||||||
|
const Window = @import("Window.zig");
|
||||||
|
const c = Window.c;
|
||||||
|
|
||||||
|
alloc: std.mem.Allocator,
|
||||||
|
events: std.ArrayListUnmanaged(Event) = .{}, // todo bounded array?
|
||||||
|
drops: std.ArrayListUnmanaged([][]const u8) = .{}, // todo bounded array?
|
||||||
|
|
||||||
|
pub fn init(alloc: std.mem.Allocator) Self {
|
||||||
|
return .{
|
||||||
|
.alloc = alloc,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: *Self) void {
|
||||||
|
self.clear();
|
||||||
|
|
||||||
|
self.events.deinit(self.alloc);
|
||||||
|
self.drops.deinit(self.alloc);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn connect(self: *Self, handle: *c.GLFWwindow) void {
|
||||||
|
// todo somehow prevent double-connect?
|
||||||
|
c.glfwSetWindowUserPointer(handle, self);
|
||||||
|
_ = c.glfwSetWindowPosCallback(handle, onWindowPos);
|
||||||
|
_ = c.glfwSetWindowSizeCallback(handle, onWindowSize);
|
||||||
|
_ = c.glfwSetWindowCloseCallback(handle, onWindowClose);
|
||||||
|
_ = c.glfwSetWindowRefreshCallback(handle, onWindowRefresh);
|
||||||
|
_ = c.glfwSetWindowFocusCallback(handle, onWindowFocus);
|
||||||
|
_ = c.glfwSetWindowIconifyCallback(handle, onWindowIconify);
|
||||||
|
_ = c.glfwSetWindowMaximizeCallback(handle, onWindowMaximize);
|
||||||
|
_ = c.glfwSetFramebufferSizeCallback(handle, onFramebufferSize);
|
||||||
|
_ = c.glfwSetWindowContentScaleCallback(handle, onWindowContentScale);
|
||||||
|
_ = c.glfwSetMouseButtonCallback(handle, onMouseButton);
|
||||||
|
_ = c.glfwSetCursorPosCallback(handle, onCursorPos);
|
||||||
|
_ = c.glfwSetCursorEnterCallback(handle, onCursorEnter);
|
||||||
|
_ = c.glfwSetScrollCallback(handle, onScroll);
|
||||||
|
_ = c.glfwSetKeyCallback(handle, onKey);
|
||||||
|
_ = c.glfwSetCharModsCallback(handle, onCharMods);
|
||||||
|
_ = c.glfwSetDropCallback(handle, onDrop);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn disconnect(_: *Self, handle: *c.GLFWwindow) void {
|
||||||
|
// todo somehow prevent double-disconnect?
|
||||||
|
c.glfwSetWindowUserPointer(handle, null);
|
||||||
|
_ = c.glfwSetWindowPosCallback(handle, null);
|
||||||
|
_ = c.glfwSetWindowSizeCallback(handle, null);
|
||||||
|
_ = c.glfwSetWindowCloseCallback(handle, null);
|
||||||
|
_ = c.glfwSetWindowRefreshCallback(handle, null);
|
||||||
|
_ = c.glfwSetWindowFocusCallback(handle, null);
|
||||||
|
_ = c.glfwSetWindowIconifyCallback(handle, null);
|
||||||
|
_ = c.glfwSetWindowMaximizeCallback(handle, null);
|
||||||
|
_ = c.glfwSetFramebufferSizeCallback(handle, null);
|
||||||
|
_ = c.glfwSetWindowContentScaleCallback(handle, null);
|
||||||
|
_ = c.glfwSetMouseButtonCallback(handle, null);
|
||||||
|
_ = c.glfwSetCursorPosCallback(handle, null);
|
||||||
|
_ = c.glfwSetCursorEnterCallback(handle, null);
|
||||||
|
_ = c.glfwSetScrollCallback(handle, null);
|
||||||
|
_ = c.glfwSetKeyCallback(handle, null);
|
||||||
|
_ = c.glfwSetCharModsCallback(handle, null);
|
||||||
|
_ = c.glfwSetDropCallback(handle, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear(self: *Self) void {
|
||||||
|
for (self.drops.items) |drop| {
|
||||||
|
for (drop) |path| {
|
||||||
|
self.alloc.free(path);
|
||||||
|
}
|
||||||
|
self.alloc.free(drop);
|
||||||
|
}
|
||||||
|
self.drops.clearAndFree(self.alloc);
|
||||||
|
|
||||||
|
self.events.clearRetainingCapacity();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn getBus(handle: ?*c.GLFWwindow) *Self {
|
||||||
|
return @alignCast(@ptrCast(c.glfwGetWindowUserPointer(handle)));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const Event = union(enum) {
|
||||||
|
const WindowPos = struct { x: i32, y: i32 };
|
||||||
|
const WindowSize = struct { x: i32, y: i32 };
|
||||||
|
const WindowClose = struct {};
|
||||||
|
const WindowRefresh = struct {};
|
||||||
|
const WindowFocus = struct { focused: bool };
|
||||||
|
const WindowIconify = struct { iconified: bool };
|
||||||
|
const WindowMaximize = struct { maximized: bool };
|
||||||
|
const FramebufferSize = struct { width: u32, height: u32 };
|
||||||
|
const WindowContentScale = struct { x: f32, y: f32 };
|
||||||
|
const MouseButton = struct {
|
||||||
|
button: c_int, // todo enum
|
||||||
|
action: c_int, // todo enum
|
||||||
|
mods: c_int, // todo bitmask
|
||||||
|
};
|
||||||
|
const CursorPos = struct { x: f64, y: f64 };
|
||||||
|
const CursorEnter = struct { entered: bool };
|
||||||
|
const Scroll = struct { dx: f64, dy: f64 };
|
||||||
|
const Key = struct {
|
||||||
|
key: c_int, // todo enum
|
||||||
|
scan: c_int, // todo ???
|
||||||
|
action: c_int, // todo enum
|
||||||
|
mods: c_int, // todo bitmask
|
||||||
|
};
|
||||||
|
const Char = struct {
|
||||||
|
code: u21,
|
||||||
|
};
|
||||||
|
const CharMods = struct {
|
||||||
|
code: u21,
|
||||||
|
mods: c_int, // todo bitmask
|
||||||
|
};
|
||||||
|
const Drop = struct {
|
||||||
|
paths: []const []const u8,
|
||||||
|
};
|
||||||
|
|
||||||
|
windowPos: WindowPos,
|
||||||
|
windowSize: WindowSize,
|
||||||
|
windowClose: WindowClose,
|
||||||
|
windowRefresh: WindowRefresh,
|
||||||
|
windowFocus: WindowFocus,
|
||||||
|
windowIconify: WindowIconify,
|
||||||
|
windowMaximize: WindowMaximize,
|
||||||
|
framebufferSize: FramebufferSize,
|
||||||
|
windowContentScale: WindowContentScale,
|
||||||
|
mouseButton: MouseButton,
|
||||||
|
cursorPos: CursorPos,
|
||||||
|
cursorEnter: CursorEnter,
|
||||||
|
scroll: Scroll,
|
||||||
|
key: Key,
|
||||||
|
char: Char,
|
||||||
|
charMods: CharMods,
|
||||||
|
drop: Drop,
|
||||||
|
};
|
||||||
|
|
||||||
|
fn onWindowPos(handle: ?*c.GLFWwindow, x: c_int, y: c_int) callconv(.C) void {
|
||||||
|
const bus = getBus(handle);
|
||||||
|
bus.events.append(bus.alloc, .{
|
||||||
|
.windowPos = .{
|
||||||
|
.x = @intCast(x),
|
||||||
|
.y = @intCast(y),
|
||||||
|
},
|
||||||
|
}) catch unreachable; // todo circular queue; warn
|
||||||
|
}
|
||||||
|
|
||||||
|
fn onWindowSize(handle: ?*c.GLFWwindow, x: c_int, y: c_int) callconv(.C) void {
|
||||||
|
const bus = getBus(handle);
|
||||||
|
bus.events.append(bus.alloc, .{
|
||||||
|
.windowSize = .{
|
||||||
|
.x = @intCast(x),
|
||||||
|
.y = @intCast(y),
|
||||||
|
},
|
||||||
|
}) catch unreachable; // todo circular queue; warn
|
||||||
|
}
|
||||||
|
|
||||||
|
fn onWindowClose(handle: ?*c.GLFWwindow) callconv(.C) void {
|
||||||
|
const bus = getBus(handle);
|
||||||
|
bus.events.append(bus.alloc, .{
|
||||||
|
.windowClose = .{},
|
||||||
|
}) catch unreachable; // todo circular queue; warn
|
||||||
|
}
|
||||||
|
|
||||||
|
fn onWindowRefresh(handle: ?*c.GLFWwindow) callconv(.C) void {
|
||||||
|
const bus = getBus(handle);
|
||||||
|
bus.events.append(bus.alloc, .{
|
||||||
|
.windowRefresh = .{},
|
||||||
|
}) catch unreachable; // todo circular queue; warn
|
||||||
|
}
|
||||||
|
|
||||||
|
fn onWindowFocus(handle: ?*c.GLFWwindow, focused: c_int) callconv(.C) void {
|
||||||
|
const bus = getBus(handle);
|
||||||
|
bus.events.append(bus.alloc, .{
|
||||||
|
.windowFocus = .{
|
||||||
|
.focused = focused == c.GLFW_TRUE,
|
||||||
|
},
|
||||||
|
}) catch unreachable; // todo circular queue; warn
|
||||||
|
}
|
||||||
|
|
||||||
|
fn onWindowIconify(handle: ?*c.GLFWwindow, iconified: c_int) callconv(.C) void {
|
||||||
|
const bus = getBus(handle);
|
||||||
|
bus.events.append(bus.alloc, .{
|
||||||
|
.windowIconify = .{
|
||||||
|
.iconified = iconified == c.GLFW_TRUE,
|
||||||
|
},
|
||||||
|
}) catch unreachable; // todo circular queue; warn
|
||||||
|
}
|
||||||
|
|
||||||
|
fn onWindowMaximize(handle: ?*c.GLFWwindow, maximized: c_int) callconv(.C) void {
|
||||||
|
const bus = getBus(handle);
|
||||||
|
bus.events.append(bus.alloc, .{
|
||||||
|
.windowMaximize = .{
|
||||||
|
.maximized = maximized == c.GLFW_TRUE,
|
||||||
|
},
|
||||||
|
}) catch unreachable; // todo circular queue; warn
|
||||||
|
}
|
||||||
|
|
||||||
|
fn onFramebufferSize(handle: ?*c.GLFWwindow, width: c_int, height: c_int) callconv(.C) void {
|
||||||
|
const bus = getBus(handle);
|
||||||
|
bus.events.append(bus.alloc, .{
|
||||||
|
.framebufferSize = .{
|
||||||
|
.width = @intCast(width),
|
||||||
|
.height = @intCast(height),
|
||||||
|
},
|
||||||
|
}) catch unreachable; // todo circular queue; warn
|
||||||
|
}
|
||||||
|
|
||||||
|
fn onWindowContentScale(handle: ?*c.GLFWwindow, x: f32, y: f32) callconv(.C) void {
|
||||||
|
const bus = getBus(handle);
|
||||||
|
bus.events.append(bus.alloc, .{
|
||||||
|
.windowContentScale = .{
|
||||||
|
.x = x,
|
||||||
|
.y = y,
|
||||||
|
},
|
||||||
|
}) catch unreachable; // todo circular queue; warn
|
||||||
|
}
|
||||||
|
|
||||||
|
fn onMouseButton(handle: ?*c.GLFWwindow, button: c_int, action: c_int, mods: c_int) callconv(.C) void {
|
||||||
|
const bus = getBus(handle);
|
||||||
|
bus.events.append(bus.alloc, .{
|
||||||
|
.mouseButton = .{
|
||||||
|
.button = button,
|
||||||
|
.action = action,
|
||||||
|
.mods = mods,
|
||||||
|
},
|
||||||
|
}) catch unreachable; // todo circular queue; warn
|
||||||
|
}
|
||||||
|
|
||||||
|
fn onCursorPos(handle: ?*c.GLFWwindow, x: f64, y: f64) callconv(.C) void {
|
||||||
|
const bus = getBus(handle);
|
||||||
|
bus.events.append(bus.alloc, .{
|
||||||
|
.cursorPos = .{
|
||||||
|
.x = x,
|
||||||
|
.y = y,
|
||||||
|
},
|
||||||
|
}) catch unreachable; // todo circular queue; warn
|
||||||
|
}
|
||||||
|
|
||||||
|
fn onCursorEnter(handle: ?*c.GLFWwindow, entered: c_int) callconv(.C) void {
|
||||||
|
const bus = getBus(handle);
|
||||||
|
bus.events.append(bus.alloc, .{
|
||||||
|
.cursorEnter = .{
|
||||||
|
.entered = entered == c.GLFW_TRUE,
|
||||||
|
},
|
||||||
|
}) catch unreachable; // todo circular queue; warn
|
||||||
|
}
|
||||||
|
|
||||||
|
fn onScroll(handle: ?*c.GLFWwindow, dx: f64, dy: f64) callconv(.C) void {
|
||||||
|
const bus = getBus(handle);
|
||||||
|
bus.events.append(bus.alloc, .{
|
||||||
|
.scroll = .{
|
||||||
|
.dx = dx,
|
||||||
|
.dy = dy,
|
||||||
|
},
|
||||||
|
}) catch unreachable; // todo circular queue; warn
|
||||||
|
}
|
||||||
|
|
||||||
|
fn onKey(handle: ?*c.GLFWwindow, key: c_int, scan: c_int, action: c_int, mods: c_int) callconv(.C) void {
|
||||||
|
const bus = getBus(handle);
|
||||||
|
bus.events.append(bus.alloc, .{
|
||||||
|
.key = .{
|
||||||
|
.key = key,
|
||||||
|
.scan = scan,
|
||||||
|
.action = action,
|
||||||
|
.mods = mods,
|
||||||
|
},
|
||||||
|
}) catch unreachable; // todo circular queue; warn
|
||||||
|
}
|
||||||
|
|
||||||
|
fn onCharMods(handle: ?*c.GLFWwindow, code: c_uint, mods: c_int) callconv(.C) void {
|
||||||
|
const bus = getBus(handle);
|
||||||
|
bus.events.append(bus.alloc, .{
|
||||||
|
.charMods = .{
|
||||||
|
.code = @intCast(code),
|
||||||
|
.mods = mods,
|
||||||
|
},
|
||||||
|
}) catch unreachable; // todo circular queue; warn
|
||||||
|
}
|
||||||
|
|
||||||
|
fn onDrop(handle: ?*c.GLFWwindow, count: c_int, paths: [*c][*c]const u8) callconv(.C) void {
|
||||||
|
const bus = getBus(handle);
|
||||||
|
|
||||||
|
const drops = bus.alloc.alloc([]const u8, @intCast(count)) catch unreachable; // todo warn
|
||||||
|
for (drops, paths) |*dst, src| {
|
||||||
|
dst.* = bus.alloc.dupe(u8, std.mem.sliceTo(src, 0)) catch unreachable; // todo warn
|
||||||
|
}
|
||||||
|
bus.drops.append(bus.alloc, drops) catch unreachable; // todo warn
|
||||||
|
|
||||||
|
bus.events.append(bus.alloc, .{
|
||||||
|
.drop = .{ .paths = drops },
|
||||||
|
}) catch unreachable; // todo circular queue; warn
|
||||||
|
}
|
20
src/nu/ImGui.zig
Normal file
20
src/nu/ImGui.zig
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
//! all imgui code through this path
|
||||||
|
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
const Self = @This();
|
||||||
|
|
||||||
|
const Window = @import("Window.zig");
|
||||||
|
const Render = @import("Render.zig");
|
||||||
|
|
||||||
|
pub fn init(alloc: std.mem.Allocator, window: *Window, render: *Render) !Self {
|
||||||
|
_ = alloc;
|
||||||
|
_ = window;
|
||||||
|
_ = render;
|
||||||
|
|
||||||
|
return .{};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: *Self) void {
|
||||||
|
_ = self;
|
||||||
|
}
|
23
src/nu/Render.zig
Normal file
23
src/nu/Render.zig
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
const Window = @import("Window.zig");
|
||||||
|
|
||||||
|
const Self = @This();
|
||||||
|
|
||||||
|
// isolate all the vulkan code through this path
|
||||||
|
// except for imgui code
|
||||||
|
|
||||||
|
// const au = @import("au.zig");
|
||||||
|
|
||||||
|
pub fn init(alloc: std.mem.Allocator, window: *Window) !Self {
|
||||||
|
_ = alloc;
|
||||||
|
_ = window;
|
||||||
|
|
||||||
|
// todo check vulkan supported
|
||||||
|
// todo create window surface
|
||||||
|
return .{};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: *Self) void {
|
||||||
|
_ = self;
|
||||||
|
}
|
77
src/nu/Window.zig
Normal file
77
src/nu/Window.zig
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
//! GLFW Adaptor
|
||||||
|
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
pub const c = @cImport({
|
||||||
|
@cDefine("GLFW_INCLUDE_NONE", {});
|
||||||
|
@cInclude("GLFW/glfw3.h");
|
||||||
|
});
|
||||||
|
|
||||||
|
const Self = @This();
|
||||||
|
|
||||||
|
pub const Bus = @import("Bus.zig");
|
||||||
|
|
||||||
|
pub const Options = struct {
|
||||||
|
title: [*:0]const u8,
|
||||||
|
width: u32 = 1280,
|
||||||
|
height: u32 = 720,
|
||||||
|
x11_class_name: [*:0]const u8 = "floating_window",
|
||||||
|
x11_instance_name: [*:0]const u8 = "floating_window",
|
||||||
|
};
|
||||||
|
|
||||||
|
alloc: std.mem.Allocator,
|
||||||
|
bus: *Bus,
|
||||||
|
handle: *c.GLFWwindow,
|
||||||
|
|
||||||
|
pub fn init(alloc: std.mem.Allocator, options: Options) !Self {
|
||||||
|
if (c.glfwInit() != c.GLFW_TRUE)
|
||||||
|
return error.glfwInitFailed;
|
||||||
|
errdefer c.glfwTerminate();
|
||||||
|
|
||||||
|
const bus: *Bus = try alloc.create(Bus);
|
||||||
|
errdefer alloc.destroy(bus);
|
||||||
|
bus.* = Bus.init(alloc);
|
||||||
|
errdefer bus.deinit();
|
||||||
|
|
||||||
|
c.glfwWindowHint(c.GLFW_CLIENT_API, c.GLFW_NO_API);
|
||||||
|
c.glfwWindowHintString(c.GLFW_X11_CLASS_NAME, options.x11_class_name);
|
||||||
|
c.glfwWindowHintString(c.GLFW_X11_INSTANCE_NAME, options.x11_instance_name);
|
||||||
|
|
||||||
|
const handle: *c.GLFWwindow = c.glfwCreateWindow(
|
||||||
|
@intCast(options.width),
|
||||||
|
@intCast(options.height),
|
||||||
|
options.title,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
) orelse
|
||||||
|
return error.glfWCreateWindowFailed;
|
||||||
|
errdefer c.glfwDestroyWindow(handle);
|
||||||
|
|
||||||
|
bus.connect(handle);
|
||||||
|
errdefer bus.disconnect(handle);
|
||||||
|
|
||||||
|
return .{
|
||||||
|
.alloc = alloc,
|
||||||
|
.bus = bus,
|
||||||
|
.handle = handle,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: *Self) void {
|
||||||
|
self.bus.deinit();
|
||||||
|
self.alloc.destroy(self.bus);
|
||||||
|
c.glfwDestroyWindow(self.handle);
|
||||||
|
c.glfwTerminate();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn next(self: *Self) ?[]Bus.Event {
|
||||||
|
self.bus.clear();
|
||||||
|
|
||||||
|
if (c.glfwWindowShouldClose(self.handle) == c.GLFW_TRUE)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// c.glfwPollEvents();
|
||||||
|
c.glfwWaitEvents();
|
||||||
|
|
||||||
|
return self.bus.events.items;
|
||||||
|
}
|
Reference in New Issue
Block a user