Add 'shape/' from commit '8c82294c9190463a2fe19de485ff706ae21ef758'
git-subtree-dir: shape git-subtree-mainline:f61860e87e
git-subtree-split:8c82294c91
This commit is contained in:
3
shape/.gitignore
vendored
Normal file
3
shape/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
.zig-cache/
|
||||||
|
zig-out/
|
||||||
|
.idea/
|
3
shape/.tool-versions
Normal file
3
shape/.tool-versions
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
zig 0.14.0-dev.3217+5b9b5e45c
|
||||||
|
|
||||||
|
# zig 0.14.0-dev.2647+5322459a0
|
18
shape/README.md
Normal file
18
shape/README.md
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
### Configuring CLion for debugging
|
||||||
|
|
||||||
|
Use https://github.com/asdf-vm/asdf with https://github.com/allemangd/asdf-zig for the versioned zig master in `.tool-versions`.
|
||||||
|
|
||||||
|
Build ZLS with that zig and point ZigBrains to it.
|
||||||
|
|
||||||
|
Custom Build Application configurations:
|
||||||
|
|
||||||
|
- `zig-shape` uses custom target `zig build -fincremental` and executes `zig-out/bin/zig-shape`.
|
||||||
|
- `exe-unit-tests` uses custom target `zig build -fincremental build-tests` and executes `zig-out/dev/exe-unit-tests`
|
||||||
|
- `lib-unit-tests` uses custom target `zig build -fincremental build-tests` and executes `zig-out/dev/lib-unit-tests`
|
||||||
|
|
||||||
|
Then native "build", "run", and "debug" buttons will work.
|
||||||
|
|
||||||
|
Optionally create a "clean" target that executes `rm -r .zig-cache zig-out`
|
||||||
|
|
||||||
|
Switching between debug and release build is more difficult. Probably easier to run release builds
|
||||||
|
only via CLI, like `zig build --release=fast` or `zig build --release=fast test`.
|
83
shape/build.zig
Normal file
83
shape/build.zig
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
pub fn build(b: *std.Build) void {
|
||||||
|
const target = b.standardTargetOptions(.{});
|
||||||
|
const optimize = b.standardOptimizeOption(.{});
|
||||||
|
|
||||||
|
const vulkan = b.dependency("vulkan_zig", .{
|
||||||
|
.registry = b.dependency("vulkan_headers", .{}).path("registry/vk.xml"),
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
}).module("vulkan-zig");
|
||||||
|
|
||||||
|
const glfw = b.dependency("glfw", .{
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
}).artifact("glfw");
|
||||||
|
|
||||||
|
const lib_mod = b.createModule(.{
|
||||||
|
.root_source_file = b.path("src/root.zig"),
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
});
|
||||||
|
lib_mod.addImport("vk", vulkan);
|
||||||
|
|
||||||
|
const exe_mod = b.createModule(.{
|
||||||
|
.root_source_file = b.path("src/main.zig"),
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
});
|
||||||
|
exe_mod.addImport("vk", vulkan);
|
||||||
|
exe_mod.addImport("zig-shape-lib", lib_mod);
|
||||||
|
exe_mod.linkLibrary(glfw);
|
||||||
|
|
||||||
|
const lib = b.addStaticLibrary(.{
|
||||||
|
.name = "zig-shape",
|
||||||
|
.root_module = lib_mod,
|
||||||
|
});
|
||||||
|
|
||||||
|
b.installArtifact(lib);
|
||||||
|
|
||||||
|
const exe = b.addExecutable(.{
|
||||||
|
.name = "zig-shape",
|
||||||
|
.root_module = exe_mod,
|
||||||
|
});
|
||||||
|
|
||||||
|
b.installArtifact(exe);
|
||||||
|
|
||||||
|
const run_cmd = b.addRunArtifact(exe);
|
||||||
|
|
||||||
|
run_cmd.step.dependOn(b.getInstallStep());
|
||||||
|
if (b.args) |args| {
|
||||||
|
run_cmd.addArgs(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
const run_step = b.step("run", "Run the app");
|
||||||
|
run_step.dependOn(&run_cmd.step);
|
||||||
|
|
||||||
|
const lib_unit_tests = b.addTest(.{
|
||||||
|
.root_module = lib_mod,
|
||||||
|
.name = "lib-unit-tests",
|
||||||
|
});
|
||||||
|
|
||||||
|
const run_lib_unit_tests = b.addRunArtifact(lib_unit_tests);
|
||||||
|
|
||||||
|
const exe_unit_tests = b.addTest(.{
|
||||||
|
.root_module = exe_mod,
|
||||||
|
.name = "exe-unit-tests",
|
||||||
|
});
|
||||||
|
|
||||||
|
const build_test_step = b.step("build-test", "Build unit tests");
|
||||||
|
|
||||||
|
const install_lib_test = b.addInstallArtifact(lib_unit_tests, .{ .dest_dir = .{ .override = .{ .custom = "dev" } } });
|
||||||
|
build_test_step.dependOn(&install_lib_test.step);
|
||||||
|
|
||||||
|
const install_exe_test = b.addInstallArtifact(exe_unit_tests, .{ .dest_dir = .{ .override = .{ .custom = "dev" } } });
|
||||||
|
build_test_step.dependOn(&install_exe_test.step);
|
||||||
|
|
||||||
|
const run_exe_unit_tests = b.addRunArtifact(exe_unit_tests);
|
||||||
|
|
||||||
|
const test_step = b.step("test", "Run unit tests");
|
||||||
|
test_step.dependOn(&run_lib_unit_tests.step);
|
||||||
|
test_step.dependOn(&run_exe_unit_tests.step);
|
||||||
|
}
|
27
shape/build.zig.zon
Normal file
27
shape/build.zig.zon
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
.{
|
||||||
|
.name = "zig-shape",
|
||||||
|
.version = "0.0.0",
|
||||||
|
|
||||||
|
.minimum_zig_version = "0.14.0",
|
||||||
|
|
||||||
|
.dependencies = .{
|
||||||
|
.glfw = .{
|
||||||
|
.url = "https://github.com/emidoots/glfw/archive/ec656e10d3643a3a71149bb96ae6b0831b84b677.tar.gz",
|
||||||
|
.hash = "12207be469bad84baed2ede75cf89ede37e1ed5ee8be62a54d2b2112c5f56a44cc89",
|
||||||
|
},
|
||||||
|
.vulkan_zig = .{
|
||||||
|
.url = "https://github.com/Snektron/vulkan-zig/archive/604416bf44baf95568c428e1aa55499aa8e07607.tar.gz",
|
||||||
|
.hash = "1220129ea1652cc0f8578db3dcba254bc9fbc6fdd195b5e1021bf4da8592ea5dc9fb",
|
||||||
|
},
|
||||||
|
.vulkan_headers = .{
|
||||||
|
.url = "https://github.com/KhronosGroup/Vulkan-Headers/archive/v1.3.283.tar.gz",
|
||||||
|
.hash = "1220a7e73d72a0d56bc2a65f9d8999a7c019e42260a0744c408d1cded111bc205e10",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
.paths = .{
|
||||||
|
"build.zig",
|
||||||
|
"build.zig.zon",
|
||||||
|
"src",
|
||||||
|
},
|
||||||
|
}
|
308
shape/src/Core.zig
Normal file
308
shape/src/Core.zig
Normal file
@@ -0,0 +1,308 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const lib = @import("std");
|
||||||
|
const builtin = @import("builtin");
|
||||||
|
|
||||||
|
const vk = @import("vk");
|
||||||
|
const glfw = @cImport({
|
||||||
|
@cDefine("GLFW_INCLUDE_NONE", {});
|
||||||
|
@cInclude("GLFW/glfw3.h");
|
||||||
|
});
|
||||||
|
|
||||||
|
const apis: []const vk.ApiInfo = &(.{
|
||||||
|
vk.features.version_1_0,
|
||||||
|
vk.features.version_1_1,
|
||||||
|
vk.features.version_1_2,
|
||||||
|
vk.features.version_1_3,
|
||||||
|
vk.extensions.khr_surface,
|
||||||
|
vk.extensions.khr_swapchain,
|
||||||
|
vk.extensions.khr_dynamic_rendering,
|
||||||
|
vk.extensions.khr_timeline_semaphore,
|
||||||
|
} ++ switch (builtin.mode) {
|
||||||
|
.Debug, .ReleaseSafe => .{
|
||||||
|
vk.extensions.ext_debug_utils,
|
||||||
|
},
|
||||||
|
else => .{},
|
||||||
|
});
|
||||||
|
|
||||||
|
const Base = vk.BaseWrapper(apis);
|
||||||
|
const Instance = vk.InstanceProxy(apis);
|
||||||
|
const Device = vk.DeviceProxy(apis);
|
||||||
|
const Queue = vk.QueueProxy(apis);
|
||||||
|
|
||||||
|
const Core = @This();
|
||||||
|
|
||||||
|
alloc: std.mem.Allocator,
|
||||||
|
b: *Base,
|
||||||
|
i: Instance,
|
||||||
|
d: Device,
|
||||||
|
q: Queue,
|
||||||
|
window: *glfw.GLFWwindow,
|
||||||
|
pdev: vk.PhysicalDevice,
|
||||||
|
surface: vk.SurfaceKHR,
|
||||||
|
msg: switch (builtin.mode) {
|
||||||
|
.Debug, .ReleaseSafe => vk.DebugUtilsMessengerEXT,
|
||||||
|
else => void,
|
||||||
|
},
|
||||||
|
|
||||||
|
pub fn init(
|
||||||
|
alloc: std.mem.Allocator,
|
||||||
|
options: struct {
|
||||||
|
width: u32 = 1280,
|
||||||
|
height: u32 = 720,
|
||||||
|
title: []const u8 = "Hello World",
|
||||||
|
},
|
||||||
|
) !Core {
|
||||||
|
var self: Core = undefined;
|
||||||
|
self.alloc = alloc;
|
||||||
|
|
||||||
|
var arena = std.heap.ArenaAllocator.init(alloc);
|
||||||
|
defer arena.deinit();
|
||||||
|
const ialloc = arena.allocator();
|
||||||
|
|
||||||
|
const titlez = try ialloc.dupeZ(u8, options.title);
|
||||||
|
|
||||||
|
if (glfw.glfwInit() != glfw.GLFW_TRUE) {
|
||||||
|
return error.GLFWInitFailed;
|
||||||
|
}
|
||||||
|
errdefer glfw.glfwTerminate();
|
||||||
|
|
||||||
|
glfw.glfwWindowHint(glfw.GLFW_CLIENT_API, glfw.GLFW_NO_API);
|
||||||
|
glfw.glfwWindowHintString(glfw.GLFW_X11_CLASS_NAME, "floating_window");
|
||||||
|
glfw.glfwWindowHintString(glfw.GLFW_X11_INSTANCE_NAME, "floating_window");
|
||||||
|
self.window = glfw.glfwCreateWindow(
|
||||||
|
@intCast(options.width),
|
||||||
|
@intCast(options.height),
|
||||||
|
titlez,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
) orelse
|
||||||
|
return error.GLFWWindowFailed;
|
||||||
|
|
||||||
|
const bw = try alloc.create(vk.BaseWrapper(apis));
|
||||||
|
errdefer alloc.destroy(bw);
|
||||||
|
bw.* = try vk.BaseWrapper(apis).load(glfwGetInstanceProcAddress);
|
||||||
|
self.b = bw;
|
||||||
|
|
||||||
|
var iexts = std.ArrayList([*:0]const u8).init(ialloc);
|
||||||
|
var ilyrs = std.ArrayList([*:0]const u8).init(ialloc);
|
||||||
|
|
||||||
|
switch (builtin.mode) {
|
||||||
|
.Debug, .ReleaseSafe => {
|
||||||
|
try iexts.appendSlice(&.{
|
||||||
|
vk.extensions.ext_debug_utils.name,
|
||||||
|
});
|
||||||
|
try ilyrs.appendSlice(&.{
|
||||||
|
"VK_LAYER_KHRONOS_validation",
|
||||||
|
});
|
||||||
|
},
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
var count: u32 = undefined;
|
||||||
|
const ptr = glfwGetRequiredInstanceExtensions(&count);
|
||||||
|
try iexts.appendSlice(ptr[0..count]);
|
||||||
|
}
|
||||||
|
|
||||||
|
var dmci = switch (builtin.mode) {
|
||||||
|
.Debug, .ReleaseSafe => vk.DebugUtilsMessengerCreateInfoEXT{
|
||||||
|
.message_severity = .{
|
||||||
|
.error_bit_ext = true,
|
||||||
|
.info_bit_ext = true,
|
||||||
|
.verbose_bit_ext = true,
|
||||||
|
.warning_bit_ext = true,
|
||||||
|
},
|
||||||
|
.message_type = .{
|
||||||
|
.device_address_binding_bit_ext = true,
|
||||||
|
.general_bit_ext = true,
|
||||||
|
.performance_bit_ext = true,
|
||||||
|
.validation_bit_ext = true,
|
||||||
|
},
|
||||||
|
.pfn_user_callback = &debug_callback,
|
||||||
|
.p_user_data = null,
|
||||||
|
},
|
||||||
|
else => {},
|
||||||
|
};
|
||||||
|
|
||||||
|
var ici: vk.InstanceCreateInfo = .{
|
||||||
|
.p_application_info = &vk.ApplicationInfo{
|
||||||
|
.api_version = vk.API_VERSION_1_3,
|
||||||
|
.engine_version = 0,
|
||||||
|
.application_version = 0,
|
||||||
|
.p_application_name = titlez,
|
||||||
|
.p_engine_name = titlez,
|
||||||
|
},
|
||||||
|
.enabled_extension_count = @intCast(iexts.items.len),
|
||||||
|
.pp_enabled_extension_names = iexts.items.ptr,
|
||||||
|
.enabled_layer_count = @intCast(ilyrs.items.len),
|
||||||
|
.pp_enabled_layer_names = ilyrs.items.ptr,
|
||||||
|
};
|
||||||
|
|
||||||
|
switch (builtin.mode) {
|
||||||
|
.Debug, .ReleaseSafe => {
|
||||||
|
ici.p_next = &dmci;
|
||||||
|
},
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
|
||||||
|
self.i.handle = try self.b.createInstance(&ici, null);
|
||||||
|
const iw = try alloc.create(vk.InstanceWrapper(apis));
|
||||||
|
errdefer alloc.destroy(iw);
|
||||||
|
iw.* = try vk.InstanceWrapper(apis).load(self.i.handle, bw.dispatch.vkGetInstanceProcAddr);
|
||||||
|
self.i.wrapper = iw;
|
||||||
|
errdefer self.i.destroyInstance(null);
|
||||||
|
|
||||||
|
self.msg = switch (builtin.mode) {
|
||||||
|
.Debug, .ReleaseSafe => try self.i.createDebugUtilsMessengerEXT(&dmci, null),
|
||||||
|
else => {},
|
||||||
|
};
|
||||||
|
errdefer switch (builtin.mode) {
|
||||||
|
.Debug, .ReleaseSafe => self.i.destroyDebugUtilsMessengerEXT(self.msg, null),
|
||||||
|
else => {},
|
||||||
|
};
|
||||||
|
|
||||||
|
// Device selection. Just use the first one.
|
||||||
|
const pdevs: []vk.PhysicalDevice = try self.i.enumeratePhysicalDevicesAlloc(ialloc);
|
||||||
|
std.debug.assert(pdevs.len >= 1);
|
||||||
|
self.pdev = pdevs[0];
|
||||||
|
|
||||||
|
switch (glfwCreateWindowSurface(
|
||||||
|
self.i.handle,
|
||||||
|
self.window,
|
||||||
|
null,
|
||||||
|
&self.surface,
|
||||||
|
)) {
|
||||||
|
.success => {},
|
||||||
|
else => return error.GLFWWindowSurfaceFailed,
|
||||||
|
}
|
||||||
|
errdefer self.i.destroySurfaceKHR(self.surface, null);
|
||||||
|
|
||||||
|
// Queue selection. Just use the first one.
|
||||||
|
const qci: []const vk.DeviceQueueCreateInfo = &.{
|
||||||
|
vk.DeviceQueueCreateInfo{
|
||||||
|
.queue_family_index = 0,
|
||||||
|
.queue_count = 1,
|
||||||
|
.p_queue_priorities = &.{1},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
var dexts = std.ArrayList([*:0]const u8).init(ialloc);
|
||||||
|
var dlyrs = std.ArrayList([*:0]const u8).init(ialloc);
|
||||||
|
|
||||||
|
_ = &dlyrs;
|
||||||
|
|
||||||
|
try dexts.appendSlice(&.{
|
||||||
|
vk.extensions.khr_swapchain.name,
|
||||||
|
vk.extensions.khr_dynamic_rendering.name,
|
||||||
|
vk.extensions.khr_timeline_semaphore.name,
|
||||||
|
});
|
||||||
|
|
||||||
|
self.d.handle = try self.i.createDevice(self.pdev, &.{
|
||||||
|
.enabled_extension_count = @intCast(dexts.items.len),
|
||||||
|
.pp_enabled_extension_names = dexts.items.ptr,
|
||||||
|
.enabled_layer_count = @intCast(dlyrs.items.len),
|
||||||
|
.pp_enabled_layer_names = dlyrs.items.ptr,
|
||||||
|
.queue_create_info_count = @intCast(qci.len),
|
||||||
|
.p_queue_create_infos = qci.ptr,
|
||||||
|
.p_next = &vk.PhysicalDeviceDynamicRenderingFeatures{
|
||||||
|
.dynamic_rendering = vk.TRUE,
|
||||||
|
},
|
||||||
|
}, null);
|
||||||
|
const dw = try alloc.create(vk.DeviceWrapper(apis));
|
||||||
|
dw.* = try vk.DeviceWrapper(apis).load(self.d.handle, iw.dispatch.vkGetDeviceProcAddr);
|
||||||
|
self.d.wrapper = dw;
|
||||||
|
errdefer self.d.destroyDevice(null);
|
||||||
|
|
||||||
|
self.q.handle = self.d.getDeviceQueue(0, 0);
|
||||||
|
self.q.wrapper = dw;
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: Core) void {
|
||||||
|
self.d.destroyDevice(null);
|
||||||
|
|
||||||
|
self.i.destroySurfaceKHR(self.surface, null);
|
||||||
|
|
||||||
|
switch (builtin.mode) {
|
||||||
|
.Debug, .ReleaseSafe => self.i.destroyDebugUtilsMessengerEXT(self.msg, null),
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
|
||||||
|
self.i.destroyInstance(null);
|
||||||
|
|
||||||
|
self.alloc.destroy(self.d.wrapper);
|
||||||
|
self.alloc.destroy(self.i.wrapper);
|
||||||
|
self.alloc.destroy(self.b);
|
||||||
|
|
||||||
|
glfw.glfwTerminate();
|
||||||
|
}
|
||||||
|
|
||||||
|
extern fn glfwGetInstanceProcAddress(
|
||||||
|
instance: vk.Instance,
|
||||||
|
procname: [*:0]const u8,
|
||||||
|
) vk.PfnVoidFunction;
|
||||||
|
|
||||||
|
extern fn glfwGetRequiredInstanceExtensions(
|
||||||
|
count: *u32,
|
||||||
|
) [*][*:0]const u8;
|
||||||
|
|
||||||
|
fn debug_callback(
|
||||||
|
msg_severity: vk.DebugUtilsMessageSeverityFlagsEXT,
|
||||||
|
msg_type: vk.DebugUtilsMessageTypeFlagsEXT,
|
||||||
|
p_data: ?*const vk.DebugUtilsMessengerCallbackDataEXT,
|
||||||
|
_: ?*anyopaque,
|
||||||
|
) callconv(vk.vulkan_call_conv) vk.Bool32 {
|
||||||
|
// ripped from std.log.defaultLog
|
||||||
|
|
||||||
|
const data = p_data orelse return vk.FALSE;
|
||||||
|
const message = data.p_message orelse return vk.FALSE;
|
||||||
|
|
||||||
|
const severity_prefix = if (msg_severity.verbose_bit_ext)
|
||||||
|
"verbose:"
|
||||||
|
else if (msg_severity.info_bit_ext)
|
||||||
|
"info:"
|
||||||
|
else if (msg_severity.warning_bit_ext)
|
||||||
|
"warning:"
|
||||||
|
else if (msg_severity.error_bit_ext)
|
||||||
|
"error:"
|
||||||
|
else
|
||||||
|
"?:";
|
||||||
|
|
||||||
|
const type_prefix = if (msg_type.general_bit_ext)
|
||||||
|
""
|
||||||
|
else if (msg_type.validation_bit_ext)
|
||||||
|
"validation:"
|
||||||
|
else if (msg_type.performance_bit_ext)
|
||||||
|
"performance:"
|
||||||
|
else if (msg_type.device_address_binding_bit_ext)
|
||||||
|
"device_address_binding:"
|
||||||
|
else
|
||||||
|
"?:";
|
||||||
|
|
||||||
|
const stderr = std.io.getStdErr().writer();
|
||||||
|
var bw = std.io.bufferedWriter(stderr);
|
||||||
|
const writer = bw.writer();
|
||||||
|
|
||||||
|
std.debug.lockStdErr();
|
||||||
|
defer std.debug.unlockStdErr();
|
||||||
|
nosuspend {
|
||||||
|
writer.print("vk-{s}{s} {s}\n", .{ severity_prefix, type_prefix, message }) catch return vk.FALSE;
|
||||||
|
bw.flush() catch return vk.FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return vk.FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern fn glfwCreateWindowSurface(
|
||||||
|
instance: vk.Instance,
|
||||||
|
window: *glfw.GLFWwindow,
|
||||||
|
allocation_callbacks: ?*const vk.AllocationCallbacks,
|
||||||
|
surface: *vk.SurfaceKHR,
|
||||||
|
) vk.Result;
|
||||||
|
|
||||||
|
extern fn glfwGetPhysicalDevicePresentationSupport(
|
||||||
|
instance: vk.Instance,
|
||||||
|
pdev: vk.PhysicalDevice,
|
||||||
|
queuefamily: u32,
|
||||||
|
) c_int;
|
164
shape/src/main.zig
Normal file
164
shape/src/main.zig
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const lib = @import("zig-shape-lib");
|
||||||
|
const builtin = @import("builtin");
|
||||||
|
|
||||||
|
const Core = @import("Core.zig");
|
||||||
|
|
||||||
|
pub fn main() !void {
|
||||||
|
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||||
|
defer _ = gpa.deinit();
|
||||||
|
const alloc = gpa.allocator();
|
||||||
|
|
||||||
|
const core = try Core.init(alloc, .{});
|
||||||
|
defer core.deinit();
|
||||||
|
|
||||||
|
std.log.debug("Created instance: {any}", .{core.i.handle});
|
||||||
|
std.log.debug("Created device: {any}", .{core.d.handle});
|
||||||
|
std.log.debug("Created queue: {any}", .{core.q.handle});
|
||||||
|
std.log.debug("Created surface: {any}", .{core.surface});
|
||||||
|
|
||||||
|
// var caps = try I.getPhysicalDeviceSurfaceCapabilitiesKHR(pdev, surface);
|
||||||
|
// const format = search: {
|
||||||
|
// const formats = try I.getPhysicalDeviceSurfaceFormatsAllocKHR(pdev, surface, alloc);
|
||||||
|
// defer alloc.free(formats);
|
||||||
|
// for (formats) |f| {
|
||||||
|
// if (f.color_space == .srgb_nonlinear_khr) break :search f;
|
||||||
|
// } else break :search formats[0];
|
||||||
|
// };
|
||||||
|
// const mode: vk.PresentModeKHR = .fifo_khr;
|
||||||
|
|
||||||
|
// var scinfo: vk.SwapchainCreateInfoKHR = .{
|
||||||
|
// .surface = surface,
|
||||||
|
// .min_image_count = std.math.clamp(
|
||||||
|
// @min(3, caps.min_image_count + 1),
|
||||||
|
// caps.min_image_count,
|
||||||
|
// if (caps.max_image_count > 0) caps.max_image_count else 127,
|
||||||
|
// ),
|
||||||
|
// .image_format = format.format,
|
||||||
|
// .image_color_space = format.color_space,
|
||||||
|
// .image_extent = undefined, // set in rebuild
|
||||||
|
// .image_array_layers = 1,
|
||||||
|
// .image_usage = .{ .color_attachment_bit = true },
|
||||||
|
// .image_sharing_mode = .exclusive,
|
||||||
|
// .pre_transform = .{ .identity_bit_khr = true },
|
||||||
|
// .composite_alpha = .{ .opaque_bit_khr = true },
|
||||||
|
// .present_mode = mode,
|
||||||
|
// .clipped = vk.TRUE,
|
||||||
|
// .old_swapchain = .null_handle,
|
||||||
|
// };
|
||||||
|
|
||||||
|
// var sc: vk.SwapchainKHR = .null_handle;
|
||||||
|
// defer D.destroySwapchainKHR(device, sc, null);
|
||||||
|
|
||||||
|
// const FRAMES_IN_FLIGHT = 3;
|
||||||
|
//
|
||||||
|
// var pools = [FRAMES_IN_FLIGHT]vk.CommandPool;
|
||||||
|
// var fence = [FRAMES_IN_FLIGHT]vk.Fence;
|
||||||
|
|
||||||
|
// const pool = D.createCommandPool(device, &.{
|
||||||
|
// .queue_family_index = family,
|
||||||
|
// }, null);
|
||||||
|
// defer D.destroyCommandPool(device, pool, null);
|
||||||
|
|
||||||
|
// var cmd: vk.CommandBuffer = undefined;
|
||||||
|
// try D.allocateCommandBuffers(device, &.{vk.CommandBufferAllocateInfo{
|
||||||
|
// .command_buffer_count = 1,
|
||||||
|
// .command_pool = pool,
|
||||||
|
// .level = .primary,
|
||||||
|
// }}, @ptrCast(&cmd));
|
||||||
|
// defer D.freeCommandBuffers(device, pool, 1, @ptrCast(&cmd));
|
||||||
|
|
||||||
|
// while (glfw.glfwWindowShouldClose(window) == glfw.GLFW_FALSE) {
|
||||||
|
// if (glfw.glfwGetWindowAttrib(window, glfw.GLFW_FOCUSED) == glfw.GLFW_TRUE)
|
||||||
|
// glfw.glfwPollEvents()
|
||||||
|
// else
|
||||||
|
// glfw.glfwWaitEventsTimeout(1.0 / 60.0);
|
||||||
|
//
|
||||||
|
// if (sc == .null_handle) {
|
||||||
|
// caps = try I.getPhysicalDeviceSurfaceCapabilitiesKHR(pdev, surface);
|
||||||
|
// scinfo.image_extent = caps.current_extent;
|
||||||
|
// sc = try D.createSwapchainKHR(device, &scinfo, null);
|
||||||
|
// D.destroySwapchainKHR(device, scinfo.old_swapchain, null);
|
||||||
|
// scinfo.old_swapchain = .null_handle;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// const render_area: vk.Rect2D = .{
|
||||||
|
// .offset = .{ .x = 0, .y = 0 },
|
||||||
|
// .extent = scinfo.image_extent,
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// try D.resetCommandPool(device, pool, .{});
|
||||||
|
// try D.beginCommandBuffer(cmd, .{ .flags = .{ .one_time_submit_bit = true } });
|
||||||
|
// {
|
||||||
|
// D.cmdPipelineBarrier(
|
||||||
|
// cmd,
|
||||||
|
// .{ .top_of_pipe_bit = true },
|
||||||
|
// .{ .color_attachment_output_bit = true },
|
||||||
|
// .{},
|
||||||
|
// 0,
|
||||||
|
// null,
|
||||||
|
// 0,
|
||||||
|
// null,
|
||||||
|
// 1,
|
||||||
|
// &.{
|
||||||
|
// vk.ImageMemoryBarrier{
|
||||||
|
// .src_access_mask = .{},
|
||||||
|
// .dst_access_mask = .{ .color_attachment_write_bit = true },
|
||||||
|
// .old_layout = .undefined,
|
||||||
|
// .new_layout = .color_attachment_optimal,
|
||||||
|
// .src_queue_family_index = 0,
|
||||||
|
// .dst_queue_family_index = 0,
|
||||||
|
// .image = image,
|
||||||
|
// .subresource_range = .{
|
||||||
|
// .aspect_mask = .{ .color_bit = true },
|
||||||
|
// .base_mip_level = 0,
|
||||||
|
// .level_count = 1,
|
||||||
|
// .base_array_layer = 0,
|
||||||
|
// .layer_count = 1,
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// );
|
||||||
|
//
|
||||||
|
// D.cmdPipelineBarrier(
|
||||||
|
// cmd,
|
||||||
|
// .{ .color_attachment_output_bit = true },
|
||||||
|
// .{ .bottom_of_pipe_bit = true },
|
||||||
|
// .{},
|
||||||
|
// 0,
|
||||||
|
// null,
|
||||||
|
// 0,
|
||||||
|
// null,
|
||||||
|
// 1,
|
||||||
|
// &.{
|
||||||
|
// vk.ImageMemoryBarrier{
|
||||||
|
// // todo !
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// try D.endCommandBuffer(cmd);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
test "simple test" {
|
||||||
|
var list = std.ArrayList(i32).init(std.testing.allocator);
|
||||||
|
defer list.deinit(); // Try commenting this out and see if zig detects the memory leak!
|
||||||
|
try list.append(42);
|
||||||
|
try std.testing.expectEqual(@as(i32, 42), list.pop());
|
||||||
|
}
|
||||||
|
|
||||||
|
test "use other module" {
|
||||||
|
try std.testing.expectEqual(@as(i32, 150), lib.add(100, 50));
|
||||||
|
}
|
||||||
|
|
||||||
|
test "fuzz example" {
|
||||||
|
const Context = struct {
|
||||||
|
fn testOne(context: @This(), input: []const u8) anyerror!void {
|
||||||
|
_ = context;
|
||||||
|
// Try passing `--fuzz` to `zig build test` and see if it manages to fail this test case!
|
||||||
|
try std.testing.expect(!std.mem.eql(u8, "canyoufindme", input));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
try std.testing.fuzz(Context{}, Context.testOne, .{});
|
||||||
|
}
|
13
shape/src/root.zig
Normal file
13
shape/src/root.zig
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
//! By convention, root.zig is the root source file when making a library. If
|
||||||
|
//! you are making an executable, the convention is to delete this file and
|
||||||
|
//! start with main.zig instead.
|
||||||
|
const std = @import("std");
|
||||||
|
const testing = std.testing;
|
||||||
|
|
||||||
|
pub export fn add(a: i32, b: i32) i32 {
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
|
||||||
|
test "basic add functionality" {
|
||||||
|
try testing.expect(add(3, 7) == 10);
|
||||||
|
}
|
92
shape/src/swapchain.zig
Normal file
92
shape/src/swapchain.zig
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const builtin = @import("builtin");
|
||||||
|
|
||||||
|
const Core = @import("Core.zig");
|
||||||
|
|
||||||
|
const vk = @import("vk");
|
||||||
|
|
||||||
|
const I = &Core.I;
|
||||||
|
const D = &Core.D;
|
||||||
|
const pdev = &Core.pdev;
|
||||||
|
const surface = &Core.surface;
|
||||||
|
|
||||||
|
pub fn SwapChain(Flight: type, N: u3) type {
|
||||||
|
return struct {
|
||||||
|
handle: vk.SwapchainKHR = .null_handle,
|
||||||
|
cinfo: vk.SwapchainCreateInfoKHR,
|
||||||
|
|
||||||
|
// todo populate and use this.
|
||||||
|
flights: std.MultiArrayList(struct{
|
||||||
|
fence: vk.Fence,
|
||||||
|
acquired: vk.Semaphore,
|
||||||
|
complete: vk.Semaphore,
|
||||||
|
}),
|
||||||
|
|
||||||
|
pub fn init(alloc: std.mem.Allocator) !SwapChain {
|
||||||
|
var arena = std.heap.ArenaAllocator.init(alloc);
|
||||||
|
defer arena.deinit();
|
||||||
|
const ialloc = arena.allocator();
|
||||||
|
|
||||||
|
const caps = try I.getPhysicalDeviceSurfaceCapabilitiesKHR(
|
||||||
|
pdev,
|
||||||
|
surface,
|
||||||
|
);
|
||||||
|
|
||||||
|
const formats = try I.getPhysicalDeviceSurfaceFormatsAllocKHR(
|
||||||
|
pdev,
|
||||||
|
surface,
|
||||||
|
ialloc,
|
||||||
|
);
|
||||||
|
const format: vk.SurfaceFormatKHR = formats[0];
|
||||||
|
const mode: vk.PresentModeKHR = .fifo_khr;
|
||||||
|
|
||||||
|
return .{
|
||||||
|
.cinfo = vk.SwapchainCreateInfoKHR{
|
||||||
|
.surface = surface,
|
||||||
|
.min_image_count = std.math.clamp(
|
||||||
|
@min(3, caps.min_image_count + 1),
|
||||||
|
caps.min_image_count,
|
||||||
|
if (caps.max_image_count > 0) caps.max_image_count else 127,
|
||||||
|
),
|
||||||
|
.image_format = format.format,
|
||||||
|
.image_color_space = format.color_space,
|
||||||
|
.image_extent = undefined, // set in rebuild
|
||||||
|
.image_array_layers = 1,
|
||||||
|
.image_usage = .{ .color_attachment_bit = true },
|
||||||
|
.image_sharing_mode = .exclusive,
|
||||||
|
.pre_transform = .{ .identity_bit_khr = true },
|
||||||
|
.composite_alpha = .{ .opaque_bit_khr = true },
|
||||||
|
.present_mode = mode,
|
||||||
|
.clipped = vk.TRUE,
|
||||||
|
.old_swapchain = .null_handle,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build(self: *SwapChain) !void {
|
||||||
|
if (self.handle != .null_handle) return;
|
||||||
|
|
||||||
|
const caps = try I.getPhysicalDeviceSurfaceCapabilitiesKHR(
|
||||||
|
pdev,
|
||||||
|
surface,
|
||||||
|
);
|
||||||
|
self.cinfo.image_extent = caps.current_extent;
|
||||||
|
|
||||||
|
self.handle = try D.createSwapchainKHR(&self.cinfo, null);
|
||||||
|
D.destroySwapchainKHR(self.cinfo.old_swapchain, null);
|
||||||
|
self.cinfo.old_swapchain = self.handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn acquire(self: *SwapChain) !void {
|
||||||
|
D.acquireNextImageKHR(self.handle, std.math.maxInt(u64), semaphore: Semaphore, fence: Fence)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn invalidate(self: *SwapChain) void {
|
||||||
|
self.handle = .null_handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: SwapChain) void {
|
||||||
|
D.destroySwapchainKHR(self.cinfo.old_swapchain, null);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
Reference in New Issue
Block a user