impriving architecture
This commit is contained in:
96
.gdb_history
git.filemode.normal_file
96
.gdb_history
git.filemode.normal_file
@@ -0,0 +1,96 @@
|
||||
run
|
||||
bt
|
||||
q
|
||||
run
|
||||
bt
|
||||
q
|
||||
rim
|
||||
run
|
||||
bt
|
||||
q
|
||||
run
|
||||
bt
|
||||
q
|
||||
run
|
||||
bt
|
||||
run
|
||||
bt
|
||||
q
|
||||
c
|
||||
start
|
||||
n
|
||||
n
|
||||
n
|
||||
n
|
||||
s
|
||||
n
|
||||
n
|
||||
s
|
||||
n
|
||||
p vkDestroyInstance
|
||||
p vkDestroyInstance
|
||||
start
|
||||
n
|
||||
n
|
||||
n
|
||||
n
|
||||
s
|
||||
n
|
||||
s
|
||||
s
|
||||
start
|
||||
n
|
||||
n
|
||||
n
|
||||
s
|
||||
n
|
||||
s
|
||||
s
|
||||
q
|
||||
run
|
||||
q
|
||||
run
|
||||
bt
|
||||
p name
|
||||
c
|
||||
p name
|
||||
n
|
||||
bt
|
||||
q
|
||||
r
|
||||
bt
|
||||
c
|
||||
bt
|
||||
w
|
||||
y
|
||||
q
|
||||
run
|
||||
bt
|
||||
q
|
||||
run
|
||||
bt
|
||||
q
|
||||
q
|
||||
run
|
||||
bt
|
||||
q
|
||||
run
|
||||
bt
|
||||
q
|
||||
q
|
||||
q
|
||||
q
|
||||
run
|
||||
bt
|
||||
q
|
||||
q
|
||||
run
|
||||
bt
|
||||
q
|
||||
run
|
||||
bt
|
||||
q
|
||||
q
|
||||
run
|
||||
bt
|
||||
q
|
||||
@@ -21,6 +21,7 @@ pub fn build(b: *std.Build) void {
|
||||
.root_source_file = b.path("src/vulkan/lib.zig"),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.link_libc = true,
|
||||
});
|
||||
|
||||
const vulkan_headers = b.dependency("vulkan_headers", .{});
|
||||
@@ -36,6 +37,7 @@ pub fn build(b: *std.Build) void {
|
||||
const lib_mod = b.createModule(.{
|
||||
.root_source_file = b.path(impl.root_source_file),
|
||||
.target = target,
|
||||
.link_libc = true,
|
||||
.optimize = optimize,
|
||||
.imports = &.{
|
||||
.{ .name = "common", .module = common_mod },
|
||||
@@ -72,6 +74,8 @@ pub fn build(b: *std.Build) void {
|
||||
.flags = &.{b.fmt("-DLIBVK=\"{s}\"", .{lib.name})},
|
||||
});
|
||||
|
||||
b.installArtifact(c_test_exe);
|
||||
|
||||
const run_c_test = b.addRunArtifact(c_test_exe);
|
||||
const test_c_step = b.step(b.fmt("test-c-{s}", .{impl.name}), b.fmt("Run lib{s} C test", .{impl.name}));
|
||||
test_c_step.dependOn(b.getInstallStep());
|
||||
|
||||
48
src/soft/Instance.zig
git.filemode.normal_file
48
src/soft/Instance.zig
git.filemode.normal_file
@@ -0,0 +1,48 @@
|
||||
const std = @import("std");
|
||||
const vk = @import("vulkan");
|
||||
const common = @import("common");
|
||||
const PhysicalDevice = @import("PhysicalDevice.zig");
|
||||
|
||||
const dispatchable = common.dispatchable;
|
||||
|
||||
const Self = @This();
|
||||
pub const ObjectType: vk.ObjectType = .instance;
|
||||
|
||||
common_instance: common.Instance,
|
||||
physical_device: dispatchable.Dispatchable(PhysicalDevice), // Software driver only has one physical device (CPU)
|
||||
|
||||
pub fn create(p_infos: ?*const vk.InstanceCreateInfo, callbacks: ?*const vk.AllocationCallbacks, p_instance: *vk.Instance) callconv(vk.vulkan_call_conv) vk.Result {
|
||||
const allocator = std.heap.c_allocator;
|
||||
|
||||
const dispatchable_object = dispatchable.Dispatchable(Self).create(allocator, ObjectType) catch return .error_out_of_host_memory;
|
||||
common.Instance.init(&dispatchable_object.object.common_instance, p_infos, callbacks) catch return .error_initialization_failed;
|
||||
|
||||
dispatchable_object.object.common_instance.vtable = .{
|
||||
.destroyInstance = destroy,
|
||||
.enumeratePhysicalDevices = enumeratePhysicalDevices,
|
||||
.enumerateInstanceVersion = null,
|
||||
//.enumerateInstanceLayerProperties = null,
|
||||
.enumerateInstanceExtensionProperties = null,
|
||||
};
|
||||
|
||||
dispatchable_object.object.physical_device.init() catch return .error_initialization_failed;
|
||||
|
||||
p_instance.* = @enumFromInt(dispatchable.toHandle(Self, dispatchable_object));
|
||||
return .success;
|
||||
}
|
||||
|
||||
pub fn enumeratePhysicalDevices(p_instance: vk.Instance, count: *u32, devices: *vk.PhysicalDevice) callconv(vk.vulkan_call_conv) vk.Result {
|
||||
const dispatchable_object = common.dispatchable.fromHandle(Self, @intFromEnum(p_instance)) catch return .error_initialization_failed;
|
||||
_ = dispatchable_object;
|
||||
_ = count;
|
||||
_ = devices;
|
||||
return .success;
|
||||
}
|
||||
|
||||
pub fn destroy(p_instance: vk.Instance, callbacks: ?*const vk.AllocationCallbacks) callconv(vk.vulkan_call_conv) void {
|
||||
const allocator = std.heap.c_allocator;
|
||||
_ = callbacks;
|
||||
|
||||
const dispatchable_object = common.dispatchable.fromHandle(Self, @intFromEnum(p_instance)) catch return;
|
||||
dispatchable_object.destroy(allocator);
|
||||
}
|
||||
26
src/soft/PhysicalDevice.zig
git.filemode.normal_file
26
src/soft/PhysicalDevice.zig
git.filemode.normal_file
@@ -0,0 +1,26 @@
|
||||
const std = @import("std");
|
||||
const vk = @import("vulkan");
|
||||
const Instance = @import("Instance.zig");
|
||||
const common = @import("common");
|
||||
|
||||
const dispatchable = common.dispatchable;
|
||||
|
||||
const Self = @This();
|
||||
const ObjectType: vk.ObjectType = .physical_device;
|
||||
|
||||
instance: *const Instance,
|
||||
common_physical_device: common.PhysicalDevice,
|
||||
|
||||
pub fn init(self: *Self) !void {
|
||||
self.common_physical_device.props = .{
|
||||
.apiVersion = ,
|
||||
.driverVersion = VKD_DRIVER_VERSION,
|
||||
.vendorID = 0x0601,
|
||||
.deviceID = 0x060103,
|
||||
.deviceType = VK_PHYSICAL_DEVICE_TYPE_CPU,
|
||||
.deviceName = {},
|
||||
.pipelineCacheUUID = {},
|
||||
.limits = {},
|
||||
.sparseProperties = {},
|
||||
};
|
||||
}
|
||||
@@ -2,6 +2,17 @@ const std = @import("std");
|
||||
const vk = @import("vulkan");
|
||||
const common = @import("common");
|
||||
|
||||
export fn libVulkanExport() void {
|
||||
_ = common;
|
||||
const Instance = @import("Instance.zig");
|
||||
|
||||
const global_pfn_map = std.StaticStringMap(vk.PfnVoidFunction).initComptime(.{
|
||||
.{ "vkGetInstanceProcAddr", @as(vk.PfnVoidFunction, @ptrCast(&common.icd.getInstanceProcAddr)) },
|
||||
.{ "vkCreateInstance", @as(vk.PfnVoidFunction, @ptrCast(&Instance.create)) },
|
||||
});
|
||||
|
||||
pub export fn vkGetInstanceProcAddr(p_instance: vk.Instance, pName: ?[*:0]const u8) callconv(vk.vulkan_call_conv) vk.PfnVoidFunction {
|
||||
if (pName == null) {
|
||||
return null;
|
||||
}
|
||||
const name = std.mem.span(pName.?);
|
||||
return common.icd.getInstanceProcAddr(global_pfn_map, p_instance, name);
|
||||
}
|
||||
|
||||
@@ -1,24 +1,52 @@
|
||||
const std = @import("std");
|
||||
const vk = @import("vulkan");
|
||||
const PhysicalDevice = @import("PhysicalDevice.zig").PhysicalDevice;
|
||||
const Object = @import("object.zig").Object;
|
||||
const dispatchable = @import("dispatchable.zig");
|
||||
|
||||
pub const Instance = extern struct {
|
||||
const Self = @This();
|
||||
pub const ObjectType: vk.ObjectType = .instance;
|
||||
pub const vtable: VTable = .{};
|
||||
|
||||
object: Object,
|
||||
//physical_devices: std.ArrayList(*PhysicalDevice),
|
||||
alloc_callbacks: vk.AllocationCallbacks,
|
||||
|
||||
vtable: VTable,
|
||||
|
||||
pub fn init(self: *Self, p_infos: ?*const vk.InstanceCreateInfo, callbacks: ?*const vk.AllocationCallbacks) !void {
|
||||
const infos = p_infos orelse return error.NullCreateInfos;
|
||||
if (infos.s_type != .instance_create_info) {
|
||||
return error.InvalidCreateInfos;
|
||||
}
|
||||
|
||||
self.vtable = .{
|
||||
.destroyInstance = null,
|
||||
.enumeratePhysicalDevices = null,
|
||||
.enumerateInstanceVersion = null,
|
||||
//.enumerateInstanceLayerProperties = null,
|
||||
.enumerateInstanceExtensionProperties = null,
|
||||
};
|
||||
|
||||
if (callbacks) |c| {
|
||||
self.alloc_callbacks = c.*;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getProcAddr(self: *const Self, name: []const u8) vk.PfnVoidFunction {
|
||||
const allocator = std.heap.c_allocator;
|
||||
|
||||
const KV = struct { []const u8, vk.PfnVoidFunction };
|
||||
const pfn_map = std.StaticStringMap(vk.PfnVoidFunction).init([_]KV{
|
||||
.{ "vkDestroyInstance", @ptrCast(self.vtable.destroyInstance) },
|
||||
.{ "vkEnumeratePhysicalDevices", @ptrCast(self.vtable.enumeratePhysicalDevices) },
|
||||
.{ "vkEnumerateInstanceVersion", @ptrCast(self.vtable.enumerateInstanceVersion) },
|
||||
.{ "vkEnumerateInstanceExtensionProperties", @ptrCast(self.vtable.enumerateInstanceExtensionProperties) },
|
||||
}, allocator) catch return null;
|
||||
defer pfn_map.deinit(allocator);
|
||||
|
||||
return if (pfn_map.get(name)) |pfn| pfn else null;
|
||||
}
|
||||
|
||||
pub const VTable = struct {
|
||||
createInstance: ?vk.PfnCreateInstance = null,
|
||||
destroyInstance: ?vk.PfnDestroyInstance = null,
|
||||
enumeratePhysicalDevices: ?vk.PfnEnumeratePhysicalDevices = null,
|
||||
getInstanceProcAddr: ?vk.PfnGetInstanceProcAddr = null,
|
||||
enumerateInstanceVersion: ?vk.PfnEnumerateInstanceVersion = null,
|
||||
//enumerateInstanceLayerProperties: vk.PfnEnumerateInstanceProperties = null,
|
||||
enumerateInstanceExtensionProperties: ?vk.PfnEnumerateInstanceExtensionProperties = null,
|
||||
};
|
||||
destroyInstance: ?vk.PfnDestroyInstance,
|
||||
enumeratePhysicalDevices: ?vk.PfnEnumeratePhysicalDevices,
|
||||
enumerateInstanceVersion: ?vk.PfnEnumerateInstanceVersion,
|
||||
//enumerateInstanceLayerProperties: vk.PfnEnumerateInstanceProperties,
|
||||
enumerateInstanceExtensionProperties: ?vk.PfnEnumerateInstanceExtensionProperties,
|
||||
};
|
||||
|
||||
@@ -1,14 +1,8 @@
|
||||
const vk = @import("vulkan");
|
||||
const Instance = @import("Instance.zig").Instance;
|
||||
const Object = @import("object.zig").Object;
|
||||
const Instance = @import("Instance.zig");
|
||||
|
||||
pub const PhysicalDevice = extern struct {
|
||||
const Self = @This();
|
||||
const ObjectType: vk.ObjectType = .physical_device;
|
||||
|
||||
object: Object,
|
||||
|
||||
instance: *Instance,
|
||||
props: vk.PhysicalDeviceProperties,
|
||||
queue_families: [3]vk.QueueFamilyProperties,
|
||||
};
|
||||
|
||||
45
src/vulkan/dispatchable.zig
git.filemode.normal_file
45
src/vulkan/dispatchable.zig
git.filemode.normal_file
@@ -0,0 +1,45 @@
|
||||
const std = @import("std");
|
||||
const vk = @import("vulkan");
|
||||
const c = @cImport({
|
||||
@cInclude("vulkan/vk_icd.h");
|
||||
});
|
||||
|
||||
pub fn Dispatchable(comptime T: type) type {
|
||||
return extern struct {
|
||||
const Self = @This();
|
||||
|
||||
loader_data: c.VK_LOADER_DATA,
|
||||
object_type: vk.ObjectType,
|
||||
object: *T,
|
||||
|
||||
pub fn create(allocator: std.mem.Allocator, object_type: vk.ObjectType) !*Self {
|
||||
const object = try allocator.create(Self);
|
||||
object.* = .{
|
||||
.loader_data = .{ .loaderMagic = c.ICD_LOADER_MAGIC },
|
||||
.object_type = object_type,
|
||||
.object = try allocator.create(T),
|
||||
};
|
||||
return object;
|
||||
}
|
||||
|
||||
pub fn destroy(self: *Self, allocator: std.mem.Allocator) void {
|
||||
allocator.destroy(self.object);
|
||||
allocator.destroy(self);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub inline fn fromHandle(comptime T: type, handle: usize) !*Dispatchable(T) {
|
||||
if (handle == 0) {
|
||||
return error.NullHandle;
|
||||
}
|
||||
const dispatchable: *Dispatchable(T) = @ptrFromInt(handle);
|
||||
if (dispatchable.object_type != T.ObjectType) {
|
||||
return error.InvalidType;
|
||||
}
|
||||
return dispatchable;
|
||||
}
|
||||
|
||||
pub inline fn toHandle(comptime T: type, handle: *Dispatchable(T)) usize {
|
||||
return @intFromPtr(handle);
|
||||
}
|
||||
@@ -4,18 +4,25 @@ const c = @cImport({
|
||||
@cInclude("vulkan/vk_icd.h");
|
||||
});
|
||||
|
||||
const Instance = @import("Instance.zig").Instance;
|
||||
const fromHandle = @import("object.zig").fromHandle;
|
||||
const Instance = @import("Instance.zig");
|
||||
const dispatchable = @import("dispatchable.zig");
|
||||
|
||||
const global_pfn_map = std.StaticStringMap(vk.PfnVoidFunction).initComptime(.{
|
||||
.{ "vkGetInstanceProcAddr", @as(vk.PfnVoidFunction, @ptrCast(&getInstanceProcAddr)) },
|
||||
.{ "vkCreateInstance", @as(vk.PfnVoidFunction, @ptrCast(&Instance.vtable.createInstance)) },
|
||||
});
|
||||
pub fn getInstanceProcAddr(global_pfn_map: std.StaticStringMap(vk.PfnVoidFunction), p_instance: vk.Instance, name: []const u8) vk.PfnVoidFunction {
|
||||
const allocator = std.heap.c_allocator;
|
||||
const get_proc_log = std.log.scoped(.vkGetInstanceProcAddr);
|
||||
|
||||
if (std.process.hasEnvVar(allocator, "DRIVER_LOGS") catch false) {
|
||||
get_proc_log.info("Loading {s}...", .{name});
|
||||
}
|
||||
|
||||
pub fn getInstanceProcAddr(instance: vk.Instance, name: []const u8) vk.PfnVoidFunction {
|
||||
if (global_pfn_map.get(name)) |pfn| {
|
||||
return pfn;
|
||||
}
|
||||
if (instance != .null_handle) {}
|
||||
return null;
|
||||
const instance = dispatchable.fromHandle(Instance, @intFromEnum(p_instance)) catch |e| {
|
||||
if (std.process.hasEnvVar(allocator, "DRIVER_LOGS") catch false) {
|
||||
get_proc_log.err("{any}", .{e});
|
||||
}
|
||||
return null;
|
||||
};
|
||||
return instance.object.getProcAddr(name);
|
||||
}
|
||||
|
||||
@@ -2,15 +2,23 @@ const std = @import("std");
|
||||
const vk = @import("vulkan");
|
||||
|
||||
pub const icd = @import("icd.zig");
|
||||
pub const dispatchable = @import("dispatchable.zig");
|
||||
|
||||
pub const Instance = @import("Instance.zig");
|
||||
pub const PhysicalDevice = @import("PhysicalDevice.zig");
|
||||
|
||||
pub export fn vkGetInstanceProcAddr(instance: vk.Instance, pName: ?[*:0]const u8) callconv(vk.vulkan_call_conv) vk.PfnVoidFunction {
|
||||
if (pName == null) {
|
||||
return null;
|
||||
}
|
||||
const name = std.mem.span(pName.?);
|
||||
return icd.getInstanceProcAddr(instance, name);
|
||||
pub const std_options: std.Options = .{
|
||||
.log_level = .info,
|
||||
.logFn = logFn,
|
||||
};
|
||||
|
||||
pub fn logFn(comptime level: std.log.Level, comptime scope: @Type(.enum_literal), comptime format: []const u8, args: anytype) void {
|
||||
_ = level;
|
||||
_ = scope;
|
||||
std.debug.lockStdErr();
|
||||
defer std.debug.unlockStdErr();
|
||||
const stderr = std.fs.File.stderr().deprecatedWriter();
|
||||
nosuspend stderr.print(format ++ "\n", args) catch return;
|
||||
}
|
||||
|
||||
test {
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
const vk = @import("vulkan");
|
||||
const c = @cImport({
|
||||
@cInclude("vulkan/vk_icd.h");
|
||||
});
|
||||
|
||||
pub const Object = extern struct {
|
||||
const Self = @This();
|
||||
|
||||
loader_data: c.VK_LOADER_DATA,
|
||||
kind: vk.ObjectType,
|
||||
owner: ?*anyopaque,
|
||||
// VK_EXT_debug_utils
|
||||
name: ?[*]const u8,
|
||||
|
||||
pub fn init(owner: ?*anyopaque, kind: vk.ObjectType) Self {
|
||||
return .{
|
||||
.loader_data = c.ICD_LOADER_MAGIC,
|
||||
.kind = kind,
|
||||
.owner = owner,
|
||||
.name = null,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
pub inline fn fromHandle(comptime T: type, comptime VkT: type, handle: VkT) !*T {
|
||||
comptime {
|
||||
if (!@hasField(T, "object") or !@hasDecl(T, "ObjectType") or @TypeOf(T.ObjectType) != vk.ObjectType) {
|
||||
@compileError("Object type \"" ++ @typeName(T) ++ "\" is malformed.");
|
||||
}
|
||||
}
|
||||
|
||||
if (handle == .null_handle) {
|
||||
return error.NullHandle;
|
||||
}
|
||||
|
||||
const dispatchable: *T = @ptrFromInt(@intFromEnum(handle));
|
||||
if (dispatchable.object.kind != T.ObjectType) {
|
||||
return error.InvalidObjectType;
|
||||
}
|
||||
return dispatchable;
|
||||
}
|
||||
|
||||
pub inline fn toHandle(comptime T: type, handle: *T) usize {
|
||||
comptime {
|
||||
if (!@hasDecl(T, "object") or !@hasDecl(T, "ObjectType") or @TypeOf(T.ObjectType) != vk.ObjectType) {
|
||||
@compileError("Object type \"" ++ @typeName(T) ++ "\" is malformed.");
|
||||
}
|
||||
}
|
||||
return @intFromPtr(handle);
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#define VK_NO_PROTOTYPES
|
||||
#include <vulkan/vulkan.h>
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
@@ -10,15 +10,38 @@
|
||||
#define LIBVK "vulkan"
|
||||
#endif
|
||||
|
||||
#define CheckVk(x) \
|
||||
do { \
|
||||
if((x) != VK_SUCCESS) \
|
||||
{ \
|
||||
fprintf(stderr, "Vulkan call failed\n"); \
|
||||
abort(); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
int main(void)
|
||||
{
|
||||
printf("openning ./zig-out/lib/lib" LIBVK ".so\n");
|
||||
puts("openning ./zig-out/lib/lib" LIBVK ".so");
|
||||
void* lib = dlopen("./zig-out/lib/lib" LIBVK ".so", RTLD_NOW | RTLD_LOCAL);
|
||||
|
||||
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = dlsym(lib, "vkGetInstanceProcAddr");
|
||||
|
||||
printf("test %p\n", vkGetInstanceProcAddr);
|
||||
printf("test %p\n", vkGetInstanceProcAddr(NULL, "vkCreateInstance"));
|
||||
#define VULKAN_GLOBAL_FUNCTION(fn) PFN_##fn fn = (PFN_##fn)vkGetInstanceProcAddr(NULL, #fn);
|
||||
VULKAN_GLOBAL_FUNCTION(vkCreateInstance)
|
||||
|
||||
VkInstanceCreateInfo instance_create_info = { 0 };
|
||||
instance_create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
||||
|
||||
VkInstance instance = VK_NULL_HANDLE;
|
||||
CheckVk(vkCreateInstance(&instance_create_info, NULL, &instance));
|
||||
|
||||
printf("VkInstance %p\n", instance);
|
||||
|
||||
#define VULKAN_INSTANCE_FUNCTION(fn) PFN_##fn fn = (PFN_##fn)vkGetInstanceProcAddr(instance, #fn);
|
||||
VULKAN_INSTANCE_FUNCTION(vkEnumeratePhysicalDevices)
|
||||
VULKAN_INSTANCE_FUNCTION(vkDestroyInstance)
|
||||
|
||||
vkDestroyInstance(instance, NULL);
|
||||
|
||||
dlclose(lib);
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user