start writing vulkan api with pim as reference (thanks Kara!)
This commit is contained in:
parent
d67688a5a3
commit
49226a528f
|
@ -0,0 +1,172 @@
|
|||
const std = @import("std");
|
||||
const vk = @import("vulkan");
|
||||
const glfw = @import("glfw");
|
||||
|
||||
const settings = @import("settings");
|
||||
|
||||
const DebugMessenger = @import("debug.zig").DebugMessenger;
|
||||
|
||||
// TODO temp allocator
|
||||
const allocator = std.heap.GeneralPurposeAllocator;
|
||||
|
||||
const Layers = struct {
|
||||
pub const enabled = [_][*:0]u8{
|
||||
if (settings.khronos_layer_on) "KHRONOS_validation" else void,
|
||||
if (settings.assist_layer_on) "LUNARG_assistant_layer" else void,
|
||||
};
|
||||
};
|
||||
|
||||
const Extensions = struct {
|
||||
const dev_standard = [_][*:0]u8{
|
||||
"KHR_swapchain",
|
||||
"EXT_memory_budget",
|
||||
"EXT_hdr_metadata",
|
||||
"KHR_shader_float16_int8",
|
||||
"KHR_16bit_storage",
|
||||
"KHR_push_descriptor",
|
||||
"EXT_memory_priority",
|
||||
"KHR_bind_memory2",
|
||||
"KHR_shader_float_controls",
|
||||
"KHR_spirv_1_4",
|
||||
"EXT_conditional_rendering",
|
||||
"KHR_draw_indirect_count",
|
||||
};
|
||||
|
||||
const dev_rt = if (settings.rt_on) [_][*:0]u8{
|
||||
"KHR_acceleration_structure",
|
||||
"KHR_ray_tracing_pipeline",
|
||||
"KHR_ray_query",
|
||||
"KHR_deferred_host_operations",
|
||||
} else {};
|
||||
|
||||
pub const dev = dev_standard ++ dev_rt;
|
||||
|
||||
pub const inst = [_][*:0]u8{
|
||||
"KHR_get_physical_device_properties2",
|
||||
"EXT_swapchain_colorspace",
|
||||
if (settings.messenger_on) "EXT_debug_utils" else void,
|
||||
};
|
||||
};
|
||||
|
||||
pub const Instance = struct {
|
||||
const Self = @This();
|
||||
|
||||
vkInst: vk.Instance,
|
||||
messenger: DebugMessenger,
|
||||
|
||||
layers: [][*:0]const u8,
|
||||
extensions: [][*:0]const u8,
|
||||
|
||||
pub fn init(self: Self) !void {
|
||||
// TODO: do we absolutely need volk rn? Don't think so? volk init here
|
||||
|
||||
const avail_layers = try getAvailableLayers();
|
||||
defer avail_layers.deinit();
|
||||
const avail_exts = try getAvailableExtensions();
|
||||
defer avail_exts.deinit();
|
||||
|
||||
self.layers = try getLayers(&avail_layers);
|
||||
self.extensions = try getExtensions(&avail_exts);
|
||||
|
||||
const app_info = vk.ApplicationInfo{
|
||||
.p_application_name = settings.app_name,
|
||||
.application_version = vk.makeApiVersion(1, 0, 0, 0),
|
||||
.p_engine_name = settings.engine_name,
|
||||
.engine_version = vk.makeApiVersion(1, 0, 0, 0),
|
||||
.api_version = vk.API_VERSION_1_2,
|
||||
};
|
||||
|
||||
self.vkInst = try self.vkb.createInstance(&.{
|
||||
.flags = .{},
|
||||
.p_application_info = &app_info,
|
||||
.enabled_layer_count = @intCast(u32, self.layers.len),
|
||||
.pp_enabled_layer_names = self.layers.ptr,
|
||||
.enabled_extension_count = @intCast(u32, self.extensions.len),
|
||||
.pp_enabled_extension_names = self.extensions.ptr,
|
||||
}, null);
|
||||
|
||||
self.messenger = DebugMessenger.init();
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn deinit(self: Self) void {
|
||||
self.vki.destroyInstance(self.vkInst, null);
|
||||
|
||||
// TODO: remove when using temp allocator
|
||||
self.layers.deinit();
|
||||
self.extensions.deinit();
|
||||
}
|
||||
|
||||
/// list all available layers
|
||||
fn getAvailableLayers(self: Self) !std.StringArrayHashMap {
|
||||
var count: u32 = undefined;
|
||||
_ = try self.vki.enumerateInstanceLayerProperties(&count, null);
|
||||
const list = try allocator.alloc(self.vki.LayerProperties, count);
|
||||
defer allocator.free(list);
|
||||
_ = try self.vki.enumerateInstanceLayerProperties(&count, list.ptr);
|
||||
|
||||
const hashMap = std.StringArrayHashMap(void).init(allocator);
|
||||
try hashMap.ensureTotalCapacity(count);
|
||||
|
||||
// TODO log
|
||||
std.debug.print("{} available instance layers", .{count});
|
||||
for (list) |layer| {
|
||||
std.debug.print("{s}", layer.layer_name);
|
||||
hashMap.putAssumeCapacity(layer);
|
||||
}
|
||||
|
||||
return hashMap;
|
||||
}
|
||||
|
||||
fn getLayers(avail_layers: *std.StringArrayHashMap) !std.ArrayList([*:0]const u8) {
|
||||
const list = try std.ArrayList([*:0]const u8).init(allocator);
|
||||
|
||||
for (Layers.enabled) |ext| {
|
||||
if (avail_layers.contains(ext)) {
|
||||
list.append(ext);
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/// list all available extensions
|
||||
fn getAvailableExtensions(self: Self) !std.StringArrayHashMap {
|
||||
var count: u32 = undefined;
|
||||
_ = try self.vki.enumerateInstanceExtensionProperties(&count, null);
|
||||
const list = try allocator.alloc(self.vki.ExtensionProperties, count);
|
||||
defer allocator.free(list);
|
||||
_ = try self.vki.enumerateInstanceExtensionProperties(&count, list.ptr);
|
||||
|
||||
const hashMap = std.StringArrayHashMap(void).init(allocator);
|
||||
try hashMap.ensureTotalCapacity(count);
|
||||
|
||||
// TODO log
|
||||
std.debug.print("{} available instance extensions", count);
|
||||
for (list) |ext| {
|
||||
std.debug.print("{s}", ext.extension_name);
|
||||
hashMap.putAssumeCapacity(ext);
|
||||
}
|
||||
|
||||
return hashMap;
|
||||
}
|
||||
|
||||
fn getExtensions(avail_exts: *std.StringArrayHashMap) !std.ArrayList([][*:0]const u8) {
|
||||
const list = try std.ArrayList([*:0]const u8).init(allocator);
|
||||
|
||||
for (try glfw.getRequiredInstanceExtensions()) |ext| {
|
||||
if (avail_exts.contains(ext)) {
|
||||
list.append(ext);
|
||||
}
|
||||
}
|
||||
|
||||
for (Extensions.inst) |ext| {
|
||||
if (avail_exts.contains(ext)) {
|
||||
list.append(ext);
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
};
|
|
@ -0,0 +1,165 @@
|
|||
const std = @import("std");
|
||||
|
||||
const Instance = @import("instance.zig").Instance;
|
||||
const Window = @import("window.zig").Window;
|
||||
const Device = @import("device.zig").Device;
|
||||
const Memory = @import("memory.zig").Memory;
|
||||
const Framebuffer = @import("framebuffer.zig").Framebuffer;
|
||||
const Swapchain = @import("swapchain.zig").Swapchain;
|
||||
const Context = @import("context.zig").Context;
|
||||
const MainPass = @import("main_pass.zig").MainPass;
|
||||
const Display = @import("display.zig").Display;
|
||||
const Command = @import("command.zig").Command;
|
||||
|
||||
var g_renderer: VulkanRenderer = undefined;
|
||||
|
||||
pub const VulkanRenderer = struct {
|
||||
instance: Instance,
|
||||
window: Window,
|
||||
device: Device,
|
||||
memory: Memory,
|
||||
framebuffer: Framebuffer,
|
||||
swapchain: Swapchain,
|
||||
context: Context,
|
||||
// sampler: Sampler, TODO
|
||||
// texTable: TexTable, TODO
|
||||
// bindings: Bindings, TODO
|
||||
// targets: Targets, TODO
|
||||
// meshSys: MeshSys, TODO
|
||||
// imSys: ImSys, TODO
|
||||
mainPass: MainPass,
|
||||
|
||||
const Self = @This();
|
||||
|
||||
pub fn init() !Self {
|
||||
const self = Self{};
|
||||
|
||||
errdefer std.debug.print("failed to init VulkanRenderer", .{});
|
||||
errdefer self.deinit();
|
||||
|
||||
try self.instance.init();
|
||||
try windowInit(&self.window);
|
||||
try self.device.init();
|
||||
try self.memory.init();
|
||||
try self.framebuffer.init();
|
||||
try self.swapchain.init(null);
|
||||
try self.context.init();
|
||||
// try self.sampler.init();
|
||||
// try self.texTable.init();
|
||||
// try self.bindings.init();
|
||||
// try self.targets.init();
|
||||
// try self.meshSys.init();
|
||||
// try self.imSys.init();
|
||||
try self.mainPass.init();
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn update(self: Self) bool {
|
||||
// TODO profiling
|
||||
|
||||
// base system update
|
||||
{
|
||||
self.swapchain.acquireSync();
|
||||
self.swapchain.acquireImage();
|
||||
self.memory.update();
|
||||
}
|
||||
|
||||
// system update
|
||||
{
|
||||
// TODO: sampler/meshsys/imsys update
|
||||
}
|
||||
|
||||
// setup phase
|
||||
{
|
||||
self.mainPass.setup();
|
||||
// TODO textable update
|
||||
Command.flush();
|
||||
// TODO bindings update
|
||||
}
|
||||
|
||||
// execute phase
|
||||
self.mainPass.execute();
|
||||
|
||||
// present phase
|
||||
self.swapchain.submit(Command.get());
|
||||
|
||||
// background work
|
||||
{
|
||||
// TODO upload lightmaps, imsys clear
|
||||
Command.flush();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn deinit(self: Self) void {
|
||||
self.device.waitIdle();
|
||||
|
||||
// TODO: delete lightmap pack
|
||||
|
||||
self.mainPass.deinit();
|
||||
|
||||
// self.imSys.deinit();
|
||||
// self.meshSys.deinit();
|
||||
// self.targets.deinit();
|
||||
// self.bindings.deinit();
|
||||
// self.texTable.deinit();
|
||||
// self.sampler.deinit();
|
||||
// clear other passes here.
|
||||
|
||||
self.memory.finalize();
|
||||
|
||||
self.context.deinit();
|
||||
self.swapchain.deinit();
|
||||
self.framebuffer.deinit();
|
||||
self.window.deinit();
|
||||
self.memory.deinit();
|
||||
self.device.deinit();
|
||||
self.instance.deinit();
|
||||
}
|
||||
|
||||
fn windowInit(window: *Window) !void {
|
||||
// TODO: convar cv_fullscreen
|
||||
const fullscreen = false;
|
||||
|
||||
const extents = try Display.getSize(fullscreen);
|
||||
try window.init("efemra", extents, fullscreen);
|
||||
|
||||
// TODO: convar r_width/r_height set
|
||||
// TODO: UISys_Init
|
||||
}
|
||||
|
||||
fn windowDeinit(window: *Window) void {
|
||||
// TODO: uisys_shutdown
|
||||
// TODO: convar r_width/r_height unset
|
||||
window.deinit();
|
||||
}
|
||||
|
||||
fn windowUpdate(self: Self) !void {
|
||||
if (!self.window.isOpen()) {
|
||||
return error.WindowNotOpen;
|
||||
}
|
||||
// TODO: convar fullscreen change check
|
||||
if (0) {
|
||||
self.device.waitIdle();
|
||||
|
||||
// TODO: UI pass del
|
||||
self.swapchain.deinit();
|
||||
self.window.deinit();
|
||||
|
||||
self.window.init();
|
||||
self.swapchain.init(null);
|
||||
// TODO: UI pass new
|
||||
}
|
||||
|
||||
if (self.window.updateSize()) {
|
||||
try self.swapchain.recreate();
|
||||
// TODO set r_width/r_height convar
|
||||
}
|
||||
|
||||
if (!self.swapchain.handle) {
|
||||
return error.NoSwapchainHandle;
|
||||
}
|
||||
|
||||
self.targets.maybeRecreate();
|
||||
}
|
||||
};
|
Loading…
Reference in New Issue