Files
VulkanDriver/src/intel/FlintDescriptorSet.zig
T
kbz_8 9b1b223186
Test / build_and_test (push) Successful in 5m16s
Build / build (push) Successful in 6m50s
adding backend agnostic IR
2026-07-20 22:07:41 +02:00

174 lines
6.1 KiB
Zig

const std = @import("std");
const vk = @import("vulkan");
const base = @import("base");
const VkError = base.VkError;
const NonDispatchable = base.NonDispatchable;
const Self = @This();
pub const Interface = base.DescriptorSet;
pub const DescriptorBuffer = struct {
buffer: ?*base.Buffer,
offset: vk.DeviceSize,
size: vk.DeviceSize,
};
const Descriptor = union(enum) {
buffer: []DescriptorBuffer,
unsupported,
};
interface: Interface,
heap: []u8,
descriptors: []Descriptor,
pub fn create(device: *base.Device, allocator: std.mem.Allocator, layout: *base.DescriptorSetLayout) VkError!*Self {
const self = allocator.create(Self) catch return VkError.OutOfHostMemory;
errdefer allocator.destroy(self);
var interface = try Interface.init(device, allocator, layout);
interface.vtable = &.{
.copy = copy,
.destroy = destroy,
.write = write,
};
var heap_size = layout.bindings.len * @sizeOf(Descriptor);
for (layout.bindings) |binding| {
heap_size += switch (binding.descriptor_type) {
.uniform_buffer,
.uniform_buffer_dynamic,
.storage_buffer,
.storage_buffer_dynamic,
=> binding.array_size * @sizeOf(DescriptorBuffer),
else => 0,
};
}
const heap = allocator.alloc(u8, heap_size) catch return VkError.OutOfHostMemory;
errdefer allocator.free(heap);
var fixed = std.heap.FixedBufferAllocator.init(heap);
const descriptors = fixed.allocator().alloc(Descriptor, layout.bindings.len) catch return VkError.OutOfHostMemory;
for (descriptors, layout.bindings) |*descriptor, binding| {
descriptor.* = switch (binding.descriptor_type) {
.uniform_buffer, .uniform_buffer_dynamic, .storage_buffer, .storage_buffer_dynamic => blk: {
const buffers = fixed.allocator().alloc(DescriptorBuffer, binding.array_size) catch return VkError.OutOfHostMemory;
for (buffers) |*buffer| {
buffer.* = .{
.buffer = null,
.offset = 0,
.size = 0,
};
}
break :blk .{ .buffer = buffers };
},
else => .unsupported,
};
}
self.* = .{
.interface = interface,
.heap = heap,
.descriptors = descriptors,
};
return self;
}
pub fn destroy(interface: *Interface, allocator: std.mem.Allocator) void {
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
allocator.free(self.heap);
allocator.destroy(self);
}
pub fn copy(interface: *Interface, src_interface: *const Interface, data: vk.CopyDescriptorSet) VkError!void {
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
const src: *const Self = @alignCast(@fieldParentPtr("interface", src_interface));
if (data.dst_binding >= self.descriptors.len or data.src_binding >= src.descriptors.len)
return VkError.ValidationFailed;
const dst = switch (self.descriptors[data.dst_binding]) {
.buffer => |buffers| buffers,
.unsupported => return VkError.FeatureNotPresent,
};
const source = switch (src.descriptors[data.src_binding]) {
.buffer => |buffers| buffers,
.unsupported => return VkError.FeatureNotPresent,
};
const dst_start: usize = @intCast(data.dst_array_element);
const src_start: usize = @intCast(data.src_array_element);
const count: usize = @intCast(data.descriptor_count);
if (dst_start > dst.len or count > dst.len - dst_start)
return VkError.ValidationFailed;
if (src_start > source.len or count > source.len - src_start)
return VkError.ValidationFailed;
@memcpy(dst[dst_start .. dst_start + count], source[src_start .. src_start + count]);
}
pub fn write(interface: *Interface, write_data: vk.WriteDescriptorSet) VkError!void {
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
switch (write_data.descriptor_type) {
.uniform_buffer,
.uniform_buffer_dynamic,
.storage_buffer,
.storage_buffer_dynamic,
=> {
if (write_data.dst_binding >= self.descriptors.len)
return VkError.ValidationFailed;
const descriptors = switch (self.descriptors[write_data.dst_binding]) {
.buffer => |buffers| buffers,
.unsupported => return VkError.FeatureNotPresent,
};
const start: usize = @intCast(write_data.dst_array_element);
const count: usize = @intCast(write_data.descriptor_count);
if (start > descriptors.len or count > descriptors.len - start)
return VkError.ValidationFailed;
for (write_data.p_buffer_info, 0..write_data.descriptor_count) |buffer_info, index| {
const descriptor = &descriptors[start + index];
descriptor.* = .{ .buffer = null, .offset = buffer_info.offset, .size = buffer_info.range };
if (buffer_info.buffer == .null_handle)
continue;
const buffer = try NonDispatchable(base.Buffer).fromHandleObject(buffer_info.buffer);
if (descriptor.offset > buffer.size)
return VkError.ValidationFailed;
if (descriptor.size == vk.WHOLE_SIZE)
descriptor.size = buffer.size - descriptor.offset;
if (descriptor.size > buffer.size - descriptor.offset)
return VkError.ValidationFailed;
descriptor.buffer = buffer;
}
},
else => return VkError.FeatureNotPresent,
}
}
pub fn getBuffer(self: *const Self, binding: u32, array_element: u32) VkError!DescriptorBuffer {
if (binding >= self.descriptors.len) return VkError.ValidationFailed;
const buffers = switch (self.descriptors[binding]) {
.buffer => |items| items,
.unsupported => return VkError.FeatureNotPresent,
};
if (array_element >= buffers.len) return VkError.ValidationFailed;
return buffers[array_element];
}