168 lines
5.4 KiB
Zig
168 lines
5.4 KiB
Zig
|
|
//! ----------------------------------------------------
|
||
|
|
//! `🗲` Vulkan Device `🗲`
|
||
|
|
//! ----------------------------------------------------
|
||
|
|
|
||
|
|
const std = @import("std");
|
||
|
|
const vk = @import("vulkan");
|
||
|
|
const Adapter = @import("adapter.zig");
|
||
|
|
const Surface = @import("surface.zig");
|
||
|
|
const Self = @This();
|
||
|
|
|
||
|
|
/// ----------------------------------------------------
|
||
|
|
/// ----------------------------------------------------
|
||
|
|
pub const QueueFamilies = struct {
|
||
|
|
graphics: ?u32 = null,
|
||
|
|
present: ?u32 = null,
|
||
|
|
};
|
||
|
|
|
||
|
|
//
|
||
|
|
// FIELDS
|
||
|
|
//
|
||
|
|
|
||
|
|
raw: *vk.VkDevice_T,
|
||
|
|
graphics_queue: *vk.VkQueue_T,
|
||
|
|
present_queue: *vk.VkQueue_T,
|
||
|
|
graphics_command_pool: *vk.VkCommandPool_T,
|
||
|
|
|
||
|
|
/// ----------------------------------------------------
|
||
|
|
/// ----------------------------------------------------
|
||
|
|
pub fn init(
|
||
|
|
adapter: *Adapter,
|
||
|
|
surface: *Surface,
|
||
|
|
alloc: std.mem.Allocator,
|
||
|
|
) !Self {
|
||
|
|
// --- # ---
|
||
|
|
const extensions: []const [*:0]const u8 = &.{
|
||
|
|
"VK_KHR_swapchain",
|
||
|
|
};
|
||
|
|
|
||
|
|
// --- # ---
|
||
|
|
var features13: vk.VkPhysicalDeviceVulkan13Features = .{
|
||
|
|
.sType = vk.VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES,
|
||
|
|
.dynamicRendering = vk.VK_TRUE,
|
||
|
|
};
|
||
|
|
|
||
|
|
// --- FIND QUEUE FAMILIES ---
|
||
|
|
const queue_families = try findQueueFamilies(adapter.raw, surface.raw, alloc);
|
||
|
|
if (queue_families.graphics == null or queue_families.present == null) {
|
||
|
|
return error.FailedToFindSuitableQueueFamily;
|
||
|
|
}
|
||
|
|
|
||
|
|
// --- CREATE QUEUE INFOS ---
|
||
|
|
const queue_priority: f32 = 1.0;
|
||
|
|
var queue_create_infos: [2]vk.VkDeviceQueueCreateInfo = undefined;
|
||
|
|
var queue_create_info_count: u32 = 0;
|
||
|
|
|
||
|
|
queue_create_infos[0] = .{
|
||
|
|
.sType = vk.VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
|
||
|
|
.queueFamilyIndex = queue_families.graphics.?,
|
||
|
|
.queueCount = 1,
|
||
|
|
.pQueuePriorities = &queue_priority,
|
||
|
|
};
|
||
|
|
queue_create_info_count += 1;
|
||
|
|
|
||
|
|
if (queue_families.present.? != queue_families.graphics.?) {
|
||
|
|
queue_create_infos[1] = .{
|
||
|
|
.sType = vk.VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
|
||
|
|
.queueFamilyIndex = queue_families.present.?,
|
||
|
|
.queueCount = 1,
|
||
|
|
.pQueuePriorities = &queue_priority,
|
||
|
|
};
|
||
|
|
queue_create_info_count += 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
// --- DEVICE CREATE INFO ---
|
||
|
|
var features: vk.VkPhysicalDeviceFeatures = .{};
|
||
|
|
var create_info: vk.VkDeviceCreateInfo = .{
|
||
|
|
.sType = vk.VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
|
||
|
|
.pQueueCreateInfos = &queue_create_infos,
|
||
|
|
.queueCreateInfoCount = queue_create_info_count,
|
||
|
|
.pEnabledFeatures = &features,
|
||
|
|
.enabledExtensionCount = extensions.len,
|
||
|
|
.ppEnabledExtensionNames = extensions.ptr,
|
||
|
|
.pNext = &features13,
|
||
|
|
};
|
||
|
|
|
||
|
|
// --- # ---
|
||
|
|
var device: vk.VkDevice = null;
|
||
|
|
if (vk.vkCreateDevice(adapter.raw, &create_info, null, &device) != vk.VK_SUCCESS) {
|
||
|
|
return error.FailedToCreateVulkanDevice;
|
||
|
|
}
|
||
|
|
|
||
|
|
// --- # ---
|
||
|
|
var pool_info: vk.VkCommandPoolCreateInfo = .{
|
||
|
|
.sType = vk.VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
|
||
|
|
.flags = vk.VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
|
||
|
|
.queueFamilyIndex = queue_families.graphics.?,
|
||
|
|
};
|
||
|
|
var graphics_command_pool: vk.VkCommandPool = null;
|
||
|
|
if (vk.vkCreateCommandPool(device, &pool_info, null, &graphics_command_pool) != vk.VK_SUCCESS) {
|
||
|
|
return error.FailedToCreateCommandPool;
|
||
|
|
}
|
||
|
|
|
||
|
|
// --- GET QUEUES ---
|
||
|
|
var graphics_queue: vk.VkQueue = null;
|
||
|
|
vk.vkGetDeviceQueue(device, queue_families.graphics.?, 0, &graphics_queue);
|
||
|
|
|
||
|
|
var present_queue: vk.VkQueue = null;
|
||
|
|
vk.vkGetDeviceQueue(device, queue_families.present.?, 0, &present_queue);
|
||
|
|
|
||
|
|
return .{
|
||
|
|
.raw = device.?,
|
||
|
|
.graphics_queue = graphics_queue.?,
|
||
|
|
.present_queue = present_queue.?,
|
||
|
|
.graphics_command_pool = graphics_command_pool.?,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
/// ----------------------------------------------------
|
||
|
|
/// ----------------------------------------------------
|
||
|
|
pub fn deinit(self: *Self) void {
|
||
|
|
vk.vkDestroyCommandPool(self.raw, self.graphics_command_pool, null);
|
||
|
|
vk.vkDestroyDevice(self.raw, null);
|
||
|
|
}
|
||
|
|
|
||
|
|
/// ----------------------------------------------------
|
||
|
|
/// ----------------------------------------------------
|
||
|
|
fn findQueueFamilies(
|
||
|
|
adapter: vk.VkPhysicalDevice,
|
||
|
|
surface: *vk.VkSurfaceKHR_T,
|
||
|
|
alloc: std.mem.Allocator,
|
||
|
|
) !QueueFamilies {
|
||
|
|
var indices: QueueFamilies = .{};
|
||
|
|
|
||
|
|
// --- GET FAMILY COUNT ---
|
||
|
|
var queue_family_count: u32 = 0;
|
||
|
|
vk.vkGetPhysicalDeviceQueueFamilyProperties(adapter, &queue_family_count, null);
|
||
|
|
|
||
|
|
// --- CREATE BUFFER ---
|
||
|
|
const queue_families = try alloc.alloc(vk.VkQueueFamilyProperties, queue_family_count);
|
||
|
|
defer alloc.free(queue_families);
|
||
|
|
vk.vkGetPhysicalDeviceQueueFamilyProperties(adapter, &queue_family_count, queue_families.ptr);
|
||
|
|
|
||
|
|
// --- FIND SUPPORTED FAMILIES ---
|
||
|
|
for (queue_families, 0..) |family, i| {
|
||
|
|
var supported: vk.VkBool32 = vk.VK_FALSE;
|
||
|
|
|
||
|
|
if (family.queueFlags & @as(vk.VkQueueFlags, @intCast(vk.VK_QUEUE_GRAPHICS_BIT)) != 0) {
|
||
|
|
indices.graphics = @intCast(i);
|
||
|
|
}
|
||
|
|
|
||
|
|
_ = vk.vkGetPhysicalDeviceSurfaceSupportKHR(
|
||
|
|
adapter,
|
||
|
|
@intCast(i),
|
||
|
|
surface,
|
||
|
|
&supported,
|
||
|
|
);
|
||
|
|
if (supported == vk.VK_TRUE) {
|
||
|
|
indices.present = @intCast(i);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (indices.graphics != null and indices.present != null) {
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return indices;
|
||
|
|
}
|