xcb: add Vulkan init to sample
This commit is contained in:
@@ -4,6 +4,14 @@ pub fn build(b: *std.Build) void {
|
|||||||
const target = b.standardTargetOptions(.{});
|
const target = b.standardTargetOptions(.{});
|
||||||
const optimize = b.standardOptimizeOption(.{});
|
const optimize = b.standardOptimizeOption(.{});
|
||||||
|
|
||||||
|
const vulkan_dep = b.dependency("vulkan_zig", .{
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
.registry = b.path("vendor/vk.xml"),
|
||||||
|
});
|
||||||
|
|
||||||
|
const vulkan_mod = vulkan_dep.module("vulkan-zig");
|
||||||
|
|
||||||
const mod = b.addModule("xcb", .{
|
const mod = b.addModule("xcb", .{
|
||||||
.root_source_file = b.path("src/root.zig"),
|
.root_source_file = b.path("src/root.zig"),
|
||||||
.target = target,
|
.target = target,
|
||||||
@@ -27,6 +35,7 @@ pub fn build(b: *std.Build) void {
|
|||||||
.target = target,
|
.target = target,
|
||||||
.optimize = optimize,
|
.optimize = optimize,
|
||||||
.imports = &.{
|
.imports = &.{
|
||||||
|
.{ .name = "vulkan", .module = vulkan_mod },
|
||||||
.{ .name = "xcb", .module = mod },
|
.{ .name = "xcb", .module = mod },
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,6 +2,12 @@
|
|||||||
.name = .xcb,
|
.name = .xcb,
|
||||||
.version = "0.0.0",
|
.version = "0.0.0",
|
||||||
.minimum_zig_version = "0.16.0",
|
.minimum_zig_version = "0.16.0",
|
||||||
|
.dependencies = .{
|
||||||
|
.vulkan_zig = .{
|
||||||
|
.url = "git+https://github.com/Snektron/vulkan-zig#b496a6a561ffbbeb530b0f9ed4e059f88c0723a5",
|
||||||
|
.hash = "vulkan-0.0.0-r7Ytx7N9AwD7IZt5_XNHtkJ4G9qY0pCH-cpcOsbL8wzD",
|
||||||
|
},
|
||||||
|
},
|
||||||
.paths = .{
|
.paths = .{
|
||||||
"src",
|
"src",
|
||||||
"build.zig",
|
"build.zig",
|
||||||
|
|||||||
176
packages/xcb/sample/Vulkan.zig
Normal file
176
packages/xcb/sample/Vulkan.zig
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
const Vulkan = @This();
|
||||||
|
|
||||||
|
const std = @import("std");
|
||||||
|
const vk = @import("vulkan");
|
||||||
|
const xcb = @import("xcb");
|
||||||
|
|
||||||
|
vulkan_loader: *DynamicLibrary,
|
||||||
|
|
||||||
|
base: vk.BaseWrapper,
|
||||||
|
instance: vk.InstanceProxy,
|
||||||
|
surface: vk.SurfaceKHR,
|
||||||
|
device: vk.DeviceProxy,
|
||||||
|
|
||||||
|
queue_family: u32,
|
||||||
|
queue: vk.Queue,
|
||||||
|
command_pool: vk.CommandPool,
|
||||||
|
|
||||||
|
pub fn init(allocator: std.mem.Allocator, connection: *xcb.Connection, window: xcb.Window) !Vulkan {
|
||||||
|
const vulkan_loader = try DynamicLibrary.open("libvulkan.so.1");
|
||||||
|
errdefer vulkan_loader.close();
|
||||||
|
|
||||||
|
const vkGetInstanceProcAddr = try vulkan_loader.sym(vk.PfnGetInstanceProcAddr, "vkGetInstanceProcAddr");
|
||||||
|
|
||||||
|
const base = vk.BaseWrapper.load(vkGetInstanceProcAddr);
|
||||||
|
|
||||||
|
const instance_handle = blk: {
|
||||||
|
const enabled_layers: []const [*:0]const u8 = &.{};
|
||||||
|
const enabled_extensions: []const [*:0]const u8 = &.{
|
||||||
|
vk.extensions.khr_surface.name,
|
||||||
|
vk.extensions.khr_xcb_surface.name,
|
||||||
|
};
|
||||||
|
|
||||||
|
break :blk try base.createInstance(&.{
|
||||||
|
.p_application_info = &.{
|
||||||
|
.p_application_name = "xcb_sample",
|
||||||
|
.application_version = vk.makeApiVersion(0, 0, 0, 0).toU32(),
|
||||||
|
.p_engine_name = "xcb_sample",
|
||||||
|
.engine_version = vk.makeApiVersion(0, 0, 0, 0).toU32(),
|
||||||
|
.api_version = vk.API_VERSION_1_0.toU32(),
|
||||||
|
},
|
||||||
|
.enabled_layer_count = @intCast(enabled_layers.len),
|
||||||
|
.pp_enabled_layer_names = enabled_layers.ptr,
|
||||||
|
.enabled_extension_count = @intCast(enabled_extensions.len),
|
||||||
|
.pp_enabled_extension_names = enabled_extensions.ptr,
|
||||||
|
}, null);
|
||||||
|
};
|
||||||
|
|
||||||
|
const instance_wrapper_ptr = try allocator.create(vk.InstanceWrapper);
|
||||||
|
errdefer allocator.destroy(instance_wrapper_ptr);
|
||||||
|
|
||||||
|
instance_wrapper_ptr.* = .load(instance_handle, vkGetInstanceProcAddr);
|
||||||
|
const instance = vk.InstanceProxy.init(instance_handle, instance_wrapper_ptr);
|
||||||
|
errdefer instance.destroyInstance(null);
|
||||||
|
|
||||||
|
const surface = try instance.createXcbSurfaceKHR(&.{
|
||||||
|
.connection = connection,
|
||||||
|
.window = window,
|
||||||
|
}, null);
|
||||||
|
errdefer instance.destroySurfaceKHR(surface, null);
|
||||||
|
|
||||||
|
const physical_device = blk: {
|
||||||
|
const physical_devices = try instance.enumeratePhysicalDevicesAlloc(allocator);
|
||||||
|
defer allocator.free(physical_devices);
|
||||||
|
|
||||||
|
if (physical_devices.len > 0) {
|
||||||
|
break :blk physical_devices[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return error.NoDevice;
|
||||||
|
};
|
||||||
|
|
||||||
|
const queue_family: u32 = blk: {
|
||||||
|
const queue_families_properties = try instance.getPhysicalDeviceQueueFamilyPropertiesAlloc(physical_device, allocator);
|
||||||
|
defer allocator.free(queue_families_properties);
|
||||||
|
|
||||||
|
// Look for the first family that has the `graphics_bit` set and
|
||||||
|
// supports presentation to a given surface.
|
||||||
|
|
||||||
|
for (queue_families_properties, 0..) |queue_family_properties, i| {
|
||||||
|
const graphics_bit = queue_family_properties.queue_flags.graphics_bit;
|
||||||
|
const supports_presentation = try instance.getPhysicalDeviceSurfaceSupportKHR(physical_device, @intCast(i), surface) != .false;
|
||||||
|
|
||||||
|
if (graphics_bit and supports_presentation) {
|
||||||
|
break :blk @intCast(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return error.NoQueue;
|
||||||
|
};
|
||||||
|
|
||||||
|
const device_handle = blk: {
|
||||||
|
const queue_create_infos: []const vk.DeviceQueueCreateInfo = &.{
|
||||||
|
.{
|
||||||
|
.queue_family_index = queue_family,
|
||||||
|
.queue_count = 1,
|
||||||
|
.p_queue_priorities = &.{0},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const enabled_extensions: []const [*:0]const u8 = &.{
|
||||||
|
vk.extensions.khr_swapchain.name,
|
||||||
|
};
|
||||||
|
|
||||||
|
break :blk try instance.createDevice(physical_device, &.{
|
||||||
|
.queue_create_info_count = @intCast(queue_create_infos.len),
|
||||||
|
.p_queue_create_infos = queue_create_infos.ptr,
|
||||||
|
.enabled_extension_count = @intCast(enabled_extensions.len),
|
||||||
|
.pp_enabled_extension_names = enabled_extensions.ptr,
|
||||||
|
}, null);
|
||||||
|
};
|
||||||
|
|
||||||
|
const device_wrapper_ptr = try allocator.create(vk.DeviceWrapper);
|
||||||
|
errdefer allocator.destroy(device_wrapper_ptr);
|
||||||
|
|
||||||
|
device_wrapper_ptr.* = .load(device_handle, instance.wrapper.dispatch.vkGetDeviceProcAddr.?);
|
||||||
|
const device = vk.DeviceProxy.init(device_handle, device_wrapper_ptr);
|
||||||
|
errdefer device.destroyDevice(null);
|
||||||
|
|
||||||
|
const queue = device.getDeviceQueue(queue_family, 0);
|
||||||
|
|
||||||
|
const command_pool = try device.createCommandPool(&.{
|
||||||
|
.flags = .{ .transient_bit = true },
|
||||||
|
.queue_family_index = queue_family,
|
||||||
|
}, null);
|
||||||
|
errdefer device.destroyCommandPool(command_pool, null);
|
||||||
|
|
||||||
|
return .{
|
||||||
|
.vulkan_loader = vulkan_loader,
|
||||||
|
|
||||||
|
.base = base,
|
||||||
|
.instance = instance,
|
||||||
|
.surface = surface,
|
||||||
|
.device = device,
|
||||||
|
|
||||||
|
.queue_family = queue_family,
|
||||||
|
.queue = queue,
|
||||||
|
.command_pool = command_pool,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: *Vulkan, allocator: std.mem.Allocator) void {
|
||||||
|
self.device.destroyCommandPool(self.command_pool, null);
|
||||||
|
|
||||||
|
self.device.destroyDevice(null);
|
||||||
|
allocator.destroy(self.device.wrapper);
|
||||||
|
self.instance.destroySurfaceKHR(self.surface, null);
|
||||||
|
self.instance.destroyInstance(null);
|
||||||
|
allocator.destroy(self.instance.wrapper);
|
||||||
|
|
||||||
|
self.vulkan_loader.close();
|
||||||
|
|
||||||
|
self.* = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
const DynamicLibrary = opaque {
|
||||||
|
fn open(path: [*:0]const u8) !*DynamicLibrary {
|
||||||
|
const ptr = std.c.dlopen(path, .{ .NOW = true }) orelse {
|
||||||
|
std.debug.print("{s}\n", .{std.c.dlerror().?});
|
||||||
|
return error.DlOpen;
|
||||||
|
};
|
||||||
|
|
||||||
|
return @ptrCast(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn close(self: *DynamicLibrary) void {
|
||||||
|
_ = std.c.dlclose(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sym(self: *DynamicLibrary, comptime Ptr: type, symbol: [*:0]const u8) !Ptr {
|
||||||
|
const ptr = std.c.dlsym(self, symbol) orelse {
|
||||||
|
std.debug.print("{s}\n", .{std.c.dlerror().?});
|
||||||
|
return error.DlSym;
|
||||||
|
};
|
||||||
|
|
||||||
|
return @ptrCast(@alignCast(ptr));
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -1,9 +1,15 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const xcb = @import("xcb");
|
const xcb = @import("xcb");
|
||||||
|
|
||||||
pub fn main(init: std.process.Init) !void {
|
const Vulkan = @import("Vulkan.zig");
|
||||||
_ = init;
|
|
||||||
|
|
||||||
|
// Declarations picked up by "vulkan" module
|
||||||
|
|
||||||
|
pub const xcb_connection_t = xcb.Connection;
|
||||||
|
pub const xcb_visualid_t = xcb.Visualid;
|
||||||
|
pub const xcb_window_t = xcb.Window;
|
||||||
|
|
||||||
|
pub fn main(init: std.process.Init) !void {
|
||||||
const connection = xcb.Connection.connect(null, null);
|
const connection = xcb.Connection.connect(null, null);
|
||||||
defer connection.disconnect();
|
defer connection.disconnect();
|
||||||
|
|
||||||
@@ -64,6 +70,9 @@ pub fn main(init: std.process.Init) !void {
|
|||||||
_ = connection.mapWindow(window);
|
_ = connection.mapWindow(window);
|
||||||
_ = connection.flush();
|
_ = connection.flush();
|
||||||
|
|
||||||
|
var vulkan = try Vulkan.init(init.gpa, connection, window);
|
||||||
|
defer vulkan.deinit(init.gpa);
|
||||||
|
|
||||||
var running = true;
|
var running = true;
|
||||||
while (running) {
|
while (running) {
|
||||||
if (connection.waitForEvent()) |event| {
|
if (connection.waitForEvent()) |event| {
|
||||||
|
|||||||
35719
packages/xcb/vendor/vk.xml
vendored
Normal file
35719
packages/xcb/vendor/vk.xml
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user