adding backend agnostic IR
This commit is contained in:
@@ -3,11 +3,25 @@ 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;
|
||||
@@ -21,26 +35,139 @@ pub fn create(device: *base.Device, allocator: std.mem.Allocator, layout: *base.
|
||||
.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));
|
||||
_ = self;
|
||||
_ = src_interface;
|
||||
_ = data;
|
||||
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));
|
||||
_ = self;
|
||||
_ = write_data;
|
||||
|
||||
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];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user