NYXGFX/src/rhi/vulkan/resource/device.zig
2026-08-11 21:06:28 +01:00

167 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;
}