Begin implementing validation layers
This commit is contained in:
parent
a08065fbdf
commit
5c50f5eb7c
1 changed files with 96 additions and 9 deletions
|
@ -3,6 +3,9 @@ const sdl = @import("sdl2");
|
|||
const vk = @import("vulkan");
|
||||
const QueueFamilyIndices = @import("utilities.zig").QueueFamilyIndices;
|
||||
|
||||
const enable_validation_layers = true;
|
||||
const validation_layers = [_][*:0]const u8{"VK_LAYER_KHRONOS_validation"};
|
||||
|
||||
const apis: []const vk.ApiInfo = &.{
|
||||
.{
|
||||
.base_commands = .{
|
||||
|
@ -10,7 +13,6 @@ const apis: []const vk.ApiInfo = &.{
|
|||
},
|
||||
.instance_commands = .{
|
||||
.createDevice = true,
|
||||
// .getDeviceProcAddr = true,
|
||||
},
|
||||
},
|
||||
vk.features.version_1_0,
|
||||
|
@ -18,7 +20,8 @@ const apis: []const vk.ApiInfo = &.{
|
|||
vk.features.version_1_2,
|
||||
vk.features.version_1_3,
|
||||
vk.extensions.khr_surface,
|
||||
vk.extensions.khr_swapchain,
|
||||
// vk.extensions.khr_swapchain,
|
||||
vk.extensions.ext_debug_utils,
|
||||
};
|
||||
|
||||
const BaseDispatch = vk.BaseWrapper(apis);
|
||||
|
@ -44,6 +47,8 @@ pub const VulkanRenderer = struct {
|
|||
graphics_queue: Queue,
|
||||
surface: vk.SurfaceKHR,
|
||||
|
||||
debug_utils: ?vk.DebugUtilsMessengerEXT,
|
||||
|
||||
pub fn init(window: sdl.Window, allocator: std.mem.Allocator) !Self {
|
||||
var self: Self = undefined;
|
||||
self.window = window;
|
||||
|
@ -58,15 +63,18 @@ pub const VulkanRenderer = struct {
|
|||
vki.* = try InstanceDispatch.load(instance, self.vkb.dispatch.vkGetInstanceProcAddr);
|
||||
|
||||
self.instance = Instance.init(instance, vki);
|
||||
// self.surface = try sdl.vulkan.createSurface(self.window, self.instance.handle);
|
||||
self.surface = try sdl.vulkan.createSurface(self.window, self.instance.handle);
|
||||
self.physical_device = try self.getPhysicalDevice();
|
||||
|
||||
if (enable_validation_layers) {
|
||||
self.debug_utils = try self.createDebugMessenger();
|
||||
}
|
||||
|
||||
const device = try self.createLogicalDevice();
|
||||
|
||||
const vkd = try allocator.create(DeviceDispatch);
|
||||
errdefer allocator.destroy(vkd);
|
||||
// FIXME Why does it only work with no fail?
|
||||
vkd.* = DeviceDispatch.loadNoFail(device, self.instance.wrapper.dispatch.vkGetDeviceProcAddr);
|
||||
vkd.* = try DeviceDispatch.load(device, self.instance.wrapper.dispatch.vkGetDeviceProcAddr);
|
||||
|
||||
self.device = Device.init(device, vkd);
|
||||
const queue = try self.getDeviceQueues();
|
||||
|
@ -77,7 +85,11 @@ pub const VulkanRenderer = struct {
|
|||
}
|
||||
|
||||
fn createInstance(self: Self) !vk.Instance {
|
||||
const extensions = try sdl.vulkan.getInstanceExtensionsAlloc(self.window, self.allocator);
|
||||
if (enable_validation_layers and !self.checkValidationLayersSupport()) {
|
||||
return error.LayerNotPresent;
|
||||
}
|
||||
|
||||
const extensions = try self.getRequiredExtensions();
|
||||
defer self.allocator.free(extensions);
|
||||
|
||||
std.debug.print("[Required instance extensions]\n", .{});
|
||||
|
@ -97,11 +109,35 @@ pub const VulkanRenderer = struct {
|
|||
.api_version = vk.API_VERSION_1_3,
|
||||
};
|
||||
|
||||
return try self.vkb.createInstance(&.{
|
||||
var instance_create_info: vk.InstanceCreateInfo = .{
|
||||
.p_application_info = &app_info,
|
||||
.enabled_extension_count = @intCast(extensions.len),
|
||||
.pp_enabled_extension_names = @ptrCast(extensions),
|
||||
}, null);
|
||||
};
|
||||
|
||||
if (enable_validation_layers) {
|
||||
instance_create_info.enabled_layer_count = @intCast(validation_layers.len);
|
||||
instance_create_info.pp_enabled_layer_names = &validation_layers;
|
||||
}
|
||||
|
||||
return try self.vkb.createInstance(&instance_create_info, null);
|
||||
}
|
||||
|
||||
fn getRequiredExtensions(self: Self) ![][*:0]const u8 {
|
||||
var ext_count = sdl.vulkan.getInstanceExtensionsCount(self.window);
|
||||
|
||||
if (enable_validation_layers) {
|
||||
ext_count += 1;
|
||||
}
|
||||
|
||||
var extensions = try self.allocator.alloc([*:0]const u8, ext_count);
|
||||
_ = try sdl.vulkan.getInstanceExtensions(self.window, extensions);
|
||||
|
||||
if (enable_validation_layers) {
|
||||
extensions[extensions.len - 1] = vk.extensions.ext_debug_utils.name;
|
||||
}
|
||||
|
||||
return extensions;
|
||||
}
|
||||
|
||||
fn checkExtensions(self: Self, required_extensions: *const [][*:0]const u8) !bool {
|
||||
|
@ -213,12 +249,63 @@ pub const VulkanRenderer = struct {
|
|||
return self.device.getDeviceQueue(indices.graphics_family.?, 0);
|
||||
}
|
||||
|
||||
fn checkValidationLayersSupport(self: Self) bool {
|
||||
var layer_count: u32 = undefined;
|
||||
_ = self.vkb.enumerateInstanceLayerProperties(&layer_count, null) catch {
|
||||
return false;
|
||||
};
|
||||
|
||||
const available_layers = self.allocator.alloc(vk.LayerProperties, layer_count) catch unreachable;
|
||||
defer self.allocator.free(available_layers);
|
||||
|
||||
_ = self.vkb.enumerateInstanceLayerProperties(&layer_count, available_layers.ptr) catch {
|
||||
return false;
|
||||
};
|
||||
|
||||
for (validation_layers) |validation_layer| {
|
||||
for (available_layers) |available_layer| {
|
||||
if (std.mem.eql(u8, std.mem.span(validation_layer), std.mem.sliceTo(&available_layer.layer_name, 0))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
fn createDebugMessenger(self: Self) !vk.DebugUtilsMessengerEXT {
|
||||
const debug_create_info: vk.DebugUtilsMessengerCreateInfoEXT = .{
|
||||
.message_severity = .{ .verbose_bit_ext = true, .warning_bit_ext = true, .error_bit_ext = true },
|
||||
.message_type = .{ .general_bit_ext = true, .validation_bit_ext = true, .performance_bit_ext = true },
|
||||
.pfn_user_callback = debugCallback,
|
||||
};
|
||||
|
||||
return try self.instance.createDebugUtilsMessengerEXT(&debug_create_info, null);
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Self) void {
|
||||
if (enable_validation_layers) {
|
||||
self.instance.destroyDebugUtilsMessengerEXT(self.debug_utils.?, null);
|
||||
}
|
||||
self.device.destroyDevice(null);
|
||||
// self.instance.destroySurfaceKHR(self.surface, null);
|
||||
self.instance.destroySurfaceKHR(self.surface, null);
|
||||
self.instance.destroyInstance(null);
|
||||
|
||||
self.allocator.destroy(self.device.wrapper);
|
||||
self.allocator.destroy(self.instance.wrapper);
|
||||
}
|
||||
};
|
||||
|
||||
// message_severity: vk.DebugUtilsMessageSeverityFlagsEXT,
|
||||
// message_types: vk.DebugUtilsMessageTypeFlagsEXT,
|
||||
// p_callback_data: ?*const vk.DebugUtilsMessengerCallbackDataEXT,
|
||||
// p_user_data: ?*anyopaque,
|
||||
fn debugCallback(
|
||||
_: vk.DebugUtilsMessageSeverityFlagsEXT,
|
||||
_: vk.DebugUtilsMessageTypeFlagsEXT,
|
||||
p_callback_data: ?*const vk.DebugUtilsMessengerCallbackDataEXT,
|
||||
_: ?*anyopaque,
|
||||
) callconv(vk.vulkan_call_conv) vk.Bool32 {
|
||||
std.debug.print("Validation layers: {s}\n", .{p_callback_data.?.p_message.?});
|
||||
return vk.TRUE;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue