forked from mirror/vulkan-zig
150 lines
4.6 KiB
Zig
150 lines
4.6 KiB
Zig
const std = @import("std");
|
|
const vk = @import("vulkan");
|
|
const c = @import("c.zig");
|
|
const GraphicsContext = @import("graphics_context.zig").GraphicsContext;
|
|
const Swapchain = @import("swapchain.zig").Swapchain;
|
|
|
|
const app_name = "vulkan-zig example";
|
|
const app_info = vk.ApplicationInfo{
|
|
.p_application_name = app_name,
|
|
.application_version = vk.makeVersion(0, 0, 0),
|
|
.p_engine_name = app_name,
|
|
.engine_version = vk.makeVersion(0, 0, 0),
|
|
.api_version = vk.API_VERSION_1_2,
|
|
};
|
|
|
|
pub fn main() !void {
|
|
if (c.glfwInit() != c.GLFW_TRUE) return error.GlfwInitFailed;
|
|
defer c.glfwTerminate();
|
|
|
|
const extent = vk.Extent2D{.width = 800, .height = 600};
|
|
|
|
c.glfwWindowHint(c.GLFW_CLIENT_API, c.GLFW_NO_API);
|
|
const window = c.glfwCreateWindow(
|
|
extent.width,
|
|
extent.height,
|
|
app_name,
|
|
null,
|
|
null
|
|
) orelse return error.WindowInitFailed;
|
|
defer c.glfwDestroyWindow(window);
|
|
|
|
const gc = try GraphicsContext.init(std.heap.page_allocator, &app_info, window);
|
|
defer gc.deinit();
|
|
|
|
std.debug.print("Using device: {}\n", .{gc.deviceName()});
|
|
|
|
var swapchain = try Swapchain.init(&gc, std.heap.page_allocator, extent);
|
|
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) {
|
|
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.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)
|
|
);
|
|
}
|