vulkan-tutorial 06
This commit is contained in:
@@ -21,11 +21,14 @@ device: vk.Device,
|
|||||||
|
|
||||||
queues: struct {
|
queues: struct {
|
||||||
graphics: vk.Queue,
|
graphics: vk.Queue,
|
||||||
|
present: vk.Queue,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
surface: vk.SurfaceKHR,
|
||||||
|
|
||||||
messenger: if (USE_DEBUG_LAYERS) vk.DebugUtilsMessengerEXT else void,
|
messenger: if (USE_DEBUG_LAYERS) vk.DebugUtilsMessengerEXT else void,
|
||||||
|
|
||||||
pub fn init(allocator: std.mem.Allocator) !Self {
|
pub fn init(allocator: std.mem.Allocator, window: *c.GLFWwindow) !Self {
|
||||||
var self: Self = undefined;
|
var self: Self = undefined;
|
||||||
self.allocator = allocator;
|
self.allocator = allocator;
|
||||||
|
|
||||||
@@ -107,7 +110,7 @@ pub fn init(allocator: std.mem.Allocator) !Self {
|
|||||||
.api_version = vk.API_VERSION_1_3,
|
.api_version = vk.API_VERSION_1_3,
|
||||||
};
|
};
|
||||||
|
|
||||||
const create_info = vk.InstanceCreateInfo{
|
const instance_create_info = vk.InstanceCreateInfo{
|
||||||
.p_application_info = &app_info,
|
.p_application_info = &app_info,
|
||||||
.enabled_extension_count = @intCast(exts.items.len),
|
.enabled_extension_count = @intCast(exts.items.len),
|
||||||
.pp_enabled_extension_names = exts.items.ptr,
|
.pp_enabled_extension_names = exts.items.ptr,
|
||||||
@@ -116,7 +119,7 @@ pub fn init(allocator: std.mem.Allocator) !Self {
|
|||||||
.p_next = if (USE_DEBUG_LAYERS) &debug_create_info else null,
|
.p_next = if (USE_DEBUG_LAYERS) &debug_create_info else null,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.instance = try vkb.createInstance(&create_info, null);
|
self.instance = try vkb.createInstance(&instance_create_info, null);
|
||||||
self.vki = try InstanceDispatch.load(self.instance, vkb.dispatch.vkGetInstanceProcAddr);
|
self.vki = try InstanceDispatch.load(self.instance, vkb.dispatch.vkGetInstanceProcAddr);
|
||||||
const vki = self.vki;
|
const vki = self.vki;
|
||||||
errdefer vki.destroyInstance(self.instance, null);
|
errdefer vki.destroyInstance(self.instance, null);
|
||||||
@@ -132,6 +135,20 @@ pub fn init(allocator: std.mem.Allocator) !Self {
|
|||||||
null,
|
null,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
switch (c.glfwCreateWindowSurface(
|
||||||
|
self.instance,
|
||||||
|
window,
|
||||||
|
null,
|
||||||
|
&self.surface,
|
||||||
|
)) {
|
||||||
|
.success => {},
|
||||||
|
else => |e| {
|
||||||
|
std.log.err("{}", .{e});
|
||||||
|
return error.Unknown;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
errdefer vki.destroySurfaceKHR(self.instance, self.surface, null);
|
||||||
|
|
||||||
var device_count: u32 = 0;
|
var device_count: u32 = 0;
|
||||||
_ = try vki.enumeratePhysicalDevices(self.instance, &device_count, null);
|
_ = try vki.enumeratePhysicalDevices(self.instance, &device_count, null);
|
||||||
const devices = try allocator.alloc(vk.PhysicalDevice, device_count);
|
const devices = try allocator.alloc(vk.PhysicalDevice, device_count);
|
||||||
@@ -170,35 +187,76 @@ pub fn init(allocator: std.mem.Allocator) !Self {
|
|||||||
// todo this should be incorporated with physical device selection/ranking.
|
// todo this should be incorporated with physical device selection/ranking.
|
||||||
const Indices = struct {
|
const Indices = struct {
|
||||||
graphics: u32,
|
graphics: u32,
|
||||||
|
present: u32,
|
||||||
};
|
};
|
||||||
const indices: Indices = find_index: {
|
const indices: Indices = find_index: {
|
||||||
var graphics: ?u32 = null;
|
var graphics: ?u32 = null;
|
||||||
|
var present: ?u32 = null;
|
||||||
|
|
||||||
for (queue_family_properties, 0..) |prop, idx| {
|
for (queue_family_properties, 0..) |prop, idx| {
|
||||||
if (graphics == null and prop.queue_flags.graphics_bit) {
|
if (graphics == null and prop.queue_flags.graphics_bit) {
|
||||||
graphics = @intCast(idx);
|
graphics = @intCast(idx);
|
||||||
|
// continue; // forces distinct queue families
|
||||||
}
|
}
|
||||||
|
|
||||||
if (graphics != null) {
|
if (present == null) {
|
||||||
break :find_index .{ .graphics = graphics.? };
|
const present_support = try vki.getPhysicalDeviceSurfaceSupportKHR(
|
||||||
|
selected.device,
|
||||||
|
@intCast(idx),
|
||||||
|
self.surface,
|
||||||
|
) == vk.TRUE;
|
||||||
|
if (present_support) {
|
||||||
|
present = @intCast(idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (graphics != null and present != null) {
|
||||||
|
break :find_index .{
|
||||||
|
.graphics = graphics.?,
|
||||||
|
.present = present.?,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return error.IncompatibleDeviceQueues;
|
return error.IncompatibleDeviceQueues;
|
||||||
};
|
};
|
||||||
|
|
||||||
const priorities = [_]f32{1.0};
|
const gp_priorities = [_]f32{ 1.0, 1.0 };
|
||||||
const queue_create_infos = [_]vk.DeviceQueueCreateInfo{
|
|
||||||
.{
|
var queue_create_infos = std.ArrayList(vk.DeviceQueueCreateInfo).init(allocator);
|
||||||
|
defer queue_create_infos.deinit();
|
||||||
|
|
||||||
|
// queue info family indices must be unique. so if the graphics and present queues are the same, create two queues
|
||||||
|
// in the same family. otherwise create queues in separate families. there should probably be some general way to
|
||||||
|
// group and unpack the queues, but I'm not bothering with that for now until I restructure this monolithic function
|
||||||
|
// in general.
|
||||||
|
if (indices.graphics == indices.present) {
|
||||||
|
std.log.info("using one queue family", .{});
|
||||||
|
const gp_slice = gp_priorities[0..2];
|
||||||
|
try queue_create_infos.append(.{
|
||||||
.queue_family_index = indices.graphics,
|
.queue_family_index = indices.graphics,
|
||||||
.queue_count = priorities.len,
|
.queue_count = @intCast(gp_slice.len),
|
||||||
.p_queue_priorities = &priorities,
|
.p_queue_priorities = gp_slice.ptr,
|
||||||
},
|
});
|
||||||
};
|
} else {
|
||||||
|
std.log.info("using two queue families", .{});
|
||||||
|
const g_slice = gp_priorities[0..1];
|
||||||
|
const p_slice = gp_priorities[1..2];
|
||||||
|
try queue_create_infos.append(.{
|
||||||
|
.queue_family_index = indices.graphics,
|
||||||
|
.queue_count = @intCast(g_slice.len),
|
||||||
|
.p_queue_priorities = g_slice.ptr,
|
||||||
|
});
|
||||||
|
try queue_create_infos.append(.{
|
||||||
|
.queue_family_index = indices.present,
|
||||||
|
.queue_count = @intCast(p_slice.len),
|
||||||
|
.p_queue_priorities = p_slice.ptr,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const device_create_info = vk.DeviceCreateInfo{
|
const device_create_info = vk.DeviceCreateInfo{
|
||||||
.queue_create_info_count = queue_create_infos.len,
|
.queue_create_info_count = @intCast(queue_create_infos.items.len),
|
||||||
.p_queue_create_infos = &queue_create_infos,
|
.p_queue_create_infos = queue_create_infos.items.ptr,
|
||||||
.p_enabled_features = &selected.feats,
|
.p_enabled_features = &selected.feats,
|
||||||
// .enabled_extension_count = @intCast(exts.items.len),
|
// .enabled_extension_count = @intCast(exts.items.len),
|
||||||
// .pp_enabled_extension_names = exts.items.ptr,
|
// .pp_enabled_extension_names = exts.items.ptr,
|
||||||
@@ -215,14 +273,25 @@ pub fn init(allocator: std.mem.Allocator) !Self {
|
|||||||
const vkd = self.vkd;
|
const vkd = self.vkd;
|
||||||
errdefer vkd.destroyDevice(self.device, null);
|
errdefer vkd.destroyDevice(self.device, null);
|
||||||
|
|
||||||
|
if (indices.graphics == indices.present) {
|
||||||
|
// two queues in the same family
|
||||||
self.queues = .{
|
self.queues = .{
|
||||||
.graphics = vkd.getDeviceQueue(self.device, indices.graphics, 0),
|
.graphics = vkd.getDeviceQueue(self.device, indices.graphics, 0),
|
||||||
|
.present = vkd.getDeviceQueue(self.device, indices.present, 1),
|
||||||
};
|
};
|
||||||
|
} else {
|
||||||
|
// queues from different families
|
||||||
|
self.queues = .{
|
||||||
|
.graphics = vkd.getDeviceQueue(self.device, indices.graphics, 0),
|
||||||
|
.present = vkd.getDeviceQueue(self.device, indices.present, 0),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: Self) void {
|
pub fn deinit(self: Self) void {
|
||||||
|
self.vki.destroySurfaceKHR(self.instance, self.surface, null);
|
||||||
self.vkd.destroyDevice(self.device, null);
|
self.vkd.destroyDevice(self.device, null);
|
||||||
if (USE_DEBUG_LAYERS) self.vki.destroyDebugUtilsMessengerEXT(
|
if (USE_DEBUG_LAYERS) self.vki.destroyDebugUtilsMessengerEXT(
|
||||||
self.instance,
|
self.instance,
|
||||||
@@ -305,6 +374,8 @@ const InstanceDispatch = vk.InstanceWrapper(.{
|
|||||||
.getPhysicalDeviceQueueFamilyProperties = true,
|
.getPhysicalDeviceQueueFamilyProperties = true,
|
||||||
.createDevice = true,
|
.createDevice = true,
|
||||||
.getDeviceProcAddr = true,
|
.getDeviceProcAddr = true,
|
||||||
|
.destroySurfaceKHR = true,
|
||||||
|
.getPhysicalDeviceSurfaceSupportKHR = true,
|
||||||
});
|
});
|
||||||
|
|
||||||
const DeviceDispatch = vk.DeviceWrapper(.{
|
const DeviceDispatch = vk.DeviceWrapper(.{
|
||||||
|
@@ -1,42 +0,0 @@
|
|||||||
const Self = @This();
|
|
||||||
|
|
||||||
const std = @import("std");
|
|
||||||
const c = @import("c.zig");
|
|
||||||
const vk = @import("vk");
|
|
||||||
const builtin = @import("builtin");
|
|
||||||
|
|
||||||
allocator: std.mem.Allocator,
|
|
||||||
|
|
||||||
window: *c.GLFWwindow,
|
|
||||||
|
|
||||||
pub fn mainLoop(self: Self) void {
|
|
||||||
while (c.glfwWindowShouldClose(self.window) == 0) : (c.glfwPollEvents()) {
|
|
||||||
c.glfwSwapBuffers(self.window);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn init(
|
|
||||||
allocator: std.mem.Allocator,
|
|
||||||
width: u32,
|
|
||||||
height: u32,
|
|
||||||
title: []const u8,
|
|
||||||
) !Self {
|
|
||||||
var self: Self = undefined;
|
|
||||||
self.allocator = allocator;
|
|
||||||
|
|
||||||
c.glfwWindowHint(c.GLFW_CLIENT_API, c.GLFW_NO_API);
|
|
||||||
self.window = c.glfwCreateWindow(
|
|
||||||
@intCast(width),
|
|
||||||
@intCast(height),
|
|
||||||
title.ptr,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
) orelse return error.glfwCreateWindowFailed;
|
|
||||||
errdefer c.glfwDestroyWindow(self.window);
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn deinit(self: Self) void {
|
|
||||||
c.glfwDestroyWindow(self.window);
|
|
||||||
}
|
|
25
src/main.zig
25
src/main.zig
@@ -2,7 +2,6 @@ const std = @import("std");
|
|||||||
const c = @import("c.zig");
|
const c = @import("c.zig");
|
||||||
const vk = @import("vk");
|
const vk = @import("vk");
|
||||||
|
|
||||||
const Window = @import("Window.zig");
|
|
||||||
const Context = @import("Context.zig");
|
const Context = @import("Context.zig");
|
||||||
|
|
||||||
pub fn main() !void {
|
pub fn main() !void {
|
||||||
@@ -15,16 +14,20 @@ pub fn main() !void {
|
|||||||
}
|
}
|
||||||
defer c.glfwTerminate();
|
defer c.glfwTerminate();
|
||||||
|
|
||||||
const ctx = try Context.init(allocator);
|
c.glfwWindowHint(c.GLFW_CLIENT_API, c.GLFW_NO_API);
|
||||||
|
const window = c.glfwCreateWindow(
|
||||||
|
720,
|
||||||
|
1280,
|
||||||
|
"Hello World!",
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
) orelse return error.glfwCreateWindowFailed;
|
||||||
|
defer c.glfwDestroyWindow(window);
|
||||||
|
|
||||||
|
const ctx = try Context.init(allocator, window);
|
||||||
defer ctx.deinit();
|
defer ctx.deinit();
|
||||||
|
|
||||||
const window = try Window.init(
|
while (c.glfwWindowShouldClose(window) == 0) : (c.glfwPollEvents()) {
|
||||||
allocator,
|
c.glfwSwapBuffers(window);
|
||||||
1280,
|
}
|
||||||
720,
|
|
||||||
"Hello World",
|
|
||||||
);
|
|
||||||
defer window.deinit();
|
|
||||||
|
|
||||||
window.mainLoop();
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user