working on wsi
Test / build_and_test (push) Failing after 1m4s
Build / build (push) Successful in 1m9s

This commit is contained in:
2026-05-05 02:21:35 +02:00
parent ed50a39cb4
commit 82a13f47a4
17 changed files with 458 additions and 115 deletions
+5 -5
View File
@@ -168,10 +168,10 @@ vkGetPhysicalDeviceMemoryProperties | ✅ Implemented
vkGetPhysicalDeviceProperties | ✅ Implemented
vkGetPhysicalDeviceQueueFamilyProperties | ✅ Implemented
vkGetPhysicalDeviceSparseImageFormatProperties | ⚙️ WIP
vkGetPhysicalDeviceSurfaceCapabilitiesKHR | ⚙️ WIP
vkGetPhysicalDeviceSurfaceFormatsKHR | ⚙️ WIP
vkGetPhysicalDeviceSurfacePresentModesKHR | ⚙️ WIP
vkGetPhysicalDeviceSurfaceSupportKHR | ⚙️ WIP
vkGetPhysicalDeviceSurfaceCapabilitiesKHR | ✅ Implemented
vkGetPhysicalDeviceSurfaceFormatsKHR | ✅ Implemented
vkGetPhysicalDeviceSurfacePresentModesKHR | ✅ Implemented
vkGetPhysicalDeviceSurfaceSupportKHR | ✅ Implemented
vkGetPhysicalDeviceWaylandPresentationSupportKHR | ⚙️ WIP
vkGetPhysicalDeviceWin32PresentationSupportKHR | ⚙️ WIP
vkGetPhysicalDeviceXcbPresentationSupportKHR | ⚙️ WIP
@@ -184,7 +184,7 @@ vkInvalidateMappedMemoryRanges | ✅ Implemented
vkMapMemory | ✅ Implemented
vkMergePipelineCaches | ⚙️ WIP
vkQueueBindSparse | ⚙️ WIP
vkQueuePresentKHR | ⚙️ WIP
vkQueuePresentKHR | ✅ Implemented
vkQueueSubmit | ✅ Implemented
vkQueueWaitIdle | ✅ Implemented
vkResetCommandBuffer | ✅ Implemented
+28 -16
View File
@@ -29,6 +29,9 @@ pub fn create(device: *base.Device, allocator: std.mem.Allocator, info: *const v
.getMemoryRequirements = getMemoryRequirements,
.getSubresourceLayout = getSubresourceLayout,
.getTotalSizeForAspect = getTotalSizeForAspect,
.getSliceMemSizeForMipLevel = getSliceMemSizeForMipLevel,
.getRowPitchMemSizeForMipLevel = getRowPitchMemSizeForMipLevel,
.copyToMemory = copyToMemory,
};
self.* = .{
@@ -106,10 +109,10 @@ pub fn copyToImageSingleAspect(self: *const Self, dst: *Self, region: vk.ImageCo
const one_is_3D = (self.interface.image_type == .@"3d") != (dst.interface.image_type == .@"3d");
const both_are_3D = (self.interface.image_type == .@"3d") and (dst.interface.image_type == .@"3d");
const src_row_pitch_bytes = self.getRowPitchMemSizeForMipLevel(region.src_subresource.aspect_mask, region.src_subresource.mip_level);
const src_depth_pitch_bytes = self.getSliceMemSizeForMipLevel(region.src_subresource.aspect_mask, region.src_subresource.mip_level);
const dst_row_pitch_bytes = dst.getRowPitchMemSizeForMipLevel(region.dst_subresource.aspect_mask, region.dst_subresource.mip_level);
const dst_depth_pitch_bytes = dst.getSliceMemSizeForMipLevel(region.dst_subresource.aspect_mask, region.dst_subresource.mip_level);
const src_row_pitch_bytes = self.interface.getRowPitchMemSizeForMipLevel(region.src_subresource.aspect_mask, region.src_subresource.mip_level);
const src_depth_pitch_bytes = self.interface.getSliceMemSizeForMipLevel(region.src_subresource.aspect_mask, region.src_subresource.mip_level);
const dst_row_pitch_bytes = dst.interface.getRowPitchMemSizeForMipLevel(region.dst_subresource.aspect_mask, region.dst_subresource.mip_level);
const dst_depth_pitch_bytes = dst.interface.getSliceMemSizeForMipLevel(region.dst_subresource.aspect_mask, region.dst_subresource.mip_level);
const src_array_pitch = self.getLayerSize(region.src_subresource.aspect_mask);
const dst_array_pitch = dst.getLayerSize(region.dst_subresource.aspect_mask);
@@ -238,6 +241,11 @@ pub fn copyFromBuffer(self: *const Self, src: *const SoftBuffer, region: vk.Buff
);
}
pub fn copyToMemory(interface: *const Interface, memory: []u8, subresource: vk.ImageSubresourceLayers) VkError!void {
const self: *const Self = @alignCast(@fieldParentPtr("interface", interface));
try self.copy(null, memory, subresource, .{ .x = 0, .y = 0, .z = 0 }, interface.extent);
}
/// Based on SwiftShader vk::Image::copy
pub fn copy(
self: *const Self,
@@ -284,10 +292,10 @@ pub fn copy(
var src_memory = if (is_source) base_src_memory orelse return VkError.InvalidDeviceMemoryDrv else image_map;
var dst_memory = if (is_source) image_map else base_dst_memory orelse return VkError.InvalidDeviceMemoryDrv;
const src_slice_pitch_bytes = if (is_source) memory_slice_pitch_bytes else self.getSliceMemSizeForMipLevel(image_subresource.aspect_mask, image_subresource.mip_level);
const dst_slice_pitch_bytes = if (is_source) self.getSliceMemSizeForMipLevel(image_subresource.aspect_mask, image_subresource.mip_level) else memory_slice_pitch_bytes;
const src_row_pitch_bytes = if (is_source) memory_row_pitch_bytes else self.getRowPitchMemSizeForMipLevel(image_subresource.aspect_mask, image_subresource.mip_level);
const dst_row_pitch_bytes = if (is_source) self.getRowPitchMemSizeForMipLevel(image_subresource.aspect_mask, image_subresource.mip_level) else memory_row_pitch_bytes;
const src_slice_pitch_bytes = if (is_source) memory_slice_pitch_bytes else self.interface.getSliceMemSizeForMipLevel(image_subresource.aspect_mask, image_subresource.mip_level);
const dst_slice_pitch_bytes = if (is_source) self.interface.getSliceMemSizeForMipLevel(image_subresource.aspect_mask, image_subresource.mip_level) else memory_slice_pitch_bytes;
const src_row_pitch_bytes = if (is_source) memory_row_pitch_bytes else self.interface.getRowPitchMemSizeForMipLevel(image_subresource.aspect_mask, image_subresource.mip_level);
const dst_row_pitch_bytes = if (is_source) self.interface.getRowPitchMemSizeForMipLevel(image_subresource.aspect_mask, image_subresource.mip_level) else memory_row_pitch_bytes;
const src_layer_size = if (is_source) memory_slice_pitch_bytes else self.getLayerSize(image_subresource.aspect_mask);
const dst_layer_size = if (is_source) self.getLayerSize(image_subresource.aspect_mask) else memory_slice_pitch_bytes;
@@ -352,8 +360,8 @@ pub fn writeInt4(self: *Self, offset: vk.Offset3D, subresource: vk.ImageSubresou
}
pub fn getTexelMemoryOffsetInSubresource(self: *const Self, offset: vk.Offset3D, subresource: vk.ImageSubresource) usize {
return @as(usize, @intCast(offset.z)) * self.getSliceMemSizeForMipLevel(subresource.aspect_mask, subresource.mip_level) +
@as(usize, @intCast(offset.y)) * self.getRowPitchMemSizeForMipLevel(subresource.aspect_mask, subresource.mip_level) +
return @as(usize, @intCast(offset.z)) * self.interface.getSliceMemSizeForMipLevel(subresource.aspect_mask, subresource.mip_level) +
@as(usize, @intCast(offset.y)) * self.interface.getRowPitchMemSizeForMipLevel(subresource.aspect_mask, subresource.mip_level) +
@as(usize, @intCast(offset.x)) * base.format.texelSize(base.format.fromAspect(self.interface.format, subresource.aspect_mask));
}
@@ -369,7 +377,7 @@ fn getSubresourceOffset(self: *const Self, aspect_mask: vk.ImageAspectFlags, mip
const is_3D = (self.interface.image_type == .@"3d") and self.interface.flags.@"2d_array_compatible_bit";
const layer_offset = if (is_3D)
self.getSliceMemSizeForMipLevel(aspect_mask, mip_level)
self.interface.getSliceMemSizeForMipLevel(aspect_mask, mip_level)
else
self.getLayerSize(aspect_mask);
return offset + layer * layer_offset;
@@ -427,8 +435,8 @@ fn getSubresourceLayout(interface: *const Interface, subresource: vk.ImageSubres
return .{
.offset = try self.getSubresourceOffset(subresource.aspect_mask, subresource.mip_level, subresource.array_layer),
.size = self.getMultiSampledLevelSize(subresource.aspect_mask, subresource.mip_level),
.row_pitch = self.getRowPitchMemSizeForMipLevel(subresource.aspect_mask, subresource.mip_level),
.array_pitch = self.getSliceMemSizeForMipLevel(subresource.aspect_mask, subresource.mip_level),
.row_pitch = self.interface.getRowPitchMemSizeForMipLevel(subresource.aspect_mask, subresource.mip_level),
.array_pitch = self.interface.getSliceMemSizeForMipLevel(subresource.aspect_mask, subresource.mip_level),
.depth_pitch = self.getLayerSize(subresource.aspect_mask),
};
}
@@ -446,7 +454,7 @@ pub inline fn getMultiSampledLevelSize(self: *const Self, aspect_mask: vk.ImageA
}
pub inline fn getMipLevelSize(self: *const Self, aspect_mask: vk.ImageAspectFlags, mip_level: u32) usize {
return self.getSliceMemSizeForMipLevel(aspect_mask, mip_level) * self.getMipLevelExtent(mip_level).depth;
return self.interface.getSliceMemSizeForMipLevel(aspect_mask, mip_level) * self.getMipLevelExtent(mip_level).depth;
}
pub fn getMipLevelExtent(self: *const Self, mip_level: u32) vk.Extent3D {
@@ -463,13 +471,17 @@ pub fn getMipLevelExtent(self: *const Self, mip_level: u32) vk.Extent3D {
return extent;
}
pub fn getSliceMemSizeForMipLevel(self: *const Self, aspect_mask: vk.ImageAspectFlags, mip_level: u32) usize {
pub fn getSliceMemSizeForMipLevel(interface: *const Interface, aspect_mask: vk.ImageAspectFlags, mip_level: u32) usize {
const self: *const Self = @alignCast(@fieldParentPtr("interface", interface));
const mip_extent = self.getMipLevelExtent(mip_level);
const format = self.interface.formatFromAspect(aspect_mask);
return base.format.sliceMemSize(format, mip_extent.width, mip_extent.height);
}
pub fn getRowPitchMemSizeForMipLevel(self: *const Self, aspect_mask: vk.ImageAspectFlags, mip_level: u32) usize {
pub fn getRowPitchMemSizeForMipLevel(interface: *const Interface, aspect_mask: vk.ImageAspectFlags, mip_level: u32) usize {
const self: *const Self = @alignCast(@fieldParentPtr("interface", interface));
const mip_extent = self.getMipLevelExtent(mip_level);
const format = self.interface.formatFromAspect(aspect_mask);
return base.format.pitchMemSize(format, mip_extent.width);
+5 -1
View File
@@ -17,7 +17,7 @@ allocator: std.mem.Allocator,
fn castExtension(comptime ext: vk.ApiInfo) vk.ExtensionProperties {
var props: vk.ExtensionProperties = .{
.extension_name = undefined,
.extension_name = @splat(0),
.spec_version = @bitCast(ext.version),
};
@memcpy(props.extension_name[0..ext.name.len], ext.name);
@@ -25,7 +25,11 @@ fn castExtension(comptime ext: vk.ApiInfo) vk.ExtensionProperties {
}
pub const EXTENSIONS = [_]vk.ExtensionProperties{
//castExtension(vk.extensions.lunarg_direct_driver_loading),
castExtension(vk.extensions.khr_get_physical_device_properties_2),
castExtension(vk.extensions.khr_surface),
castExtension(vk.extensions.khr_wayland_surface),
castExtension(vk.extensions.khr_swapchain),
};
pub fn create(allocator: std.mem.Allocator, infos: *const vk.InstanceCreateInfo) VkError!*Interface {
+11 -1
View File
@@ -8,6 +8,7 @@ const SoftDevice = @import("SoftDevice.zig");
const VkError = base.VkError;
const VulkanAllocator = base.VulkanAllocator;
const SurfaceKHR = base.SurfaceKHR;
const Self = @This();
pub const Interface = base.PhysicalDevice;
@@ -30,8 +31,13 @@ pub fn create(allocator: std.mem.Allocator, instance: *base.Instance) VkError!*S
.getFormatProperties = getFormatProperties,
.getImageFormatProperties = getImageFormatProperties,
.getSparseImageFormatProperties = getSparseImageFormatProperties,
.getSparseImageFormatProperties2 = getSparseImageFormatProperties2,
.release = destroy,
// VK_KHR_get_physical_device_properties_2
.getSparseImageFormatProperties2 = getSparseImageFormatProperties2,
// VK_KHR_surface
.getSurfaceSupportKHR = getSurfaceSupportKHR,
};
interface.props.api_version = @bitCast(lib.VULKAN_VERSION);
@@ -813,3 +819,7 @@ fn checkFormatUsage(usage: vk.ImageUsageFlags, features: vk.FormatFeatureFlags)
return false;
return true;
}
pub fn getSurfaceSupportKHR(_: *Interface, _: u32, _: *SurfaceKHR) VkError!bool {
return true;
}
+8 -8
View File
@@ -98,8 +98,8 @@ pub fn clear(pixel: vk.ClearValue, format: vk.Format, dst: *SoftImage, view_form
.array_layer = range.base_array_layer,
};
const dst_slice_pitch_bytes = dst.getSliceMemSizeForMipLevel(subresource.aspect_mask, subresource.mip_level);
const dst_row_pitch_bytes = dst.getRowPitchMemSizeForMipLevel(subresource.aspect_mask, subresource.mip_level);
const dst_slice_pitch_bytes = dst.interface.getSliceMemSizeForMipLevel(subresource.aspect_mask, subresource.mip_level);
const dst_row_pitch_bytes = dst.interface.getRowPitchMemSizeForMipLevel(subresource.aspect_mask, subresource.mip_level);
const last_mip_level = dst.interface.getLastMipLevel(range);
const last_layer = dst.interface.getLastLayerIndex(range);
@@ -207,8 +207,8 @@ fn fastClear(clear_value: vk.ClearValue, clear_format: vk.Format, dst: *SoftImag
const dst_memory = if (dst.interface.memory) |memory| memory else return VkError.InvalidDeviceMemoryDrv;
while (subresource.mip_level <= last_mip_level) : (subresource.mip_level += 1) {
const dst_slice_pitch_bytes = dst.getSliceMemSizeForMipLevel(subresource.aspect_mask, subresource.mip_level);
const dst_row_pitch_bytes = dst.getRowPitchMemSizeForMipLevel(subresource.aspect_mask, subresource.mip_level);
const dst_slice_pitch_bytes = dst.interface.getSliceMemSizeForMipLevel(subresource.aspect_mask, subresource.mip_level);
const dst_row_pitch_bytes = dst.interface.getRowPitchMemSizeForMipLevel(subresource.aspect_mask, subresource.mip_level);
const extent = dst.getMipLevelExtent(subresource.mip_level);
if (render_area == null) {
@@ -375,10 +375,10 @@ pub fn blitRegion(src: *const SoftImage, dst: *SoftImage, region: vk.ImageBlit,
const y0 = @as(f32, @floatFromInt(src_offset_0.y)) + (0.5 - @as(f32, @floatFromInt(dst_offset_0.y))) * height_ratio;
const z0 = @as(f32, @floatFromInt(src_offset_0.z)) + (0.5 - @as(f32, @floatFromInt(dst_offset_0.z))) * depth_ratio;
const src_slice_pitch_bytes = src.getSliceMemSizeForMipLevel(region.src_subresource.aspect_mask, region.src_subresource.mip_level);
const src_row_pitch_bytes = src.getRowPitchMemSizeForMipLevel(region.src_subresource.aspect_mask, region.src_subresource.mip_level);
const dst_slice_pitch_bytes = dst.getSliceMemSizeForMipLevel(region.dst_subresource.aspect_mask, region.dst_subresource.mip_level);
const dst_row_pitch_bytes = dst.getRowPitchMemSizeForMipLevel(region.dst_subresource.aspect_mask, region.dst_subresource.mip_level);
const src_slice_pitch_bytes = src.interface.getSliceMemSizeForMipLevel(region.src_subresource.aspect_mask, region.src_subresource.mip_level);
const src_row_pitch_bytes = src.interface.getRowPitchMemSizeForMipLevel(region.src_subresource.aspect_mask, region.src_subresource.mip_level);
const dst_slice_pitch_bytes = dst.interface.getSliceMemSizeForMipLevel(region.dst_subresource.aspect_mask, region.dst_subresource.mip_level);
const dst_row_pitch_bytes = dst.interface.getRowPitchMemSizeForMipLevel(region.dst_subresource.aspect_mask, region.dst_subresource.mip_level);
const src_format = base.format.fromAspect(src.interface.format, region.src_subresource.aspect_mask);
const dst_format = base.format.fromAspect(dst.interface.format, region.dst_subresource.aspect_mask);
+1 -1
View File
@@ -80,7 +80,7 @@ pub fn init(allocator: std.mem.Allocator, instance: *Instance, physical_device:
.instance = instance,
.physical_device = physical_device,
.queues = .empty,
.host_allocator = VulkanAllocator.from(allocator).clone(),
.host_allocator = VulkanAllocator.from(allocator).cloneWithScope(.object),
.dispatch_table = undefined,
.vtable = undefined,
};
+3 -3
View File
@@ -23,13 +23,13 @@ pub fn Dispatchable(comptime T: type) type {
return self;
}
pub inline fn intrusiveDestroy(self: *Self, allocator: std.mem.Allocator) void {
pub fn intrusiveDestroy(self: *Self, allocator: std.mem.Allocator) void {
self.object.destroy(allocator);
allocator.destroy(self);
std.log.debug("Destroyed dispatchable handle of type '{s}' at 0x{X}", .{ @typeName(T), @intFromPtr(self) });
}
pub inline fn destroy(self: *Self, allocator: std.mem.Allocator) void {
pub fn destroy(self: *Self, allocator: std.mem.Allocator) void {
allocator.destroy(self);
std.log.debug("Destroyed dispatchable handle of type '{s}' at 0x{X}", .{ @typeName(T), @intFromPtr(self) });
}
@@ -42,7 +42,7 @@ pub fn Dispatchable(comptime T: type) type {
return @enumFromInt(@intFromPtr(self));
}
pub inline fn fromHandle(vk_handle: anytype) VkError!*Self {
pub fn fromHandle(vk_handle: anytype) VkError!*Self {
const handle = @intFromEnum(vk_handle);
if (handle == 0) {
return VkError.InvalidHandleDrv;
+17 -2
View File
@@ -32,6 +32,9 @@ pub const VTable = struct {
getMemoryRequirements: *const fn (*Self, *vk.MemoryRequirements) VkError!void,
getSubresourceLayout: *const fn (*const Self, vk.ImageSubresource) VkError!vk.SubresourceLayout,
getTotalSizeForAspect: *const fn (*const Self, vk.ImageAspectFlags) VkError!usize,
getSliceMemSizeForMipLevel: *const fn (*const Self, vk.ImageAspectFlags, u32) usize,
getRowPitchMemSizeForMipLevel: *const fn (*const Self, vk.ImageAspectFlags, u32) usize,
copyToMemory: *const fn (*const Self, []u8, vk.ImageSubresourceLayers) VkError!void,
};
pub fn init(device: *Device, allocator: std.mem.Allocator, info: *const vk.ImageCreateInfo) VkError!Self {
@@ -58,7 +61,7 @@ pub inline fn destroy(self: *Self, allocator: std.mem.Allocator) void {
self.vtable.destroy(self, allocator);
}
pub inline fn bindMemory(self: *Self, memory: *DeviceMemory, offset: vk.DeviceSize) VkError!void {
pub fn bindMemory(self: *Self, memory: *DeviceMemory, offset: vk.DeviceSize) VkError!void {
const image_size = try self.getTotalSize();
if (offset >= image_size or !self.allowed_memory_types.isSet(memory.memory_type_index)) {
return VkError.ValidationFailed;
@@ -67,12 +70,24 @@ pub inline fn bindMemory(self: *Self, memory: *DeviceMemory, offset: vk.DeviceSi
self.memory_offset = offset;
}
pub inline fn getMemoryRequirements(self: *Self, requirements: *vk.MemoryRequirements) VkError!void {
pub fn getMemoryRequirements(self: *Self, requirements: *vk.MemoryRequirements) VkError!void {
requirements.size = try self.getTotalSize();
requirements.memory_type_bits = self.allowed_memory_types.mask;
try self.vtable.getMemoryRequirements(self, requirements);
}
pub fn getSliceMemSizeForMipLevel(self: *const Self, aspect_mask: vk.ImageAspectFlags, mip_level: u32) usize {
return self.vtable.getSliceMemSizeForMipLevel(self, aspect_mask, mip_level);
}
pub fn getRowPitchMemSizeForMipLevel(self: *const Self, aspect_mask: vk.ImageAspectFlags, mip_level: u32) usize {
return self.vtable.getRowPitchMemSizeForMipLevel(self, aspect_mask, mip_level);
}
pub inline fn copyToMemory(self: *const Self, memory: []u8, subresource: vk.ImageSubresourceLayers) VkError!void {
try self.vtable.copyToMemory(self, memory, subresource);
}
pub inline fn getTexelSize(self: *const Self) usize {
return lib.format.texelSize(self.format);
}
+4 -3
View File
@@ -66,11 +66,12 @@ pub fn enumerateExtensionProperties(layer_name: ?[]const u8, count: *u32, p_prop
if (layer_name) |_| {
return VkError.LayerNotPresent;
}
if (@hasDecl(root, "EXTENSIONS")) {
if (comptime @hasDecl(root.Instance, "EXTENSIONS")) {
count.* = root.Instance.EXTENSIONS.len;
if (p_properties) |properties| {
for (root.Instance.EXTENSIONS, 0..) |ext, i| {
properties[i] = ext;
for (root.Instance.EXTENSIONS, properties[0..]) |ext, *prop| {
prop.* = ext;
}
}
} else {
+7 -3
View File
@@ -20,13 +20,13 @@ pub fn NonDispatchable(comptime T: type) type {
return self;
}
pub inline fn intrusiveDestroy(self: *Self, allocator: std.mem.Allocator) void {
pub fn intrusiveDestroy(self: *Self, allocator: std.mem.Allocator) void {
self.object.destroy(allocator);
allocator.destroy(self);
std.log.debug("Destroyed non dispatchable handle of type '{s}' at 0x{X}", .{ @typeName(T), @intFromPtr(self) });
}
pub inline fn destroy(self: *Self, allocator: std.mem.Allocator) void {
pub fn destroy(self: *Self, allocator: std.mem.Allocator) void {
allocator.destroy(self);
std.log.debug("Destroyed non dispatchable handle of type '{s}' at 0x{X}", .{ @typeName(T), @intFromPtr(self) });
}
@@ -39,7 +39,11 @@ pub fn NonDispatchable(comptime T: type) type {
return @enumFromInt(@intFromPtr(self));
}
pub inline fn fromHandle(vk_handle: anytype) VkError!*Self {
pub fn fromObject(object: *T) *Self {
return @alignCast(@constCast(@fieldParentPtr("object", &object)));
}
pub fn fromHandle(vk_handle: anytype) VkError!*Self {
const handle = @intFromEnum(vk_handle);
if (handle == 0) {
return VkError.InvalidHandleDrv;
+46 -9
View File
@@ -5,6 +5,7 @@ const root = @import("lib.zig");
const Instance = @import("Instance.zig");
const VkError = @import("error_set.zig").VkError;
const Device = @import("Device.zig");
const SurfaceKHR = @import("wsi/SurfaceKHR.zig");
const Self = @This();
pub const ObjectType: vk.ObjectType = .physical_device;
@@ -21,8 +22,13 @@ pub const DispatchTable = struct {
getFormatProperties: *const fn (*Self, vk.Format) VkError!vk.FormatProperties,
getImageFormatProperties: *const fn (*Self, vk.Format, vk.ImageType, vk.ImageTiling, vk.ImageUsageFlags, vk.ImageCreateFlags) VkError!vk.ImageFormatProperties,
getSparseImageFormatProperties: *const fn (*Self, vk.Format, vk.ImageType, vk.SampleCountFlags, vk.ImageTiling, vk.ImageUsageFlags, ?[*]vk.SparseImageFormatProperties) VkError!u32,
getSparseImageFormatProperties2: ?*const fn (*Self, vk.Format, vk.ImageType, vk.SampleCountFlags, vk.ImageTiling, vk.ImageUsageFlags, ?[*]vk.SparseImageFormatProperties2) VkError!u32,
release: *const fn (*Self, std.mem.Allocator) VkError!void,
// VK_KHR_get_physical_device_properties_2
getSparseImageFormatProperties2: ?*const fn (*Self, vk.Format, vk.ImageType, vk.SampleCountFlags, vk.ImageTiling, vk.ImageUsageFlags, ?[*]vk.SparseImageFormatProperties2) VkError!u32,
// VK_KHR_surface
getSurfaceSupportKHR: ?*const fn (*Self, u32, *SurfaceKHR) VkError!bool,
};
pub fn init(allocator: std.mem.Allocator, instance: *Instance) VkError!Self {
@@ -52,15 +58,15 @@ pub fn init(allocator: std.mem.Allocator, instance: *Instance) VkError!Self {
};
}
pub fn createDevice(self: *Self, allocator: std.mem.Allocator, infos: *const vk.DeviceCreateInfo) VkError!*Device {
pub inline fn createDevice(self: *Self, allocator: std.mem.Allocator, infos: *const vk.DeviceCreateInfo) VkError!*Device {
return try self.dispatch_table.createDevice(self, allocator, infos);
}
pub fn getFormatProperties(self: *Self, format: vk.Format) VkError!vk.FormatProperties {
pub inline fn getFormatProperties(self: *Self, format: vk.Format) VkError!vk.FormatProperties {
return try self.dispatch_table.getFormatProperties(self, format);
}
pub fn getImageFormatProperties(
pub inline fn getImageFormatProperties(
self: *Self,
format: vk.Format,
image_type: vk.ImageType,
@@ -71,7 +77,7 @@ pub fn getImageFormatProperties(
return self.dispatch_table.getImageFormatProperties(self, format, image_type, tiling, usage, flags);
}
pub fn getSparseImageFormatProperties(
pub inline fn getSparseImageFormatProperties(
self: *Self,
format: vk.Format,
image_type: vk.ImageType,
@@ -83,6 +89,12 @@ pub fn getSparseImageFormatProperties(
return self.dispatch_table.getSparseImageFormatProperties(self, format, image_type, samples, tiling, usage, properties);
}
pub fn releasePhysicalDevice(self: *Self, allocator: std.mem.Allocator) VkError!void {
self.queue_family_props.deinit(allocator);
self.queue_family_props = .empty;
try self.dispatch_table.release(self, allocator);
}
pub fn getSparseImageFormatProperties2(
self: *Self,
format: vk.Format,
@@ -98,8 +110,33 @@ pub fn getSparseImageFormatProperties2(
0;
}
pub fn releasePhysicalDevice(self: *Self, allocator: std.mem.Allocator) VkError!void {
self.queue_family_props.deinit(allocator);
self.queue_family_props = .empty;
try self.dispatch_table.release(self, allocator);
pub fn getSurfaceCapabilitiesKHR(_: *Self, surface: *SurfaceKHR, capabilities: *vk.SurfaceCapabilitiesKHR) VkError!void {
capabilities.* = try surface.getCapabilities();
}
pub fn getSurfaceFormatsKHR(_: *Self, _: *SurfaceKHR, count: *u32, p_formats: ?[*]vk.SurfaceFormatKHR) VkError!void {
const surface_formats = SurfaceKHR.getFormats();
count.* = surface_formats.len;
if (p_formats) |formats| {
for (formats[0..], surface_formats[0..]) |*format, surface_format| {
format.* = surface_format;
}
}
}
pub fn getSurfacePresentModesKHR(_: *Self, _: *SurfaceKHR, count: *u32, p_modes: ?[*]vk.PresentModeKHR) VkError!void {
const surface_modes = SurfaceKHR.getPresentModes();
count.* = surface_modes.len;
if (p_modes) |modes| {
for (modes[0..], surface_modes[0..]) |*mode, surface_mode| {
mode.* = surface_mode;
}
}
}
pub fn getSurfaceSupportKHR(self: *Self, queue_family_index: u32, surface: *SurfaceKHR) VkError!bool {
return if (self.dispatch_table.getSurfaceSupportKHR) |pfn|
pfn(self, queue_family_index, surface)
else
false;
}
+40 -4
View File
@@ -1,12 +1,18 @@
const std = @import("std");
const vk = @import("vulkan");
const Dispatchable = @import("Dispatchable.zig").Dispatchable;
const VkError = @import("error_set.zig").VkError;
const VulkanAllocator = @import("VulkanAllocator.zig");
const errors = @import("error_set.zig");
const Dispatchable = @import("Dispatchable.zig").Dispatchable;
const NonDispatchable = @import("NonDispatchable.zig").NonDispatchable;
const VkError = errors.VkError;
const VulkanAllocator = @import("VulkanAllocator.zig");
const toVkResult = errors.toVkResult;
const BinarySemaphore = @import("BinarySemaphore.zig");
const CommandBuffer = @import("CommandBuffer.zig");
const Device = @import("Device.zig");
const SwapchainKHR = @import("wsi/SwapchainKHR.zig");
const Fence = @import("Fence.zig");
@@ -76,7 +82,7 @@ pub inline fn bindSparse(self: *Self, info: []const vk.BindSparseInfo, fence: ?*
try self.dispatch_table.bindSparse(self, info, fence);
}
pub inline fn submit(self: *Self, infos: []const vk.SubmitInfo, p_fence: ?*Fence) VkError!void {
pub fn submit(self: *Self, infos: []const vk.SubmitInfo, p_fence: ?*Fence) VkError!void {
if (infos.len == 0) {
if (p_fence) |fence| {
try fence.signal();
@@ -92,6 +98,36 @@ pub inline fn submit(self: *Self, infos: []const vk.SubmitInfo, p_fence: ?*Fence
try self.dispatch_table.submit(self, submit_infos.items, p_fence);
}
pub fn presentKHR(_: *Self, info: *const vk.PresentInfoKHR) VkError!void {
if (info.p_wait_semaphores) |p_wait_semaphores| {
for (p_wait_semaphores[0..], 0..info.wait_semaphore_count) |p_semaphore, _| {
const semaphore = try NonDispatchable(BinarySemaphore).fromHandleObject(p_semaphore);
// TODO: handle semaphores
_ = semaphore;
}
}
var cmd_err: ?VkError = null;
for (info.p_swapchains[0..], info.p_image_indices[0..], 0..info.swapchain_count) |p_swapchain, image_index, i| {
const swapchain = try NonDispatchable(SwapchainKHR).fromHandleObject(p_swapchain);
swapchain.present(image_index) catch |err| {
if (info.p_results) |results| {
results[i] = toVkResult(err);
}
if (cmd_err) |cmd_err_type|
switch (cmd_err_type) {
VkError.SuboptimalKhr => cmd_err = err,
else => {},
}
else
cmd_err = err;
};
}
if (cmd_err) |err|
return err;
}
pub inline fn waitIdle(self: *Self) VkError!void {
try self.dispatch_table.waitIdle(self);
}
+127 -16
View File
@@ -84,7 +84,9 @@ const global_pfn_map = std.StaticStringMap(vk.PfnVoidFunction).initComptime(.{
});
const instance_pfn_map = std.StaticStringMap(vk.PfnVoidFunction).initComptime(.{
functionMapEntryPoint("vkCreateWaylandSurfaceKHR"),
functionMapEntryPoint("vkDestroyInstance"),
functionMapEntryPoint("vkDestroySurfaceKHR"),
functionMapEntryPoint("vkEnumeratePhysicalDevices"),
functionMapEntryPoint("vkGetDeviceProcAddr"),
});
@@ -106,11 +108,17 @@ const physical_device_pfn_map = std.StaticStringMap(vk.PfnVoidFunction).initComp
functionMapEntryPoint("vkGetPhysicalDeviceQueueFamilyProperties2KHR"),
functionMapEntryPoint("vkGetPhysicalDeviceSparseImageFormatProperties"),
functionMapEntryPoint("vkGetPhysicalDeviceSparseImageFormatProperties2KHR"),
functionMapEntryPoint("vkGetPhysicalDeviceSurfaceCapabilitiesKHR"),
functionMapEntryPoint("vkGetPhysicalDeviceSurfaceFormatsKHR"),
functionMapEntryPoint("vkGetPhysicalDeviceSurfacePresentModesKHR"),
functionMapEntryPoint("vkGetPhysicalDeviceSurfaceSupportKHR"),
functionMapEntryPoint("vkGetPhysicalDeviceWaylandPresentationSupportKHR"),
});
const device_pfn_map = block: {
@setEvalBranchQuota(65535);
break :block std.StaticStringMap(vk.PfnVoidFunction).initComptime(.{
functionMapEntryPoint("vkAcquireNextImageKHR"),
functionMapEntryPoint("vkAllocateCommandBuffers"),
functionMapEntryPoint("vkAllocateDescriptorSets"),
functionMapEntryPoint("vkAllocateDescriptorSets"),
@@ -181,6 +189,7 @@ const device_pfn_map = block: {
functionMapEntryPoint("vkCreateSampler"),
functionMapEntryPoint("vkCreateSemaphore"),
functionMapEntryPoint("vkCreateShaderModule"),
functionMapEntryPoint("vkCreateSwapchainKHR"),
functionMapEntryPoint("vkDestroyBuffer"),
functionMapEntryPoint("vkDestroyBufferView"),
functionMapEntryPoint("vkDestroyCommandPool"),
@@ -200,6 +209,7 @@ const device_pfn_map = block: {
functionMapEntryPoint("vkDestroySampler"),
functionMapEntryPoint("vkDestroySemaphore"),
functionMapEntryPoint("vkDestroyShaderModule"),
functionMapEntryPoint("vkDestroySwapchainKHR"),
functionMapEntryPoint("vkDeviceWaitIdle"),
functionMapEntryPoint("vkEndCommandBuffer"),
functionMapEntryPoint("vkFlushMappedMemoryRanges"),
@@ -218,10 +228,12 @@ const device_pfn_map = block: {
functionMapEntryPoint("vkGetPipelineCacheData"),
functionMapEntryPoint("vkGetQueryPoolResults"),
functionMapEntryPoint("vkGetRenderAreaGranularity"),
functionMapEntryPoint("vkGetSwapchainImagesKHR"),
functionMapEntryPoint("vkInvalidateMappedMemoryRanges"),
functionMapEntryPoint("vkMapMemory"),
functionMapEntryPoint("vkMergePipelineCaches"),
functionMapEntryPoint("vkQueueBindSparse"),
functionMapEntryPoint("vkQueuePresentKHR"),
functionMapEntryPoint("vkQueueSubmit"),
functionMapEntryPoint("vkQueueWaitIdle"),
functionMapEntryPoint("vkResetCommandBuffer"),
@@ -2194,6 +2206,19 @@ pub export fn strollResetCommandBuffer(p_cmd: vk.CommandBuffer, flags: vk.Comman
// WSI functions ===================================================================================================================================
pub export fn strollAcquireNextImageKHR(p_device: vk.Device, p_swapchain: vk.SwapchainKHR, timeout: u64, p_semaphore: vk.Semaphore, p_fence: vk.Fence, image_index: *u32) callconv(vk.vulkan_call_conv) vk.Result {
entryPointBeginLogTrace(.vkAcquireNextImageKHR);
defer entryPointEndLogTrace();
Dispatchable(Device).checkHandleValidity(p_device) catch |err| return toVkResult(err);
const swapchain = NonDispatchable(SwapchainKHR).fromHandleObject(p_swapchain) catch |err| return toVkResult(err);
const semaphore = NonDispatchable(BinarySemaphore).fromHandleObject(p_semaphore) catch |err| return toVkResult(err);
const fence = NonDispatchable(Fence).fromHandleObject(p_fence) catch |err| return toVkResult(err);
swapchain.getNextImage(timeout, semaphore, fence, image_index) catch |err| return toVkResult(err);
return .success;
}
pub export fn strollCreateSwapchainKHR(p_device: vk.Device, info: *const vk.SwapchainCreateInfoKHR, callbacks: ?*const vk.AllocationCallbacks, p_swapchain: *vk.SwapchainKHR) callconv(vk.vulkan_call_conv) vk.Result {
entryPointBeginLogTrace(.vkCreateSwapchainKHR);
defer entryPointEndLogTrace();
@@ -2201,13 +2226,47 @@ pub export fn strollCreateSwapchainKHR(p_device: vk.Device, info: *const vk.Swap
if (info.s_type != .swapchain_create_info_khr) {
return .error_validation_failed;
}
if (info.old_swapchain != .null_handle) {
const old_swapchain = NonDispatchable(SwapchainKHR).fromHandleObject(info.old_swapchain) catch |err| return toVkResult(err);
old_swapchain.detachSurface() catch |err| return toVkResult(err);
}
const allocator = VulkanAllocator.init(callbacks, .object).allocator();
const device = Dispatchable(Device).fromHandleObject(p_device) catch |err| return toVkResult(err);
const surface = NonDispatchable(SurfaceKHR).fromHandleObject(info.surface) catch |err| return toVkResult(err);
const swapchain = SwapchainKHR.create(device, allocator, info) catch |err| return toVkResult(err);
swapchain.surface = surface;
surface.swapchain = swapchain;
p_swapchain.* = (NonDispatchable(SwapchainKHR).wrap(allocator, swapchain) catch |err| return toVkResult(err)).toVkHandle(vk.SwapchainKHR);
return .success;
}
pub export fn strollCreateWaylandSurfaceKHR(p_instance: vk.Instance, info: *const vk.WaylandSurfaceCreateInfoKHR, callbacks: ?*const vk.AllocationCallbacks, p_surface: *vk.SurfaceKHR) callconv(vk.vulkan_call_conv) vk.Result {
entryPointBeginLogTrace(.vkCreateWaylandSurfaceKHR);
defer entryPointEndLogTrace();
if (info.s_type != .wayland_surface_create_info_khr) {
return .error_validation_failed;
}
const allocator = VulkanAllocator.init(callbacks, .object).allocator();
const instance = Dispatchable(Instance).fromHandleObject(p_instance) catch |err| return toVkResult(err);
const surface = WaylandSurfaceKHR.create(instance, allocator, info) catch |err| return toVkResult(err);
p_surface.* = (NonDispatchable(SurfaceKHR).wrap(allocator, surface) catch |err| return toVkResult(err)).toVkHandle(vk.SurfaceKHR);
return .success;
}
pub export fn strollDestroySurfaceKHR(p_instance: vk.Instance, p_surface: vk.SurfaceKHR, callbacks: ?*const vk.AllocationCallbacks) callconv(vk.vulkan_call_conv) void {
entryPointBeginLogTrace(.vkDestroySurfaceKHR);
defer entryPointEndLogTrace();
NonDispatchable(Instance).checkHandleValidity(p_instance) catch |err| return errorLogger(err);
const allocator = VulkanAllocator.init(callbacks, .object).allocator();
const non_dispatchable = NonDispatchable(SurfaceKHR).fromHandle(p_surface) catch |err| return errorLogger(err);
non_dispatchable.intrusiveDestroy(allocator);
}
pub export fn strollDestroySwapchainKHR(p_device: vk.Device, p_swapchain: vk.SwapchainKHR, callbacks: ?*const vk.AllocationCallbacks) callconv(vk.vulkan_call_conv) void {
entryPointBeginLogTrace(.vkDestroySwapchainKHR);
defer entryPointEndLogTrace();
@@ -2219,27 +2278,79 @@ pub export fn strollDestroySwapchainKHR(p_device: vk.Device, p_swapchain: vk.Swa
non_dispatchable.intrusiveDestroy(allocator);
}
pub export fn strollCreateWaylandSurfaceKHR(p_device: vk.Device, info: *const vk.WaylandSurfaceCreateInfoKHR, callbacks: ?*const vk.AllocationCallbacks, p_surface: *vk.SurfaceKHR) callconv(vk.vulkan_call_conv) vk.Result {
entryPointBeginLogTrace(.vkCreateWaylandSurfaceKHR);
pub export fn strollGetPhysicalDeviceSurfaceCapabilitiesKHR(p_physical_device: vk.PhysicalDevice, p_surface: vk.SurfaceKHR, capabilities: *vk.SurfaceCapabilitiesKHR) callconv(vk.vulkan_call_conv) vk.Result {
entryPointBeginLogTrace(.vkGetPhysicalDeviceSurfaceCapabilitiesKHR);
defer entryPointEndLogTrace();
if (info.s_type != .wayland_surface_create_info_khr) {
return .error_validation_failed;
}
const allocator = VulkanAllocator.init(callbacks, .object).allocator();
const device = Dispatchable(Device).fromHandleObject(p_device) catch |err| return toVkResult(err);
const surface = WaylandSurfaceKHR.create(device, allocator, info) catch |err| return toVkResult(err);
p_surface.* = (NonDispatchable(SurfaceKHR).wrap(allocator, surface) catch |err| return toVkResult(err)).toVkHandle(vk.SurfaceKHR);
const physical_device = Dispatchable(PhysicalDevice).fromHandleObject(p_physical_device) catch |err| return toVkResult(err);
const surface = NonDispatchable(SurfaceKHR).fromHandleObject(p_surface) catch |err| return toVkResult(err);
physical_device.getSurfaceCapabilitiesKHR(surface, capabilities) catch |err| return toVkResult(err);
return .success;
}
pub export fn strollDestroySurfaceKHR(p_device: vk.Device, p_surface: vk.SurfaceKHR, callbacks: ?*const vk.AllocationCallbacks) callconv(vk.vulkan_call_conv) void {
entryPointBeginLogTrace(.vkDestroySurfaceKHR);
pub export fn strollGetPhysicalDeviceSurfaceFormatsKHR(p_physical_device: vk.PhysicalDevice, p_surface: vk.SurfaceKHR, count: *u32, p_formats: ?[*]vk.SurfaceFormatKHR) callconv(vk.vulkan_call_conv) vk.Result {
entryPointBeginLogTrace(.vkGetPhysicalDeviceSurfaceFormatsKHR);
defer entryPointEndLogTrace();
Dispatchable(Device).checkHandleValidity(p_device) catch |err| return errorLogger(err);
const allocator = VulkanAllocator.init(callbacks, .object).allocator();
const non_dispatchable = NonDispatchable(SurfaceKHR).fromHandle(p_surface) catch |err| return errorLogger(err);
non_dispatchable.intrusiveDestroy(allocator);
const physical_device = Dispatchable(PhysicalDevice).fromHandleObject(p_physical_device) catch |err| return toVkResult(err);
const surface = NonDispatchable(SurfaceKHR).fromHandleObject(p_surface) catch |err| return toVkResult(err);
physical_device.getSurfaceFormatsKHR(surface, count, p_formats) catch |err| return toVkResult(err);
return .success;
}
pub export fn strollGetPhysicalDeviceSurfacePresentModesKHR(p_physical_device: vk.PhysicalDevice, p_surface: vk.SurfaceKHR, count: *u32, p_modes: ?[*]vk.PresentModeKHR) callconv(vk.vulkan_call_conv) vk.Result {
entryPointBeginLogTrace(.vkGetPhysicalDeviceSurfacePresentModesKHR);
defer entryPointEndLogTrace();
const physical_device = Dispatchable(PhysicalDevice).fromHandleObject(p_physical_device) catch |err| return toVkResult(err);
const surface = NonDispatchable(SurfaceKHR).fromHandleObject(p_surface) catch |err| return toVkResult(err);
physical_device.getSurfacePresentModesKHR(surface, count, p_modes) catch |err| return toVkResult(err);
return .success;
}
pub export fn strollGetPhysicalDeviceSurfaceSupportKHR(p_physical_device: vk.PhysicalDevice, queue_family_index: u32, p_surface: vk.SurfaceKHR, p_supported: *vk.Bool32) callconv(vk.vulkan_call_conv) vk.Result {
entryPointBeginLogTrace(.vkGetPhysicalDeviceSurfaceSupportKHR);
defer entryPointEndLogTrace();
const physical_device = Dispatchable(PhysicalDevice).fromHandleObject(p_physical_device) catch |err| return toVkResult(err);
const surface = NonDispatchable(SurfaceKHR).fromHandleObject(p_surface) catch |err| return toVkResult(err);
p_supported.* = if (physical_device.getSurfaceSupportKHR(queue_family_index, surface) catch |err| return toVkResult(err)) .true else .false;
return .success;
}
pub export fn strollGetPhysicalDeviceWaylandPresentationSupportKHR(p_physical_device: vk.PhysicalDevice, _: u32, _: *anyopaque) callconv(vk.vulkan_call_conv) vk.Bool32 {
entryPointBeginLogTrace(.vkGetPhysicalDeviceWaylandPresentationSupportKHR);
defer entryPointEndLogTrace();
Dispatchable(PhysicalDevice).checkHandleValidity(p_physical_device) catch |err| errorLogger(err);
return .true;
}
pub export fn strollGetSwapchainImagesKHR(p_device: vk.Device, p_swapchain: vk.SwapchainKHR, count: *u32, p_images: ?[*]vk.Image) callconv(vk.vulkan_call_conv) vk.Result {
entryPointBeginLogTrace(.vkGetSwapchainImagesKHR);
defer entryPointEndLogTrace();
Dispatchable(Device).checkHandleValidity(p_device) catch |err| return toVkResult(err);
const swapchain = NonDispatchable(SwapchainKHR).fromHandleObject(p_swapchain) catch |err| return toVkResult(err);
count.* = @intCast(swapchain.images.len);
if (p_images) |images| {
for (images[0..], swapchain.images[0..]) |*image, swapchain_image| {
image.* = NonDispatchable(Image).fromObject(swapchain_image.image).toVkHandle(vk.Image);
}
}
return .success;
}
pub export fn strollQueuePresentKHR(p_queue: vk.Queue, info: *const vk.PresentInfoKHR) callconv(vk.vulkan_call_conv) vk.Result {
entryPointBeginLogTrace(.vkQueuePresentKHR);
defer entryPointEndLogTrace();
if (info.s_type != .present_info_khr) {
return .error_validation_failed;
}
const queue = Dispatchable(Queue).fromHandleObject(p_queue) catch |err| return toVkResult(err);
queue.presentKHR(info) catch |err| return toVkResult(err);
return .success;
}
+8 -8
View File
@@ -4,7 +4,7 @@ const lib = @import("../lib.zig");
const VkError = @import("../error_set.zig").VkError;
const Device = @import("../Device.zig");
const Instance = lib.Instance;
const PresentImage = @import("PresentImage.zig");
const SwapchainKHR = @import("SwapchainKHR.zig");
@@ -20,7 +20,7 @@ const present_modes = [_]vk.PresentModeKHR{
.immediate_khr,
};
owner: *Device,
owner: *Instance,
swapchain: ?*SwapchainKHR,
vtable: *const VTable,
@@ -33,10 +33,10 @@ pub const VTable = struct {
presentImage: *const fn (*Self, std.mem.Allocator, *PresentImage) VkError!void,
};
pub fn init(device: *Device, allocator: std.mem.Allocator) VkError!Self {
pub fn init(instance: *Instance, allocator: std.mem.Allocator) VkError!Self {
_ = allocator;
return .{
.owner = device,
.owner = instance,
.swapchain = null,
.vtable = undefined,
};
@@ -83,10 +83,10 @@ pub inline fn presentImage(self: *Self, allocator: std.mem.Allocator, image: *Pr
try self.vtable.presentImage(self, allocator, image);
}
pub inline fn getFormats() []vk.SurfaceFormatKHR {
return formats;
pub inline fn getFormats() []const vk.SurfaceFormatKHR {
return &formats;
}
pub inline fn getPresentModes() []vk.PresentModeKHR {
return present_modes;
pub inline fn getPresentModes() []const vk.PresentModeKHR {
return &present_modes;
}
+47 -6
View File
@@ -4,16 +4,18 @@ const lib = @import("../lib.zig");
const VkError = @import("../error_set.zig").VkError;
const BinarySemaphore = lib.BinarySemaphore;
const Device = @import("../Device.zig");
const SurfaceKHR = @import("SurfaceKHR.zig");
const Fence = lib.Fence;
const Image = lib.Image;
const PresentImage = @import("PresentImage.zig");
const Image = @import("../Image.zig");
const SurfaceKHR = lib.SurfaceKHR;
const Self = @This();
pub const ObjectType: vk.ObjectType = .swapchain_khr;
owner: *Device,
surface: *SurfaceKHR,
surface: ?*SurfaceKHR,
images: []PresentImage,
pub fn create(device: *Device, allocator: std.mem.Allocator, info: *const vk.SwapchainCreateInfoKHR) VkError!*Self {
@@ -48,19 +50,58 @@ pub fn create(device: *Device, allocator: std.mem.Allocator, info: *const vk.Swa
self.* = .{
.owner = device,
.surface = undefined,
.surface = null,
.images = images,
};
return self;
}
pub fn getImage(self: *const Self, index: usize) VkError!*Image {
return if (index < self.images.len) self.images[index].image else VkError.Incomplete;
pub fn getNextImage(self: *const Self, timeout: u64, semaphore: *BinarySemaphore, fence: *Fence, index: *u32) VkError!void {
// TODO: handle timeout correctly
for (self.images, 0..) |*image, i| {
if (image.state == .Available) {
image.state = .Drawing;
index.* = @intCast(i);
// TODO: signal semaphore
_ = semaphore;
try fence.signal();
return;
}
}
return if (timeout > 0) VkError.Timeout else VkError.NotReady;
}
pub fn present(self: *Self, index: usize) VkError!void {
const allocator = self.owner.host_allocator.allocator();
const image = &self.images[index];
if (self.surface) |surface| {
image.state = .Presenting;
try surface.presentImage(allocator, image);
}
}
pub fn detachSurface(self: *Self) VkError!void {
const allocator = self.owner.host_allocator.allocator();
if (self.surface) |surface| {
surface.swapchain = null;
for (self.images) |*image| {
if (image.state == .Available)
try surface.detachImage(allocator, image);
}
}
self.surface = null;
}
pub fn destroy(self: *Self, allocator: std.mem.Allocator) void {
if (self.surface) |surface| {
for (self.images) |*image| {
surface.detachImage(allocator, image) catch {};
image.deinit(allocator);
}
}
allocator.destroy(self);
}
+78 -12
View File
@@ -6,14 +6,17 @@ const wayland = @import("clients/wayland.zig");
const PresentImage = @import("PresentImage.zig");
const VkError = @import("../error_set.zig").VkError;
const Device = @import("../Device.zig");
const Instance = lib.Instance;
const Self = @This();
pub const Interface = @import("SurfaceKHR.zig");
const WaylandImage = struct {
buffer: *wayland.wl_buffer,
data: []u8,
data: []align(std.heap.page_size_min) u8,
width: u32,
height: u32,
stride: u32,
};
fn wlRegistryHandleGlobal(data: *anyopaque, registry: *wayland.wl_registry, name: c_uint, interface: [*:0]const u8, _: c_uint) callconv(.c) void {
@@ -38,13 +41,13 @@ surface: *wayland.wl_surface,
shm: *wayland.wl_shm,
image_map: std.AutoHashMapUnmanaged(*PresentImage, *WaylandImage),
pub fn create(device: *Device, allocator: std.mem.Allocator, info: *const vk.WaylandSurfaceCreateInfoKHR) VkError!*Interface {
pub fn create(instance: *Instance, allocator: std.mem.Allocator, info: *const vk.WaylandSurfaceCreateInfoKHR) VkError!*Interface {
const self = allocator.create(Self) catch return VkError.OutOfHostMemory;
errdefer allocator.destroy(self);
try wayland.load();
var interface = try Interface.init(device, allocator);
var interface = try Interface.init(instance, allocator);
interface.vtable = &.{
.destroy = destroy,
@@ -84,21 +87,84 @@ pub fn getCapabilities(interface: *const Interface, capabilities: *vk.SurfaceCap
pub fn attachImage(interface: *Interface, allocator: std.mem.Allocator, image: *PresentImage) VkError!void {
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
_ = self;
_ = image;
_ = allocator;
if (self.image_map.contains(image))
return;
const width: u32 = image.image.extent.width;
const height: u32 = image.image.extent.height;
const stride: u32 = @intCast(image.image.getRowPitchMemSizeForMipLevel(.{ .color_bit = true }, 0));
const size: usize = @as(usize, stride) * @as(usize, height);
const wl_image = allocator.create(WaylandImage) catch return VkError.OutOfHostMemory;
errdefer allocator.destroy(wl_image);
const fd = try createShmFile(size);
defer _ = std.c.close(fd);
const data = std.posix.mmap(null, size, .{ .READ = true, .WRITE = true }, .{ .TYPE = .SHARED }, fd, 0) catch return VkError.OutOfHostMemory;
errdefer std.posix.munmap(data);
const pool = wayland.wl_shm_create_pool(self.shm, fd, @intCast(size)) orelse return VkError.Unknown;
defer wayland.wl_shm_pool_destroy(pool);
const buffer = wayland.wl_shm_pool_create_buffer(pool, 0, @intCast(width), @intCast(height), @intCast(stride), wayland.WL_SHM_FORMAT_ARGB8888) orelse return VkError.Unknown;
errdefer wayland.wl_buffer_destroy(buffer);
wl_image.* = .{
.buffer = buffer,
.data = data,
.width = width,
.height = height,
.stride = stride,
};
self.image_map.put(allocator, image, wl_image) catch return VkError.OutOfHostMemory;
}
pub fn detachImage(interface: *Interface, allocator: std.mem.Allocator, image: *PresentImage) VkError!void {
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
_ = self;
_ = image;
_ = allocator;
const entry = self.image_map.fetchRemove(image) orelse return;
const wl_image = entry.value;
wayland.wl_buffer_destroy(wl_image.buffer);
std.posix.munmap(wl_image.data);
allocator.destroy(wl_image);
}
pub fn presentImage(interface: *Interface, allocator: std.mem.Allocator, image: *PresentImage) VkError!void {
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
_ = self;
_ = image;
_ = allocator;
const wl_image = self.image_map.get(image) orelse return VkError.Unknown;
try image.image.copyToMemory(wl_image.data, .{
.aspect_mask = .{ .color_bit = true },
.mip_level = 0,
.base_array_layer = 0,
.layer_count = 1,
});
wayland.wl_surface_attach(self.surface, wl_image.buffer, 0, 0);
wayland.wl_surface_damage(self.surface, 0, 0, @intCast(wl_image.width), @intCast(wl_image.height));
wayland.wl_surface_commit(self.surface);
// Better: bind wl_display_flush in wayland.zig and call it here.
// With the currently available bindings, roundtrip forces the commit out,
// but it is heavier than necessary.
_ = wayland.wl_display_roundtrip(self.display);
image.state = .Available;
}
fn createShmFile(size: usize) VkError!std.posix.fd_t {
const name = "stroll_vk_wayland_surface";
const fd = std.posix.memfd_create(name, std.posix.FD_CLOEXEC) catch return VkError.Unknown;
errdefer std.c.close(fd);
_ = std.c.ftruncate(fd, @intCast(size));
return fd;
}
+7 -1
View File
@@ -9,6 +9,8 @@ pub const wl_registry_listener = extern struct {
global_remove: *const fn (*anyopaque, *wl_registry, c_uint) callconv(.c) void,
};
pub const WL_SHM_FORMAT_ARGB8888 = 0;
pub const wl_buffer = opaque {};
pub const wl_callback = opaque {};
pub const wl_display = vk.wl_display;
@@ -42,8 +44,12 @@ pub fn load() VkError!void {
if (ref_count.load(.monotonic) != 0)
return;
module = std.DynLib.open("libwayland-client.so.0") catch return VkError.Unknown;
module = std.DynLib.open("libwayland-client.so.0") catch {
_ = ref_count.fetchSub(1, .monotonic);
return VkError.Unknown;
};
errdefer module.close();
errdefer std.debug.print("test {s}\n", .{std.c.dlerror().?});
// zig fmt: off
wl_display_dispatch = module.lookup(@TypeOf(wl_display_dispatch), "wl_display_dispatch" ) orelse return VkError.Unknown;