Implemented wayland initialization code
This commit is contained in:
parent
f43e03d6f3
commit
f894fb317d
10 changed files with 244 additions and 155 deletions
|
|
@ -1 +0,0 @@
|
||||||
# Sideros
|
|
||||||
|
|
@ -7,5 +7,6 @@ layout (binding = 0) uniform Uniform {
|
||||||
} ubo;
|
} ubo;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
gl_Position = ubo.proj * vec4(vertPos, 1.0);
|
vec4 out_vec = ubo.proj * vec4(vertPos, 1.0);
|
||||||
|
gl_Position = vec4(out_vec.x, out_vec.y, 0.5, out_vec.w);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
56
build.zig
56
build.zig
|
|
@ -6,58 +6,6 @@ pub fn build(b: *std.Build) void {
|
||||||
const target = b.standardTargetOptions(.{});
|
const target = b.standardTargetOptions(.{});
|
||||||
const optimize = b.standardOptimizeOption(.{});
|
const optimize = b.standardOptimizeOption(.{});
|
||||||
|
|
||||||
const glfw_module = b.createModule(.{
|
|
||||||
.target = target,
|
|
||||||
.optimize = optimize,
|
|
||||||
.link_libc = true,
|
|
||||||
});
|
|
||||||
const glfw = b.addLibrary(.{
|
|
||||||
.name = "glfw",
|
|
||||||
.root_module = glfw_module,
|
|
||||||
});
|
|
||||||
glfw_module.addCSourceFiles(.{ .files = &[_][]const u8{
|
|
||||||
"ext/glfw/src/cocoa_init.m",
|
|
||||||
"ext/glfw/src/cocoa_joystick.m",
|
|
||||||
"ext/glfw/src/cocoa_monitor.m",
|
|
||||||
"ext/glfw/src/cocoa_time.c",
|
|
||||||
"ext/glfw/src/cocoa_window.m",
|
|
||||||
"ext/glfw/src/context.c",
|
|
||||||
"ext/glfw/src/egl_context.c",
|
|
||||||
"ext/glfw/src/glx_context.c",
|
|
||||||
"ext/glfw/src/init.c",
|
|
||||||
"ext/glfw/src/input.c",
|
|
||||||
"ext/glfw/src/linux_joystick.c",
|
|
||||||
"ext/glfw/src/monitor.c",
|
|
||||||
"ext/glfw/src/nsgl_context.m",
|
|
||||||
"ext/glfw/src/null_init.c",
|
|
||||||
"ext/glfw/src/null_joystick.c",
|
|
||||||
"ext/glfw/src/null_monitor.c",
|
|
||||||
"ext/glfw/src/null_window.c",
|
|
||||||
"ext/glfw/src/osmesa_context.c",
|
|
||||||
"ext/glfw/src/platform.c",
|
|
||||||
"ext/glfw/src/posix_module.c",
|
|
||||||
"ext/glfw/src/posix_poll.c",
|
|
||||||
"ext/glfw/src/posix_thread.c",
|
|
||||||
"ext/glfw/src/posix_time.c",
|
|
||||||
"ext/glfw/src/vulkan.c",
|
|
||||||
"ext/glfw/src/wgl_context.c",
|
|
||||||
"ext/glfw/src/win32_init.c",
|
|
||||||
"ext/glfw/src/win32_joystick.c",
|
|
||||||
"ext/glfw/src/win32_module.c",
|
|
||||||
"ext/glfw/src/win32_monitor.c",
|
|
||||||
"ext/glfw/src/win32_thread.c",
|
|
||||||
"ext/glfw/src/win32_time.c",
|
|
||||||
"ext/glfw/src/win32_window.c",
|
|
||||||
"ext/glfw/src/window.c",
|
|
||||||
"ext/glfw/src/wl_init.c",
|
|
||||||
"ext/glfw/src/wl_monitor.c",
|
|
||||||
"ext/glfw/src/wl_window.c",
|
|
||||||
"ext/glfw/src/x11_init.c",
|
|
||||||
"ext/glfw/src/x11_monitor.c",
|
|
||||||
"ext/glfw/src/x11_window.c",
|
|
||||||
"ext/glfw/src/xkb_unicode.c",
|
|
||||||
}, .flags = &[_][]const u8{ "-D_GLFW_X11", "-Wall", "-Wextra" } });
|
|
||||||
|
|
||||||
const sideros = b.createModule(.{
|
const sideros = b.createModule(.{
|
||||||
.root_source_file = b.path("src/sideros.zig"),
|
.root_source_file = b.path("src/sideros.zig"),
|
||||||
.target = target,
|
.target = target,
|
||||||
|
|
@ -88,7 +36,6 @@ pub fn build(b: *std.Build) void {
|
||||||
renderer.addImport("ecs", ecs);
|
renderer.addImport("ecs", ecs);
|
||||||
ecs.addImport("renderer", renderer);
|
ecs.addImport("renderer", renderer);
|
||||||
|
|
||||||
renderer.addIncludePath(b.path("ext/glfw/include"));
|
|
||||||
compileAllShaders(b, renderer);
|
compileAllShaders(b, renderer);
|
||||||
|
|
||||||
sideros.addImport("mods", mods);
|
sideros.addImport("mods", mods);
|
||||||
|
|
@ -104,10 +51,11 @@ pub fn build(b: *std.Build) void {
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
exe.root_module.addImport("sideros", sideros);
|
exe.root_module.addImport("sideros", sideros);
|
||||||
|
exe.root_module.addCSourceFile(.{ .file = b.path("ext/xdg-shell.c") });
|
||||||
|
exe.root_module.addIncludePath(b.path("ext"));
|
||||||
|
|
||||||
exe.linkSystemLibrary("vulkan");
|
exe.linkSystemLibrary("vulkan");
|
||||||
exe.linkSystemLibrary("wayland-client");
|
exe.linkSystemLibrary("wayland-client");
|
||||||
exe.linkLibrary(glfw);
|
|
||||||
exe.linkLibC();
|
exe.linkLibC();
|
||||||
|
|
||||||
b.installArtifact(exe);
|
b.installArtifact(exe);
|
||||||
|
|
|
||||||
4
src/c.zig
Normal file
4
src/c.zig
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
pub const c = @cImport({
|
||||||
|
@cInclude("wayland-client.h");
|
||||||
|
@cInclude("xdg-shell.h");
|
||||||
|
});
|
||||||
94
src/main.zig
94
src/main.zig
|
|
@ -4,73 +4,67 @@ const math = @import("sideros").math;
|
||||||
const Input = @import("sideros").Input;
|
const Input = @import("sideros").Input;
|
||||||
const mods = @import("sideros").mods;
|
const mods = @import("sideros").mods;
|
||||||
const ecs = @import("sideros").ecs;
|
const ecs = @import("sideros").ecs;
|
||||||
const Renderer = @import("sideros").Renderer;
|
//const Renderer = @import("sideros").Renderer;
|
||||||
|
const wayland = @import("wayland.zig");
|
||||||
|
|
||||||
fn testSystem2(pool: *ecs.Pool) void {
|
//fn testSystem2(pool: *ecs.Pool) void {
|
||||||
std.debug.print("{any}\n", .{pool.resources.input.isKeyDown(.a)});
|
// std.debug.print("{any}\n", .{pool.resources.input.isKeyDown(.a)});
|
||||||
}
|
//}
|
||||||
|
|
||||||
pub fn main() !void {
|
pub fn main() !void {
|
||||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||||
const allocator = gpa.allocator();
|
const allocator = gpa.allocator();
|
||||||
defer if (gpa.deinit() != .ok) @panic("Leaked memory");
|
defer if (gpa.deinit() != .ok) @panic("Leaked memory");
|
||||||
|
|
||||||
var global_runtime = mods.GlobalRuntime.init(allocator);
|
//var global_runtime = mods.GlobalRuntime.init(allocator);
|
||||||
defer global_runtime.deinit();
|
//defer global_runtime.deinit();
|
||||||
try global_runtime.addFunction("debug", mods.Wasm.debug);
|
//try global_runtime.addFunction("debug", mods.Wasm.debug);
|
||||||
|
|
||||||
const file = try std.fs.cwd().openFile("assets/core.wasm", .{});
|
//const file = try std.fs.cwd().openFile("assets/core.wasm", .{});
|
||||||
const all = try file.readToEndAlloc(allocator, 1_000_000); // 1 MB
|
//const all = try file.readToEndAlloc(allocator, 1_000_000); // 1 MB
|
||||||
defer allocator.free(all);
|
//defer allocator.free(all);
|
||||||
var parser = try mods.Parser.init(allocator, all);
|
//var parser = try mods.Parser.init(allocator, all);
|
||||||
defer parser.deinit();
|
//defer parser.deinit();
|
||||||
parser.parseModule() catch |err| {
|
//parser.parseModule() catch |err| {
|
||||||
std.debug.print("[ERROR]: error at byte {x}(0x{x})\n", .{ parser.byte_idx, parser.bytes[parser.byte_idx] });
|
// std.debug.print("[ERROR]: error at byte {x}(0x{x})\n", .{ parser.byte_idx, parser.bytes[parser.byte_idx] });
|
||||||
return err;
|
// return err;
|
||||||
};
|
//};
|
||||||
const module = parser.module();
|
//const module = parser.module();
|
||||||
// defer module.deinit(allocator);
|
//// defer module.deinit(allocator);
|
||||||
|
|
||||||
var runtime = try mods.Runtime.init(allocator, module, &global_runtime);
|
//var runtime = try mods.Runtime.init(allocator, module, &global_runtime);
|
||||||
defer runtime.deinit(allocator);
|
//defer runtime.deinit(allocator);
|
||||||
|
|
||||||
var parameters = [_]mods.VM.Value{.{ .i32 = 17 }};
|
//var parameters = [_]mods.VM.Value{.{ .i32 = 17 }};
|
||||||
try runtime.callExternal(allocator, .preinit, ¶meters);
|
//try runtime.callExternal(allocator, .preinit, ¶meters);
|
||||||
const result = runtime.stack.pop().?;
|
//const result = runtime.stack.pop().?;
|
||||||
std.debug.print("Result of preinit: {any}\n", .{result});
|
//std.debug.print("Result of preinit: {any}\n", .{result});
|
||||||
var w = try Renderer.Window.create(800, 600, "sideros");
|
//var w = try Renderer.Window.create(800, 600, "sideros");
|
||||||
defer w.destroy();
|
//defer w.destroy();
|
||||||
|
|
||||||
var r = try Renderer.init(allocator, w);
|
//var r = try Renderer.init(allocator, w);
|
||||||
defer r.deinit();
|
//defer r.deinit();
|
||||||
|
|
||||||
const resources = ecs.Resources{
|
//const resources = ecs.Resources{
|
||||||
.window = w,
|
// .window = w,
|
||||||
.renderer = r,
|
// .renderer = r,
|
||||||
.input = .{ .key_pressed = .{false} ** @intFromEnum(Input.KeyCode.menu) },
|
// .input = .{ .key_pressed = .{false} ** @intFromEnum(Input.KeyCode.menu) },
|
||||||
};
|
//};
|
||||||
|
|
||||||
var pool = try ecs.Pool.init(allocator, resources);
|
//var pool = try ecs.Pool.init(allocator, resources);
|
||||||
defer pool.deinit();
|
//defer pool.deinit();
|
||||||
w.setResources(&pool.resources);
|
//w.setResources(&pool.resources);
|
||||||
try pool.addSystemGroup(&[_]ecs.System{
|
//try pool.addSystemGroup(&[_]ecs.System{
|
||||||
Renderer.render,
|
// Renderer.render,
|
||||||
}, true);
|
//}, true);
|
||||||
// try pool.addSystemGroup(&[_]ecs.System{
|
//try pool.addSystemGroup(&[_]ecs.System{
|
||||||
// testSystem2,
|
// testSystem2,
|
||||||
// });
|
//});
|
||||||
|
|
||||||
// for (0..1000) |_| {
|
// for (0..1000) |_| {
|
||||||
// const entity = try pool.createEntity();
|
// const entity = try pool.createEntity();
|
||||||
// try pool.addComponent(entity, ecs.components.Position{ .x = 1.0, .y = 0.5, .z = 3.0 });
|
// try pool.addComponent(entity, ecs.components.Position{ .x = 1.0, .y = 0.5, .z = 3.0 });
|
||||||
// try pool.addComponent(entity, ecs.components.Speed{ .speed = 5.0 });
|
// try pool.addComponent(entity, ecs.components.Speed{ .speed = 5.0 });
|
||||||
// }
|
// }
|
||||||
var last_time: f64 = 0.0;
|
try wayland.init(allocator);
|
||||||
while (!w.shouldClose()) {
|
|
||||||
const current_time = Renderer.Window.getTime();
|
|
||||||
pool.resources.delta_time = current_time - last_time;
|
|
||||||
last_time = current_time;
|
|
||||||
Renderer.Window.pollEvents();
|
|
||||||
pool.tick();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,10 +19,10 @@ current_frame: u32,
|
||||||
vertex_buffer: vk.Buffer,
|
vertex_buffer: vk.Buffer,
|
||||||
index_buffer: vk.Buffer,
|
index_buffer: vk.Buffer,
|
||||||
|
|
||||||
pub fn init(allocator: Allocator, w: Window) !Renderer {
|
pub fn init(allocator: Allocator, display: ?*anyopaque, s: ?*anyopaque) !Renderer {
|
||||||
const instance = try vk.Instance.create(allocator);
|
const instance = try vk.Instance.create(allocator);
|
||||||
|
|
||||||
const surface = try vk.Surface.create(instance, w);
|
const surface = try vk.Surface.create(instance, display, s);
|
||||||
|
|
||||||
var physical_device = try vk.PhysicalDevice.pick(allocator, instance);
|
var physical_device = try vk.PhysicalDevice.pick(allocator, instance);
|
||||||
const device = try physical_device.create_device(surface, allocator, 2);
|
const device = try physical_device.create_device(surface, allocator, 2);
|
||||||
|
|
@ -34,7 +34,7 @@ pub fn init(allocator: Allocator, w: Window) !Renderer {
|
||||||
|
|
||||||
const render_pass = try vk.RenderPass(2).create(allocator, device, surface, physical_device);
|
const render_pass = try vk.RenderPass(2).create(allocator, device, surface, physical_device);
|
||||||
|
|
||||||
const swapchain = try vk.Swapchain(2).create(allocator, surface, device, physical_device, w, render_pass);
|
const swapchain = try vk.Swapchain(2).create(allocator, surface, device, physical_device, render_pass);
|
||||||
|
|
||||||
const graphics_pipeline = try vk.GraphicsPipeline(2).create(device, swapchain, render_pass, vertex_shader, fragment_shader);
|
const graphics_pipeline = try vk.GraphicsPipeline(2).create(device, swapchain, render_pass, vertex_shader, fragment_shader);
|
||||||
|
|
||||||
|
|
@ -75,8 +75,9 @@ pub fn deinit(self: Renderer) void {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: render is maybe a bad name? something like present() or submit() is better?
|
// TODO: render is maybe a bad name? something like present() or submit() is better?
|
||||||
pub fn render(pool: *ecs.Pool) anyerror!void {
|
//pub fn render(pool: *ecs.Pool) anyerror!void {
|
||||||
var renderer = pool.resources.renderer;
|
pub fn render(renderer: *Renderer) anyerror!void {
|
||||||
|
//var renderer = pool.resources.renderer;
|
||||||
|
|
||||||
try renderer.device.waitFence(renderer.current_frame);
|
try renderer.device.waitFence(renderer.current_frame);
|
||||||
const image = try renderer.swapchain.nextImage(renderer.device, renderer.current_frame);
|
const image = try renderer.swapchain.nextImage(renderer.device, renderer.current_frame);
|
||||||
|
|
@ -94,4 +95,6 @@ pub fn render(pool: *ecs.Pool) anyerror!void {
|
||||||
try renderer.device.submit(renderer.swapchain, image, renderer.current_frame);
|
try renderer.device.submit(renderer.swapchain, image, renderer.current_frame);
|
||||||
|
|
||||||
renderer.current_frame = (renderer.current_frame + 1) % 2;
|
renderer.current_frame = (renderer.current_frame + 1) % 2;
|
||||||
|
|
||||||
|
renderer.device.waitIdle();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,8 @@ pub const Error = error{
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn getExtensions() [][*c]const u8 {
|
pub fn getExtensions() [][*c]const u8 {
|
||||||
var extension_count: u32 = undefined;
|
const raw: [*c][*c]const u8 = .{"VK_KHR_wayland_surface", "VK_KHR_surface"};
|
||||||
const raw: [*c][*c]const u8 = c.glfwGetRequiredInstanceExtensions(&extension_count);
|
const extensions = raw[0..2];
|
||||||
const extensions = raw[0..extension_count];
|
|
||||||
|
|
||||||
return extensions;
|
return extensions;
|
||||||
}
|
}
|
||||||
|
|
@ -20,25 +19,10 @@ pub fn getExtensions() [][*c]const u8 {
|
||||||
title: []const u8,
|
title: []const u8,
|
||||||
width: usize,
|
width: usize,
|
||||||
height: usize,
|
height: usize,
|
||||||
raw: *c.GLFWwindow,
|
raw: *c.wl_display,
|
||||||
|
|
||||||
pub fn create(width: usize, height: usize, title: []const u8) !Window {
|
pub fn create(width: usize, height: usize, title: []const u8) !Window {
|
||||||
if (c.glfwInit() != c.GLFW_TRUE) {
|
const raw = c.wl_display_connect(null);
|
||||||
const status = c.glfwGetError(null);
|
|
||||||
|
|
||||||
return switch (status) {
|
|
||||||
c.GLFW_PLATFORM_UNAVAILABLE => Error.platform_unavailable,
|
|
||||||
c.GLFW_PLATFORM_ERROR => Error.platform_error,
|
|
||||||
else => unreachable,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
c.glfwWindowHint(c.GLFW_RESIZABLE, c.GLFW_FALSE);
|
|
||||||
c.glfwWindowHint(c.GLFW_CLIENT_API, c.GLFW_NO_API);
|
|
||||||
const raw = c.glfwCreateWindow(@intCast(width), @intCast(height), title.ptr, null, null);
|
|
||||||
c.glfwShowWindow(raw);
|
|
||||||
_ = c.glfwSetKeyCallback(raw, keyCallback);
|
|
||||||
_ = c.glfwSetCursorPosCallback(raw, cursorCallback);
|
|
||||||
|
|
||||||
return Window{
|
return Window{
|
||||||
.title = title,
|
.title = title,
|
||||||
|
|
@ -52,12 +36,8 @@ pub fn setResources(self: *Window, resources: *ecs.Resources) void {
|
||||||
c.glfwSetWindowUserPointer(self.raw, resources);
|
c.glfwSetWindowUserPointer(self.raw, resources);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pollEvents() void {
|
|
||||||
c.glfwPollEvents();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn shouldClose(self: Window) bool {
|
pub fn shouldClose(self: Window) bool {
|
||||||
return c.glfwWindowShouldClose(self.raw) == c.GLFW_TRUE;
|
return c.wl_display_dispatch(self.raw) != -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn size(self: Window) struct { usize, usize } {
|
pub fn size(self: Window) struct { usize, usize } {
|
||||||
|
|
@ -70,8 +50,7 @@ pub fn size(self: Window) struct { usize, usize } {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn destroy(self: Window) void {
|
pub fn destroy(self: Window) void {
|
||||||
c.glfwDestroyWindow(self.raw);
|
c.wl_display_disconnect(self.raw);
|
||||||
c.glfwTerminate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getTime() f64 {
|
pub fn getTime() f64 {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
pub const c = @cImport({
|
pub const c = @cImport({
|
||||||
@cDefine("GLFW_INCLUDE_NONE", {});
|
|
||||||
@cInclude("vulkan/vulkan.h");
|
@cInclude("vulkan/vulkan.h");
|
||||||
@cInclude("GLFW/glfw3.h");
|
@cInclude("vulkan/vulkan_wayland.h");
|
||||||
|
@cInclude("wayland-client.h");
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,8 @@ pub const Instance = struct {
|
||||||
handle: c.VkInstance,
|
handle: c.VkInstance,
|
||||||
|
|
||||||
pub fn create(allocator: Allocator) !Instance {
|
pub fn create(allocator: Allocator) !Instance {
|
||||||
const extensions = Window.getExtensions();
|
const extensions = [_][*c]const u8 {c.VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME, c.VK_KHR_SURFACE_EXTENSION_NAME};
|
||||||
|
//const extensions = [_][:0]const u8 {"VK_KHR_wayland_surface\0", "VK_KHR_surface\0"};
|
||||||
|
|
||||||
// Querry avaliable extensions size
|
// Querry avaliable extensions size
|
||||||
var avaliableExtensionsCount: u32 = 0;
|
var avaliableExtensionsCount: u32 = 0;
|
||||||
|
|
@ -140,7 +141,7 @@ pub const Instance = struct {
|
||||||
.sType = c.VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
|
.sType = c.VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
|
||||||
.pApplicationInfo = &app_info,
|
.pApplicationInfo = &app_info,
|
||||||
.enabledExtensionCount = @intCast(extensions.len),
|
.enabledExtensionCount = @intCast(extensions.len),
|
||||||
.ppEnabledExtensionNames = extensions.ptr,
|
.ppEnabledExtensionNames = @ptrCast(extensions[0..]),
|
||||||
.enabledLayerCount = @intCast(newLayers.items.len),
|
.enabledLayerCount = @intCast(newLayers.items.len),
|
||||||
.ppEnabledLayerNames = newLayers.items.ptr,
|
.ppEnabledLayerNames = newLayers.items.ptr,
|
||||||
};
|
};
|
||||||
|
|
@ -267,7 +268,7 @@ pub fn RenderPass(comptime n: usize) type {
|
||||||
|
|
||||||
pub fn begin(self: Self, swapchain: Swapchain(n), device: Device(n), image: usize, frame: usize) void {
|
pub fn begin(self: Self, swapchain: Swapchain(n), device: Device(n), image: usize, frame: usize) void {
|
||||||
std.debug.assert(frame < n);
|
std.debug.assert(frame < n);
|
||||||
const clear_color: c.VkClearValue = .{ .color = .{ .float32 = .{ 0.0, 0.0, 0.0, 1.0 } } };
|
const clear_color: c.VkClearValue = .{ .color = .{ .float32 = .{ 1.0, 0.0, 0.0, 1.0 } } };
|
||||||
|
|
||||||
const begin_info: c.VkRenderPassBeginInfo = .{
|
const begin_info: c.VkRenderPassBeginInfo = .{
|
||||||
.sType = c.VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
|
.sType = c.VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
|
||||||
|
|
@ -604,7 +605,7 @@ pub fn Swapchain(comptime n: usize) type {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Allow to recreate so Window can be resized
|
// TODO: Allow to recreate so Window can be resized
|
||||||
pub fn create(allocator: Allocator, surface: Surface, device: Device(n), physical_device: PhysicalDevice, w: Window, render_pass: RenderPass(n)) !Self {
|
pub fn create(allocator: Allocator, surface: Surface, device: Device(n), physical_device: PhysicalDevice, render_pass: RenderPass(n)) !Self {
|
||||||
const present_modes = try surface.presentModes(allocator, physical_device);
|
const present_modes = try surface.presentModes(allocator, physical_device);
|
||||||
defer allocator.free(present_modes);
|
defer allocator.free(present_modes);
|
||||||
const capabilities = try surface.capabilities(physical_device);
|
const capabilities = try surface.capabilities(physical_device);
|
||||||
|
|
@ -625,7 +626,7 @@ pub fn Swapchain(comptime n: usize) type {
|
||||||
if (capabilities.currentExtent.width != std.math.maxInt(u32)) {
|
if (capabilities.currentExtent.width != std.math.maxInt(u32)) {
|
||||||
extent = capabilities.currentExtent;
|
extent = capabilities.currentExtent;
|
||||||
} else {
|
} else {
|
||||||
const width, const height = w.size();
|
const width: u32, const height: u32 = .{800, 600};
|
||||||
|
|
||||||
extent = .{
|
extent = .{
|
||||||
.width = @intCast(width),
|
.width = @intCast(width),
|
||||||
|
|
@ -756,10 +757,16 @@ pub fn Swapchain(comptime n: usize) type {
|
||||||
pub const Surface = struct {
|
pub const Surface = struct {
|
||||||
handle: c.VkSurfaceKHR,
|
handle: c.VkSurfaceKHR,
|
||||||
|
|
||||||
pub fn create(instance: Instance, w: Window) !Surface {
|
pub fn create(instance: Instance, display: ?*anyopaque, surface: ?*anyopaque) !Surface {
|
||||||
var handle: c.VkSurfaceKHR = undefined;
|
var handle: c.VkSurfaceKHR = undefined;
|
||||||
try mapError(c.glfwCreateWindowSurface(instance.handle, w.raw, null, &handle));
|
const create_info: c.VkWaylandSurfaceCreateInfoKHR = .{
|
||||||
return Surface{
|
.sType = c.VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR,
|
||||||
|
.display = @ptrCast(display),
|
||||||
|
.surface = @ptrCast(surface),
|
||||||
|
};
|
||||||
|
|
||||||
|
try mapError(c.vkCreateWaylandSurfaceKHR(instance.handle, &create_info, null, &handle));
|
||||||
|
return .{
|
||||||
.handle = handle,
|
.handle = handle,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -834,7 +841,7 @@ pub fn Device(comptime n: usize) type {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn waitFence(self: Self, frame: usize) !void {
|
pub fn waitFence(self: Self, frame: usize) !void {
|
||||||
std.debug.assert(frame < n);
|
//std.debug.assert(frame < n);
|
||||||
try mapError(c.vkWaitForFences(self.handle, 1, &self.in_flight_fence[frame], c.VK_TRUE, std.math.maxInt(u64)));
|
try mapError(c.vkWaitForFences(self.handle, 1, &self.in_flight_fence[frame], c.VK_TRUE, std.math.maxInt(u64)));
|
||||||
try mapError(c.vkResetFences(self.handle, 1, &self.in_flight_fence[frame]));
|
try mapError(c.vkResetFences(self.handle, 1, &self.in_flight_fence[frame]));
|
||||||
}
|
}
|
||||||
|
|
@ -917,28 +924,30 @@ pub fn Device(comptime n: usize) type {
|
||||||
|
|
||||||
pub fn submit(self: Self, swapchain: Swapchain(n), image: usize, frame: usize) !void {
|
pub fn submit(self: Self, swapchain: Swapchain(n), image: usize, frame: usize) !void {
|
||||||
std.debug.assert(frame < n);
|
std.debug.assert(frame < n);
|
||||||
//const wait_semaphores: [1]c.VkSemaphore = .{self.image_available[frame]};
|
const wait_semaphores: [1]c.VkSemaphore = .{self.image_available[frame]};
|
||||||
//const signal_semaphores: [1]c.VkSemaphore = .{self.render_finished[frame]};
|
const signal_semaphores: [1]c.VkSemaphore = .{self.render_finished[frame]};
|
||||||
//const swapchains: [1]c.VkSwapchainKHR = .{swapchain.handle};
|
const swapchains: [1]c.VkSwapchainKHR = .{swapchain.handle};
|
||||||
|
_ = swapchains;
|
||||||
const stages: []const u32 = &[_]u32{c.VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
|
const stages: []const u32 = &[_]u32{c.VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
|
||||||
|
|
||||||
const submit_info: c.VkSubmitInfo = .{
|
const submit_info: c.VkSubmitInfo = .{
|
||||||
.sType = c.VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
.sType = c.VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
||||||
.waitSemaphoreCount = 1,
|
.waitSemaphoreCount = 1,
|
||||||
.pWaitSemaphores = &self.image_available[frame],
|
.pWaitSemaphores = wait_semaphores[0..].ptr,
|
||||||
.pWaitDstStageMask = stages.ptr,
|
.pWaitDstStageMask = stages.ptr,
|
||||||
.commandBufferCount = 1,
|
.commandBufferCount = 1,
|
||||||
.pCommandBuffers = &self.command_buffers[frame],
|
.pCommandBuffers = &self.command_buffers[frame],
|
||||||
.signalSemaphoreCount = 1,
|
.signalSemaphoreCount = 1,
|
||||||
.pSignalSemaphores = &self.render_finished[frame],
|
.pSignalSemaphores = signal_semaphores[0..].ptr,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
_ = c.vkResetFences(self.handle, 1, &self.in_flight_fence[frame]);
|
||||||
try mapError(c.vkQueueSubmit(self.graphics_queue, 1, &submit_info, self.in_flight_fence[frame]));
|
try mapError(c.vkQueueSubmit(self.graphics_queue, 1, &submit_info, self.in_flight_fence[frame]));
|
||||||
|
|
||||||
const present_info: c.VkPresentInfoKHR = .{
|
const present_info: c.VkPresentInfoKHR = .{
|
||||||
.sType = c.VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
|
.sType = c.VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
|
||||||
.waitSemaphoreCount = 1,
|
.waitSemaphoreCount = 1,
|
||||||
.pWaitSemaphores = &self.render_finished[frame],
|
.pWaitSemaphores = signal_semaphores[0..].ptr,
|
||||||
.swapchainCount = 1,
|
.swapchainCount = 1,
|
||||||
.pSwapchains = &swapchain.handle,
|
.pSwapchains = &swapchain.handle,
|
||||||
.pImageIndices = @ptrCast(&image),
|
.pImageIndices = @ptrCast(&image),
|
||||||
|
|
|
||||||
152
src/wayland.zig
Normal file
152
src/wayland.zig
Normal file
|
|
@ -0,0 +1,152 @@
|
||||||
|
const c = @import("c.zig").c;
|
||||||
|
const std = @import("std");
|
||||||
|
const Renderer = @import("sideros").Renderer;
|
||||||
|
|
||||||
|
var resize = false;
|
||||||
|
var quit = false;
|
||||||
|
var new_width: u32 = 0;
|
||||||
|
var new_height: u32 = 0;
|
||||||
|
|
||||||
|
const State = struct {
|
||||||
|
compositor: ?*c.wl_compositor = null,
|
||||||
|
shell: ?*c.xdg_wm_base = null,
|
||||||
|
surface: ?*c.wl_surface = null,
|
||||||
|
renderer: *Renderer = undefined,
|
||||||
|
configured: bool = false,
|
||||||
|
};
|
||||||
|
|
||||||
|
fn registryHandleGlobal(data: ?*anyopaque, registry: ?*c.wl_registry, name: u32, interface: [*c]const u8, version: u32) callconv(.c) void {
|
||||||
|
_ = version;
|
||||||
|
const state: *State = @alignCast(@ptrCast(data));
|
||||||
|
if (std.mem.eql(u8, std.mem.span(interface), std.mem.span(c.wl_compositor_interface.name))) {
|
||||||
|
state.compositor = @ptrCast(c.wl_registry_bind(registry.?, name, &c.wl_compositor_interface, 4));
|
||||||
|
} else if (std.mem.eql(u8, @as([:0]const u8, std.mem.span(interface)), std.mem.span(c.xdg_wm_base_interface.name))) {
|
||||||
|
state.shell = @ptrCast(c.wl_registry_bind(registry.?, name, &c.xdg_wm_base_interface, 4));
|
||||||
|
_ = c.xdg_wm_base_add_listener(state.shell, &shell_listener, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn registryHandleGlobalRemove(data: ?*anyopaque, registry: ?*c.wl_registry, name: u32) callconv(.c) void {
|
||||||
|
_ = data;
|
||||||
|
_ = registry;
|
||||||
|
_ = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn shellHandlePing(data: ?*anyopaque, shell: ?*c.xdg_wm_base, serial: u32) callconv(.c) void {
|
||||||
|
_ = data;
|
||||||
|
c.xdg_wm_base_pong(shell, serial);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn shellHandleSurfaceConfigure(data: ?*anyopaque, surface: ?*c.xdg_surface, serial: u32) callconv(.c) void {
|
||||||
|
const state: *State = @alignCast(@ptrCast(data));
|
||||||
|
|
||||||
|
c.xdg_surface_ack_configure(surface, serial);
|
||||||
|
state.configured = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn toplevelHandleConfigure(data: ?*anyopaque, toplevel: ?*c.xdg_toplevel, width: i32, height: i32, states: ?*c.wl_array) callconv(.c) void {
|
||||||
|
_ = data;
|
||||||
|
_ = toplevel;
|
||||||
|
_ = states;
|
||||||
|
|
||||||
|
if (width != 0 and height != 0) {
|
||||||
|
resize = true;
|
||||||
|
new_width = @intCast(width);
|
||||||
|
new_height = @intCast(height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn toplevelHandleClose(data: ?*anyopaque, toplevel: ?*c.xdg_toplevel) callconv(.c) void {
|
||||||
|
_ = data;
|
||||||
|
_ = toplevel;
|
||||||
|
|
||||||
|
quit = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn toplevelHandleConfigureBounds(data: ?*anyopaque, toplevel: ?*c.xdg_toplevel, width: i32, height: i32) callconv(.c) void {
|
||||||
|
_ = data;
|
||||||
|
_ = toplevel;
|
||||||
|
_ = width;
|
||||||
|
_ = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn frameHandleDone(data: ?*anyopaque, callback: ?*c.wl_callback, time: u32) callconv(.c) void {
|
||||||
|
_ = time;
|
||||||
|
const state: *State = @alignCast(@ptrCast(data));
|
||||||
|
_ = c.wl_callback_destroy(callback);
|
||||||
|
const cb = c.wl_surface_frame(state.surface);
|
||||||
|
_ = c.wl_callback_add_listener(cb, &frame_listener, state);
|
||||||
|
|
||||||
|
state.renderer.render() catch @panic("can't render");
|
||||||
|
_ = c.wl_surface_commit(state.surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
const frame_listener: c.wl_callback_listener = .{
|
||||||
|
.done = frameHandleDone,
|
||||||
|
};
|
||||||
|
|
||||||
|
const shell_listener: c.xdg_wm_base_listener = .{
|
||||||
|
.ping = shellHandlePing,
|
||||||
|
};
|
||||||
|
|
||||||
|
const surface_listener: c.xdg_surface_listener = .{
|
||||||
|
.configure = shellHandleSurfaceConfigure,
|
||||||
|
};
|
||||||
|
|
||||||
|
const toplevel_listener: c.xdg_toplevel_listener = .{
|
||||||
|
.configure = toplevelHandleConfigure,
|
||||||
|
.configure_bounds = toplevelHandleConfigureBounds,
|
||||||
|
.close = toplevelHandleClose,
|
||||||
|
};
|
||||||
|
|
||||||
|
const registry_listener: c.wl_registry_listener = .{
|
||||||
|
.global = registryHandleGlobal,
|
||||||
|
.global_remove = registryHandleGlobalRemove,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn init(allocator: std.mem.Allocator) !void {
|
||||||
|
var state: State = .{};
|
||||||
|
const display = c.wl_display_connect(null);
|
||||||
|
defer c.wl_display_disconnect(display);
|
||||||
|
if (display == null) {
|
||||||
|
return error.ConnectionFailed;
|
||||||
|
}
|
||||||
|
|
||||||
|
const registry = c.wl_display_get_registry(display);
|
||||||
|
_ = c.wl_registry_add_listener(registry, ®istry_listener, @ptrCast(&state));
|
||||||
|
_ = c.wl_display_roundtrip(display);
|
||||||
|
|
||||||
|
const surface = c.wl_compositor_create_surface(state.compositor);
|
||||||
|
const xdg_surface = c.xdg_wm_base_get_xdg_surface(state.shell, surface);
|
||||||
|
_ = c.xdg_surface_add_listener(xdg_surface, &surface_listener, @ptrCast(&state));
|
||||||
|
|
||||||
|
state.surface = surface;
|
||||||
|
|
||||||
|
const toplevel = c.xdg_surface_get_toplevel(xdg_surface);
|
||||||
|
_ = c.xdg_toplevel_add_listener(toplevel, &toplevel_listener, null);
|
||||||
|
const title = [_]u8 {'s', 'i', 'd', 'e', 'r', 'o', 's', 0};
|
||||||
|
c.xdg_toplevel_set_title(toplevel, @ptrCast(&title[0]));
|
||||||
|
c.xdg_toplevel_set_app_id(toplevel, @ptrCast(&title[0]));
|
||||||
|
c.xdg_toplevel_set_min_size(toplevel, 800, 600);
|
||||||
|
c.xdg_toplevel_set_max_size(toplevel, 800, 600);
|
||||||
|
|
||||||
|
_ = c.wl_surface_commit(surface);
|
||||||
|
|
||||||
|
while (!state.configured) {
|
||||||
|
_ = c.wl_display_dispatch(display);
|
||||||
|
}
|
||||||
|
|
||||||
|
var renderer = try Renderer.init(allocator, @ptrCast(display), @ptrCast(surface));
|
||||||
|
defer renderer.deinit();
|
||||||
|
try renderer.render();
|
||||||
|
|
||||||
|
state.renderer = &renderer;
|
||||||
|
|
||||||
|
const cb = c.wl_surface_frame(surface);
|
||||||
|
_ = c.wl_callback_add_listener(cb, &frame_listener, @ptrCast(&state));
|
||||||
|
_ = c.wl_surface_commit(surface);
|
||||||
|
|
||||||
|
while (!quit) {
|
||||||
|
_ = c.wl_display_dispatch(display);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue