vulkan-tutorial 03
This commit is contained in:
155
src/Window.zig
155
src/Window.zig
@@ -3,14 +3,19 @@ const Self = @This();
|
||||
const std = @import("std");
|
||||
const c = @import("c.zig");
|
||||
const vk = @import("vk");
|
||||
const builtin = @import("builtin");
|
||||
|
||||
const BaseDispatch = vk.BaseWrapper(.{
|
||||
.createInstance = true,
|
||||
.getInstanceProcAddr = true,
|
||||
.enumerateInstanceExtensionProperties = true,
|
||||
.enumerateInstanceLayerProperties = true,
|
||||
});
|
||||
const InstanceDispatch = vk.InstanceWrapper(.{
|
||||
.destroyInstance = true,
|
||||
.createDebugUtilsMessengerEXT = true,
|
||||
.destroyDebugUtilsMessengerEXT = true,
|
||||
.submitDebugUtilsMessageEXT = true,
|
||||
});
|
||||
const DeviceDispatch = vk.DeviceWrapper(.{});
|
||||
|
||||
@@ -23,6 +28,7 @@ vkd: DeviceDispatch,
|
||||
window: *c.GLFWwindow,
|
||||
|
||||
instance: vk.Instance,
|
||||
messenger: vk.DebugUtilsMessengerEXT,
|
||||
|
||||
pub fn mainLoop(self: Self) void {
|
||||
while (c.glfwWindowShouldClose(self.window) == 0) : (c.glfwPollEvents()) {
|
||||
@@ -46,9 +52,134 @@ fn deinitWindow(self: Self) void {
|
||||
c.glfwDestroyWindow(self.window);
|
||||
}
|
||||
|
||||
export fn debug_callback(
|
||||
message_severity: vk.DebugUtilsMessageSeverityFlagsEXT,
|
||||
message_type: vk.DebugUtilsMessageTypeFlagsEXT,
|
||||
p_callback_data: ?*const vk.DebugUtilsMessengerCallbackDataEXT,
|
||||
_: ?*anyopaque,
|
||||
) callconv(.C) vk.Bool32 {
|
||||
if (p_callback_data == null) return vk.FALSE;
|
||||
if (p_callback_data.?.p_message == null) return vk.FALSE;
|
||||
const msg = p_callback_data.?.p_message.?;
|
||||
|
||||
const scopes = .{
|
||||
"validation",
|
||||
"performance",
|
||||
"device_address_binding",
|
||||
"general",
|
||||
};
|
||||
|
||||
const scope: []const u8 = inline for (scopes) |tag| {
|
||||
if (@field(message_type, tag ++ "_bit_ext")) {
|
||||
break tag;
|
||||
}
|
||||
} else {
|
||||
return vk.FALSE;
|
||||
};
|
||||
|
||||
const levels = .{
|
||||
"error",
|
||||
"info",
|
||||
"warning",
|
||||
"verbose",
|
||||
};
|
||||
|
||||
const level: []const u8 = inline for (levels) |tag| {
|
||||
if (@field(message_severity, tag ++ "_bit_ext")) {
|
||||
break tag;
|
||||
}
|
||||
} else {
|
||||
return vk.FALSE;
|
||||
};
|
||||
|
||||
// ripped from std.log, but with my own levels and scope.
|
||||
const stderr = std.io.getStdErr().writer();
|
||||
var bw = std.io.bufferedWriter(stderr);
|
||||
const writer = bw.writer();
|
||||
|
||||
std.debug.getStderrMutex().lock();
|
||||
defer std.debug.getStderrMutex().unlock();
|
||||
nosuspend {
|
||||
writer.print("vk-{s}({s}): {s}\n", .{ level, scope, msg }) catch return vk.FALSE;
|
||||
bw.flush() catch return vk.FALSE;
|
||||
}
|
||||
|
||||
return vk.FALSE;
|
||||
}
|
||||
|
||||
fn initVulkan(self: *Self) !void {
|
||||
self.vkb = try BaseDispatch.load(&c.glfwGetInstanceProcAddress);
|
||||
|
||||
var exts = std.ArrayList([*:0]const u8).init(self.allocator);
|
||||
defer exts.deinit();
|
||||
|
||||
var layers = std.ArrayList([*:0]const u8).init(self.allocator);
|
||||
defer layers.deinit();
|
||||
|
||||
switch (builtin.mode) {
|
||||
.ReleaseSafe, .Debug => {
|
||||
try layers.append("VK_LAYER_KHRONOS_validation");
|
||||
try exts.append("VK_EXT_debug_utils");
|
||||
},
|
||||
.ReleaseSmall, .ReleaseFast => {},
|
||||
}
|
||||
|
||||
var glfw_ext_count: u32 = 0;
|
||||
const glfw_exts: [*][*:0]const u8 = @ptrCast(c.glfwGetRequiredInstanceExtensions(&glfw_ext_count));
|
||||
try exts.appendSlice(glfw_exts[0..glfw_ext_count]);
|
||||
|
||||
std.log.debug("requesting extensions: {s}", .{exts.items});
|
||||
std.log.debug("requesting layers: {s}", .{layers.items});
|
||||
|
||||
var available_ext_count: u32 = 0;
|
||||
_ = try self.vkb.enumerateInstanceExtensionProperties(null, &available_ext_count, null);
|
||||
const available_exts = try self.allocator.alloc(vk.ExtensionProperties, available_ext_count);
|
||||
defer self.allocator.free(available_exts);
|
||||
_ = try self.vkb.enumerateInstanceExtensionProperties(null, &available_ext_count, available_exts.ptr);
|
||||
|
||||
var available_layer_count: u32 = 0;
|
||||
_ = try self.vkb.enumerateInstanceLayerProperties(&available_layer_count, null);
|
||||
const available_layers = try self.allocator.alloc(vk.LayerProperties, available_layer_count);
|
||||
defer self.allocator.free(available_layers);
|
||||
_ = try self.vkb.enumerateInstanceLayerProperties(&available_layer_count, available_layers.ptr);
|
||||
|
||||
for (exts.items) |name| {
|
||||
const required_name = std.mem.sliceTo(name, 0);
|
||||
for (available_exts) |prop| {
|
||||
const available_name = std.mem.sliceTo(&prop.extension_name, 0);
|
||||
if (std.mem.eql(u8, required_name, available_name)) break;
|
||||
} else {
|
||||
return error.ExtensionNotPresent;
|
||||
}
|
||||
}
|
||||
|
||||
for (layers.items) |name| {
|
||||
const required_name = std.mem.sliceTo(name, 0);
|
||||
for (available_layers) |prop| {
|
||||
const available_name = std.mem.sliceTo(&prop.layer_name, 0);
|
||||
if (std.mem.eql(u8, required_name, available_name)) break;
|
||||
} else {
|
||||
return error.LayerNotPresent;
|
||||
}
|
||||
}
|
||||
|
||||
const debug_create_info = vk.DebugUtilsMessengerCreateInfoEXT{
|
||||
.message_severity = vk.DebugUtilsMessageSeverityFlagsEXT{
|
||||
.verbose_bit_ext = false,
|
||||
.warning_bit_ext = true,
|
||||
.error_bit_ext = true,
|
||||
.info_bit_ext = false,
|
||||
},
|
||||
.message_type = vk.DebugUtilsMessageTypeFlagsEXT{
|
||||
.general_bit_ext = true,
|
||||
.validation_bit_ext = true,
|
||||
.performance_bit_ext = true,
|
||||
.device_address_binding_bit_ext = false,
|
||||
},
|
||||
.pfn_user_callback = &debug_callback,
|
||||
.p_user_data = null,
|
||||
};
|
||||
|
||||
const app_info = vk.ApplicationInfo{
|
||||
.p_application_name = "Hello World",
|
||||
.application_version = vk.makeApiVersion(0, 0, 0, 0),
|
||||
@@ -57,33 +188,25 @@ fn initVulkan(self: *Self) !void {
|
||||
.api_version = vk.API_VERSION_1_3,
|
||||
};
|
||||
|
||||
var glfw_ext_count: u32 = 0;
|
||||
const glfw_exts = c.glfwGetRequiredInstanceExtensions(&glfw_ext_count);
|
||||
|
||||
const create_info = vk.InstanceCreateInfo{
|
||||
.p_application_info = &app_info,
|
||||
.enabled_extension_count = glfw_ext_count,
|
||||
.pp_enabled_extension_names = @as([*]const [*:0]const u8, @ptrCast(glfw_exts)),
|
||||
.enabled_layer_count = 0,
|
||||
.enabled_extension_count = @intCast(exts.items.len),
|
||||
.pp_enabled_extension_names = exts.items.ptr,
|
||||
.enabled_layer_count = @intCast(layers.items.len),
|
||||
.pp_enabled_layer_names = layers.items.ptr,
|
||||
.p_next = &debug_create_info,
|
||||
};
|
||||
|
||||
self.instance = try self.vkb.createInstance(&create_info, null);
|
||||
self.vki = try InstanceDispatch.load(self.instance, self.vkb.dispatch.vkGetInstanceProcAddr);
|
||||
errdefer self.vki.destroyInstance(self.instance, null);
|
||||
|
||||
var ext_count: u32 = 0;
|
||||
_ = try self.vkb.enumerateInstanceExtensionProperties(null, &ext_count, null);
|
||||
const extensions = try self.allocator.alloc(vk.ExtensionProperties, ext_count);
|
||||
defer self.allocator.free(extensions);
|
||||
_ = try self.vkb.enumerateInstanceExtensionProperties(null, &ext_count, extensions.ptr);
|
||||
|
||||
std.debug.print("available extensions:\n", .{});
|
||||
for (extensions) |ext| {
|
||||
std.debug.print("- {s}\n", .{ext.extension_name});
|
||||
}
|
||||
self.messenger = try self.vki.createDebugUtilsMessengerEXT(self.instance, &debug_create_info, null);
|
||||
errdefer self.vki.destroyDebugUtilsMessengerEXT(self.instance, self.messenger, null);
|
||||
}
|
||||
|
||||
fn deinitVulkan(self: Self) void {
|
||||
self.vki.destroyDebugUtilsMessengerEXT(self.instance, self.messenger, null);
|
||||
self.vki.destroyInstance(self.instance, null);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user