Start implementing the swapchain
This commit is contained in:
parent
5c50f5eb7c
commit
73a30b9d03
2 changed files with 98 additions and 37 deletions
|
@ -1,10 +1,13 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const vk = @import("vulkan");
|
const vk = @import("vulkan");
|
||||||
|
|
||||||
|
pub const device_extensions = [_][*:0]const u8{vk.extensions.khr_swapchain.name};
|
||||||
|
|
||||||
pub const QueueFamilyIndices = struct {
|
pub const QueueFamilyIndices = struct {
|
||||||
graphics_family: ?u32,
|
graphics_family: ?u32 = null,
|
||||||
|
presentation_family: ?u32 = null,
|
||||||
|
|
||||||
pub fn isValid(self: QueueFamilyIndices) bool {
|
pub fn isValid(self: QueueFamilyIndices) bool {
|
||||||
return self.graphics_family != null;
|
return self.graphics_family != null and self.presentation_family != null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,26 +1,27 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const sdl = @import("sdl2");
|
const sdl = @import("sdl2");
|
||||||
const vk = @import("vulkan");
|
const vk = @import("vulkan");
|
||||||
const QueueFamilyIndices = @import("utilities.zig").QueueFamilyIndices;
|
const Utilities = @import("utilities.zig");
|
||||||
|
const QueueFamilyIndices = Utilities.QueueFamilyIndices;
|
||||||
|
|
||||||
const enable_validation_layers = true;
|
const enable_validation_layers = true;
|
||||||
const validation_layers = [_][*:0]const u8{"VK_LAYER_KHRONOS_validation"};
|
const validation_layers = [_][*:0]const u8{"VK_LAYER_KHRONOS_validation"};
|
||||||
|
|
||||||
const apis: []const vk.ApiInfo = &.{
|
const apis: []const vk.ApiInfo = &.{
|
||||||
.{
|
// .{
|
||||||
.base_commands = .{
|
// .base_commands = .{
|
||||||
.createInstance = true,
|
// .createInstance = true,
|
||||||
},
|
// },
|
||||||
.instance_commands = .{
|
// .instance_commands = .{
|
||||||
.createDevice = true,
|
// .createDevice = true,
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
vk.features.version_1_0,
|
vk.features.version_1_0,
|
||||||
vk.features.version_1_1,
|
vk.features.version_1_1,
|
||||||
vk.features.version_1_2,
|
vk.features.version_1_2,
|
||||||
vk.features.version_1_3,
|
vk.features.version_1_3,
|
||||||
vk.extensions.khr_surface,
|
vk.extensions.khr_surface,
|
||||||
// vk.extensions.khr_swapchain,
|
vk.extensions.khr_swapchain,
|
||||||
vk.extensions.ext_debug_utils,
|
vk.extensions.ext_debug_utils,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -44,7 +45,10 @@ pub const VulkanRenderer = struct {
|
||||||
instance: Instance,
|
instance: Instance,
|
||||||
physical_device: vk.PhysicalDevice,
|
physical_device: vk.PhysicalDevice,
|
||||||
device: Device,
|
device: Device,
|
||||||
|
|
||||||
graphics_queue: Queue,
|
graphics_queue: Queue,
|
||||||
|
presentation_queue: Queue,
|
||||||
|
|
||||||
surface: vk.SurfaceKHR,
|
surface: vk.SurfaceKHR,
|
||||||
|
|
||||||
debug_utils: ?vk.DebugUtilsMessengerEXT,
|
debug_utils: ?vk.DebugUtilsMessengerEXT,
|
||||||
|
@ -64,12 +68,12 @@ pub const VulkanRenderer = struct {
|
||||||
|
|
||||||
self.instance = Instance.init(instance, vki);
|
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) {
|
if (enable_validation_layers) {
|
||||||
self.debug_utils = try self.createDebugMessenger();
|
self.debug_utils = try self.createDebugMessenger();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.physical_device = try self.getPhysicalDevice();
|
||||||
const device = try self.createLogicalDevice();
|
const device = try self.createLogicalDevice();
|
||||||
|
|
||||||
const vkd = try allocator.create(DeviceDispatch);
|
const vkd = try allocator.create(DeviceDispatch);
|
||||||
|
@ -77,9 +81,10 @@ pub const VulkanRenderer = struct {
|
||||||
vkd.* = try DeviceDispatch.load(device, self.instance.wrapper.dispatch.vkGetDeviceProcAddr);
|
vkd.* = try DeviceDispatch.load(device, self.instance.wrapper.dispatch.vkGetDeviceProcAddr);
|
||||||
|
|
||||||
self.device = Device.init(device, vkd);
|
self.device = Device.init(device, vkd);
|
||||||
const queue = try self.getDeviceQueues();
|
const queues = try self.getDeviceQueues();
|
||||||
|
|
||||||
self.graphics_queue = Queue.init(queue, vkd);
|
self.graphics_queue = Queue.init(queues[0], vkd);
|
||||||
|
self.presentation_queue = Queue.init(queues[1], vkd);
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
@ -97,7 +102,7 @@ pub const VulkanRenderer = struct {
|
||||||
std.debug.print("\t- {s}\n", .{ext});
|
std.debug.print("\t- {s}\n", .{ext});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!try self.checkExtensions(&extensions)) {
|
if (!try self.checkInstanceExtensions(&extensions)) {
|
||||||
return error.ExtensionNotPresent;
|
return error.ExtensionNotPresent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,8 +121,11 @@ pub const VulkanRenderer = struct {
|
||||||
};
|
};
|
||||||
|
|
||||||
if (enable_validation_layers) {
|
if (enable_validation_layers) {
|
||||||
|
const debug_create_info = getDebugUtilsCreateInfo();
|
||||||
|
|
||||||
instance_create_info.enabled_layer_count = @intCast(validation_layers.len);
|
instance_create_info.enabled_layer_count = @intCast(validation_layers.len);
|
||||||
instance_create_info.pp_enabled_layer_names = &validation_layers;
|
instance_create_info.pp_enabled_layer_names = &validation_layers;
|
||||||
|
instance_create_info.p_next = &debug_create_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
return try self.vkb.createInstance(&instance_create_info, null);
|
return try self.vkb.createInstance(&instance_create_info, null);
|
||||||
|
@ -140,7 +148,7 @@ pub const VulkanRenderer = struct {
|
||||||
return extensions;
|
return extensions;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn checkExtensions(self: Self, required_extensions: *const [][*:0]const u8) !bool {
|
fn checkInstanceExtensions(self: Self, required_extensions: *const [][*:0]const u8) !bool {
|
||||||
var prop_count: u32 = 0;
|
var prop_count: u32 = 0;
|
||||||
_ = try self.vkb.enumerateInstanceExtensionProperties(null, &prop_count, null);
|
_ = try self.vkb.enumerateInstanceExtensionProperties(null, &prop_count, null);
|
||||||
|
|
||||||
|
@ -150,15 +158,39 @@ pub const VulkanRenderer = struct {
|
||||||
_ = try self.vkb.enumerateInstanceExtensionProperties(null, &prop_count, props.ptr);
|
_ = try self.vkb.enumerateInstanceExtensionProperties(null, &prop_count, props.ptr);
|
||||||
|
|
||||||
for (required_extensions.*) |required_extension| {
|
for (required_extensions.*) |required_extension| {
|
||||||
var found = false;
|
|
||||||
|
|
||||||
for (props) |prop| {
|
for (props) |prop| {
|
||||||
if (std.mem.eql(u8, std.mem.sliceTo(&prop.extension_name, 0), std.mem.span(required_extension))) {
|
if (std.mem.eql(u8, std.mem.sliceTo(&prop.extension_name, 0), std.mem.span(required_extension))) {
|
||||||
found = true;
|
break;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!found) {
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn checkDeviceExtensions(self: Self, pdev: vk.PhysicalDevice) !bool {
|
||||||
|
var prop_count: u32 = 0;
|
||||||
|
_ = try self.instance.enumerateDeviceExtensionProperties(pdev, null, &prop_count, null);
|
||||||
|
|
||||||
|
if (prop_count == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std.debug.print("Ext count: {d}\n", .{prop_count});
|
||||||
|
const props = try self.allocator.alloc(vk.ExtensionProperties, prop_count);
|
||||||
|
defer self.allocator.free(props);
|
||||||
|
|
||||||
|
_ = try self.vkb.enumerateDeviceExtensionProperties(null, &prop_count, props.ptr);
|
||||||
|
|
||||||
|
for (Utilities.device_extensions) |device_extension| {
|
||||||
|
for (props) |prop| {
|
||||||
|
// std.debug.print("Ext: {s}\n", .{&prop.extension_name});
|
||||||
|
if (std.mem.eql(u8, std.mem.sliceTo(&prop.extension_name, 0), std.mem.span(device_extension))) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -196,7 +228,9 @@ pub const VulkanRenderer = struct {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
return queue_family_indices.isValid();
|
const extension_support = self.checkDeviceExtensions(pdev) catch false;
|
||||||
|
|
||||||
|
return queue_family_indices.isValid() and extension_support;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getQueueFamilies(self: Self, pdev: vk.PhysicalDevice) !QueueFamilyIndices {
|
fn getQueueFamilies(self: Self, pdev: vk.PhysicalDevice) !QueueFamilyIndices {
|
||||||
|
@ -215,6 +249,11 @@ pub const VulkanRenderer = struct {
|
||||||
indices.graphics_family = @intCast(i);
|
indices.graphics_family = @intCast(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const presentation_support = try self.instance.getPhysicalDeviceSurfaceSupportKHR(pdev, @intCast(i), self.surface);
|
||||||
|
if (queue_family.queue_count > 0 and presentation_support == vk.TRUE) {
|
||||||
|
indices.presentation_family = @intCast(i);
|
||||||
|
}
|
||||||
|
|
||||||
if (indices.isValid()) {
|
if (indices.isValid()) {
|
||||||
return indices;
|
return indices;
|
||||||
}
|
}
|
||||||
|
@ -228,25 +267,40 @@ pub const VulkanRenderer = struct {
|
||||||
// 1 is the highest priority
|
// 1 is the highest priority
|
||||||
const priority = [_]f32{1};
|
const priority = [_]f32{1};
|
||||||
|
|
||||||
const queue_create_info = [_]vk.DeviceQueueCreateInfo{.{
|
const qci = [_]vk.DeviceQueueCreateInfo{
|
||||||
.queue_family_index = indices.graphics_family.?,
|
.{
|
||||||
.queue_count = 1,
|
.queue_family_index = indices.graphics_family.?,
|
||||||
.p_queue_priorities = &priority,
|
.queue_count = 1,
|
||||||
}};
|
.p_queue_priorities = &priority,
|
||||||
|
},
|
||||||
|
.{
|
||||||
|
.queue_family_index = indices.presentation_family.?,
|
||||||
|
.queue_count = 1,
|
||||||
|
.p_queue_priorities = &priority,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const queue_count: u32 = if (indices.graphics_family.? == indices.presentation_family.?)
|
||||||
|
1
|
||||||
|
else
|
||||||
|
2;
|
||||||
|
|
||||||
const device_create_info: vk.DeviceCreateInfo = .{
|
const device_create_info: vk.DeviceCreateInfo = .{
|
||||||
.queue_create_info_count = 1,
|
.queue_create_info_count = queue_count,
|
||||||
.p_queue_create_infos = &queue_create_info,
|
.p_queue_create_infos = &qci,
|
||||||
.enabled_extension_count = 0,
|
.pp_enabled_extension_names = &Utilities.device_extensions,
|
||||||
|
.enabled_extension_count = @intCast(Utilities.device_extensions.len),
|
||||||
};
|
};
|
||||||
|
|
||||||
return try self.instance.createDevice(self.physical_device, &device_create_info, null);
|
return try self.instance.createDevice(self.physical_device, &device_create_info, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getDeviceQueues(self: Self) !vk.Queue {
|
fn getDeviceQueues(self: Self) ![2]vk.Queue {
|
||||||
const indices = try self.getQueueFamilies(self.physical_device);
|
const indices = try self.getQueueFamilies(self.physical_device);
|
||||||
|
|
||||||
return self.device.getDeviceQueue(indices.graphics_family.?, 0);
|
const graphics_queue = self.device.getDeviceQueue(indices.graphics_family.?, 0);
|
||||||
|
const presentation_queue = self.device.getDeviceQueue(indices.presentation_family.?, 0);
|
||||||
|
return .{ graphics_queue, presentation_queue };
|
||||||
}
|
}
|
||||||
|
|
||||||
fn checkValidationLayersSupport(self: Self) bool {
|
fn checkValidationLayersSupport(self: Self) bool {
|
||||||
|
@ -274,11 +328,7 @@ pub const VulkanRenderer = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn createDebugMessenger(self: Self) !vk.DebugUtilsMessengerEXT {
|
fn createDebugMessenger(self: Self) !vk.DebugUtilsMessengerEXT {
|
||||||
const debug_create_info: vk.DebugUtilsMessengerCreateInfoEXT = .{
|
const debug_create_info = getDebugUtilsCreateInfo();
|
||||||
.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);
|
return try self.instance.createDebugUtilsMessengerEXT(&debug_create_info, null);
|
||||||
}
|
}
|
||||||
|
@ -296,6 +346,14 @@ pub const VulkanRenderer = struct {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
fn getDebugUtilsCreateInfo() vk.DebugUtilsMessengerCreateInfoEXT {
|
||||||
|
return 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,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// message_severity: vk.DebugUtilsMessageSeverityFlagsEXT,
|
// message_severity: vk.DebugUtilsMessageSeverityFlagsEXT,
|
||||||
// message_types: vk.DebugUtilsMessageTypeFlagsEXT,
|
// message_types: vk.DebugUtilsMessageTypeFlagsEXT,
|
||||||
// p_callback_data: ?*const vk.DebugUtilsMessengerCallbackDataEXT,
|
// p_callback_data: ?*const vk.DebugUtilsMessengerCallbackDataEXT,
|
||||||
|
|
Loading…
Reference in a new issue