colorful box

This commit is contained in:
2024-11-25 20:54:45 -05:00
parent b8d89122ab
commit ce8109c1aa
8 changed files with 280 additions and 166 deletions

View File

@@ -14,19 +14,11 @@ pub fn build(b: *std.Build) void {
const cimgui = b.dependency("cimgui", .{});
const nu = b.addModule("nu", .{
.root_source_file = b.path("src/nu.zig"),
.target = target,
.optimize = optimize,
.link_libc = true,
});
nu.addImport("cimgui", cimgui.module("cimgui"));
nu.addImport("vk", vkmod);
nu.linkSystemLibrary("glfw3", .{
.needed = true,
.preferred_link_mode = .static,
.use_pkg_config = .force,
});
// nu.linkSystemLibrary("glfw3", .{
// .needed = true,
// .preferred_link_mode = .static,
// .use_pkg_config = .force,
// });
const exe = b.addExecutable(.{
.name = "scratchzig",
@@ -34,9 +26,15 @@ pub fn build(b: *std.Build) void {
.target = target,
.optimize = optimize,
});
exe.root_module.addImport("nu", nu);
// exe.root_module.addImport("nu", nu);
exe.root_module.addImport("vk", vkmod);
exe.root_module.addImport("cimgui", cimgui.module("cimgui"));
exe.root_module.linkSystemLibrary("glfw3", .{
.needed = true,
.preferred_link_mode = .static,
.use_pkg_config = .force,
});
exe.linkLibC();
const shaders = vkgen.ShaderCompileStep.create(
b,
@@ -59,42 +57,6 @@ pub fn build(b: *std.Build) void {
const run_step = b.step("run", "Run the app");
run_step.dependOn(&run_cmd.step);
const nu_unit_tests = b.addTest(.{
.root_source_file = b.path("src/nu.zig"),
.target = target,
.optimize = optimize,
});
nu_unit_tests.root_module.addImport("cimgui", cimgui.module("cimgui"));
nu_unit_tests.root_module.addImport("vk", vkmod);
nu_unit_tests.root_module.linkSystemLibrary("glfw3", .{
.needed = true,
.preferred_link_mode = .static,
.use_pkg_config = .force,
});
nu_unit_tests.linkLibC();
const nu_test_runner = b.addInstallArtifact(nu_unit_tests, .{
.dest_dir = .{ .override = .{ .custom = "dev" } },
.dest_sub_path = "nu_test_runner",
});
const devel_step = b.step("dev", "Build development tools and test runners");
devel_step.dependOn(&nu_test_runner.step);
// const exe_unit_tests = b.addTest(.{
// .root_source_file = b.path("src/main.zig"),
// .target = target,
// .optimize = optimize,
// });
// exe_unit_tests.linkSystemLibrary2("glfw3", .{
// .needed = true,
// .preferred_link_mode = .static,
// .use_pkg_config = .force,
// });
// exe_unit_tests.linkLibC();
// const run_exe_unit_tests = b.addRunArtifact(exe_unit_tests);
// const test_step = b.step("test", "Run unit tests");
// test_step.dependOn(&run_exe_unit_tests.step);
// test_step.dependOn(&run_nu_unit_tests.step);
// const devel_step = b.step("dev", "Build development tools and test runners");
// devel_step.dependOn(&nu_test_runner.step);
}

View File

@@ -2,8 +2,11 @@ const std = @import("std");
const vk = @import("vk");
const shaders = @import("shaders");
const nu = @import("nu.zig");
const Self = @This();
const ctx = nu.Render.ctx;
set_layout: vk.DescriptorSetLayout,
layout: vk.PipelineLayout,
pipeline: vk.Pipeline,
@@ -50,34 +53,34 @@ pub const Vertex = extern struct {
};
pub fn init(cache: vk.PipelineCache) !Self {
const vert = try au.D.createShaderModule(&.{
const vert = try ctx.D.createShaderModule(&.{
.code_size = shaders.triangle_vert.len,
.p_code = @ptrCast(&shaders.triangle_vert),
}, null);
defer au.D.destroyShaderModule(vert, null);
defer ctx.D.destroyShaderModule(vert, null);
const frag = try au.D.createShaderModule(&.{
const frag = try ctx.D.createShaderModule(&.{
.code_size = shaders.triangle_frag.len,
.p_code = @ptrCast(&shaders.triangle_frag),
}, null);
defer au.D.destroyShaderModule(frag, null);
defer ctx.D.destroyShaderModule(frag, null);
const set_layout = try au.D.createDescriptorSetLayout(&vk.DescriptorSetLayoutCreateInfo{
const set_layout = try ctx.D.createDescriptorSetLayout(&vk.DescriptorSetLayoutCreateInfo{
.flags = .{},
.binding_count = @intCast(Uniform.Bindings.len),
.p_bindings = &Uniform.Bindings,
}, null);
errdefer au.D.destroyDescriptorSetLayout(set_layout, null);
errdefer ctx.D.destroyDescriptorSetLayout(set_layout, null);
const layout = try au.D.createPipelineLayout(&vk.PipelineLayoutCreateInfo{
const layout = try ctx.D.createPipelineLayout(&vk.PipelineLayoutCreateInfo{
.push_constant_range_count = 0,
.set_layout_count = 1,
.p_set_layouts = &.{set_layout},
}, null);
errdefer au.D.destroyPipelineLayout(layout, null);
errdefer ctx.D.destroyPipelineLayout(layout, null);
var pipeline: vk.Pipeline = .null_handle;
_ = try au.D.createGraphicsPipelines(cache, 1, &[1]vk.GraphicsPipelineCreateInfo{
_ = try ctx.D.createGraphicsPipelines(cache, 1, &[1]vk.GraphicsPipelineCreateInfo{
vk.GraphicsPipelineCreateInfo{
.stage_count = 2,
.p_stages = &.{
@@ -152,20 +155,20 @@ pub fn init(cache: vk.PipelineCache) !Self {
},
.p_next = &vk.PipelineRenderingCreateInfo{
.color_attachment_count = 1,
.p_color_attachment_formats = &.{au.device_config.format.format},
.p_color_attachment_formats = &.{nu.Render.sc.cinfo.image_format},
.depth_attachment_format = .undefined,
.stencil_attachment_format = .undefined,
.view_mask = 0,
},
},
}, null, @ptrCast(&pipeline));
errdefer au.D.destroyPipeline(pipeline, null);
errdefer ctx.D.destroyPipeline(pipeline, null);
return .{ .pipeline = pipeline, .layout = layout, .set_layout = set_layout };
}
pub fn deinit(self: Self) void {
au.D.destroyPipeline(self.pipeline, null);
au.D.destroyPipelineLayout(self.layout, null);
au.D.destroyDescriptorSetLayout(self.set_layout, null);
ctx.D.destroyPipeline(self.pipeline, null);
ctx.D.destroyPipelineLayout(self.layout, null);
ctx.D.destroyDescriptorSetLayout(self.set_layout, null);
}

View File

@@ -1,86 +1,219 @@
const std = @import("std");
const nu = @import("nu.zig");
const Uber = @import("Uber.zig");
pub const nu_modules = .{
App,
// UI,
};
pub const nu_modules = .{@This()};
pub const main = nu.main;
pub const nu_options: nu.Options = .{
.window = .{ .title = "Hello World" },
pub const nu_config: nu.Config = .{
.window = nu.Window.Config{
.title = "au",
},
.render = .{
.app_name = "hello-world",
.frames_in_flight = 3,
.app_name = "au",
.frames_in_flight = 2,
},
};
// pub const UI = struct {
// const im = nu.ImGui;
//
// pub const depends = .{im};
//
// var color: @Vector(4, f32) = @splat(1);
//
// pub fn setup(_: std.mem.Allocator) !void {
// const io: *nu.ImGui.ImGuiIO = @ptrCast(nu.ImGui.igGetIO());
// io.ConfigFlags |= nu.ImGui.ImGuiConfigFlags_DockingEnable;
// }
//
// pub fn frame() !void {
// nu.ImGui.igShowMetricsWindow(null);
//
// {
// const viewport = im.igGetMainViewport();
// im.igSetNextWindowPos(viewport.*.WorkPos, 0, .{ .x = 0, .y = 0 });
// im.igSetNextWindowSize(viewport.*.WorkSize, 0);
// im.igSetNextWindowViewport(viewport.*.ID);
// im.igPushStyleVar_Float(im.ImGuiStyleVar_WindowRounding, 0);
// im.igPushStyleVar_Float(im.ImGuiStyleVar_WindowBorderSize, 0);
// im.igPushStyleVar_Vec2(im.ImGuiStyleVar_WindowPadding, .{ .x = 0, .y = 0 });
// defer im.igPopStyleVar(3);
//
// const window_flags =
// im.ImGuiWindowFlags_MenuBar |
// im.ImGuiWindowFlags_NoDocking |
// im.ImGuiWindowFlags_NoTitleBar |
// im.ImGuiWindowFlags_NoCollapse |
// im.ImGuiWindowFlags_NoResize |
// im.ImGuiWindowFlags_NoMove |
// im.ImGuiWindowFlags_NoBringToFrontOnFocus |
// im.ImGuiWindowFlags_NoNavFocus |
// im.ImGuiWindowFlags_NoBackground;
//
// const dock_flags =
// im.ImGuiDockNodeFlags_PassthruCentralNode |
// im.ImGuiDockNodeFlags_NoDockingOverCentralNode;
//
// _ = im.igBegin("Main Dockspace", null, window_flags);
// const id = im.igGetID_Str("maindockspace");
// _ = im.igDockSpace(id, .{ .x = 0, .y = 0 }, dock_flags, null);
// im.igEnd();
// }
//
// if (nu.ImGui.igBegin("Color", null, nu.ImGui.ImGuiWindowFlags_None)) {
// if (nu.ImGui.igColorEdit4("color", @ptrCast(&color), nu.ImGui.ImGuiColorEditFlags_AlphaPreviewHalf)) {}
// }
// nu.ImGui.igEnd();
// }
// };
const im = nu.ImGui;
const ctx = nu.Render.ctx;
const vk = @import("vk");
const App = struct {
const vk = @import("vk");
// const au = @import("nu/Render/au.zig");
pub const depends = .{nu.ImGui};
pub const depends = .{nu.Render};
// todo timeline semaphore
pub fn setup(_: std.mem.Allocator) !void {}
pub fn teardown() void {}
pub fn frame() !void {}
// pub fn present(_: au.CommandBufferProxy) void {}
const vertices: []const Uber.Vertex = &.{
.{ .pos = .{ 0.0, 0.0, 0.0, 1.0 }, .color = .{ 1.0, 1.0, 0.0 } },
.{ .pos = .{ 1.0, 0.0, 0.0, 1.0 }, .color = .{ 1.0, 0.0, 1.0 } },
.{ .pos = .{ 0.0, 1.0, 0.0, 1.0 }, .color = .{ 0.0, 1.0, 1.0 } },
.{ .pos = .{ 1.0, 1.0, 0.0, 1.0 }, .color = .{ 1.0, 1.0, 1.0 } },
};
const Index = u16;
const indices: []const Index = &.{
1, 0, 2,
2, 3, 1,
};
const uniform: Uber.Uniform = .{
.mat = .{
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
},
};
var mem: vk.DeviceMemory = .null_handle;
var vbo: vk.Buffer = .null_handle;
var ibo: vk.Buffer = .null_handle;
var ubo: vk.Buffer = .null_handle;
var pool: vk.DescriptorPool = .null_handle;
var descriptor_set: vk.DescriptorSet = .null_handle;
var cache: vk.PipelineCache = .null_handle;
var uber: Uber = undefined;
pub fn setup(_: std.mem.Allocator) !void {
errdefer teardown();
const props = ctx.I.getPhysicalDeviceMemoryProperties(ctx.pdevice.*);
const memory_type_index: u32 = for (0..props.memory_type_count) |idx| {
const t = props.memory_types[idx];
if (t.property_flags.host_coherent_bit and t.property_flags.host_visible_bit) {
break @intCast(idx);
}
} else {
unreachable;
};
const SIZE = 0x10000;
mem = try ctx.D.allocateMemory(&vk.MemoryAllocateInfo{
.allocation_size = SIZE,
.memory_type_index = memory_type_index,
}, null);
const raw: [*]u8 = @ptrCast(try ctx.D.mapMemory(mem, 0, vk.WHOLE_SIZE, .{}) orelse unreachable);
errdefer ctx.D.unmapMemory(mem);
// todo VMA. This doesn't work for some reason to do with alignment.
// var fba = std.heap.FixedBufferAllocator.init(raw[0..SIZE]);
// const aa = fba.allocator();
var bump: usize = 0;
const vbytes = std.mem.sliceAsBytes(vertices);
vbo = try ctx.D.createBuffer(&vk.BufferCreateInfo{
.queue_family_index_count = 1,
.p_queue_family_indices = &.{ctx.family.*},
.sharing_mode = .exclusive,
.size = vbytes.len,
.usage = .{ .vertex_buffer_bit = true },
}, null);
const vreq = ctx.D.getBufferMemoryRequirements(vbo);
bump = std.mem.alignForward(usize, bump, vreq.alignment);
@memcpy(raw + bump, vbytes);
try ctx.D.bindBufferMemory(vbo, mem, bump);
bump += vreq.size;
const ibytes = std.mem.sliceAsBytes(indices);
ibo = try ctx.D.createBuffer(&vk.BufferCreateInfo{
.queue_family_index_count = 1,
.p_queue_family_indices = &.{ctx.family.*},
.sharing_mode = .exclusive,
.size = ibytes.len,
.usage = .{ .index_buffer_bit = true },
}, null);
const ireq = ctx.D.getBufferMemoryRequirements(ibo);
bump = std.mem.alignForward(usize, bump, ireq.alignment);
@memcpy(raw + bump, ibytes);
try ctx.D.bindBufferMemory(ibo, mem, bump);
bump += ireq.size;
const ubytes = std.mem.asBytes(&uniform);
ubo = try ctx.D.createBuffer(&vk.BufferCreateInfo{
.queue_family_index_count = 1,
.p_queue_family_indices = &.{ctx.family.*},
.sharing_mode = .exclusive,
.size = ubytes.len,
.usage = .{ .uniform_buffer_bit = true },
}, null);
const ureq = ctx.D.getBufferMemoryRequirements(ubo);
bump = std.mem.alignForward(usize, bump, ureq.alignment);
@memcpy(raw + bump, ubytes);
try ctx.D.bindBufferMemory(ubo, mem, bump);
bump += ureq.size;
cache = try ctx.D.createPipelineCache(&vk.PipelineCacheCreateInfo{}, null);
uber = try Uber.init(cache);
const pool_sizes: []const vk.DescriptorPoolSize = &.{vk.DescriptorPoolSize{
.descriptor_count = 8,
.type = .uniform_buffer,
}};
pool = try ctx.D.createDescriptorPool(&vk.DescriptorPoolCreateInfo{
.flags = .{ .free_descriptor_set_bit = true },
.pool_size_count = @intCast(pool_sizes.len),
.p_pool_sizes = pool_sizes.ptr,
.max_sets = 32,
}, null);
var sets: [1]vk.DescriptorSet = .{.null_handle};
try ctx.D.allocateDescriptorSets(&vk.DescriptorSetAllocateInfo{
.descriptor_pool = pool,
.descriptor_set_count = 1,
.p_set_layouts = &.{uber.set_layout},
}, &sets);
descriptor_set = sets[0];
ctx.D.updateDescriptorSets(
1,
&.{
vk.WriteDescriptorSet{
.dst_set = descriptor_set,
.dst_binding = 0,
.dst_array_element = 0,
.descriptor_count = 1,
.descriptor_type = .uniform_buffer,
.p_buffer_info = &.{
vk.DescriptorBufferInfo{
.buffer = ubo,
.offset = 0,
.range = vk.WHOLE_SIZE,
},
},
.p_image_info = undefined,
.p_texel_buffer_view = undefined,
},
},
0,
null,
);
}
pub fn teardown() void {
ctx.Q.waitIdle() catch {};
uber.deinit();
ctx.D.destroyPipelineCache(cache, null);
ctx.D.destroyBuffer(ubo, null);
ctx.D.destroyBuffer(ibo, null);
ctx.D.destroyBuffer(vbo, null);
ctx.D.freeMemory(mem, null);
ctx.D.freeDescriptorSets(pool, 1, &.{descriptor_set}) catch unreachable;
ctx.D.destroyDescriptorPool(pool, null);
}
pub fn frame() !void {
im.igShowMetricsWindow(null);
}
pub fn present(cmd: ctx.CommandBufferProxy) void {
const w, const h = nu.Window.size();
cmd.bindPipeline(.graphics, uber.pipeline);
cmd.setScissor(0, 1, &.{vk.Rect2D{
.offset = .{ .x = 0, .y = 0 },
.extent = .{ .width = w, .height = h },
}});
cmd.setViewport(0, 1, &.{vk.Viewport{
.x = 0,
.y = 0,
.width = @floatFromInt(w),
.height = @floatFromInt(h),
.min_depth = 0,
.max_depth = 1,
}});
cmd.bindIndexBuffer(ibo, 0, .uint16);
cmd.bindVertexBuffers(0, 1, &.{vbo}, &.{0});
cmd.bindDescriptorSets(
.graphics,
uber.layout,
0,
1,
&.{descriptor_set},
0,
null,
);
cmd.drawIndexed(@intCast(indices.len), 1, 0, 0, 0);
}

View File

@@ -3,11 +3,12 @@ const root = @import("root");
pub const Window = @import("nu/Window.zig");
pub const Render = @import("nu/Render.zig");
// pub const ImGui = @import("nu/ImGui.zig");
pub const ImGui = @import("nu/ImGui.zig");
pub const ctx = @import("nu/Render/ctx.zig");
pub const Bus = @import("nu/Bus.zig");
// pub const Bus = @import("nu/Bus.zig");
const Config = struct {
pub const Config = struct {
window: Window.Config = .{},
render: Render.Config = .{},
};
@@ -52,6 +53,7 @@ pub fn Engine(comptime D: type, comptime R: type, comptime M: anytype) type {
return R.render();
}
// todo remove this
pub fn try_invoke(comptime name: []const u8, args: anytype) !void {
inline for (modules) |mod| {
if (@hasDecl(mod, name)) {
@@ -68,6 +70,7 @@ pub fn Engine(comptime D: type, comptime R: type, comptime M: anytype) type {
}
}
// todo remove this
pub fn try_rinvoke(comptime name: []const u8, args: anytype) !void {
comptime var it = std.mem.reverseIterator(modules);
inline while (it.next()) |mod| {

View File

@@ -17,7 +17,7 @@ const config = nu.config.imgui;
pub const depends = .{ Render, Window };
pub fn loader_wrapper(procname: [*c]const u8, _: ?*anyopaque) callconv(.C) vk.PfnVoidFunction {
return nu.glfwGetInstanceProcAddress(nu.I.handle, procname);
return Render.ctx.glfwGetInstanceProcAddress(Render.ctx.instance.*, procname);
}
var ctx: *im.ImGuiContext = undefined;
@@ -38,8 +38,7 @@ pub fn setup(_: std.mem.Allocator) !void {
}
errdefer im.impl.ImGui_ImplGlfw_Shutdown();
descriptor_pool = try Render.ctx.dw.createDescriptorPool(
Render.ctx.device,
descriptor_pool = try Render.ctx.D.createDescriptorPool(
&vk.DescriptorPoolCreateInfo{
.flags = .{ .free_descriptor_set_bit = true },
.pool_size_count = 1,
@@ -51,24 +50,24 @@ pub fn setup(_: std.mem.Allocator) !void {
},
null,
);
errdefer Render.ctx.dw.destroyDescriptorPool(Render.ctx.device, descriptor_pool, null);
errdefer Render.ctx.D.destroyDescriptorPool(descriptor_pool, null);
if (im.impl.ImGui_ImplVulkan_Init(@constCast(&im.impl.ImGui_ImplVulkan_InitInfo{
.Instance = @ptrFromInt(@intFromEnum(Render.ctx.instance)),
.PhysicalDevice = @ptrFromInt(@intFromEnum(Render.ctx.pdevice)),
.Device = @ptrFromInt(@intFromEnum(Render.ctx.device)),
.QueueFamily = au.device_config.family, // todo
.Queue = @ptrFromInt(@intFromEnum(au.Q.handle)), // todo
.Instance = @ptrFromInt(@intFromEnum(Render.ctx.instance.*)),
.PhysicalDevice = @ptrFromInt(@intFromEnum(Render.ctx.pdevice.*)),
.Device = @ptrFromInt(@intFromEnum(Render.ctx.device.*)),
.QueueFamily = Render.ctx.family.*, // todo
.Queue = @ptrFromInt(@intFromEnum(Render.ctx.Q.handle)), // todo
.DescriptorPool = @ptrFromInt(@intFromEnum(descriptor_pool)),
.RenderPass = null,
.MinImageCount = 2,
.ImageCount = @intCast(nu.config.render.frames_in_flight),
.ImageCount = @intCast(Render.sc.frames_in_flight),
.PipelineRenderingCreateInfo = @bitCast(vk.PipelineRenderingCreateInfo{
.view_mask = 0,
.depth_attachment_format = .undefined,
.stencil_attachment_format = .undefined,
.color_attachment_count = 1,
.p_color_attachment_formats = &.{au.device_config.format.format}, // todo
.p_color_attachment_formats = &.{Render.sc.cinfo.image_format}, // todo
}),
.MSAASamples = 0,
.PipelineCache = null,
@@ -86,9 +85,9 @@ pub fn setup(_: std.mem.Allocator) !void {
}
pub fn teardown() void {
Render.ctx.dw.deviceWaitIdle(Render.ctx.device) catch |err| std.debug.panic("Device wait failed: {!}", .{err});
Render.ctx.D.deviceWaitIdle() catch |err| std.debug.panic("Device wait failed: {!}", .{err});
im.impl.ImGui_ImplVulkan_Shutdown();
Render.ctx.dw.destroyDescriptorPool(Render.ctx.device, descriptor_pool, null);
Render.ctx.D.destroyDescriptorPool(descriptor_pool, null);
im.impl.ImGui_ImplGlfw_Shutdown();
im.igDestroyContext(ctx);
}
@@ -99,7 +98,7 @@ pub fn frame() !void {
im.igNewFrame();
}
pub fn present(cmd: au.CommandBufferProxy) void { // todo
pub fn rpresent(cmd: Render.ctx.CommandBufferProxy) void { // todo
im.igEndFrame();
im.igRender();

View File

@@ -8,7 +8,8 @@ const vk = @import("vk");
const nu = @import("../nu.zig");
const ctx = @import("Render/ctx.zig");
pub const ctx = @import("Render/ctx.zig");
const SwapChain = @import("Render/SwapChain.zig");
pub const Config = struct {
@@ -30,6 +31,7 @@ pub const Config = struct {
.Debug, .ReleaseSafe => true,
.ReleaseSmall, .ReleaseFast => false,
},
frames_in_flight: u8 = 2,
};
const config = nu.config.render;
@@ -70,17 +72,17 @@ const Flight = struct {
}
};
pub const sc: *const SwapChain = &_sc;
var _sc: SwapChain = undefined;
var _flights: []Flight = undefined;
var _flights: [nu.config.render.frames_in_flight]Flight = undefined;
pub fn setup(alloc: std.mem.Allocator) !void {
try ctx.init(alloc);
errdefer ctx.deinit();
_flights = try alloc.alloc(Flight, 3);
errdefer alloc.free(_flights);
errdefer for (_flights) |flight| flight.deinit();
for (_flights) |*flight| flight.* = try Flight.init();
for (&_flights) |*flight| flight.* = try Flight.init();
_sc = try SwapChain.init(alloc, _flights.len);
errdefer _sc.deinit();
@@ -143,6 +145,9 @@ pub fn render() !void {
},
});
nu.engine.invoke("present", .{cmd});
nu.engine.rinvoke("rpresent", .{cmd});
cmd.endRendering();
cmd.pipelineBarrier(

View File

@@ -96,6 +96,7 @@ const View = struct {
alloc: std.mem.Allocator,
frames_in_flight: u32,
flight_index: usize = 0,
flight_syncs: std.MultiArrayList(Sync) = .{},
@@ -104,13 +105,14 @@ handle: vk.SwapchainKHR = .null_handle,
chain: std.MultiArrayList(View) = .{},
pub fn init(alloc: std.mem.Allocator, flight_count: usize) !Self {
pub fn init(alloc: std.mem.Allocator, frames_in_flight: usize) !Self {
var self: Self = .{
.alloc = alloc,
.frames_in_flight = @intCast(frames_in_flight),
};
errdefer self.deinit();
try self.flight_syncs.resize(alloc, flight_count);
try self.flight_syncs.resize(alloc, frames_in_flight);
for (self.flight_syncs.items(.acquired)) |*sem|
sem.* = try ctx.D.createSemaphore(&.{}, null);
for (self.flight_syncs.items(.complete)) |*sem|
@@ -275,11 +277,11 @@ pub fn present(self: *Self, target: Target) !void {
.p_swapchains = &.{self.handle},
.p_image_indices = &.{target.image_index},
.p_results = null,
})) |res| switch(res) {
})) |res| switch (res) {
.success => {},
.suboptimal_khr => self.handle = .null_handle,
else => unreachable,
} else |err| switch(err) {
} else |err| switch (err) {
error.OutOfDateKHR => self.handle = .null_handle,
else => return err,
}

View File

@@ -93,3 +93,10 @@ pub fn add_resize_callback(cb: *const fn (u32, u32) void) void {
pub fn set_title(title: [:0]const u8) void {
c.glfwSetWindowTitle(handle, title);
}
pub fn size() std.meta.Tuple(&[_]type{ u32, u32 }) {
var w: c_int = undefined;
var h: c_int = undefined;
c.glfwGetFramebufferSize(handle, &w, &h);
return .{ @intCast(w), @intCast(h) };
}