forked from mirror/vulkan-zig
Basic rendering
This commit is contained in:
@@ -46,6 +46,15 @@ const DeviceDispatch = struct {
|
|||||||
vkResetFences: vk.PfnResetFences,
|
vkResetFences: vk.PfnResetFences,
|
||||||
vkQueueSubmit: vk.PfnQueueSubmit,
|
vkQueueSubmit: vk.PfnQueueSubmit,
|
||||||
vkQueuePresentKHR: vk.PfnQueuePresentKHR,
|
vkQueuePresentKHR: vk.PfnQueuePresentKHR,
|
||||||
|
vkCreateCommandPool: vk.PfnCreateCommandPool,
|
||||||
|
vkDestroyCommandPool: vk.PfnDestroyCommandPool,
|
||||||
|
vkAllocateCommandBuffers: vk.PfnAllocateCommandBuffers,
|
||||||
|
vkFreeCommandBuffers: vk.PfnFreeCommandBuffers,
|
||||||
|
vkBeginCommandBuffer: vk.PfnBeginCommandBuffer,
|
||||||
|
vkCmdClearColorImage: vk.PfnCmdClearColorImage,
|
||||||
|
vkEndCommandBuffer: vk.PfnEndCommandBuffer,
|
||||||
|
vkQueueWaitIdle: vk.PfnQueueWaitIdle,
|
||||||
|
vkCmdPipelineBarrier: vk.PfnCmdPipelineBarrier,
|
||||||
usingnamespace vk.DeviceWrapper(@This());
|
usingnamespace vk.DeviceWrapper(@This());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -34,11 +34,116 @@ pub fn main() !void {
|
|||||||
|
|
||||||
std.debug.print("Using device: {}\n", .{gc.deviceName()});
|
std.debug.print("Using device: {}\n", .{gc.deviceName()});
|
||||||
|
|
||||||
const swapchain = try Swapchain.init(&gc, std.heap.page_allocator, extent);
|
var swapchain = try Swapchain.init(&gc, std.heap.page_allocator, extent);
|
||||||
defer swapchain.deinit();
|
defer swapchain.deinit();
|
||||||
|
|
||||||
|
const pool = try gc.vkd.createCommandPool(gc.dev, .{
|
||||||
|
.flags = .{},
|
||||||
|
.queue_family_index = gc.graphics_queue.family,
|
||||||
|
}, null);
|
||||||
|
defer gc.vkd.destroyCommandPool(gc.dev, pool, null);
|
||||||
|
|
||||||
while (c.glfwWindowShouldClose(window) == c.GLFW_FALSE) {
|
while (c.glfwWindowShouldClose(window) == c.GLFW_FALSE) {
|
||||||
|
var cmdbuf: vk.CommandBuffer = undefined;
|
||||||
|
try gc.vkd.allocateCommandBuffers(gc.dev, .{
|
||||||
|
.command_pool = pool,
|
||||||
|
.level = .primary,
|
||||||
|
.command_buffer_count = 1,
|
||||||
|
}, @ptrCast([*]vk.CommandBuffer, &cmdbuf));
|
||||||
|
defer gc.vkd.freeCommandBuffers(gc.dev, pool, 1, @ptrCast([*]const vk.CommandBuffer, &cmdbuf));
|
||||||
|
|
||||||
|
try gc.vkd.beginCommandBuffer(cmdbuf, .{
|
||||||
|
.flags = .{.one_time_submit_bit = true},
|
||||||
|
.p_inheritance_info = null,
|
||||||
|
});
|
||||||
|
|
||||||
|
const subresource_range = vk.ImageSubresourceRange{
|
||||||
|
.aspect_mask = .{.color_bit = true},
|
||||||
|
.base_mip_level = 0,
|
||||||
|
.level_count = 1,
|
||||||
|
.base_array_layer = 0,
|
||||||
|
.layer_count = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
const color = vk.ClearColorValue{.float_32 = .{1, 0, 1, 1}};
|
||||||
|
|
||||||
|
imageTransition(
|
||||||
|
&gc,
|
||||||
|
cmdbuf,
|
||||||
|
swapchain.currentImage(),
|
||||||
|
subresource_range,
|
||||||
|
.{.layout = .@"undefined", .stage = .{.top_of_pipe_bit = true}},
|
||||||
|
.{.layout = .general, .stage = .{.top_of_pipe_bit = true}},
|
||||||
|
);
|
||||||
|
|
||||||
|
gc.vkd.cmdClearColorImage(
|
||||||
|
cmdbuf,
|
||||||
|
swapchain.currentImage(),
|
||||||
|
.general,
|
||||||
|
color,
|
||||||
|
1,
|
||||||
|
@ptrCast([*]const vk.ImageSubresourceRange, &subresource_range),
|
||||||
|
);
|
||||||
|
|
||||||
|
imageTransition(
|
||||||
|
&gc,
|
||||||
|
cmdbuf,
|
||||||
|
swapchain.currentImage(),
|
||||||
|
subresource_range,
|
||||||
|
.{.layout = .general, .stage = .{.top_of_pipe_bit = true}},
|
||||||
|
.{.layout = .present_src_khr, .stage = .{.bottom_of_pipe_bit = true}},
|
||||||
|
);
|
||||||
|
|
||||||
|
try gc.vkd.endCommandBuffer(cmdbuf);
|
||||||
|
const result = swapchain.present(cmdbuf);
|
||||||
|
try gc.vkd.queueWaitIdle(gc.graphics_queue.handle);
|
||||||
|
const state = result catch |err| switch (err) {
|
||||||
|
error.OutOfDateKHR => Swapchain.PresentState.suboptimal,
|
||||||
|
else => |narrow| return narrow,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (state == .suboptimal) {
|
||||||
|
var w: c_int = undefined;
|
||||||
|
var h: c_int = undefined;
|
||||||
|
c.glfwGetWindowSize(window, &w, &h);
|
||||||
|
|
||||||
|
try swapchain.recreate(.{.width = @intCast(u32, w), .height = @intCast(u32, h)});
|
||||||
|
}
|
||||||
|
|
||||||
c.glfwSwapBuffers(window);
|
c.glfwSwapBuffers(window);
|
||||||
c.glfwPollEvents();
|
c.glfwPollEvents();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ImageState = struct {
|
||||||
|
layout: vk.ImageLayout,
|
||||||
|
stage: vk.PipelineStageFlags,
|
||||||
|
access_mask: vk.AccessFlags = .{},
|
||||||
|
};
|
||||||
|
|
||||||
|
fn imageTransition(
|
||||||
|
gc: *const GraphicsContext,
|
||||||
|
cmdbuf: vk.CommandBuffer,
|
||||||
|
image: vk.Image,
|
||||||
|
subresource_range: vk.ImageSubresourceRange,
|
||||||
|
src: ImageState,
|
||||||
|
dst: ImageState
|
||||||
|
) void {
|
||||||
|
const barrier = vk.ImageMemoryBarrier{
|
||||||
|
.src_access_mask = src.access_mask,
|
||||||
|
.dst_access_mask = dst.access_mask,
|
||||||
|
.old_layout = src.layout,
|
||||||
|
.new_layout = dst.layout,
|
||||||
|
.src_queue_family_index = vk.QUEUE_FAMILY_IGNORED,
|
||||||
|
.dst_queue_family_index = vk.QUEUE_FAMILY_IGNORED,
|
||||||
|
.image = image,
|
||||||
|
.subresource_range = subresource_range,
|
||||||
|
};
|
||||||
|
|
||||||
|
gc.vkd.cmdPipelineBarrier(
|
||||||
|
cmdbuf, src.stage, dst.stage, .{},
|
||||||
|
0, undefined,
|
||||||
|
0, undefined,
|
||||||
|
1, @ptrCast([*]const vk.ImageMemoryBarrier, &barrier)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ pub const Swapchain = struct {
|
|||||||
self.gc.vkd.destroySwapchainKHR(self.gc.dev, self.handle, null);
|
self.gc.vkd.destroySwapchainKHR(self.gc.dev, self.handle, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn recreate(self: *Swapchain, new_extent: vk.Extnet2D) !void {
|
pub fn recreate(self: *Swapchain, new_extent: vk.Extent2D) !void {
|
||||||
const gc = self.gc;
|
const gc = self.gc;
|
||||||
const allocator = self.allocator;
|
const allocator = self.allocator;
|
||||||
const old_handle = self.handle;
|
const old_handle = self.handle;
|
||||||
@@ -142,22 +142,22 @@ pub const Swapchain = struct {
|
|||||||
|
|
||||||
// Step 2: Submit the command buffer
|
// Step 2: Submit the command buffer
|
||||||
const wait_stage = [_]vk.PipelineStageFlags{.{.top_of_pipe_bit = true}};
|
const wait_stage = [_]vk.PipelineStageFlags{.{.top_of_pipe_bit = true}};
|
||||||
try self.gc.vkd.queueSubmit(self.gc.graphics_queue.handle, 1, .{
|
try self.gc.vkd.queueSubmit(self.gc.graphics_queue.handle, 1, &[_]vk.SubmitInfo{.{
|
||||||
.wait_semaphore_count = 1,
|
.wait_semaphore_count = 1,
|
||||||
.p_wait_semaphores = @ptrCast([*]const vk.Semaphore, ¤t.image_acquired),
|
.p_wait_semaphores = @ptrCast([*]const vk.Semaphore, ¤t.image_acquired),
|
||||||
.p_wait_dst_stage_mask = &wait_stage,
|
.p_wait_dst_stage_mask = &wait_stage,
|
||||||
.command_buffer_count = 1,
|
.command_buffer_count = 1,
|
||||||
.p_command_buffers = @ptrCast([*]const CommandBuffer, &cmdbuf),
|
.p_command_buffers = @ptrCast([*]const vk.CommandBuffer, &cmdbuf),
|
||||||
.signal_semaphore_count = 1,
|
.signal_semaphore_count = 1,
|
||||||
.p_signal_semaphores = @ptrCast([*]const vk.Semaphore, ¤t.render_finished),
|
.p_signal_semaphores = @ptrCast([*]const vk.Semaphore, ¤t.render_finished),
|
||||||
}, current_swap_image.frame_fence);
|
}}, current.frame_fence);
|
||||||
|
|
||||||
// Step 3: Present the current frame
|
// Step 3: Present the current frame
|
||||||
_ = try self.gc.vkd.queuePresentKHR(self.gc.present_queue.handle, .{
|
_ = try self.gc.vkd.queuePresentKHR(self.gc.present_queue.handle, .{
|
||||||
.wait_semaphore_count = 1,
|
.wait_semaphore_count = 1,
|
||||||
.p_signal_semaphores = @ptrCast([*]const vk.Semaphore, ¤t.render_finished),
|
.p_wait_semaphores = @ptrCast([*]const vk.Semaphore, ¤t.render_finished),
|
||||||
.swapchain_count = 1,
|
.swapchain_count = 1,
|
||||||
.p_swapchains = @ptrCast([*]const vk.Swapchain, &self.handle),
|
.p_swapchains = @ptrCast([*]const vk.SwapchainKHR, &self.handle),
|
||||||
.p_image_indices = @ptrCast([*]const u32, &self.image_index),
|
.p_image_indices = @ptrCast([*]const u32, &self.image_index),
|
||||||
.p_results = null,
|
.p_results = null,
|
||||||
});
|
});
|
||||||
@@ -174,9 +174,10 @@ pub const Swapchain = struct {
|
|||||||
std.mem.swap(vk.Semaphore, &self.swap_images[result.image_index].image_acquired, &self.next_image_acquired);
|
std.mem.swap(vk.Semaphore, &self.swap_images[result.image_index].image_acquired, &self.next_image_acquired);
|
||||||
self.image_index = result.image_index;
|
self.image_index = result.image_index;
|
||||||
|
|
||||||
return switch (result) {
|
return switch (result.result) {
|
||||||
.success => .optimal,
|
.success => .optimal,
|
||||||
.suboptimal_khr => .suboptimal,
|
.suboptimal_khr => .suboptimal,
|
||||||
|
else => unreachable,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -211,6 +211,13 @@ fn Renderer(comptime WriterType: type) type {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn isFlags(self: Self, name: []const u8) bool {
|
||||||
|
const tag = util.getAuthorTag(name, self.registry.tags);
|
||||||
|
const base_name = if (tag) |tag_name| name[0 .. name.len - tag_name.len] else name;
|
||||||
|
|
||||||
|
return mem.endsWith(u8, base_name, "Flags");
|
||||||
|
}
|
||||||
|
|
||||||
fn classifyParam(self: Self, param: reg.Command.Param) !ParamType {
|
fn classifyParam(self: Self, param: reg.Command.Param) !ParamType {
|
||||||
switch (param.param_type) {
|
switch (param.param_type) {
|
||||||
.pointer => |ptr| {
|
.pointer => |ptr| {
|
||||||
@@ -240,7 +247,7 @@ fn Renderer(comptime WriterType: type) type {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
.name => |name| {
|
.name => |name| {
|
||||||
if (self.extractBitflagName(param.param_type.name) != null) {
|
if (self.extractBitflagName(param.param_type.name) != null or self.isFlags(param.param_type.name)) {
|
||||||
return .bitflags;
|
return .bitflags;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -440,6 +447,10 @@ fn Renderer(comptime WriterType: type) type {
|
|||||||
});
|
});
|
||||||
try self.writer.writeAll(".IntType");
|
try self.writer.writeAll(".IntType");
|
||||||
break :blk;
|
break :blk;
|
||||||
|
} else if (self.isFlags(param.param_type.name)) {
|
||||||
|
try self.renderTypeInfo(param.param_type);
|
||||||
|
try self.writer.writeAll(".IntType");
|
||||||
|
break :blk;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -870,7 +881,7 @@ fn Renderer(comptime WriterType: type) type {
|
|||||||
},
|
},
|
||||||
.bitflags => {
|
.bitflags => {
|
||||||
try self.writeIdentifierWithCase(.snake, param.name);
|
try self.writeIdentifierWithCase(.snake, param.name);
|
||||||
try self.writer.writeAll(".toInt()"); // TODO: Generate wrapper
|
try self.writer.writeAll(".toInt()");
|
||||||
},
|
},
|
||||||
.buffer_len, .mut_buffer_len, .other => {
|
.buffer_len, .mut_buffer_len, .other => {
|
||||||
try self.writeIdentifierWithCase(.snake, param.name);
|
try self.writeIdentifierWithCase(.snake, param.name);
|
||||||
|
|||||||
Reference in New Issue
Block a user