graphics_context incremental teardown
This commit is contained in:
29
box.zig
29
box.zig
@@ -1,29 +0,0 @@
|
||||
const std = @import("std");
|
||||
|
||||
pub fn Box(comptime T: type) type {
|
||||
return struct {
|
||||
val: T,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn AddBoxType(comptime LHS: type, comptime RHS: type) type {
|
||||
const x = std.mem.zeroes(std.meta.FieldType(LHS, .val));
|
||||
const y = std.mem.zeroes(std.meta.FieldType(RHS, .val));
|
||||
return Box(@TypeOf(x + y));
|
||||
}
|
||||
|
||||
pub fn addbox(lhs: anytype, rhs: anytype) AddBoxType(@TypeOf(lhs), @TypeOf(rhs)) {
|
||||
return .{ .val = lhs.val + rhs.val };
|
||||
}
|
||||
|
||||
test {
|
||||
std.testing.refAllDecls(@This());
|
||||
}
|
||||
|
||||
test "widen" {
|
||||
const foo: Box(u8) = .{ .val = 99 };
|
||||
const bar: Box(u16) = .{ .val = 599 };
|
||||
const actual = addbox(foo, bar);
|
||||
const expected: Box(u16) = .{ .val = 698 };
|
||||
try std.testing.expectEqual(expected, actual);
|
||||
}
|
75
src/gfx.zig
Normal file
75
src/gfx.zig
Normal file
@@ -0,0 +1,75 @@
|
||||
const vk = @import("vk");
|
||||
|
||||
pub const BaseDispatch = vk.BaseWrapper(.{
|
||||
.createInstance = true,
|
||||
.getInstanceProcAddr = true,
|
||||
});
|
||||
|
||||
pub const InstanceDispatch = vk.InstanceWrapper(.{
|
||||
.destroyInstance = true,
|
||||
.createDevice = true,
|
||||
.destroySurfaceKHR = true,
|
||||
.enumeratePhysicalDevices = true,
|
||||
.getPhysicalDeviceProperties = true,
|
||||
.enumerateDeviceExtensionProperties = true,
|
||||
.getPhysicalDeviceSurfaceFormatsKHR = true,
|
||||
.getPhysicalDeviceSurfacePresentModesKHR = true,
|
||||
.getPhysicalDeviceSurfaceCapabilitiesKHR = true,
|
||||
.getPhysicalDeviceQueueFamilyProperties = true,
|
||||
.getPhysicalDeviceSurfaceSupportKHR = true,
|
||||
.getPhysicalDeviceMemoryProperties = true,
|
||||
.getDeviceProcAddr = true,
|
||||
});
|
||||
|
||||
pub const DeviceDispatch = vk.DeviceWrapper(.{
|
||||
.destroyDevice = true,
|
||||
.getDeviceQueue = true,
|
||||
.createSemaphore = true,
|
||||
.createFence = true,
|
||||
.createImageView = true,
|
||||
.destroyImageView = true,
|
||||
.destroySemaphore = true,
|
||||
.destroyFence = true,
|
||||
.getSwapchainImagesKHR = true,
|
||||
.createSwapchainKHR = true,
|
||||
.destroySwapchainKHR = true,
|
||||
.acquireNextImageKHR = true,
|
||||
.deviceWaitIdle = true,
|
||||
.waitForFences = true,
|
||||
.resetFences = true,
|
||||
.queueSubmit = true,
|
||||
.queuePresentKHR = true,
|
||||
.createCommandPool = true,
|
||||
.destroyCommandPool = true,
|
||||
.allocateCommandBuffers = true,
|
||||
.freeCommandBuffers = true,
|
||||
.queueWaitIdle = true,
|
||||
.createShaderModule = true,
|
||||
.destroyShaderModule = true,
|
||||
.createPipelineLayout = true,
|
||||
.destroyPipelineLayout = true,
|
||||
.createGraphicsPipelines = true,
|
||||
.destroyPipeline = true,
|
||||
.beginCommandBuffer = true,
|
||||
.endCommandBuffer = true,
|
||||
.allocateMemory = true,
|
||||
.freeMemory = true,
|
||||
.createBuffer = true,
|
||||
.destroyBuffer = true,
|
||||
.getBufferMemoryRequirements = true,
|
||||
.mapMemory = true,
|
||||
.unmapMemory = true,
|
||||
.bindBufferMemory = true,
|
||||
.cmdBeginRenderPass = true,
|
||||
.cmdEndRenderPass = true,
|
||||
.cmdBindPipeline = true,
|
||||
.cmdDraw = true,
|
||||
.cmdDrawIndexed = true,
|
||||
.cmdSetViewport = true,
|
||||
.cmdSetScissor = true,
|
||||
.cmdBindVertexBuffers = true,
|
||||
.cmdBindIndexBuffer = true,
|
||||
.cmdCopyBuffer = true,
|
||||
.cmdBeginRenderingKHR = true,
|
||||
.cmdEndRenderingKHR = true,
|
||||
});
|
6
src/gfx/Context.zig
Normal file
6
src/gfx/Context.zig
Normal file
@@ -0,0 +1,6 @@
|
||||
const std = @import("std");
|
||||
const vk = @import("vk");
|
||||
|
||||
const d = @import("dispatch.zig");
|
||||
|
||||
const Self = @This();
|
@@ -3,91 +3,21 @@ 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,
|
||||
};
|
||||
|
||||
const BaseDispatch = vk.BaseWrapper(.{
|
||||
.createInstance = true,
|
||||
.getInstanceProcAddr = true,
|
||||
});
|
||||
|
||||
const InstanceDispatch = vk.InstanceWrapper(.{
|
||||
.destroyInstance = true,
|
||||
.createDevice = true,
|
||||
.destroySurfaceKHR = true,
|
||||
.enumeratePhysicalDevices = true,
|
||||
.getPhysicalDeviceProperties = true,
|
||||
.enumerateDeviceExtensionProperties = true,
|
||||
.getPhysicalDeviceSurfaceFormatsKHR = true,
|
||||
.getPhysicalDeviceSurfacePresentModesKHR = true,
|
||||
.getPhysicalDeviceSurfaceCapabilitiesKHR = true,
|
||||
.getPhysicalDeviceQueueFamilyProperties = true,
|
||||
.getPhysicalDeviceSurfaceSupportKHR = true,
|
||||
.getPhysicalDeviceMemoryProperties = true,
|
||||
.getDeviceProcAddr = true,
|
||||
});
|
||||
|
||||
const DeviceDispatch = vk.DeviceWrapper(.{
|
||||
.destroyDevice = true,
|
||||
.getDeviceQueue = true,
|
||||
.createSemaphore = true,
|
||||
.createFence = true,
|
||||
.createImageView = true,
|
||||
.destroyImageView = true,
|
||||
.destroySemaphore = true,
|
||||
.destroyFence = true,
|
||||
.getSwapchainImagesKHR = true,
|
||||
.createSwapchainKHR = true,
|
||||
.destroySwapchainKHR = true,
|
||||
.acquireNextImageKHR = true,
|
||||
.deviceWaitIdle = true,
|
||||
.waitForFences = true,
|
||||
.resetFences = true,
|
||||
.queueSubmit = true,
|
||||
.queuePresentKHR = true,
|
||||
.createCommandPool = true,
|
||||
.destroyCommandPool = true,
|
||||
.allocateCommandBuffers = true,
|
||||
.freeCommandBuffers = true,
|
||||
.queueWaitIdle = true,
|
||||
.createShaderModule = true,
|
||||
.destroyShaderModule = true,
|
||||
.createPipelineLayout = true,
|
||||
.destroyPipelineLayout = true,
|
||||
.createGraphicsPipelines = true,
|
||||
.destroyPipeline = true,
|
||||
.beginCommandBuffer = true,
|
||||
.endCommandBuffer = true,
|
||||
.allocateMemory = true,
|
||||
.freeMemory = true,
|
||||
.createBuffer = true,
|
||||
.destroyBuffer = true,
|
||||
.getBufferMemoryRequirements = true,
|
||||
.mapMemory = true,
|
||||
.unmapMemory = true,
|
||||
.bindBufferMemory = true,
|
||||
.cmdBeginRenderPass = true,
|
||||
.cmdEndRenderPass = true,
|
||||
.cmdBindPipeline = true,
|
||||
.cmdDraw = true,
|
||||
.cmdDrawIndexed = true,
|
||||
.cmdSetViewport = true,
|
||||
.cmdSetScissor = true,
|
||||
.cmdBindVertexBuffers = true,
|
||||
.cmdBindIndexBuffer = true,
|
||||
.cmdCopyBuffer = true,
|
||||
.cmdBeginRenderingKHR = true,
|
||||
.cmdEndRenderingKHR = true,
|
||||
});
|
||||
|
||||
pub const GraphicsContext = struct {
|
||||
vkb: BaseDispatch,
|
||||
vki: InstanceDispatch,
|
||||
vkd: DeviceDispatch,
|
||||
|
||||
instance: vk.Instance,
|
||||
surface: vk.SurfaceKHR,
|
||||
pdev: vk.PhysicalDevice,
|
||||
props: vk.PhysicalDeviceProperties,
|
||||
@@ -97,52 +27,28 @@ pub const GraphicsContext = struct {
|
||||
graphics_queue: Queue,
|
||||
present_queue: Queue,
|
||||
|
||||
pub fn init(allocator: Allocator, app_name: [*:0]const u8, window: *c.GLFWwindow) !GraphicsContext {
|
||||
pub fn init(allocator: Allocator, instance: vk.Instance, surface: vk.SurfaceKHR, vki: InstanceDispatch) !GraphicsContext {
|
||||
var self: GraphicsContext = undefined;
|
||||
self.vkb = try BaseDispatch.load(c.glfwGetInstanceProcAddress);
|
||||
self.vki = vki;
|
||||
self.surface = surface;
|
||||
|
||||
var glfw_exts_count: u32 = 0;
|
||||
const glfw_exts = c.glfwGetRequiredInstanceExtensions(&glfw_exts_count);
|
||||
|
||||
const app_info = vk.ApplicationInfo{
|
||||
.p_application_name = app_name,
|
||||
.application_version = vk.makeApiVersion(0, 0, 0, 0),
|
||||
.p_engine_name = app_name,
|
||||
.engine_version = vk.makeApiVersion(0, 0, 0, 0),
|
||||
.api_version = vk.API_VERSION_1_3,
|
||||
};
|
||||
|
||||
self.instance = try self.vkb.createInstance(&.{
|
||||
.p_application_info = &app_info,
|
||||
.enabled_extension_count = glfw_exts_count,
|
||||
.pp_enabled_extension_names = @as([*]const [*:0]const u8, @ptrCast(glfw_exts)),
|
||||
}, null);
|
||||
|
||||
self.vki = try InstanceDispatch.load(self.instance, self.vkb.dispatch.vkGetInstanceProcAddr);
|
||||
errdefer self.vki.destroyInstance(self.instance, null);
|
||||
|
||||
self.surface = try createSurface(self.instance, window);
|
||||
errdefer self.vki.destroySurfaceKHR(self.instance, self.surface, null);
|
||||
|
||||
const candidate = try pickPhysicalDevice(self.vki, self.instance, allocator, self.surface);
|
||||
const candidate = try pickPhysicalDevice(vki, instance, allocator, surface);
|
||||
self.pdev = candidate.pdev;
|
||||
self.props = candidate.props;
|
||||
self.dev = try initializeCandidate(self.vki, candidate);
|
||||
self.vkd = try DeviceDispatch.load(self.dev, self.vki.dispatch.vkGetDeviceProcAddr);
|
||||
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 = self.vki.getPhysicalDeviceMemoryProperties(self.pdev);
|
||||
self.mem_props = vki.getPhysicalDeviceMemoryProperties(self.pdev);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn deinit(self: GraphicsContext) void {
|
||||
self.vkd.destroyDevice(self.dev, null);
|
||||
self.vki.destroySurfaceKHR(self.instance, self.surface, null);
|
||||
self.vki.destroyInstance(self.instance, null);
|
||||
}
|
||||
|
||||
pub fn deviceName(self: *const GraphicsContext) []const u8 {
|
||||
|
75
src/main.zig
75
src/main.zig
@@ -6,6 +6,8 @@ const GraphicsContext = @import("graphics_context.zig").GraphicsContext;
|
||||
const Swapchain = @import("swapchain.zig").Swapchain;
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
const gfx = @import("gfx.zig");
|
||||
|
||||
const app_name = "vulkan-zig triangle example";
|
||||
|
||||
const Vertex = extern struct {
|
||||
@@ -50,7 +52,57 @@ const vertices = [_]Vertex{
|
||||
|
||||
const indices = [_]Index{ 4, 5, 6, 6, 5, 7 };
|
||||
|
||||
/// note: destroy with vki.destroyInstance(instance, null)
|
||||
fn create_instance(vkb: gfx.BaseDispatch) !std.meta.Tuple(&.{ vk.Instance, gfx.InstanceDispatch }) {
|
||||
var glfw_exts_count: u32 = 0;
|
||||
const glfw_exts = c.glfwGetRequiredInstanceExtensions(&glfw_exts_count);
|
||||
|
||||
const instance = try vkb.createInstance(&vk.InstanceCreateInfo{
|
||||
.p_application_info = &vk.ApplicationInfo{
|
||||
.p_application_name = app_name,
|
||||
.application_version = vk.makeApiVersion(0, 0, 0, 0),
|
||||
.p_engine_name = app_name,
|
||||
.engine_version = vk.makeApiVersion(0, 0, 0, 0),
|
||||
.api_version = vk.API_VERSION_1_3,
|
||||
},
|
||||
.enabled_extension_count = glfw_exts_count,
|
||||
.pp_enabled_extension_names = @ptrCast(glfw_exts),
|
||||
}, null);
|
||||
|
||||
const vki = try gfx.InstanceDispatch.load(instance, vkb.dispatch.vkGetInstanceProcAddr);
|
||||
|
||||
return .{ instance, vki };
|
||||
}
|
||||
|
||||
/// note: destroy with vki.destroySurfaceKHR(instance, surface, null)
|
||||
fn create_surface(instance: vk.Instance, window: *c.GLFWwindow) !vk.SurfaceKHR {
|
||||
var surface: vk.SurfaceKHR = undefined;
|
||||
if (c.glfwCreateWindowSurface(instance, window, null, &surface) != .success) {
|
||||
return error.SurfaceInitFailed;
|
||||
}
|
||||
return surface;
|
||||
}
|
||||
|
||||
/// note: destroy with c.glfwDestroyWindow(window)
|
||||
fn create_window(extent: vk.Extent2D, title: [*:0]const u8) !*c.GLFWwindow {
|
||||
c.glfwWindowHintString(c.GLFW_X11_CLASS_NAME, "floating_window");
|
||||
c.glfwWindowHintString(c.GLFW_X11_INSTANCE_NAME, "floating_window");
|
||||
c.glfwWindowHint(c.GLFW_CLIENT_API, c.GLFW_NO_API);
|
||||
|
||||
return c.glfwCreateWindow(
|
||||
@intCast(extent.width),
|
||||
@intCast(extent.height),
|
||||
title,
|
||||
null,
|
||||
null,
|
||||
) orelse error.WindowInitFailed;
|
||||
}
|
||||
|
||||
pub fn main() !void {
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
defer _ = gpa.deinit();
|
||||
const allocator = gpa.allocator();
|
||||
|
||||
if (c.glfwInit() != c.GLFW_TRUE) return error.GlfwInitFailed;
|
||||
defer c.glfwTerminate();
|
||||
|
||||
@@ -61,23 +113,18 @@ pub fn main() !void {
|
||||
|
||||
var extent = vk.Extent2D{ .width = 800, .height = 600 };
|
||||
|
||||
c.glfwWindowHintString(c.GLFW_X11_CLASS_NAME, "floating_window");
|
||||
c.glfwWindowHintString(c.GLFW_X11_INSTANCE_NAME, "floating_window");
|
||||
c.glfwWindowHint(c.GLFW_CLIENT_API, c.GLFW_NO_API);
|
||||
const window = c.glfwCreateWindow(
|
||||
@intCast(extent.width),
|
||||
@intCast(extent.height),
|
||||
app_name,
|
||||
null,
|
||||
null,
|
||||
) orelse return error.WindowInitFailed;
|
||||
const window = try create_window(extent, app_name);
|
||||
defer c.glfwDestroyWindow(window);
|
||||
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
defer _ = gpa.deinit();
|
||||
const allocator = gpa.allocator();
|
||||
const vkb = try gfx.BaseDispatch.load(c.glfwGetInstanceProcAddress);
|
||||
|
||||
const gc = try GraphicsContext.init(allocator, app_name, window);
|
||||
const instance, const vki = try create_instance(vkb);
|
||||
defer vki.destroyInstance(instance, null);
|
||||
|
||||
const surface = try create_surface(instance, window);
|
||||
defer vki.destroySurfaceKHR(instance, surface, null);
|
||||
|
||||
const gc = try GraphicsContext.init(allocator, instance, surface, vki);
|
||||
defer gc.deinit();
|
||||
|
||||
std.log.debug("Using device: {s}", .{gc.deviceName()});
|
||||
|
97
vecs.zig
97
vecs.zig
@@ -1,97 +0,0 @@
|
||||
const std = @import("std");
|
||||
|
||||
const mat4f = mat(4, 4, f32);
|
||||
const vec4f = mat(4, 1, f32);
|
||||
|
||||
const mat4i = mat(4, 4, i32);
|
||||
const vec4i = mat(4, 1, i32);
|
||||
|
||||
const mat4u = mat(4, 4, u32);
|
||||
const vec4u = mat(4, 1, u32);
|
||||
|
||||
pub fn mat(comptime R_: usize, comptime C_: usize, comptime T_: type) type {
|
||||
return struct {
|
||||
pub const Rows = R_;
|
||||
pub const Cols = C_;
|
||||
pub const T = T_;
|
||||
|
||||
data: [Cols][Rows]T,
|
||||
|
||||
pub fn mul(l: @This(), r: anytype) MatMulReturnType(@This(), @TypeOf(r)) {
|
||||
return matmul(l, r);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn MatMulReturnType(comptime L: type, comptime R: type) type {
|
||||
if (L.Cols != R.Rows) @compileError("invalid dimensions");
|
||||
|
||||
const x: L.T = std.mem.zeroes(L.T);
|
||||
const y: R.T = std.mem.zeroes(R.T);
|
||||
const T = @TypeOf(x + y);
|
||||
|
||||
return mat(L.Rows, R.Cols, T);
|
||||
}
|
||||
|
||||
pub fn matmul(lhs: anytype, rhs: anytype) MatMulReturnType(@TypeOf(lhs), @TypeOf(rhs)) {
|
||||
@setFloatMode(.optimized);
|
||||
|
||||
const L = @TypeOf(lhs);
|
||||
const R = @TypeOf(rhs);
|
||||
const Ret = MatMulReturnType(L, R);
|
||||
|
||||
var res = std.mem.zeroes(Ret);
|
||||
|
||||
if (L.Cols != R.Rows) @compileError("invalid dimensions");
|
||||
|
||||
inline for (0..R.Cols) |col| {
|
||||
inline for (0..L.Rows) |row| {
|
||||
inline for (0..L.Cols) |k| {
|
||||
res.data[col][row] += lhs.data[k][row] * rhs.data[col][k];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
export fn c_matmul_f_4x4_1x4(lhs: *const anyopaque, rhs: *const anyopaque, out: *anyopaque) void {
|
||||
const l: *const mat4f = @alignCast(@ptrCast(lhs));
|
||||
const r: *const vec4f = @alignCast(@ptrCast(rhs));
|
||||
const o: *vec4f = @alignCast(@ptrCast(out));
|
||||
|
||||
o.* = matmul(l.*, r.*);
|
||||
}
|
||||
|
||||
export fn c_matmul_i_4x4_1x4(lhs: *const anyopaque, rhs: *const anyopaque, out: *anyopaque) void {
|
||||
const l: *const mat4i = @alignCast(@ptrCast(lhs));
|
||||
const r: *const vec4i = @alignCast(@ptrCast(rhs));
|
||||
const o: *vec4i = @alignCast(@ptrCast(out));
|
||||
|
||||
o.* = matmul(l.*, r.*);
|
||||
}
|
||||
|
||||
export fn c_matmul_u_4x4_1x4(lhs: *const anyopaque, rhs: *const anyopaque, out: *anyopaque) void {
|
||||
const l: *const mat4u = @alignCast(@ptrCast(lhs));
|
||||
const r: *const vec4u = @alignCast(@ptrCast(rhs));
|
||||
const o: *vec4u = @alignCast(@ptrCast(out));
|
||||
|
||||
o.* = matmul(l.*, r.*);
|
||||
}
|
||||
|
||||
test "matmul" {
|
||||
// note, column major; it's transposed.
|
||||
const m: mat4u = .{ .data = .{
|
||||
.{ 85, 84, 87, 37 },
|
||||
.{ 33, 54, 49, 83 },
|
||||
.{ 96, 97, 3, 13 },
|
||||
.{ 69, 12, 45, 77 },
|
||||
} };
|
||||
const u: vec4u = .{ .data = .{.{ 37, 69, 94, 87 }} };
|
||||
|
||||
const actual: vec4u = matmul(m, u);
|
||||
|
||||
const expect: vec4u = .{ .data = .{.{ 20449, 16996, 10797, 15017 }} };
|
||||
|
||||
try std.testing.expectEqualDeep(expect, actual);
|
||||
}
|
Reference in New Issue
Block a user