forked from vv/efemra
1
0
Fork 0

we got to the render loop, huzzah.

This commit is contained in:
Vivianne 2022-07-15 23:07:31 -07:00
parent 86f754b32b
commit 200e91c1f0
13 changed files with 115 additions and 113 deletions

View File

@ -86,11 +86,17 @@ pub fn build(b: *std.build.Builder) void {
const exe = b.addExecutable("efemra", "src/main.zig");
exe.setTarget(target);
exe.setBuildMode(mode);
exe.install();
const gen = vkgen.VkGenerateStep.init(b, "etc/vk.xml", "vk.zig");
exe.addPackage(pkgs.glfw);
exe.addPackage(gen.package);
exe.addPackage(pkgs.glfw);
build_glfw.link(b, exe, .{});
build_vma.link(exe, gen.output_file.getPath(), mode, target);
build_imgui.link(exe);
const res = ResourceGenStep.init(b, "resources.zig");
res.addShader("test_frag", "src/shaders/test.frag");
@ -98,11 +104,6 @@ pub fn build(b: *std.build.Builder) void {
res.addShader("triangle_frag", "src/shaders/triangle.frag");
exe.addPackage(res.package);
build_vma.link(exe, gen.output_file.getPath(), mode, target);
build_imgui.link(exe);
exe.install();
const run_cmd = exe.run();
run_cmd.step.dependOn(b.getInstallStep());
if (b.args) |args| {

View File

@ -13,16 +13,6 @@ pub fn main() !void {
try glfw.init(.{});
defer glfw.terminate();
var extent = vk.Extent2D{ .width = 1280, .height = 720 };
var window = try glfw.Window.create(extent.width, extent.height, app_name, null, null, .{ .client_api = .no_api });
defer window.destroy();
// temp allocator
//var gpa = std.heap.GeneralPurposeAllocator(.{}){};
//defer _ = gpa.deinit();
//const allocator = gpa.allocator();
var renderer = try Renderer.init();
defer renderer.deinit();
@ -30,8 +20,7 @@ pub fn main() !void {
defer renderer.deinit();
while (!window.shouldClose()) {
std.debug.print("hi", .{});
while (!renderer.window.handle.shouldClose()) {
try renderer.update();
try glfw.pollEvents();
}

View File

@ -51,8 +51,6 @@ pub fn init(device: *const Device, queue: *queues.Queue, id: queues.QueueId) !vo
pm_init.begin();
defer pm_init.end();
assert(queue == queues.get(id));
queue.index = id;
queue.cmd_pool = try Pool.init(device, queue.family, .{ .reset_command_buffer_bit = true });
errdefer queue.cmd_pool.deinit(device);

View File

@ -25,9 +25,27 @@ pub const Device = struct {
return getExtensions(@This(), props);
}
pub fn toArray(allocator: std.mem.Allocator) [][*:0]const u8 {
pub fn toArray(allocator: std.mem.Allocator) ![][*:0]const u8 {
return extToArray(@This(), allocator);
}
pub fn enabledToArray(self: *Device, allocator: std.mem.Allocator) ![][*:0]const u8 {
const arr = try allocator.alloc([*:0]const u8, @typeInfo(Device).Struct.fields.len);
var i: u32 = 0;
inline for (@typeInfo(Device).Struct.fields) |field| {
if (field.field_type == void) {
continue;
}
if (@field(self, field.name)) {
const name_info = @field(vk.extension_info, field.name);
arr[i] = name_info.name;
i += 1;
}
}
return arr[0..i];
}
};
pub const Instance = struct {
@ -39,7 +57,7 @@ pub const Instance = struct {
return getExtensions(@This(), props);
}
pub fn toArray(allocator: std.mem.Allocator) [][*:0]const u8 {
pub fn toArray(allocator: std.mem.Allocator) ![][*:0]const u8 {
return extToArray(@This(), allocator);
}
};
@ -62,8 +80,8 @@ fn getExtensions(comptime T: type, props: []vk.ExtensionProperties) T {
return ext;
}
pub fn extToArray(comptime T: type, allocator: std.mem.Allocator) [][*:0]const u8 {
const arr = allocator.alloc([*:0]const u8, @typeInfo(T).Struct.fields.len) catch unreachable;
pub fn extToArray(comptime T: type, allocator: std.mem.Allocator) ![][*:0]const u8 {
const arr = try allocator.alloc([*:0]const u8, @typeInfo(T).Struct.fields.len);
comptime for (@typeInfo(T).Struct.fields) |field, i| {
const name_info = @field(vk.extension_info, field.name);
arr[i] = name_info.name;

View File

@ -29,7 +29,7 @@ const Self = @This();
pub fn init() !Self {
errdefer {
std.debug.print("failed to init VulkanRenderer", .{});
std.debug.print("failed to init VulkanRenderer\n", .{});
}
try Base.init();

View File

@ -18,6 +18,7 @@ const std = @import("std");
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator();
// TODO: filter by settings!
const DeviceDispatch = vk.DeviceWrapper(.{
.destroyDevice = true,
.getDeviceQueue = true,
@ -178,6 +179,11 @@ pub const Device = struct {
defer allocator.free(feats_list);
for (feats_list) |*feat, i| {
feat.* = .{
.phdev = .{
.features = .{},
},
};
feat.phdev.s_type = .physical_device_features_2;
if (settings.rt_on) {
feat.phdev.p_next = &feat.accstr;
@ -267,11 +273,11 @@ pub const Device = struct {
self.feats = feats_list[chosen];
self.exts = exts_list[chosen];
self.physical_device = pdevs[chosen];
} else unreachable;
} else return error.NoDeviceChosen;
}
fn hasRequired(exts: *Extensions.Device) bool {
var has_all = false;
var has_all = true;
has_all = has_all and exts.khr_swapchain;
return has_all;
}
@ -441,6 +447,7 @@ pub const Device = struct {
defer queue_support.deinit();
var families = std.AutoArrayHashMap(u32, i32).init(allocator);
try families.ensureTotalCapacity(queue_support.families.len);
defer families.deinit();
for (queue_support.families) |f| {
if (f) |family| {
@ -520,10 +527,10 @@ pub const Device = struct {
self.props.rtpipe.p_next = &self.props.rquery;
}
const ext_arr = Extensions.Device.toArray(allocator);
const ext_arr = try self.exts.enabledToArray(allocator);
defer allocator.free(ext_arr);
_ = try instance.dispatch.createDevice(self.physical_device, &.{
self.handle = try instance.dispatch.createDevice(self.physical_device, &.{
.flags = .{},
.p_next = &self.props.phdev,
.queue_create_info_count = @intCast(u32, families.count()),
@ -535,22 +542,4 @@ pub const Device = struct {
.pp_enabled_extension_names = ext_arr.ptr,
}, null);
}
fn getExtensions(avail_exts: *std.StringArrayHashMap) !std.ArrayList([][*:0]const u8) {
const list = try std.ArrayList([*:0]const u8).init(allocator);
for (try glfw.getRequiredDeviceExtensions()) |ext| {
if (avail_exts.contains(ext)) {
list.append(ext);
}
}
for (Extensions.dev) |ext| {
if (avail_exts.contains(ext)) {
list.append(ext);
}
}
return list;
}
};

View File

@ -10,8 +10,6 @@ const allocator = gpa.allocator();
pub const Display = struct {
pub fn getWorkSize() !glfw.Window.Size {
try glfw.init(.{});
const monitor = try glfw.Monitor.getPrimary() orelse error.NoPrimaryMonitor;
const work_area = try monitor.getWorkarea();
@ -26,8 +24,6 @@ pub const Display = struct {
}
pub fn getFullSize() !glfw.Window.Size {
try glfw.init(.{});
const monitor = try glfw.Monitor.getPrimary() orelse error.NoPrimaryMonitor;
const modes = try monitor.getVideoModes(allocator);
defer allocator.free(modes);
@ -69,7 +65,6 @@ pub const Window = struct {
surface: vk.SurfaceKHR,
pub fn init(instance: *const Instance, title: [*:0]const u8, width: u32, height: u32, fullscreen: bool) !Self {
try glfw.init(.{});
const handle = try glfw.Window.create(width, height, title, try glfw.Monitor.getPrimary() orelse error.NoPrimaryMonitor, null, .{
.client_api = .no_api,
.srgb_capable = true,

View File

@ -43,7 +43,7 @@ pub const Image = struct {
}
/// import vk.Image handle into an existing Image object.
pub fn import(self: *Image, device: *const Device, info: *const vk.ImageCreateInfo, handle: vk.Image) !void {
pub fn import(self: *Image, device: *const Device, info: vk.ImageCreateInfo, handle: vk.Image) !void {
self.handle = handle;
self.image_type = info.image_type;
self.format = info.format;
@ -56,7 +56,7 @@ pub const Image = struct {
self.array_layers = @intCast(u8, info.array_layers);
self.imported = true;
var view_info = try infoToViewInfo(info);
var view_info = try infoToViewInfo(&info);
view_info.image = self.handle;
self.view = try device.dispatch.createImageView(device.handle, &view_info, null);
@ -148,8 +148,8 @@ pub fn infoToViewInfo(info: *const vk.ImageCreateInfo) !vk.ImageViewCreateInfo {
.flags = .{},
.format = info.format,
.view_type = infoToViewType(info),
.image = undefined,
.components = undefined,
.image = .null_handle,
.components = .{ .r = .identity, .g = .identity, .b = .identity, .a = .identity },
.subresource_range = .{
.aspect_mask = infoToAspects(info),
.base_mip_level = 0,

View File

@ -13,13 +13,14 @@ const DebugMessenger = @import("DebugMessenger.zig");
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator();
// TODO: filter by settings!
const InstanceDispatch = vk.InstanceWrapper(.{
.destroyInstance = true,
.createDevice = true,
.destroySurfaceKHR = true,
.enumeratePhysicalDevices = true,
.createDebugUtilsMessengerEXT = true,
.destroyDebugUtilsMessengerEXT = true,
.createDebugUtilsMessengerEXT = settings.messenger_on,
.destroyDebugUtilsMessengerEXT = settings.messenger_on,
.getPhysicalDeviceProperties2 = true,
.getPhysicalDeviceFeatures2 = true,
.enumerateDeviceExtensionProperties = true,
@ -45,12 +46,12 @@ pub const Instance = struct {
pub fn init() !Self {
// TODO: do we absolutely need volk rn? Don't think so? volk init here
var avail_layers = try getAvailableLayers();
defer avail_layers.deinit();
defer allocator.free(avail_layers);
var avail_exts = try getAvailableExtensions();
defer avail_exts.deinit();
defer allocator.free(avail_exts);
const layers_to_load = try getLayers(&avail_layers);
const extensions = try getExtensions(&avail_exts);
const layers_to_load = try getLayers(avail_layers);
const extensions = try getExtensions(avail_exts);
const app_info = vk.ApplicationInfo{
.p_application_name = settings.app_name,
@ -78,7 +79,7 @@ pub const Instance = struct {
.extensions = extensions,
.handle = handle,
};
self.messenger = try DebugMessenger.init(&self);
self.messenger = if (settings.messenger_on) try DebugMessenger.init(&self) else undefined;
return self;
}
@ -91,34 +92,32 @@ pub const Instance = struct {
}
/// list all available layers
fn getAvailableLayers() !std.StringArrayHashMap(void) {
fn getAvailableLayers() ![]vk.LayerProperties {
var count: u32 = undefined;
_ = try Base.dispatch.enumerateInstanceLayerProperties(&count, null);
const list = try allocator.alloc(vk.LayerProperties, count);
defer allocator.free(list);
_ = try Base.dispatch.enumerateInstanceLayerProperties(&count, list.ptr);
var hash_map = std.StringArrayHashMap(void).init(allocator);
try hash_map.ensureTotalCapacity(count);
// TODO log
std.debug.print("{} available instance layers", .{count});
std.debug.print("{} available instance layers\n", .{count});
for (list) |layer| {
const layer_name = std.mem.sliceTo(&layer.layer_name, 0);
std.debug.print("{s}", .{layer_name});
hash_map.putAssumeCapacity(layer_name, {});
std.debug.print("\t{s}\n", .{layer_name});
}
return hash_map;
return list;
}
fn getLayers(avail_layers: *std.StringArrayHashMap(void)) !std.ArrayList([*:0]const u8) {
fn getLayers(avail_layers: []vk.LayerProperties) !std.ArrayList([*:0]const u8) {
var list = std.ArrayList([*:0]const u8).init(allocator);
for (enabled_layers) |layer| {
const layer_name = std.mem.sliceTo(layer, 0);
if (avail_layers.contains(layer_name)) {
try list.append(layer);
for (avail_layers) |avail_layer| {
const avail_layer_name = std.mem.sliceTo(&avail_layer.layer_name, 0);
if (std.mem.eql(u8, layer_name, avail_layer_name)) {
try list.append(layer);
}
}
}
@ -126,43 +125,44 @@ pub const Instance = struct {
}
/// list all available extensions
fn getAvailableExtensions() !std.StringArrayHashMap(void) {
fn getAvailableExtensions() ![]vk.ExtensionProperties {
var count: u32 = undefined;
_ = try Base.dispatch.enumerateInstanceExtensionProperties(null, &count, null);
const list = try allocator.alloc(vk.ExtensionProperties, count);
defer allocator.free(list);
_ = try Base.dispatch.enumerateInstanceExtensionProperties(null, &count, list.ptr);
var hash_map = std.StringArrayHashMap(void).init(allocator);
try hash_map.ensureTotalCapacity(count);
// TODO log
std.debug.print("{} available instance extensions", .{count});
std.debug.print("{} available instance extensions\n", .{count});
for (list) |ext| {
const extension_name = std.mem.sliceTo(&ext.extension_name, 0);
std.debug.print("{s}", .{extension_name});
hash_map.putAssumeCapacity(extension_name, {});
std.debug.print("\t{s}\n", .{extension_name});
}
return hash_map;
return list;
}
fn getExtensions(avail_exts: *std.StringArrayHashMap(void)) !std.ArrayList([*:0]const u8) {
fn getExtensions(avail_exts: []vk.ExtensionProperties) !std.ArrayList([*:0]const u8) {
var list = std.ArrayList([*:0]const u8).init(allocator);
for (try glfw.getRequiredInstanceExtensions()) |ext| {
const extension_name = std.mem.sliceTo(ext, 0);
if (avail_exts.contains(extension_name)) {
try list.append(extension_name);
for (avail_exts) |avail_ext| {
const avail_ext_name = std.mem.sliceTo(&avail_ext.extension_name, 0);
if (std.mem.eql(u8, extension_name, avail_ext_name)) {
try list.append(extension_name);
}
}
}
const instExts = Extensions.Instance.toArray(allocator);
const instExts = try Extensions.Instance.toArray(allocator);
defer allocator.free(instExts);
for (instExts) |ext| {
const extension_name = std.mem.sliceTo(ext, 0);
if (avail_exts.contains(extension_name)) {
try list.append(ext);
for (avail_exts) |avail_ext| {
const avail_ext_name = std.mem.sliceTo(&avail_ext.extension_name, 0);
if (std.mem.eql(u8, extension_name, avail_ext_name)) {
try list.append(ext);
}
}
}

View File

@ -1,6 +1,7 @@
const std = @import("std");
const vk = @import("vulkan");
const framebuffer = @import("framebuffer.zig");
const Base = @import("Base.zig");
const Device = @import("device.zig").Device;
const Instance = @import("instance.zig").Instance;
const SubmitId = @import("swapchain.zig").SubmitId;
@ -270,11 +271,13 @@ const Allocator = struct {
device_buffer_pool: Pool,
dynamic_buffer_pool: Pool,
device_texture_pool: Pool,
releasables: []Releasable = undefined,
releasables: []Releasable = &[_]Releasable{},
pub fn init(instance: *const Instance, device: *const Device) !Self {
const funcs = vma.VulkanFunctions.init(instance.handle, device.handle, Base.vk_proc);
const handle = try vma.Allocator.create(.{
.vulkanApiVersion = vk.API_VERSION_1_3,
.vulkanApiVersion = vk.API_VERSION_1_1, // LIES
.flags = .{
.memoryBudgetEXT = true,
.externallySynchronized = true,
@ -282,6 +285,7 @@ const Allocator = struct {
.instance = instance.handle,
.physicalDevice = device.physical_device,
.device = device.handle,
.pVulkanFunctions = &funcs,
.pAllocationCallbacks = null,
.frameInUseCount = settings.resource_sets,
});

View File

@ -147,16 +147,20 @@ pub const Support = struct {
var count: u32 = undefined;
instance.dispatch.getPhysicalDeviceQueueFamilyProperties(physical_device, &count, null);
self.properties = try allocator.alloc(vk.QueueFamilyProperties, count);
instance.dispatch.getPhysicalDeviceQueueFamilyProperties(physical_device, &count, self.properties.ptr);
// self.properties =
const props = try allocator.alloc(vk.QueueFamilyProperties, count);
instance.dispatch.getPhysicalDeviceQueueFamilyProperties(physical_device, &count, props.ptr);
self.families[@enumToInt(QueueId.graphics)] = selectGfxFamily(self.properties);
self.families[@enumToInt(QueueId.compute)] = selectCompFamily(self.properties);
self.families[@enumToInt(QueueId.transfer)] = selectXferFamily(self.properties);
self.families[@enumToInt(QueueId.present)] = try selectPresFamily(instance, physical_device, window.surface, self.properties);
self.families[@enumToInt(QueueId.graphics)] = selectGfxFamily(props);
self.families[@enumToInt(QueueId.compute)] = selectCompFamily(props);
self.families[@enumToInt(QueueId.transfer)] = selectXferFamily(props);
self.families[@enumToInt(QueueId.present)] = try selectPresFamily(instance, physical_device, window.surface, props);
self.properties = props;
// TODO: don't understand the purpose of 'indices' yet...
const choice_counts = try allocator.alloc(u32, count);
std.mem.set(u32, choice_counts, 0);
defer allocator.free(choice_counts);
for (self.families) |family, i| {
if (family) |f| {
@ -294,7 +298,7 @@ pub const Queue = struct {
};
const pres_family = support.families[@enumToInt(QueueId.present)];
const queue_flags = support.properties[@enumToInt(QueueId.present)].queue_flags;
const queue_flags = support.properties[0].queue_flags; // ?
if (queue_flags.graphics_bit) {
self.gfx = true;

View File

@ -5,7 +5,7 @@ pub const engine_name = "efemra";
pub const khronos_layer_on = true;
pub const assist_layer_on = true;
pub const messenger_on = true;
pub const messenger_on = false; // fixme!
pub const rt_on = false;
pub const hdr_on = true;

View File

@ -70,7 +70,7 @@ const Support = struct {
}
pub fn selectSwapFormat(self: *const Self) !vk.SurfaceFormatKHR {
if (self.formats.len > 0) {
if (self.formats.len <= 0) {
return error.NoSurfaceFormats;
}
@ -168,6 +168,8 @@ pub const Swapchain = struct {
const queue_support = try queues.Support.init(instance, device.physical_device, window);
defer queue_support.deinit();
_ = previous;
const format = try support.selectSwapFormat();
const mode = try support.selectSwapMode();
const ext = support.selectSwapExtent(window);
@ -182,13 +184,15 @@ pub const Swapchain = struct {
const usage: vk.ImageUsageFlags = .{ .color_attachment_bit = true };
const image_format = .r5g6b5_unorm_pack16;
const swap_info = vk.SwapchainCreateInfoKHR{
.s_type = .swapchain_create_info_khr,
.flags = .{},
.surface = window.surface,
.present_mode = mode,
.min_image_count = img_count,
.image_format = format.format,
.image_format = image_format,
.image_color_space = format.color_space,
.image_extent = ext,
.image_array_layers = 1,
@ -209,12 +213,12 @@ pub const Swapchain = struct {
errdefer device.dispatch.destroySwapchainKHR(device.handle, handle, null);
if (previous == null) {
std.debug.print("Present mode: '{s}'", .{@tagName(mode)});
std.debug.print("Present extent: '{} x {}'", .{ ext.width, ext.height });
std.debug.print("Present images: '{}'", .{img_count});
std.debug.print("Present sharing mode: '{s}'", .{if (concurrent) @as([]const u8, "Concurrent") else "Exclusive"});
std.debug.print("Color space: '{s}'", .{@tagName(format.color_space)});
std.debug.print("Format: '{s}'", .{@tagName(format.format)});
std.debug.print("Present mode: '{s}'\n", .{@tagName(mode)});
std.debug.print("Present extent: '{} x {}'\n", .{ ext.width, ext.height });
std.debug.print("Present images: '{}'\n", .{img_count});
std.debug.print("Present sharing mode: '{s}'\n", .{if (concurrent) @as([]const u8, "Concurrent") else "Exclusive"});
std.debug.print("Color space: '{s}'\n", .{@tagName(format.color_space)});
std.debug.print("Format: '{s}'\n", .{@tagName(image_format)});
}
var images: [settings.max_swapchain_len]vk.Image = undefined;
@ -225,20 +229,20 @@ pub const Swapchain = struct {
_ = try device.dispatch.getSwapchainImagesKHR(device.handle, handle, &img_count, &images);
const color_format = .r5g6b5_unorm_pack16;
var self = Self{
.handle = handle,
.mode = mode,
.color_format = format.format,
.color_format = color_format,
.color_space = format.color_space,
.width = ext.width,
.height = ext.height,
.length = img_count,
};
const color_format = format.format;
for (images) |img, i| {
try self.images[i].import(device, &.{
for (images[0..img_count]) |img, i| {
try self.images[i].import(device, .{
.s_type = .image_create_info,
.flags = .{},
.image_type = .@"2d",