[Phi] fixing device memory creation, implemented AVX copy and fill for
vkCmdCopyBuffers and vkCmdFillBuffer
This commit is contained in:
+113
-39
@@ -13,14 +13,42 @@ const Self = @This();
|
||||
pub const Interface = base.DeviceMemory;
|
||||
|
||||
interface: Interface,
|
||||
|
||||
remote_handle: u64,
|
||||
scif_offset: ?u64,
|
||||
|
||||
/// Size of the region registered with SCIF.
|
||||
/// This is allocation size rounded up to page size.
|
||||
registered_size: usize,
|
||||
|
||||
/// Bytes exposed through vkMapMemory.
|
||||
/// For HOST_VISIBLE memory this is a slice of host_backing.
|
||||
data: ?[]u8,
|
||||
|
||||
/// Full page-aligned/page-rounded allocation registered with SCIF.
|
||||
host_backing: ?[]u8,
|
||||
|
||||
pub fn create(device: *PhiDevice, allocator: std.mem.Allocator, size: vk.DeviceSize, memory_type_index: u32) VkError!*Self {
|
||||
if (memory_type_index >= device.interface.physical_device.mem_props.memory_type_count) {
|
||||
return VkError.ValidationFailed;
|
||||
}
|
||||
|
||||
const allocation_size =
|
||||
std.math.cast(usize, size) orelse return VkError.OutOfDeviceMemory;
|
||||
|
||||
const memory_type =
|
||||
device.interface.physical_device.mem_props.memory_types[memory_type_index];
|
||||
|
||||
const host_visible = memory_type.property_flags.host_visible_bit;
|
||||
|
||||
const self = allocator.create(Self) catch return VkError.OutOfHostMemory;
|
||||
errdefer allocator.destroy(self);
|
||||
|
||||
var interface = try Interface.init(&device.interface, size, memory_type_index);
|
||||
var interface = try Interface.init(
|
||||
&device.interface,
|
||||
size,
|
||||
memory_type_index,
|
||||
);
|
||||
|
||||
interface.vtable = &.{
|
||||
.destroy = destroy,
|
||||
@@ -30,68 +58,109 @@ pub fn create(device: *PhiDevice, allocator: std.mem.Allocator, size: vk.DeviceS
|
||||
.invalidateRange = invalidateRange,
|
||||
};
|
||||
|
||||
if (memory_type_index >= device.interface.physical_device.mem_props.memory_type_count) {
|
||||
return VkError.ValidationFailed;
|
||||
}
|
||||
if (host_visible) {
|
||||
const page_size = std.heap.pageSize();
|
||||
const registered_size = std.mem.alignForward(usize, allocation_size, page_size);
|
||||
|
||||
const memory_type = device.interface.physical_device.mem_props.memory_types[memory_type_index];
|
||||
const host_visible = memory_type.property_flags.host_visible_bit;
|
||||
const device_local = memory_type.property_flags.device_local_bit;
|
||||
const allocation_size = std.math.cast(usize, size) orelse return VkError.OutOfDeviceMemory;
|
||||
// This needs to be page aligned
|
||||
const backing = device.interface.device_allocator.allocator().alignedAlloc(u8, .fromByteUnits(std.heap.page_size_max), registered_size) catch return VkError.OutOfHostMemory;
|
||||
errdefer device.interface.device_allocator.allocator().free(backing);
|
||||
|
||||
const remote_handle = if (device_local) blk: {
|
||||
const alloc_request: proto.PhiAllocMemoryRequest = .{
|
||||
.size = size,
|
||||
.memory_type_index = memory_type_index,
|
||||
.flags = 0,
|
||||
const offset = device.transport.registerHostMemory(backing) catch return VkError.OutOfHostMemory;
|
||||
errdefer device.transport.unregisterHostMemory(offset, backing.len) catch {};
|
||||
|
||||
const request: proto.PhiMapHostMemoryRequest = .{
|
||||
.scif_offset = offset,
|
||||
.scif_size = backing.len,
|
||||
.size = allocation_size,
|
||||
};
|
||||
|
||||
var reply = std.mem.zeroes(proto.PhiAllocMemoryReply);
|
||||
try device.transport.request(proto.PHI_PACKET_ALLOC_MEMORY, std.mem.asBytes(&alloc_request), std.mem.asBytes(&reply));
|
||||
var reply = std.mem.zeroes(proto.PhiNewMemoryReply);
|
||||
|
||||
try device.transport.request(
|
||||
proto.PHI_PACKET_MAP_HOST_MEMORY,
|
||||
std.mem.asBytes(&request),
|
||||
std.mem.asBytes(&reply),
|
||||
);
|
||||
|
||||
if (reply.result.status != proto.PHI_STATUS_OK) {
|
||||
return PhiTransport.statusToErr(reply.result.status);
|
||||
}
|
||||
|
||||
std.log.scoped(.PhiDeviceMemory).info("Recieved remote handle 0x{X}", .{reply.remote_handle});
|
||||
self.* = .{
|
||||
.interface = interface,
|
||||
.remote_handle = reply.remote_handle,
|
||||
.scif_offset = offset,
|
||||
.registered_size = registered_size,
|
||||
.data = backing[0..allocation_size],
|
||||
.host_backing = backing,
|
||||
};
|
||||
} else {
|
||||
const request: proto.PhiAllocMemoryRequest = .{
|
||||
.size = size,
|
||||
.memory_type_index = memory_type_index,
|
||||
.flags = 0,
|
||||
};
|
||||
|
||||
break :blk reply.remote_handle;
|
||||
} else 0;
|
||||
errdefer if (remote_handle != 0) self.interface.destroy(allocator);
|
||||
var reply = std.mem.zeroes(proto.PhiNewMemoryReply);
|
||||
|
||||
const data = if (host_visible)
|
||||
device.interface.device_allocator.allocator().alloc(u8, allocation_size) catch return VkError.OutOfDeviceMemory
|
||||
else
|
||||
null;
|
||||
try device.transport.request(
|
||||
proto.PHI_PACKET_ALLOC_MEMORY,
|
||||
std.mem.asBytes(&request),
|
||||
std.mem.asBytes(&reply),
|
||||
);
|
||||
|
||||
self.* = .{
|
||||
.interface = interface,
|
||||
.remote_handle = remote_handle,
|
||||
.data = data,
|
||||
};
|
||||
if (reply.result.status != proto.PHI_STATUS_OK) {
|
||||
return PhiTransport.statusToErr(reply.result.status);
|
||||
}
|
||||
|
||||
self.* = .{
|
||||
.interface = interface,
|
||||
.remote_handle = reply.remote_handle,
|
||||
.scif_offset = null,
|
||||
.registered_size = 0,
|
||||
.data = null,
|
||||
.host_backing = null,
|
||||
};
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn destroy(interface: *Interface, allocator: std.mem.Allocator) void {
|
||||
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
|
||||
const device: *PhiDevice = @alignCast(@fieldParentPtr("interface", interface.owner));
|
||||
if (self.data) |data| {
|
||||
interface.owner.device_allocator.allocator().free(data);
|
||||
}
|
||||
const self: *Self =
|
||||
@alignCast(@fieldParentPtr("interface", interface));
|
||||
|
||||
const device: *PhiDevice =
|
||||
@alignCast(@fieldParentPtr("interface", interface.owner));
|
||||
|
||||
if (self.remote_handle != 0) {
|
||||
const request_payload: proto.PhiFreeMemoryRequest = .{
|
||||
const request_payload: proto.PhiDestroyMemoryRequest = .{
|
||||
.remote_handle = self.remote_handle,
|
||||
};
|
||||
var reply: proto.PhiFreeMemoryReply = undefined;
|
||||
device.transport.request(proto.PHI_PACKET_FREE_MEMORY, std.mem.asBytes(&request_payload), std.mem.asBytes(&reply)) catch |err| {
|
||||
std.log.scoped(.PhiTransport).err("Remote free failed: {s}", .{@errorName(err)});
|
||||
|
||||
var reply = std.mem.zeroes(proto.PhiResultReply);
|
||||
|
||||
device.transport.request(proto.PHI_PACKET_DESTROY_MEMORY, std.mem.asBytes(&request_payload), std.mem.asBytes(&reply)) catch |err| {
|
||||
std.log.scoped(.PhiDeviceMemory).err("Remote free/unmap failed for handle 0x{X}: {s}", .{ self.remote_handle, @errorName(err) });
|
||||
return;
|
||||
};
|
||||
|
||||
if (reply.result.status != proto.PHI_STATUS_OK) {
|
||||
std.log.scoped(.PhiTransport).err("Remote free returned status {d}", .{reply.result.status});
|
||||
std.log.scoped(.PhiDeviceMemory).err("Remote free/unmap for handle 0x{X} returned status {d}", .{ self.remote_handle, reply.result.status });
|
||||
}
|
||||
}
|
||||
|
||||
if (self.scif_offset) |scif_offset| {
|
||||
device.transport.unregisterHostMemory(scif_offset, self.interface.size) catch |err| {
|
||||
std.log.scoped(.PhiDeviceMemory).err("SCIF unregister failed: {s}", .{@errorName(err)});
|
||||
};
|
||||
}
|
||||
|
||||
if (self.host_backing) |host_backing| {
|
||||
interface.owner.device_allocator.allocator().free(host_backing);
|
||||
}
|
||||
|
||||
allocator.destroy(self);
|
||||
}
|
||||
|
||||
@@ -109,19 +178,24 @@ pub fn invalidateRange(interface: *Interface, offset: vk.DeviceSize, size: vk.De
|
||||
|
||||
pub fn map(interface: *Interface, offset: vk.DeviceSize, size: vk.DeviceSize) VkError![]u8 {
|
||||
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
|
||||
|
||||
const data = self.data orelse return VkError.MemoryMapFailed;
|
||||
const map_offset = std.math.cast(usize, offset) orelse return VkError.MemoryMapFailed;
|
||||
|
||||
if (map_offset >= data.len) {
|
||||
return VkError.MemoryMapFailed;
|
||||
}
|
||||
|
||||
const map_size = if (size == vk.WHOLE_SIZE)
|
||||
data.len - map_offset
|
||||
else
|
||||
std.math.cast(usize, size) orelse return VkError.MemoryMapFailed;
|
||||
|
||||
if (map_size > data.len - map_offset) {
|
||||
return VkError.MemoryMapFailed;
|
||||
}
|
||||
return data[map_offset..(map_offset + map_size)];
|
||||
|
||||
return data[map_offset .. map_offset + map_size];
|
||||
}
|
||||
|
||||
pub fn unmap(_: *Interface) void {}
|
||||
|
||||
Reference in New Issue
Block a user