hand-written interface wrapper
This commit is contained in:
44
build.zig
44
build.zig
@@ -7,38 +7,39 @@ pub fn build(b: *std.Build) void {
|
|||||||
const vk_dep = b.dependency("vk", .{});
|
const vk_dep = b.dependency("vk", .{});
|
||||||
const volk_dep = b.dependency("volk", .{});
|
const volk_dep = b.dependency("volk", .{});
|
||||||
|
|
||||||
// const volk_c = b.addTranslateC(.{
|
const volk_h = b.addTranslateC(.{
|
||||||
// .target = target,
|
|
||||||
// .optimize = optimize,
|
|
||||||
// .root_source_file = volk_dep.path("volk.c"),
|
|
||||||
// .link_libc = true,
|
|
||||||
// });
|
|
||||||
// volk_c.addIncludePath(vk_dep.path("include"));
|
|
||||||
|
|
||||||
const vk = b.addModule("vulkan", .{
|
|
||||||
.target = target,
|
.target = target,
|
||||||
.optimize = optimize,
|
.optimize = optimize,
|
||||||
.root_source_file = b.path("src/volk.zig"),
|
.root_source_file = volk_dep.path("volk.h"),
|
||||||
.link_libc = true,
|
.link_libc = true,
|
||||||
});
|
});
|
||||||
vk.addIncludePath(vk_dep.path("include"));
|
|
||||||
vk.addIncludePath(volk_dep.path("."));
|
|
||||||
vk.addCSourceFile(.{ .file = volk_dep.path("volk.c"), .language = .c });
|
|
||||||
|
|
||||||
const mod = b.addModule("zig_vk_api_test", .{
|
const volk = b.addModule("volk", .{
|
||||||
.root_source_file = b.path("src/root.zig"),
|
|
||||||
.target = target,
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
.root_source_file = volk_h.getOutput(),
|
||||||
|
.link_libc = true,
|
||||||
|
});
|
||||||
|
volk.addIncludePath(vk_dep.path("include"));
|
||||||
|
volk.addCSourceFile(.{ .file = volk_dep.path("volk.c"), .language = .c });
|
||||||
|
|
||||||
|
const vulkan = b.addModule("vulkan", .{
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
.root_source_file = b.path("vk/root.zig"),
|
||||||
|
.imports = &.{
|
||||||
|
.{ .name = "volk", .module = volk },
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const exe = b.addExecutable(.{
|
const exe = b.addExecutable(.{
|
||||||
.name = "zig_vk_api_test",
|
.name = "main",
|
||||||
.root_module = b.createModule(.{
|
.root_module = b.createModule(.{
|
||||||
.root_source_file = b.path("src/main.zig"),
|
.root_source_file = b.path("src/main.zig"),
|
||||||
.target = target,
|
.target = target,
|
||||||
.optimize = optimize,
|
.optimize = optimize,
|
||||||
.imports = &.{
|
.imports = &.{
|
||||||
.{ .name = "zig_vk_api_test", .module = mod },
|
.{ .name = "vk", .module = vulkan },
|
||||||
.{ .name = "vk", .module = vk },
|
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
@@ -56,12 +57,6 @@ pub fn build(b: *std.Build) void {
|
|||||||
run_cmd.addArgs(args);
|
run_cmd.addArgs(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
const mod_tests = b.addTest(.{
|
|
||||||
.root_module = mod,
|
|
||||||
});
|
|
||||||
|
|
||||||
const run_mod_tests = b.addRunArtifact(mod_tests);
|
|
||||||
|
|
||||||
const exe_tests = b.addTest(.{
|
const exe_tests = b.addTest(.{
|
||||||
.root_module = exe.root_module,
|
.root_module = exe.root_module,
|
||||||
});
|
});
|
||||||
@@ -69,6 +64,5 @@ pub fn build(b: *std.Build) void {
|
|||||||
const run_exe_tests = b.addRunArtifact(exe_tests);
|
const run_exe_tests = b.addRunArtifact(exe_tests);
|
||||||
|
|
||||||
const test_step = b.step("test", "Run tests");
|
const test_step = b.step("test", "Run tests");
|
||||||
test_step.dependOn(&run_mod_tests.step);
|
|
||||||
test_step.dependOn(&run_exe_tests.step);
|
test_step.dependOn(&run_exe_tests.step);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
[tools]
|
[tools]
|
||||||
zig = "latest"
|
zig = "0.16.0"
|
||||||
zls = "latest"
|
zls = "0.16.0"
|
||||||
|
|||||||
168
src/main.zig
168
src/main.zig
@@ -1,67 +1,135 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const Io = std.Io;
|
const builtin = @import("builtin");
|
||||||
|
|
||||||
const vk = @import("vk");
|
const vk = @import("vk");
|
||||||
|
|
||||||
pub fn main() !void {
|
pub fn main() !void {
|
||||||
if (vk.c.volkInitialize() != vk.c.VK_SUCCESS) @panic("Failed to initialize vk");
|
// const log = std.log.scoped(.main);
|
||||||
defer vk.c.volkFinalize();
|
|
||||||
|
|
||||||
const app_info = vk.c.VkApplicationInfo{
|
try vk.init();
|
||||||
.sType = vk.c.VK_STRUCTURE_TYPE_APPLICATION_INFO,
|
defer vk.deinit();
|
||||||
.pNext = null,
|
|
||||||
.apiVersion = vk.c.VK_API_VERSION_1_4,
|
|
||||||
.pApplicationName = "WIP",
|
|
||||||
.applicationVersion = vk.c.VK_MAKE_VERSION(0, 0, 1),
|
|
||||||
.pEngineName = "WIP",
|
|
||||||
.engineVersion = vk.c.VK_MAKE_VERSION(0, 0, 1),
|
|
||||||
};
|
|
||||||
|
|
||||||
const ext_names: []const [*c]const u8 = &.{"VK_EXT_debug_utils"};
|
const ctx_ins: vk.InstanceContext = try .init(.{
|
||||||
const lyr_names: []const [*c]const u8 = &.{"VK_LAYER_KHRONOS_validation"};
|
.api_version = .API_1_3,
|
||||||
|
.log_message_types = .{
|
||||||
|
.general = false,
|
||||||
|
.performance = true,
|
||||||
|
.validation = true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
defer ctx_ins.deinit();
|
||||||
|
const ins = ctx_ins.interface();
|
||||||
|
|
||||||
const ins_info = vk.c.VkInstanceCreateInfo{
|
var pdevs_buf: [8]vk.PhysicalDevice = undefined;
|
||||||
.sType = vk.c.VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
|
for (try ins.enumerate_physical_devices(&pdevs_buf)) |pdev| {
|
||||||
.pNext = null,
|
std.log.debug("{s}", .{ins.get_physical_device_properties(pdev).deviceName});
|
||||||
.flags = 0,
|
}
|
||||||
.enabledExtensionCount = @intCast(ext_names.len),
|
|
||||||
.ppEnabledExtensionNames = ext_names.ptr,
|
|
||||||
.enabledLayerCount = @intCast(lyr_names.len),
|
|
||||||
.ppEnabledLayerNames = lyr_names.ptr,
|
|
||||||
.pApplicationInfo = &app_info,
|
|
||||||
};
|
|
||||||
const deb_info = vk.c.VkDebugUtilsMessengerCreateInfoEXT{
|
|
||||||
.sType = vk.c.VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
|
|
||||||
.pNext = null,
|
|
||||||
.flags = 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
var ins: vk.c.VkInstance = undefined;
|
// defer ctx_ins.deinit();
|
||||||
if (vk.c.vkCreateInstance.?(&ins_info, null, &ins) != vk.c.VK_SUCCESS) @panic("Failed to create VkInstance");
|
// ctx_ins.deinit();
|
||||||
vk.c.volkLoadInstanceOnly(ins);
|
|
||||||
defer vk.c.vkDestroyInstance.?(ins, null);
|
|
||||||
|
|
||||||
var pdevs: [3]vk.c.VkPhysicalDevice = undefined;
|
// const ins = ctx_ins.interface();
|
||||||
var pdev_count: u32 = 3;
|
|
||||||
if (vk.c.vkEnumeratePhysicalDevices.?(
|
|
||||||
ins,
|
|
||||||
&pdev_count,
|
|
||||||
&pdevs,
|
|
||||||
) != vk.c.VK_SUCCESS) @panic("Failed to enumerate physical devices.");
|
|
||||||
|
|
||||||
// pub const PFN_vkEnumeratePhysicalDevices = ?*const fn (instance: VkInstance, pPhysicalDeviceCount: [*c]u32, pPhysicalDevices: [*c]VkPhysicalDevice) callconv(.c) VkResult;
|
// const ext_names: []const [*c]const u8 = &.{"VK_EXT_debug_utils"};
|
||||||
|
// const lyr_names: []const [*c]const u8 = &.{"VK_LAYER_KHRONOS_validation"};
|
||||||
// vk.c.vkEnumerateDeviceExtensionProperties();
|
//
|
||||||
|
// const deb_info = vk.VkDebugUtilsMessengerCreateInfoEXT{
|
||||||
// const info = vk.c.VkInstanceCreateInfo {
|
// .sType = vk.VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
|
||||||
// .sType = vk.c.VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
|
|
||||||
// .pNext = null,
|
// .pNext = null,
|
||||||
// .
|
// .flags = 0,
|
||||||
|
// .messageSeverity =
|
||||||
|
// vk.VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT |
|
||||||
|
// vk.VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT |
|
||||||
|
// vk.VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
|
||||||
|
// vk.VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT,
|
||||||
|
// .messageType =
|
||||||
|
// vk.VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT |
|
||||||
|
// // vk.VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
|
||||||
|
// vk.VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT,
|
||||||
|
// .pfnUserCallback = &debug_messenger_callback,
|
||||||
|
// .pUserData = null,
|
||||||
// };
|
// };
|
||||||
|
// const ins_info = vk.VkInstanceCreateInfo{
|
||||||
// vk.c.vkCreateInstance(pCreateInfo: [*c]const VkInstanceCreateInfo, pAllocator: [*c]const VkAllocationCallbacks, pInstance: [*c]VkInstance);
|
// .sType = vk.VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
|
||||||
|
// .pNext = &deb_info,
|
||||||
|
// .flags = 0,
|
||||||
|
// .enabledExtensionCount = @intCast(ext_names.len),
|
||||||
|
// .ppEnabledExtensionNames = ext_names.ptr,
|
||||||
|
// .enabledLayerCount = @intCast(lyr_names.len),
|
||||||
|
// .ppEnabledLayerNames = lyr_names.ptr,
|
||||||
|
// .pApplicationInfo = &app_info,
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// var ins: vk.VkInstance = undefined;
|
||||||
|
// if (vk.vkCreateInstance.?(&ins_info, null, &ins) != vk.VK_SUCCESS) @panic("Failed to create VkInstance");
|
||||||
|
// vk.volkLoadInstanceOnly(ins);
|
||||||
|
// defer vk.vkDestroyInstance.?(ins, null);
|
||||||
|
//
|
||||||
|
// var deb: vk.VkDebugUtilsMessengerEXT = undefined;
|
||||||
|
// if (vk.vkCreateDebugUtilsMessengerEXT.?(ins, &deb_info, null, &deb) != vk.VK_SUCCESS) @panic("Failed to create VkDebugUtilsMessengerEXT");
|
||||||
|
// defer vk.vkDestroyDebugUtilsMessengerEXT.?(ins, deb, null);
|
||||||
|
//
|
||||||
|
// var pdevs: [8]vk.VkPhysicalDevice = undefined;
|
||||||
|
// var pdev_count: u32 = 8;
|
||||||
|
// if (vk.vkEnumeratePhysicalDevices.?(
|
||||||
|
// ins,
|
||||||
|
// &pdev_count,
|
||||||
|
// &pdevs,
|
||||||
|
// ) != vk.VK_SUCCESS) @panic("Failed to enumerate physical devices.");
|
||||||
|
// const pdev = pdevs[0]; // assume the drivers will put the best device first
|
||||||
|
// var props : vk.VkPhysicalDeviceProperties2 = .{ .sType = vk.VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2 };
|
||||||
|
// vk.vkGetPhysicalDeviceProperties2.?(pdev, &props);
|
||||||
|
// log.info("Selected device {s} (API {d}.{d}.{d}, Driver {d})", .{
|
||||||
|
// props.properties.deviceName,
|
||||||
|
// vk.VK_API_VERSION_MAJOR(props.properties.apiVersion),
|
||||||
|
// vk.VK_API_VERSION_MINOR(props.properties.apiVersion),
|
||||||
|
// vk.VK_API_VERSION_PATCH(props.properties.apiVersion),
|
||||||
|
// vk.VK_VERSION_MAJOR(props.properties.driverVersion),
|
||||||
|
// });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fn debug_messenger_callback(
|
||||||
|
// message_severity: vk.VkDebugUtilsMessageSeverityFlagBitsEXT,
|
||||||
|
// message_types: vk.VkDebugUtilsMessageTypeFlagsEXT,
|
||||||
|
// p_callback_data: [*c]const vk.VkDebugUtilsMessengerCallbackDataEXT,
|
||||||
|
// _: ?*anyopaque,
|
||||||
|
// ) callconv(.c) vk.VkBool32 {
|
||||||
|
// var types_buf: [64]u8 = undefined;
|
||||||
|
// var types_str : std.ArrayListUnmanaged(u8) = .initBuffer(&types_buf);
|
||||||
|
//
|
||||||
|
// if (message_types & vk.VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT != 0) {
|
||||||
|
// if (types_str.items.len > 0) types_str.appendSliceAssumeCapacity(" ");
|
||||||
|
// types_str.appendSliceAssumeCapacity("validation");
|
||||||
|
// }
|
||||||
|
// if (message_types & vk.VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT != 0) {
|
||||||
|
// if (types_str.items.len > 0) types_str.appendSliceAssumeCapacity(" ");
|
||||||
|
// types_str.appendSliceAssumeCapacity("performance");
|
||||||
|
// }
|
||||||
|
// if (types_str.items.len > 0) types_str.appendSliceAssumeCapacity(": ");
|
||||||
|
//
|
||||||
|
// const log = std.log.scoped(.vulkan);
|
||||||
|
//
|
||||||
|
// const fmt = "{s}{s}";
|
||||||
|
// const arg = .{
|
||||||
|
// types_str.items,
|
||||||
|
// p_callback_data.*.pMessage,
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// if (message_severity & vk.VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT != 0) {
|
||||||
|
// log.err(fmt, arg);
|
||||||
|
// if (builtin.mode == .Debug) @breakpoint();
|
||||||
|
// } else if (message_severity & vk.VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT != 0) {
|
||||||
|
// log.warn(fmt, arg);
|
||||||
|
// } else if (message_severity & vk.VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT != 0) {
|
||||||
|
// log.info(fmt, arg);
|
||||||
|
// } else if (message_severity & vk.VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT != 0) {
|
||||||
|
// log.debug(fmt, arg);
|
||||||
|
// } else {
|
||||||
|
// log.debug(fmt, arg);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return vk.VK_FALSE;
|
||||||
|
// }
|
||||||
|
|
||||||
// pub fn main(init: std.process.Init) !void {
|
// pub fn main(init: std.process.Init) !void {
|
||||||
// std.debug.print("{any}\n", .{vk});
|
// std.debug.print("{any}\n", .{vk});
|
||||||
//
|
//
|
||||||
|
|||||||
18
src/root.zig
18
src/root.zig
@@ -1,18 +0,0 @@
|
|||||||
//! By convention, root.zig is the root source file when making a package.
|
|
||||||
const std = @import("std");
|
|
||||||
const Io = std.Io;
|
|
||||||
|
|
||||||
/// This is a documentation comment to explain the `printAnotherMessage` function below.
|
|
||||||
///
|
|
||||||
/// Accepting an `Io.Writer` instance is a handy way to write reusable code.
|
|
||||||
pub fn printAnotherMessage(writer: *Io.Writer) Io.Writer.Error!void {
|
|
||||||
try writer.print("Run `zig build test` to run the tests.\n", .{});
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add(a: i32, b: i32) i32 {
|
|
||||||
return a + b;
|
|
||||||
}
|
|
||||||
|
|
||||||
test "basic add functionality" {
|
|
||||||
try std.testing.expect(add(3, 7) == 10);
|
|
||||||
}
|
|
||||||
25
src/volk.zig
25
src/volk.zig
@@ -1,25 +0,0 @@
|
|||||||
const std = @import("std");
|
|
||||||
|
|
||||||
pub const c = @cImport({
|
|
||||||
@cInclude("volk.h");
|
|
||||||
});
|
|
||||||
|
|
||||||
pub const InstanceTable = blk: {
|
|
||||||
const info = @typeInfo(c.VolkInstanceTable).@"struct";
|
|
||||||
|
|
||||||
var field_names: [info.fields.len][]const u8 = undefined;
|
|
||||||
var field_types: [info.fields.len]type = undefined;
|
|
||||||
var field_attrs: [info.fields.len]std.builtin.Type.StructField.Attributes = undefined;
|
|
||||||
|
|
||||||
for (info.fields, &field_names, &field_types, &field_attrs) |field, *field_name, *field_type, *field_attr| {
|
|
||||||
field_name.* = field.name;
|
|
||||||
field_type.* = std.meta.Child(field.type);
|
|
||||||
field_attr.* = .{};
|
|
||||||
}
|
|
||||||
|
|
||||||
break :blk @Struct(.auto, null, field_names, field_types, field_attrs);
|
|
||||||
};
|
|
||||||
|
|
||||||
// pub const InstanceTable: type = {
|
|
||||||
//
|
|
||||||
// };
|
|
||||||
267
vk/root.zig
Normal file
267
vk/root.zig
Normal file
@@ -0,0 +1,267 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const builtin = @import("builtin");
|
||||||
|
|
||||||
|
const vk = @import("volk");
|
||||||
|
|
||||||
|
pub const InitError = error{
|
||||||
|
InitializationFailed,
|
||||||
|
Unknown,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn init() InitError!void {
|
||||||
|
switch (vk.volkInitialize()) {
|
||||||
|
vk.VK_ERROR_INITIALIZATION_FAILED => return error.InitializationFailed,
|
||||||
|
vk.VK_SUCCESS => {},
|
||||||
|
else => return error.Unknown,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit() void {
|
||||||
|
vk.volkFinalize();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const Version = packed struct(u32) {
|
||||||
|
patch: u12,
|
||||||
|
minor: u10,
|
||||||
|
major: u7,
|
||||||
|
variant: u3 = 0,
|
||||||
|
|
||||||
|
pub const API_1_0: Version = .{ .variant = 0, .major = 1, .minor = 0, .patch = 0 };
|
||||||
|
pub const API_1_1: Version = .{ .variant = 0, .major = 1, .minor = 1, .patch = 0 };
|
||||||
|
pub const API_1_2: Version = .{ .variant = 0, .major = 1, .minor = 2, .patch = 0 };
|
||||||
|
pub const API_1_3: Version = .{ .variant = 0, .major = 1, .minor = 3, .patch = 0 };
|
||||||
|
pub const API_1_4: Version = .{ .variant = 0, .major = 1, .minor = 4, .patch = 0 };
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const MessageTypes = struct {
|
||||||
|
general: bool,
|
||||||
|
performance: bool,
|
||||||
|
validation: bool,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const InstanceConfig = struct {
|
||||||
|
api_version: Version,
|
||||||
|
app_name: [*:0]const u8 = "",
|
||||||
|
app_version: Version = .{ .major = 0, .minor = 0, .patch = 0 },
|
||||||
|
engine_name: [*:0]const u8 = "",
|
||||||
|
engine_version: Version = .{ .major = 0, .minor = 0, .patch = 0 },
|
||||||
|
layer_names: []const [*:0]const u8 = &.{},
|
||||||
|
extension_names: []const [*:0]const u8 = &.{},
|
||||||
|
log_scope: ?@EnumLiteral() = .vulkan,
|
||||||
|
log_message_types: MessageTypes = .{
|
||||||
|
.general = false,
|
||||||
|
.performance = true,
|
||||||
|
.validation = true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const PhysicalDevice = *const opaque {};
|
||||||
|
|
||||||
|
pub const Instance = struct {
|
||||||
|
handle: vk.VkInstance,
|
||||||
|
vtable: *const vk.VolkInstanceTable,
|
||||||
|
|
||||||
|
pub fn enumerate_physical_devices(self: Instance, buf: []PhysicalDevice) ![]PhysicalDevice {
|
||||||
|
var count: u32 = @intCast(buf.len);
|
||||||
|
if (self.vtable.vkEnumeratePhysicalDevices.?(self.handle, &count, @ptrCast(buf.ptr)) != vk.VK_SUCCESS) return error.Unknown;
|
||||||
|
return buf[0..count];
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_physical_device_properties(self: Instance, pdev: PhysicalDevice) vk.VkPhysicalDeviceProperties {
|
||||||
|
var props: vk.VkPhysicalDeviceProperties = undefined;
|
||||||
|
self.vtable.vkGetPhysicalDeviceProperties.?(@ptrCast(@constCast(pdev)), &props);
|
||||||
|
return props;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const InstanceContext = struct {
|
||||||
|
handle: vk.VkInstance,
|
||||||
|
vtable: vk.VolkInstanceTable,
|
||||||
|
debug: ?vk.VkDebugUtilsMessengerEXT,
|
||||||
|
|
||||||
|
pub const InstanceCreateError = error{
|
||||||
|
Unknown,
|
||||||
|
};
|
||||||
|
pub fn init(config: InstanceConfig) InstanceCreateError!InstanceContext {
|
||||||
|
const callback: vk.PFN_vkDebugUtilsMessengerCallbackEXT = if (config.log_scope) |scope| default_debug_callback(scope) else null;
|
||||||
|
|
||||||
|
var message_severity: vk.VkDebugUtilsMessageSeverityFlagsEXT = 0;
|
||||||
|
if (config.log_scope) |scope| {
|
||||||
|
if (std.log.logEnabled(.debug, scope)) message_severity |= vk.VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT;
|
||||||
|
if (std.log.logEnabled(.info, scope)) message_severity |= vk.VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;
|
||||||
|
if (std.log.logEnabled(.warn, scope)) message_severity |= vk.VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
|
||||||
|
if (std.log.logEnabled(.err, scope)) message_severity |= vk.VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
|
||||||
|
}
|
||||||
|
|
||||||
|
var message_type: vk.VkDebugUtilsMessageTypeFlagsEXT = 0;
|
||||||
|
if (config.log_message_types.general) message_type |= vk.VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT;
|
||||||
|
if (config.log_message_types.performance) message_type |= vk.VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
|
||||||
|
if (config.log_message_types.validation) message_type |= vk.VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT;
|
||||||
|
|
||||||
|
var extension_names_buf: [256][*:0]const u8 = undefined;
|
||||||
|
var extension_names: std.ArrayListUnmanaged([*:0]const u8) = .initBuffer(&extension_names_buf);
|
||||||
|
extension_names.appendSliceAssumeCapacity(config.extension_names);
|
||||||
|
|
||||||
|
var layer_names_buf: [256][*:0]const u8 = undefined;
|
||||||
|
var layer_names: std.ArrayListUnmanaged([*:0]const u8) = .initBuffer(&layer_names_buf);
|
||||||
|
layer_names.appendSliceAssumeCapacity(config.layer_names);
|
||||||
|
|
||||||
|
var do_logging = message_severity != 0 and message_type != 0;
|
||||||
|
|
||||||
|
if (do_logging) {
|
||||||
|
for (extension_names.items) |name| {
|
||||||
|
if (std.mem.eql(u8, std.mem.span(name), "VK_EXT_debug_utils")) break;
|
||||||
|
} else {
|
||||||
|
var extension_props_buf: [256]vk.VkExtensionProperties = undefined;
|
||||||
|
var count: u32 = @intCast(extension_props_buf.len);
|
||||||
|
if (vk.vkEnumerateInstanceExtensionProperties.?(null, &count, &extension_props_buf) != vk.VK_SUCCESS) {
|
||||||
|
do_logging = false;
|
||||||
|
} else {
|
||||||
|
for (extension_props_buf[0..count]) |prop| {
|
||||||
|
if (std.mem.eql(u8, std.mem.sliceTo(&prop.extensionName, 0), "VK_EXT_debug_utils")) {
|
||||||
|
extension_names.appendAssumeCapacity("VK_EXT_debug_utils");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
do_logging = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (do_logging and config.log_message_types.validation) {
|
||||||
|
for (layer_names.items) |name| {
|
||||||
|
if (std.mem.eql(u8, std.mem.span(name), "VK_LAYER_KHRONOS_validation")) break;
|
||||||
|
} else {
|
||||||
|
var layer_props_buf: [256]vk.VkLayerProperties = undefined;
|
||||||
|
var count: u32 = @intCast(layer_props_buf.len);
|
||||||
|
if (vk.vkEnumerateInstanceLayerProperties.?(&count, &layer_props_buf) != vk.VK_SUCCESS) {
|
||||||
|
do_logging = false;
|
||||||
|
} else {
|
||||||
|
for (layer_props_buf[0..count]) |prop| {
|
||||||
|
if (std.mem.eql(u8, std.mem.sliceTo(&prop.layerName, 0), "VK_LAYER_KHRONOS_validation")) {
|
||||||
|
layer_names.appendAssumeCapacity("VK_LAYER_KHRONOS_validation");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const debug_info: vk.VkDebugUtilsMessengerCreateInfoEXT = .{
|
||||||
|
.sType = vk.VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
|
||||||
|
.pNext = null,
|
||||||
|
.flags = 0,
|
||||||
|
.messageSeverity = message_severity,
|
||||||
|
.messageType = message_type,
|
||||||
|
.pfnUserCallback = callback,
|
||||||
|
.pUserData = null,
|
||||||
|
};
|
||||||
|
const app_info = vk.VkApplicationInfo{
|
||||||
|
.sType = vk.VK_STRUCTURE_TYPE_APPLICATION_INFO,
|
||||||
|
.pNext = null,
|
||||||
|
.apiVersion = @bitCast(config.api_version),
|
||||||
|
.applicationVersion = @bitCast(config.app_version),
|
||||||
|
.engineVersion = @bitCast(config.engine_version),
|
||||||
|
.pApplicationName = config.app_name,
|
||||||
|
.pEngineName = config.engine_name,
|
||||||
|
};
|
||||||
|
const info = vk.VkInstanceCreateInfo{
|
||||||
|
.sType = vk.VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
|
||||||
|
.pNext = if (do_logging) &debug_info else null,
|
||||||
|
.flags = 0,
|
||||||
|
.pApplicationInfo = &app_info,
|
||||||
|
.enabledLayerCount = @intCast(layer_names.items.len),
|
||||||
|
.ppEnabledLayerNames = layer_names.items.ptr,
|
||||||
|
.enabledExtensionCount = @intCast(extension_names.items.len),
|
||||||
|
.ppEnabledExtensionNames = extension_names.items.ptr,
|
||||||
|
};
|
||||||
|
|
||||||
|
// std.log.debug("{s} ", .{})
|
||||||
|
|
||||||
|
var result: InstanceContext = undefined;
|
||||||
|
switch (vk.vkCreateInstance.?(&info, null, &result.handle)) {
|
||||||
|
vk.VK_SUCCESS => {},
|
||||||
|
else => return error.Unknown,
|
||||||
|
}
|
||||||
|
vk.volkLoadInstanceTable(&result.vtable, result.handle);
|
||||||
|
|
||||||
|
result.debug = null;
|
||||||
|
if (do_logging) {
|
||||||
|
var debug_handle: vk.VkDebugUtilsMessengerEXT = undefined;
|
||||||
|
if (result.vtable.vkCreateDebugUtilsMessengerEXT.?(result.handle, &debug_info, null, &debug_handle) != vk.VK_SUCCESS) {
|
||||||
|
do_logging = false;
|
||||||
|
} else {
|
||||||
|
result.debug = debug_handle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn interface(self: *const InstanceContext) Instance {
|
||||||
|
return .{ .handle = self.handle, .vtable = &self.vtable };
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: *const InstanceContext) void {
|
||||||
|
if (self.debug) |debug_handle| {
|
||||||
|
self.vtable.vkDestroyDebugUtilsMessengerEXT.?(self.handle, debug_handle, null);
|
||||||
|
}
|
||||||
|
self.vtable.vkDestroyInstance.?(self.handle, null);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
fn default_debug_callback(scope: @EnumLiteral()) vk.PFN_vkDebugUtilsMessengerCallbackEXT {
|
||||||
|
const impl = struct {
|
||||||
|
fn impl(
|
||||||
|
message_severity: vk.VkDebugUtilsMessageSeverityFlagBitsEXT,
|
||||||
|
message_types: vk.VkDebugUtilsMessageTypeFlagsEXT,
|
||||||
|
p_callback_data: [*c]const vk.VkDebugUtilsMessengerCallbackDataEXT,
|
||||||
|
_: ?*anyopaque,
|
||||||
|
) callconv(.c) vk.VkBool32 {
|
||||||
|
var types_buf: [64]u8 = undefined;
|
||||||
|
var types_str: std.ArrayListUnmanaged(u8) = .initBuffer(&types_buf);
|
||||||
|
|
||||||
|
if (message_types & vk.VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT != 0) {
|
||||||
|
if (types_str.items.len > 0) types_str.appendSliceAssumeCapacity(" ");
|
||||||
|
types_str.appendSliceAssumeCapacity("general");
|
||||||
|
}
|
||||||
|
if (message_types & vk.VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT != 0) {
|
||||||
|
if (types_str.items.len > 0) types_str.appendSliceAssumeCapacity(" ");
|
||||||
|
types_str.appendSliceAssumeCapacity("validation");
|
||||||
|
}
|
||||||
|
if (message_types & vk.VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT != 0) {
|
||||||
|
if (types_str.items.len > 0) types_str.appendSliceAssumeCapacity(" ");
|
||||||
|
types_str.appendSliceAssumeCapacity("performance");
|
||||||
|
}
|
||||||
|
if (types_str.items.len > 0) types_str.appendSliceAssumeCapacity(": ");
|
||||||
|
|
||||||
|
const fmt = "{s}{s}";
|
||||||
|
const arg = .{
|
||||||
|
types_str.items,
|
||||||
|
p_callback_data.*.pMessage,
|
||||||
|
};
|
||||||
|
|
||||||
|
const log = std.log.scoped(scope);
|
||||||
|
|
||||||
|
if (message_severity & vk.VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT != 0) {
|
||||||
|
log.err(fmt, arg);
|
||||||
|
switch (builtin.mode) {
|
||||||
|
.Debug, .ReleaseSafe => @breakpoint(),
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
} else if (message_severity & vk.VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT != 0) {
|
||||||
|
log.warn(fmt, arg);
|
||||||
|
} else if (message_severity & vk.VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT != 0) {
|
||||||
|
log.info(fmt, arg);
|
||||||
|
} else if (message_severity & vk.VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT != 0) {
|
||||||
|
log.debug(fmt, arg);
|
||||||
|
} else {
|
||||||
|
log.debug(fmt, arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return vk.VK_FALSE;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return &impl.impl;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user