remove graphics_context.zig
This commit is contained in:
@@ -1,246 +0,0 @@
|
|||||||
const std = @import("std");
|
|
||||||
const vk = @import("vk");
|
|
||||||
const c = @import("c.zig");
|
|
||||||
const Allocator = std.mem.Allocator;
|
|
||||||
|
|
||||||
const gfx = @import("gfx.zig");
|
|
||||||
|
|
||||||
const BaseDispatch = gfx.BaseDispatch;
|
|
||||||
const InstanceDispatch = gfx.InstanceDispatch;
|
|
||||||
const DeviceDispatch = gfx.DeviceDispatch;
|
|
||||||
|
|
||||||
const required_device_extensions = [_][*:0]const u8{
|
|
||||||
vk.extension_info.khr_swapchain.name,
|
|
||||||
vk.extension_info.khr_dynamic_rendering.name,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const GraphicsContext = struct {
|
|
||||||
vki: InstanceDispatch,
|
|
||||||
vkd: DeviceDispatch,
|
|
||||||
|
|
||||||
surface: vk.SurfaceKHR,
|
|
||||||
pdev: vk.PhysicalDevice,
|
|
||||||
props: vk.PhysicalDeviceProperties,
|
|
||||||
mem_props: vk.PhysicalDeviceMemoryProperties,
|
|
||||||
|
|
||||||
dev: vk.Device,
|
|
||||||
graphics_queue: Queue,
|
|
||||||
present_queue: Queue,
|
|
||||||
|
|
||||||
pub fn init(allocator: Allocator, instance: vk.Instance, surface: vk.SurfaceKHR, vki: InstanceDispatch) !GraphicsContext {
|
|
||||||
var self: GraphicsContext = undefined;
|
|
||||||
self.vki = vki;
|
|
||||||
self.surface = surface;
|
|
||||||
|
|
||||||
const candidate = try pickPhysicalDevice(vki, instance, allocator, surface);
|
|
||||||
self.pdev = candidate.pdev;
|
|
||||||
self.props = candidate.props;
|
|
||||||
self.dev = try initializeCandidate(vki, candidate);
|
|
||||||
self.vkd = try DeviceDispatch.load(self.dev, vki.dispatch.vkGetDeviceProcAddr);
|
|
||||||
errdefer self.vkd.destroyDevice(self.dev, null);
|
|
||||||
|
|
||||||
self.graphics_queue = Queue.init(self.vkd, self.dev, candidate.queues.graphics_family);
|
|
||||||
self.present_queue = Queue.init(self.vkd, self.dev, candidate.queues.present_family);
|
|
||||||
|
|
||||||
self.mem_props = vki.getPhysicalDeviceMemoryProperties(self.pdev);
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn deinit(self: GraphicsContext) void {
|
|
||||||
self.vkd.destroyDevice(self.dev, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn deviceName(self: *const GraphicsContext) []const u8 {
|
|
||||||
return std.mem.sliceTo(&self.props.device_name, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn findMemoryTypeIndex(self: GraphicsContext, memory_type_bits: u32, flags: vk.MemoryPropertyFlags) !u32 {
|
|
||||||
for (self.mem_props.memory_types[0..self.mem_props.memory_type_count], 0..) |mem_type, i| {
|
|
||||||
if (memory_type_bits & (@as(u32, 1) << @truncate(i)) != 0 and mem_type.property_flags.contains(flags)) {
|
|
||||||
return @truncate(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return error.NoSuitableMemoryType;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn allocate(self: GraphicsContext, requirements: vk.MemoryRequirements, flags: vk.MemoryPropertyFlags) !vk.DeviceMemory {
|
|
||||||
return try self.vkd.allocateMemory(self.dev, &.{
|
|
||||||
.allocation_size = requirements.size,
|
|
||||||
.memory_type_index = try self.findMemoryTypeIndex(requirements.memory_type_bits, flags),
|
|
||||||
}, null);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const Queue = struct {
|
|
||||||
handle: vk.Queue,
|
|
||||||
family: u32,
|
|
||||||
|
|
||||||
fn init(vkd: DeviceDispatch, dev: vk.Device, family: u32) Queue {
|
|
||||||
return .{
|
|
||||||
.handle = vkd.getDeviceQueue(dev, family, 0),
|
|
||||||
.family = family,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
fn initializeCandidate(vki: InstanceDispatch, candidate: DeviceCandidate) !vk.Device {
|
|
||||||
const priority = [_]f32{1};
|
|
||||||
const qci = [_]vk.DeviceQueueCreateInfo{
|
|
||||||
.{
|
|
||||||
.queue_family_index = candidate.queues.graphics_family,
|
|
||||||
.queue_count = 1,
|
|
||||||
.p_queue_priorities = &priority,
|
|
||||||
},
|
|
||||||
.{
|
|
||||||
.queue_family_index = candidate.queues.present_family,
|
|
||||||
.queue_count = 1,
|
|
||||||
.p_queue_priorities = &priority,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const queue_count: u32 = if (candidate.queues.graphics_family == candidate.queues.present_family)
|
|
||||||
1
|
|
||||||
else
|
|
||||||
2;
|
|
||||||
|
|
||||||
return try vki.createDevice(candidate.pdev, &.{
|
|
||||||
.queue_create_info_count = queue_count,
|
|
||||||
.p_queue_create_infos = &qci,
|
|
||||||
.enabled_extension_count = required_device_extensions.len,
|
|
||||||
.pp_enabled_extension_names = @as([*]const [*:0]const u8, @ptrCast(&required_device_extensions)),
|
|
||||||
}, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
const DeviceCandidate = struct {
|
|
||||||
pdev: vk.PhysicalDevice,
|
|
||||||
props: vk.PhysicalDeviceProperties,
|
|
||||||
queues: QueueAllocation,
|
|
||||||
};
|
|
||||||
|
|
||||||
const QueueAllocation = struct {
|
|
||||||
graphics_family: u32,
|
|
||||||
present_family: u32,
|
|
||||||
};
|
|
||||||
|
|
||||||
fn pickPhysicalDevice(
|
|
||||||
vki: InstanceDispatch,
|
|
||||||
instance: vk.Instance,
|
|
||||||
allocator: Allocator,
|
|
||||||
surface: vk.SurfaceKHR,
|
|
||||||
) !DeviceCandidate {
|
|
||||||
var device_count: u32 = undefined;
|
|
||||||
_ = try vki.enumeratePhysicalDevices(instance, &device_count, null);
|
|
||||||
|
|
||||||
const pdevs = try allocator.alloc(vk.PhysicalDevice, device_count);
|
|
||||||
defer allocator.free(pdevs);
|
|
||||||
|
|
||||||
_ = try vki.enumeratePhysicalDevices(instance, &device_count, pdevs.ptr);
|
|
||||||
|
|
||||||
for (pdevs) |pdev| {
|
|
||||||
if (try checkSuitable(vki, pdev, allocator, surface)) |candidate| {
|
|
||||||
return candidate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return error.NoSuitableDevice;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn checkSuitable(
|
|
||||||
vki: InstanceDispatch,
|
|
||||||
pdev: vk.PhysicalDevice,
|
|
||||||
allocator: Allocator,
|
|
||||||
surface: vk.SurfaceKHR,
|
|
||||||
) !?DeviceCandidate {
|
|
||||||
const props = vki.getPhysicalDeviceProperties(pdev);
|
|
||||||
|
|
||||||
if (props.device_type != .discrete_gpu) return null;
|
|
||||||
|
|
||||||
if (!try checkExtensionSupport(vki, pdev, allocator)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!try checkSurfaceSupport(vki, pdev, surface)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (try allocateQueues(vki, pdev, allocator, surface)) |allocation| {
|
|
||||||
return DeviceCandidate{
|
|
||||||
.pdev = pdev,
|
|
||||||
.props = props,
|
|
||||||
.queues = allocation,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn allocateQueues(vki: InstanceDispatch, pdev: vk.PhysicalDevice, allocator: Allocator, surface: vk.SurfaceKHR) !?QueueAllocation {
|
|
||||||
var family_count: u32 = undefined;
|
|
||||||
vki.getPhysicalDeviceQueueFamilyProperties(pdev, &family_count, null);
|
|
||||||
|
|
||||||
const families = try allocator.alloc(vk.QueueFamilyProperties, family_count);
|
|
||||||
defer allocator.free(families);
|
|
||||||
vki.getPhysicalDeviceQueueFamilyProperties(pdev, &family_count, families.ptr);
|
|
||||||
|
|
||||||
var graphics_family: ?u32 = null;
|
|
||||||
var present_family: ?u32 = null;
|
|
||||||
|
|
||||||
for (families, 0..) |properties, i| {
|
|
||||||
const family: u32 = @intCast(i);
|
|
||||||
|
|
||||||
if (graphics_family == null and properties.queue_flags.graphics_bit) {
|
|
||||||
graphics_family = family;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (present_family == null and (try vki.getPhysicalDeviceSurfaceSupportKHR(pdev, family, surface)) == vk.TRUE) {
|
|
||||||
present_family = family;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (graphics_family != null and present_family != null) {
|
|
||||||
return QueueAllocation{
|
|
||||||
.graphics_family = graphics_family.?,
|
|
||||||
.present_family = present_family.?,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn checkSurfaceSupport(vki: InstanceDispatch, pdev: vk.PhysicalDevice, surface: vk.SurfaceKHR) !bool {
|
|
||||||
var format_count: u32 = undefined;
|
|
||||||
_ = try vki.getPhysicalDeviceSurfaceFormatsKHR(pdev, surface, &format_count, null);
|
|
||||||
|
|
||||||
var present_mode_count: u32 = undefined;
|
|
||||||
_ = try vki.getPhysicalDeviceSurfacePresentModesKHR(pdev, surface, &present_mode_count, null);
|
|
||||||
|
|
||||||
return format_count > 0 and present_mode_count > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn checkExtensionSupport(
|
|
||||||
vki: InstanceDispatch,
|
|
||||||
pdev: vk.PhysicalDevice,
|
|
||||||
allocator: Allocator,
|
|
||||||
) !bool {
|
|
||||||
var count: u32 = undefined;
|
|
||||||
_ = try vki.enumerateDeviceExtensionProperties(pdev, null, &count, null);
|
|
||||||
|
|
||||||
const propsv = try allocator.alloc(vk.ExtensionProperties, count);
|
|
||||||
defer allocator.free(propsv);
|
|
||||||
|
|
||||||
_ = try vki.enumerateDeviceExtensionProperties(pdev, null, &count, propsv.ptr);
|
|
||||||
|
|
||||||
for (required_device_extensions) |ext| {
|
|
||||||
for (propsv) |props| {
|
|
||||||
if (std.mem.eql(u8, std.mem.span(ext), std.mem.sliceTo(&props.extension_name, 0))) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
16
src/main.zig
16
src/main.zig
@@ -239,17 +239,17 @@ pub fn main() !void {
|
|||||||
//
|
//
|
||||||
// swapchain = try vkd.createSwapchainKHR(dev, &.{
|
// swapchain = try vkd.createSwapchainKHR(dev, &.{
|
||||||
// .surface = surface,
|
// .surface = surface,
|
||||||
// .min_image_count = 3, // todo compute
|
// .min_image_count = 3, // should compute
|
||||||
// .image_format = .r8g8b8a8_sint, // todo compute
|
// .image_format = .r8g8b8a8_sint, // should compute
|
||||||
// // .image_format = .r8g8b8a8_sint, // todo compute
|
// // .image_format = .r8g8b8a8_sint, // should compute
|
||||||
// .image_color_space = .srgb_nonlinear_khr, // todo compute
|
// .image_color_space = .srgb_nonlinear_khr, // should compute
|
||||||
// .image_extent = extent, // todo compute
|
// .image_extent = extent, // should compute
|
||||||
// .image_array_layers = 1,
|
// .image_array_layers = 1,
|
||||||
// .image_usage = .{ .color_attachment_bit = true, .transfer_dst_bit = true },
|
// .image_usage = .{ .color_attachment_bit = true, .transfer_dst_bit = true },
|
||||||
// .image_sharing_mode = .exclusive, // since we only choose one queue family
|
// .image_sharing_mode = .exclusive, // since we only choose one queue family
|
||||||
// .pre_transform = .{ .identity_bit_khr = true }, // todo compute
|
// .pre_transform = .{ .identity_bit_khr = true }, // should compute
|
||||||
// .composite_alpha = .{ .opaque_bit_khr = true },
|
// .composite_alpha = .{ .opaque_bit_khr = true },
|
||||||
// .present_mode = .mailbox_khr, // todo compute
|
// .present_mode = .mailbox_khr, // should compute
|
||||||
// .clipped = vk.TRUE,
|
// .clipped = vk.TRUE,
|
||||||
// .old_swapchain = swapchain,
|
// .old_swapchain = swapchain,
|
||||||
// }, null);
|
// }, null);
|
||||||
@@ -437,6 +437,8 @@ fn copyBuffer(gc: *const Context, pool: vk.CommandPool, dst: vk.Buffer, src: vk.
|
|||||||
// creating and submitting a queue for every copy operation seems a bad idea for "streamed" data
|
// creating and submitting a queue for every copy operation seems a bad idea for "streamed" data
|
||||||
// gonna want a way to send a copy operation WITH SYNCHRONIZATION PRIMITIVES on a particular queue
|
// gonna want a way to send a copy operation WITH SYNCHRONIZATION PRIMITIVES on a particular queue
|
||||||
// see https://stackoverflow.com/a/62183243
|
// see https://stackoverflow.com/a/62183243
|
||||||
|
//
|
||||||
|
// this may be a misunderstanding on how submission works...
|
||||||
try gc.vkd.queueSubmit(gc.queue, 1, @ptrCast(&si), .null_handle);
|
try gc.vkd.queueSubmit(gc.queue, 1, @ptrCast(&si), .null_handle);
|
||||||
try gc.vkd.queueWaitIdle(gc.queue);
|
try gc.vkd.queueWaitIdle(gc.queue);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user