adding fragment derivatives, base pipeline cache, missing KHR function to avoid CTS crash + lots of minor bugfixes
This commit is contained in:
@@ -113,7 +113,7 @@ vkCreatePipelineLayout | ✅ Implemented
|
|||||||
vkCreateQueryPool | ✅ Implemented
|
vkCreateQueryPool | ✅ Implemented
|
||||||
vkCreateRenderPass | ✅ Implemented
|
vkCreateRenderPass | ✅ Implemented
|
||||||
vkCreateSampler | ✅ Implemented
|
vkCreateSampler | ✅ Implemented
|
||||||
vkCreateSemaphore | ⚙️ WIP
|
vkCreateSemaphore | ✅ Implemented
|
||||||
vkCreateShaderModule | ✅ Implemented
|
vkCreateShaderModule | ✅ Implemented
|
||||||
vkCreateSwapchainKHR | ✅ Implemented
|
vkCreateSwapchainKHR | ✅ Implemented
|
||||||
vkCreateWaylandSurfaceKHR | ✅ Implemented
|
vkCreateWaylandSurfaceKHR | ✅ Implemented
|
||||||
@@ -149,6 +149,8 @@ vkEnumerateDeviceLayerProperties | ✅ Implemented
|
|||||||
vkEnumerateInstanceExtensionProperties | ✅ Implemented
|
vkEnumerateInstanceExtensionProperties | ✅ Implemented
|
||||||
vkEnumerateInstanceLayerProperties | ✅ Implemented
|
vkEnumerateInstanceLayerProperties | ✅ Implemented
|
||||||
vkEnumeratePhysicalDevices | ✅ Implemented
|
vkEnumeratePhysicalDevices | ✅ Implemented
|
||||||
|
vkEnumeratePhysicalDeviceGroups | ✅ Implemented
|
||||||
|
vkEnumeratePhysicalDeviceGroupsKHR | ✅ Implemented
|
||||||
vkFlushMappedMemoryRanges | ✅ Implemented
|
vkFlushMappedMemoryRanges | ✅ Implemented
|
||||||
vkFreeCommandBuffers | ✅ Implemented
|
vkFreeCommandBuffers | ✅ Implemented
|
||||||
vkFreeDescriptorSets | ✅ Implemented
|
vkFreeDescriptorSets | ✅ Implemented
|
||||||
@@ -179,7 +181,7 @@ vkGetPhysicalDeviceWin32PresentationSupportKHR | ⚙️ WIP
|
|||||||
vkGetPhysicalDeviceXcbPresentationSupportKHR | ⚙️ WIP
|
vkGetPhysicalDeviceXcbPresentationSupportKHR | ⚙️ WIP
|
||||||
vkGetPhysicalDeviceXlibPresentationSupportKHR | ⚙️ WIP
|
vkGetPhysicalDeviceXlibPresentationSupportKHR | ⚙️ WIP
|
||||||
vkGetPipelineCacheData | ⚙️ WIP
|
vkGetPipelineCacheData | ⚙️ WIP
|
||||||
vkGetQueryPoolResults | ⚙️ WIP
|
vkGetQueryPoolResults | ✅ Implemented
|
||||||
vkGetRenderAreaGranularity | ✅ Implemented
|
vkGetRenderAreaGranularity | ✅ Implemented
|
||||||
vkGetSwapchainImagesKHR | ✅ Implemented
|
vkGetSwapchainImagesKHR | ✅ Implemented
|
||||||
vkInvalidateMappedMemoryRanges | ✅ Implemented
|
vkInvalidateMappedMemoryRanges | ✅ Implemented
|
||||||
|
|||||||
+2
-2
@@ -26,8 +26,8 @@
|
|||||||
.hash = "N-V-__8AAF9uOh0I4P_99za7N822J3JwsDaqONrFVrcEQo59",
|
.hash = "N-V-__8AAF9uOh0I4P_99za7N822J3JwsDaqONrFVrcEQo59",
|
||||||
},
|
},
|
||||||
.SPIRV_Interpreter = .{
|
.SPIRV_Interpreter = .{
|
||||||
.url = "git+https://git.kbz8.me/kbz_8/SPIRV-Interpreter#7c6da62e3cc6e58260527abef6e2e161e45d7f84",
|
.url = "git+https://git.kbz8.me/kbz_8/SPIRV-Interpreter#9270d83464afc32c8ea3dd89931056421046df5b",
|
||||||
.hash = "SPIRV_Interpreter-0.0.1-ajmpnzALBgCxqYfFMsc_moezDHsaeKyImzHXuJ7dYffX",
|
.hash = "SPIRV_Interpreter-0.0.1-ajmpn_V1BgDlmfIb9PHyP2cij9m63vE-Nx0o4mFsEd9L",
|
||||||
.lazy = true,
|
.lazy = true,
|
||||||
},
|
},
|
||||||
//.SPIRV_Interpreter = .{
|
//.SPIRV_Interpreter = .{
|
||||||
|
|||||||
@@ -104,8 +104,8 @@ pub fn destroy(interface: *Interface, allocator: std.mem.Allocator) void {
|
|||||||
allocator.destroy(self);
|
allocator.destroy(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn execute(self: *Self, device: *ExecutionDevice) void {
|
pub fn execute(self: *Self, device: *ExecutionDevice) VkError!void {
|
||||||
self.interface.submit() catch return;
|
try self.interface.submit();
|
||||||
defer self.interface.finish() catch {};
|
defer self.interface.finish() catch {};
|
||||||
|
|
||||||
for (self.commands.items) |command| {
|
for (self.commands.items) |command| {
|
||||||
@@ -116,7 +116,7 @@ pub fn execute(self: *Self, device: *ExecutionDevice) void {
|
|||||||
std.debug.dumpErrorReturnTrace(trace);
|
std.debug.dumpErrorReturnTrace(trace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return; // Should we return or continue ? Maybe device lost ?
|
return VkError.DeviceLost;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -988,7 +988,7 @@ pub fn executeCommands(interface: *Interface, commands: *Interface) VkError!void
|
|||||||
|
|
||||||
pub fn execute(context: *anyopaque, device: *ExecutionDevice) VkError!void {
|
pub fn execute(context: *anyopaque, device: *ExecutionDevice) VkError!void {
|
||||||
const impl: *Impl = @ptrCast(@alignCast(context));
|
const impl: *Impl = @ptrCast(@alignCast(context));
|
||||||
impl.cmd.execute(device);
|
try impl.cmd.execute(device);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -46,6 +46,10 @@ pub fn allocateDescriptorSet(interface: *Interface, layout: *base.DescriptorSetL
|
|||||||
|
|
||||||
pub fn destroy(interface: *Interface, allocator: std.mem.Allocator) void {
|
pub fn destroy(interface: *Interface, allocator: std.mem.Allocator) void {
|
||||||
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
|
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
|
||||||
|
const set_allocator = VulkanAllocator.init(null, .object).allocator();
|
||||||
|
for (self.list.items) |set| {
|
||||||
|
set.interface.destroy(set_allocator);
|
||||||
|
}
|
||||||
self.list.deinit(allocator);
|
self.list.deinit(allocator);
|
||||||
allocator.destroy(self);
|
allocator.destroy(self);
|
||||||
}
|
}
|
||||||
@@ -59,7 +63,7 @@ pub fn freeDescriptorSet(interface: *Interface, set: *base.DescriptorSet) VkErro
|
|||||||
}
|
}
|
||||||
|
|
||||||
const allocator = VulkanAllocator.init(null, .object).allocator();
|
const allocator = VulkanAllocator.init(null, .object).allocator();
|
||||||
allocator.destroy(soft_set);
|
set.destroy(allocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reset(interface: *Interface, _: vk.DescriptorPoolResetFlags) VkError!void {
|
pub fn reset(interface: *Interface, _: vk.DescriptorPoolResetFlags) VkError!void {
|
||||||
@@ -67,7 +71,7 @@ pub fn reset(interface: *Interface, _: vk.DescriptorPoolResetFlags) VkError!void
|
|||||||
const allocator = VulkanAllocator.init(null, .object).allocator();
|
const allocator = VulkanAllocator.init(null, .object).allocator();
|
||||||
|
|
||||||
for (self.list.items) |set| {
|
for (self.list.items) |set| {
|
||||||
allocator.destroy(set);
|
set.interface.destroy(allocator);
|
||||||
}
|
}
|
||||||
self.list.clearRetainingCapacity();
|
self.list.clearRetainingCapacity();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,14 @@ device_allocator: if (config.debug_allocator) std.heap.DebugAllocator(.{}) else
|
|||||||
|
|
||||||
pub fn create(instance: *base.Instance, physical_device: *base.PhysicalDevice, allocator: std.mem.Allocator, info: *const vk.DeviceCreateInfo) VkError!*Self {
|
pub fn create(instance: *base.Instance, physical_device: *base.PhysicalDevice, allocator: std.mem.Allocator, info: *const vk.DeviceCreateInfo) VkError!*Self {
|
||||||
const self = allocator.create(Self) catch return VkError.OutOfHostMemory;
|
const self = allocator.create(Self) catch return VkError.OutOfHostMemory;
|
||||||
errdefer allocator.destroy(self);
|
var initialized = false;
|
||||||
|
errdefer {
|
||||||
|
if (initialized) {
|
||||||
|
self.interface.destroy(allocator) catch {};
|
||||||
|
} else {
|
||||||
|
allocator.destroy(self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var interface = try Interface.init(allocator, instance, physical_device, info);
|
var interface = try Interface.init(allocator, instance, physical_device, info);
|
||||||
|
|
||||||
@@ -83,6 +90,7 @@ pub fn create(instance: *base.Instance, physical_device: *base.PhysicalDevice, a
|
|||||||
.interface = interface,
|
.interface = interface,
|
||||||
.device_allocator = if (config.debug_allocator) .init else .{},
|
.device_allocator = if (config.debug_allocator) .init else .{},
|
||||||
};
|
};
|
||||||
|
initialized = true;
|
||||||
|
|
||||||
try self.interface.createQueues(allocator, info);
|
try self.interface.createQueues(allocator, info);
|
||||||
return self;
|
return self;
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ fn castExtension(comptime ext: vk.ApiInfo) vk.ExtensionProperties {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub const EXTENSIONS = [_]vk.ExtensionProperties{
|
pub const EXTENSIONS = [_]vk.ExtensionProperties{
|
||||||
|
castExtension(vk.extensions.khr_device_group_creation),
|
||||||
castExtension(vk.extensions.khr_get_physical_device_properties_2),
|
castExtension(vk.extensions.khr_get_physical_device_properties_2),
|
||||||
castExtension(vk.extensions.khr_surface),
|
castExtension(vk.extensions.khr_surface),
|
||||||
castExtension(vk.extensions.khr_wayland_surface),
|
castExtension(vk.extensions.khr_wayland_surface),
|
||||||
@@ -60,13 +61,16 @@ fn requestPhysicalDevices(interface: *Interface, allocator: std.mem.Allocator) V
|
|||||||
// Software driver has only one physical device (the CPU)
|
// Software driver has only one physical device (the CPU)
|
||||||
const physical_device = try SoftPhysicalDevice.create(allocator, interface);
|
const physical_device = try SoftPhysicalDevice.create(allocator, interface);
|
||||||
errdefer physical_device.interface.releasePhysicalDevice(allocator) catch {};
|
errdefer physical_device.interface.releasePhysicalDevice(allocator) catch {};
|
||||||
interface.physical_devices.append(allocator, try Dispatchable(base.PhysicalDevice).wrap(allocator, &physical_device.interface)) catch return VkError.OutOfHostMemory;
|
const dispatchable = try Dispatchable(base.PhysicalDevice).wrap(allocator, &physical_device.interface);
|
||||||
|
errdefer dispatchable.destroy(allocator);
|
||||||
|
interface.physical_devices.append(allocator, dispatchable) catch return VkError.OutOfHostMemory;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn releasePhysicalDevices(interface: *Interface, allocator: std.mem.Allocator) VkError!void {
|
fn releasePhysicalDevices(interface: *Interface, allocator: std.mem.Allocator) VkError!void {
|
||||||
const physical_device = interface.physical_devices.getLast();
|
for (interface.physical_devices.items) |physical_device| {
|
||||||
try physical_device.object.releasePhysicalDevice(allocator);
|
try physical_device.object.releasePhysicalDevice(allocator);
|
||||||
physical_device.destroy(allocator);
|
physical_device.destroy(allocator);
|
||||||
|
}
|
||||||
|
|
||||||
interface.physical_devices.deinit(allocator);
|
interface.physical_devices.deinit(allocator);
|
||||||
interface.physical_devices = .empty;
|
interface.physical_devices = .empty;
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ fn castExtension(comptime ext: vk.ApiInfo) vk.ExtensionProperties {
|
|||||||
return props;
|
return props;
|
||||||
}
|
}
|
||||||
|
|
||||||
const EXTENSIONS = [_]vk.ExtensionProperties{
|
pub const EXTENSIONS = [_]vk.ExtensionProperties{
|
||||||
castExtension(vk.extensions.khr_swapchain),
|
castExtension(vk.extensions.khr_swapchain),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -59,6 +59,7 @@ pub fn create(allocator: std.mem.Allocator, instance: *base.Instance) VkError!*S
|
|||||||
interface.props.driver_version = @bitCast(lib.DRIVER_VERSION);
|
interface.props.driver_version = @bitCast(lib.DRIVER_VERSION);
|
||||||
interface.props.device_id = lib.DEVICE_ID;
|
interface.props.device_id = lib.DEVICE_ID;
|
||||||
interface.props.device_type = .cpu;
|
interface.props.device_type = .cpu;
|
||||||
|
interface.props.pipeline_cache_uuid = lib.PIPELINE_CACHE_UUID;
|
||||||
interface.props.limits = .{
|
interface.props.limits = .{
|
||||||
.max_image_dimension_1d = 4096,
|
.max_image_dimension_1d = 4096,
|
||||||
.max_image_dimension_2d = 4096,
|
.max_image_dimension_2d = 4096,
|
||||||
@@ -203,7 +204,6 @@ pub fn create(allocator: std.mem.Allocator, instance: *base.Instance) VkError!*S
|
|||||||
|
|
||||||
if (device_name[0] == 0) {
|
if (device_name[0] == 0) {
|
||||||
const name = blk: {
|
const name = blk: {
|
||||||
|
|
||||||
// If arch is x86 we try to get precise CPU name through CPUID
|
// If arch is x86 we try to get precise CPU name through CPUID
|
||||||
// and fallback to vendor name if not available
|
// and fallback to vendor name if not available
|
||||||
if (comptime builtin.cpu.arch.isX86()) {
|
if (comptime builtin.cpu.arch.isX86()) {
|
||||||
@@ -251,6 +251,7 @@ pub fn create(allocator: std.mem.Allocator, instance: *base.Instance) VkError!*S
|
|||||||
self.* = .{
|
self.* = .{
|
||||||
.interface = interface,
|
.interface = interface,
|
||||||
};
|
};
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -274,11 +275,16 @@ pub fn enumerateExtensionProperties(_: *const Interface, layer_name: ?[]const u8
|
|||||||
return VkError.LayerNotPresent;
|
return VkError.LayerNotPresent;
|
||||||
}
|
}
|
||||||
|
|
||||||
count.* = EXTENSIONS.len;
|
const available = EXTENSIONS.len;
|
||||||
if (p_properties) |properties| {
|
if (p_properties) |properties| {
|
||||||
for (EXTENSIONS, properties[0..]) |ext, *prop| {
|
const write_count = @min(count.*, available);
|
||||||
|
for (EXTENSIONS[0..write_count], properties[0..write_count]) |ext, *prop| {
|
||||||
prop.* = ext;
|
prop.* = ext;
|
||||||
}
|
}
|
||||||
|
count.* = @intCast(write_count);
|
||||||
|
if (write_count < available) return VkError.Incomplete;
|
||||||
|
} else {
|
||||||
|
count.* = @intCast(available);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -52,7 +52,8 @@ stages: std.EnumMap(Stages, Shader),
|
|||||||
|
|
||||||
pub fn createCompute(device: *base.Device, allocator: std.mem.Allocator, cache: ?*base.PipelineCache, info: *const vk.ComputePipelineCreateInfo) VkError!*Self {
|
pub fn createCompute(device: *base.Device, allocator: std.mem.Allocator, cache: ?*base.PipelineCache, info: *const vk.ComputePipelineCreateInfo) VkError!*Self {
|
||||||
const self = allocator.create(Self) catch return VkError.OutOfHostMemory;
|
const self = allocator.create(Self) catch return VkError.OutOfHostMemory;
|
||||||
errdefer allocator.destroy(self);
|
var initialized = false;
|
||||||
|
errdefer if (initialized) self.interface.destroy(allocator) else allocator.destroy(self);
|
||||||
|
|
||||||
var interface = try Interface.initCompute(device, allocator, cache, info);
|
var interface = try Interface.initCompute(device, allocator, cache, info);
|
||||||
|
|
||||||
@@ -71,7 +72,7 @@ pub fn createCompute(device: *base.Device, allocator: std.mem.Allocator, cache:
|
|||||||
.runtimes_allocator = .init(device_allocator),
|
.runtimes_allocator = .init(device_allocator),
|
||||||
.stages = std.EnumMap(Stages, Shader).init(.{}),
|
.stages = std.EnumMap(Stages, Shader).init(.{}),
|
||||||
};
|
};
|
||||||
errdefer self.runtimes_allocator.deinit();
|
initialized = true;
|
||||||
const runtimes_allocator = self.runtimes_allocator.allocator();
|
const runtimes_allocator = self.runtimes_allocator.allocator();
|
||||||
|
|
||||||
const instance: *SoftInstance = @alignCast(@fieldParentPtr("interface", device.instance));
|
const instance: *SoftInstance = @alignCast(@fieldParentPtr("interface", device.instance));
|
||||||
@@ -138,7 +139,8 @@ pub fn createCompute(device: *base.Device, allocator: std.mem.Allocator, cache:
|
|||||||
|
|
||||||
pub fn createGraphics(device: *base.Device, allocator: std.mem.Allocator, cache: ?*base.PipelineCache, info: *const vk.GraphicsPipelineCreateInfo) VkError!*Self {
|
pub fn createGraphics(device: *base.Device, allocator: std.mem.Allocator, cache: ?*base.PipelineCache, info: *const vk.GraphicsPipelineCreateInfo) VkError!*Self {
|
||||||
const self = allocator.create(Self) catch return VkError.OutOfHostMemory;
|
const self = allocator.create(Self) catch return VkError.OutOfHostMemory;
|
||||||
errdefer allocator.destroy(self);
|
var initialized = false;
|
||||||
|
errdefer if (initialized) self.interface.destroy(allocator) else allocator.destroy(self);
|
||||||
|
|
||||||
var interface = try Interface.initGraphics(device, allocator, cache, info);
|
var interface = try Interface.initGraphics(device, allocator, cache, info);
|
||||||
|
|
||||||
@@ -154,7 +156,7 @@ pub fn createGraphics(device: *base.Device, allocator: std.mem.Allocator, cache:
|
|||||||
.runtimes_allocator = .init(device_allocator),
|
.runtimes_allocator = .init(device_allocator),
|
||||||
.stages = std.EnumMap(Stages, Shader).init(.{}),
|
.stages = std.EnumMap(Stages, Shader).init(.{}),
|
||||||
};
|
};
|
||||||
errdefer self.runtimes_allocator.deinit();
|
initialized = true;
|
||||||
const runtimes_allocator = self.runtimes_allocator.allocator();
|
const runtimes_allocator = self.runtimes_allocator.allocator();
|
||||||
|
|
||||||
const instance: *SoftInstance = @alignCast(@fieldParentPtr("interface", device.instance));
|
const instance: *SoftInstance = @alignCast(@fieldParentPtr("interface", device.instance));
|
||||||
|
|||||||
+10
-13
@@ -68,11 +68,11 @@ pub fn bindSparse(interface: *Interface, info: []const vk.BindSparseInfo, fence:
|
|||||||
pub fn submit(interface: *Interface, infos: []Interface.SubmitInfo, p_fence: ?*base.Fence) VkError!void {
|
pub fn submit(interface: *Interface, infos: []Interface.SubmitInfo, p_fence: ?*base.Fence) VkError!void {
|
||||||
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
|
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
|
||||||
const soft_device: *SoftDevice = @alignCast(@fieldParentPtr("interface", interface.owner));
|
const soft_device: *SoftDevice = @alignCast(@fieldParentPtr("interface", interface.owner));
|
||||||
const allocator = soft_device.device_allocator.allocator();
|
|
||||||
const io = interface.owner.io();
|
const io = interface.owner.io();
|
||||||
|
const allocator = soft_device.device_allocator.allocator();
|
||||||
|
|
||||||
const task_data = allocator.create(TaskData) catch return VkError.OutOfDeviceMemory;
|
const data = allocator.create(TaskData) catch return VkError.OutOfDeviceMemory;
|
||||||
errdefer allocator.destroy(task_data);
|
errdefer allocator.destroy(data);
|
||||||
|
|
||||||
var cloned_infos = try cloneSubmitInfos(allocator, infos);
|
var cloned_infos = try cloneSubmitInfos(allocator, infos);
|
||||||
errdefer deinitSubmitInfos(allocator, &cloned_infos);
|
errdefer deinitSubmitInfos(allocator, &cloned_infos);
|
||||||
@@ -87,7 +87,7 @@ pub fn submit(interface: *Interface, infos: []Interface.SubmitInfo, p_fence: ?*b
|
|||||||
break :blk seq;
|
break :blk seq;
|
||||||
};
|
};
|
||||||
|
|
||||||
task_data.* = .{
|
data.* = .{
|
||||||
.queue = self,
|
.queue = self,
|
||||||
.soft_device = soft_device,
|
.soft_device = soft_device,
|
||||||
.sequence = sequence,
|
.sequence = sequence,
|
||||||
@@ -95,7 +95,7 @@ pub fn submit(interface: *Interface, infos: []Interface.SubmitInfo, p_fence: ?*b
|
|||||||
.fence = p_fence,
|
.fence = p_fence,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.group.async(io, Self.taskRunner, .{task_data});
|
self.group.async(io, taskRunner, .{data});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn waitIdle(interface: *Interface) VkError!void {
|
pub fn waitIdle(interface: *Interface) VkError!void {
|
||||||
@@ -115,7 +115,7 @@ fn executeSubmitInfo(soft_device: *SoftDevice, info: Interface.SubmitInfo) VkErr
|
|||||||
|
|
||||||
for (info.command_buffers.items) |command_buffer| {
|
for (info.command_buffers.items) |command_buffer| {
|
||||||
const soft_command_buffer: *SoftCommandBuffer = @alignCast(@fieldParentPtr("interface", command_buffer));
|
const soft_command_buffer: *SoftCommandBuffer = @alignCast(@fieldParentPtr("interface", command_buffer));
|
||||||
soft_command_buffer.execute(&execution_device);
|
try soft_command_buffer.execute(&execution_device);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (info.signal_semaphores.items) |semaphore| {
|
for (info.signal_semaphores.items) |semaphore| {
|
||||||
@@ -126,6 +126,7 @@ fn executeSubmitInfo(soft_device: *SoftDevice, info: Interface.SubmitInfo) VkErr
|
|||||||
fn taskRunner(data: *TaskData) void {
|
fn taskRunner(data: *TaskData) void {
|
||||||
const io = data.queue.interface.owner.io();
|
const io = data.queue.interface.owner.io();
|
||||||
const allocator = data.soft_device.device_allocator.allocator();
|
const allocator = data.soft_device.device_allocator.allocator();
|
||||||
|
|
||||||
defer {
|
defer {
|
||||||
deinitSubmitInfos(allocator, &data.infos);
|
deinitSubmitInfos(allocator, &data.infos);
|
||||||
allocator.destroy(data);
|
allocator.destroy(data);
|
||||||
@@ -140,18 +141,13 @@ fn taskRunner(data: *TaskData) void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var submit_err: ?VkError = null;
|
|
||||||
for (data.infos.items) |info| {
|
for (data.infos.items) |info| {
|
||||||
executeSubmitInfo(data.soft_device, info) catch |err| {
|
executeSubmitInfo(data.soft_device, info) catch |err| {
|
||||||
submit_err = err;
|
std.log.scoped(.SoftQueue).err("Command buffer execution failed with '{s}'", .{@errorName(err)});
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (submit_err) |err| {
|
|
||||||
std.log.scoped(.SoftQueue).err("Queue submit failed with '{s}'", .{@errorName(err)});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.fence) |fence| {
|
if (data.fence) |fence| {
|
||||||
fence.signal() catch |err| {
|
fence.signal() catch |err| {
|
||||||
std.log.scoped(.SoftQueue).err("Queue submit fence signal failed with '{s}'", .{@errorName(err)});
|
std.log.scoped(.SoftQueue).err("Queue submit fence signal failed with '{s}'", .{@errorName(err)});
|
||||||
@@ -159,9 +155,10 @@ fn taskRunner(data: *TaskData) void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
data.queue.mutex.lock(io) catch return;
|
data.queue.mutex.lock(io) catch return;
|
||||||
|
defer data.queue.mutex.unlock(io);
|
||||||
|
|
||||||
data.queue.executing_sequence += 1;
|
data.queue.executing_sequence += 1;
|
||||||
data.queue.condition.broadcast(io);
|
data.queue.condition.broadcast(io);
|
||||||
data.queue.mutex.unlock(io);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cloneSubmitInfos(allocator: std.mem.Allocator, infos: []Interface.SubmitInfo) VkError!std.ArrayList(Interface.SubmitInfo) {
|
fn cloneSubmitInfos(allocator: std.mem.Allocator, infos: []Interface.SubmitInfo) VkError!std.ArrayList(Interface.SubmitInfo) {
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ pub const Interface = base.ShaderModule;
|
|||||||
|
|
||||||
interface: Interface,
|
interface: Interface,
|
||||||
module: spv.Module,
|
module: spv.Module,
|
||||||
module_allocator: std.heap.ArenaAllocator,
|
|
||||||
|
|
||||||
/// Pipelines need SPIR-V module reference so shader module may not
|
/// Pipelines need SPIR-V module reference so shader module may not
|
||||||
/// be destroy on call to `vkDestroyShaderModule`
|
/// be destroy on call to `vkDestroyShaderModule`
|
||||||
@@ -29,10 +28,6 @@ pub fn create(device: *base.Device, allocator: std.mem.Allocator, info: *const v
|
|||||||
const soft_device: *SoftDevice = @alignCast(@fieldParentPtr("interface", device));
|
const soft_device: *SoftDevice = @alignCast(@fieldParentPtr("interface", device));
|
||||||
const device_allocator = soft_device.device_allocator.allocator();
|
const device_allocator = soft_device.device_allocator.allocator();
|
||||||
|
|
||||||
var module_allocator_arena: std.heap.ArenaAllocator = .init(device_allocator);
|
|
||||||
errdefer module_allocator_arena.deinit();
|
|
||||||
const module_allocator = module_allocator_arena.allocator();
|
|
||||||
|
|
||||||
interface.vtable = &.{
|
interface.vtable = &.{
|
||||||
.destroy = destroy,
|
.destroy = destroy,
|
||||||
};
|
};
|
||||||
@@ -41,7 +36,7 @@ pub fn create(device: *base.Device, allocator: std.mem.Allocator, info: *const v
|
|||||||
|
|
||||||
self.* = .{
|
self.* = .{
|
||||||
.interface = interface,
|
.interface = interface,
|
||||||
.module = spv.Module.init(module_allocator, code, .{
|
.module = spv.Module.init(device_allocator, code, .{
|
||||||
.use_simd_vectors_specializations = base.config.shaders_simd,
|
.use_simd_vectors_specializations = base.config.shaders_simd,
|
||||||
}) catch |err| switch (err) {
|
}) catch |err| switch (err) {
|
||||||
spv.Module.ModuleError.OutOfMemory => return VkError.OutOfHostMemory,
|
spv.Module.ModuleError.OutOfMemory => return VkError.OutOfHostMemory,
|
||||||
@@ -55,9 +50,9 @@ pub fn create(device: *base.Device, allocator: std.mem.Allocator, info: *const v
|
|||||||
return VkError.ValidationFailed;
|
return VkError.ValidationFailed;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
.module_allocator = module_allocator_arena,
|
|
||||||
.ref_count = std.atomic.Value(usize).init(1),
|
.ref_count = std.atomic.Value(usize).init(1),
|
||||||
};
|
};
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,7 +62,11 @@ pub fn destroy(interface: *Interface, allocator: std.mem.Allocator) void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn drop(self: *Self, allocator: std.mem.Allocator) void {
|
pub fn drop(self: *Self, allocator: std.mem.Allocator) void {
|
||||||
self.module_allocator.deinit();
|
const soft_device: *SoftDevice = @alignCast(@fieldParentPtr("interface", self.interface.owner));
|
||||||
|
const device_allocator = soft_device.device_allocator.allocator();
|
||||||
|
|
||||||
|
self.module.deinit(device_allocator);
|
||||||
|
|
||||||
allocator.destroy(self);
|
allocator.destroy(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -683,6 +683,12 @@ pub fn readFloat4(map: []const u8, src_format: vk.Format) F32x4 {
|
|||||||
c[1] = std.mem.bytesToValue(f32, map[4..]);
|
c[1] = std.mem.bytesToValue(f32, map[4..]);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
.r32g32b32_sfloat => {
|
||||||
|
c[0] = std.mem.bytesToValue(f32, map[0..]);
|
||||||
|
c[1] = std.mem.bytesToValue(f32, map[4..]);
|
||||||
|
c[2] = std.mem.bytesToValue(f32, map[8..]);
|
||||||
|
},
|
||||||
|
|
||||||
.d32_sfloat,
|
.d32_sfloat,
|
||||||
.r32_sfloat,
|
.r32_sfloat,
|
||||||
=> c[0] = std.mem.bytesToValue(f32, map),
|
=> c[0] = std.mem.bytesToValue(f32, map),
|
||||||
@@ -1190,6 +1196,14 @@ pub fn readInt4(map: []const u8, src_format: vk.Format) U32x4 {
|
|||||||
c[1] = std.mem.bytesToValue(u32, map[4..]);
|
c[1] = std.mem.bytesToValue(u32, map[4..]);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
.r32g32b32_sint,
|
||||||
|
.r32g32b32_uint,
|
||||||
|
=> {
|
||||||
|
c[0] = std.mem.bytesToValue(u32, map[0..]);
|
||||||
|
c[1] = std.mem.bytesToValue(u32, map[4..]);
|
||||||
|
c[2] = std.mem.bytesToValue(u32, map[8..]);
|
||||||
|
},
|
||||||
|
|
||||||
.r8g8b8a8_uint,
|
.r8g8b8a8_uint,
|
||||||
=> {
|
=> {
|
||||||
c[0] = map[0];
|
c[0] = map[0];
|
||||||
|
|||||||
@@ -13,15 +13,51 @@ const VkError = base.VkError;
|
|||||||
const SpvRuntimeError = spv.Runtime.RuntimeError;
|
const SpvRuntimeError = spv.Runtime.RuntimeError;
|
||||||
const INTERFACE_BLOB_PADDING = @sizeOf(zm.F32x4);
|
const INTERFACE_BLOB_PADDING = @sizeOf(zm.F32x4);
|
||||||
|
|
||||||
|
pub const DerivativeInputs = struct {
|
||||||
|
dx: [spv.SPIRV_MAX_OUTPUT_LOCATIONS]VertexInterpolationLocation,
|
||||||
|
dy: [spv.SPIRV_MAX_OUTPUT_LOCATIONS]VertexInterpolationLocation,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn shaderUsesDerivatives(code: []const spv.SpvWord) bool {
|
||||||
|
var i: usize = 5;
|
||||||
|
while (i < code.len) {
|
||||||
|
const opcode_data = code[i];
|
||||||
|
const word_count = (opcode_data & (~spv.spv.SpvOpCodeMask)) >> spv.spv.SpvWordCountShift;
|
||||||
|
if (word_count == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const opcode = opcode_data & spv.spv.SpvOpCodeMask;
|
||||||
|
switch (opcode) {
|
||||||
|
@intFromEnum(spv.spv.SpvOp.DPdx),
|
||||||
|
@intFromEnum(spv.spv.SpvOp.DPdy),
|
||||||
|
@intFromEnum(spv.spv.SpvOp.DPdxFine),
|
||||||
|
@intFromEnum(spv.spv.SpvOp.DPdyFine),
|
||||||
|
@intFromEnum(spv.spv.SpvOp.DPdxCoarse),
|
||||||
|
@intFromEnum(spv.spv.SpvOp.DPdyCoarse),
|
||||||
|
=> return true,
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
|
||||||
|
i += word_count;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn shaderInvocation(
|
pub fn shaderInvocation(
|
||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
draw_call: *Renderer.DrawCall,
|
draw_call: *Renderer.DrawCall,
|
||||||
batch_id: usize,
|
batch_id: usize,
|
||||||
position: zm.F32x4,
|
position: zm.F32x4,
|
||||||
inputs: [spv.SPIRV_MAX_OUTPUT_LOCATIONS]VertexInterpolationLocation,
|
inputs: [spv.SPIRV_MAX_OUTPUT_LOCATIONS]VertexInterpolationLocation,
|
||||||
|
derivative_inputs: ?DerivativeInputs,
|
||||||
) SpvRuntimeError![spv.SPIRV_MAX_OUTPUT_LOCATIONS][@sizeOf(zm.F32x4)]u8 {
|
) SpvRuntimeError![spv.SPIRV_MAX_OUTPUT_LOCATIONS][@sizeOf(zm.F32x4)]u8 {
|
||||||
var fragment_inputs = inputs;
|
var fragment_inputs = inputs;
|
||||||
errdefer freeOwnedInputs(allocator, fragment_inputs);
|
errdefer freeOwnedInputs(allocator, fragment_inputs);
|
||||||
|
const derivatives = derivative_inputs;
|
||||||
|
errdefer if (derivatives) |owned_derivatives| {
|
||||||
|
freeOwnedInputs(allocator, owned_derivatives.dx);
|
||||||
|
freeOwnedInputs(allocator, owned_derivatives.dy);
|
||||||
|
};
|
||||||
|
|
||||||
const io = draw_call.renderer.device.interface.io();
|
const io = draw_call.renderer.device.interface.io();
|
||||||
|
|
||||||
@@ -66,6 +102,13 @@ pub fn shaderInvocation(
|
|||||||
|
|
||||||
if (input.blob.len != 0) {
|
if (input.blob.len != 0) {
|
||||||
try rt.writeInput(input.blob, result_word);
|
try rt.writeInput(input.blob, result_word);
|
||||||
|
if (derivatives) |derivative| {
|
||||||
|
const dx = derivative.dx[location][component];
|
||||||
|
const dy = derivative.dy[location][component];
|
||||||
|
if (dx.blob.len != 0 and dy.blob.len != 0) {
|
||||||
|
try rt.setDerivativeFromMemory(allocator, result_word, dx.blob, dy.blob);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -81,8 +124,7 @@ pub fn shaderInvocation(
|
|||||||
else => return err,
|
else => return err,
|
||||||
};
|
};
|
||||||
|
|
||||||
var outputs: [spv.SPIRV_MAX_OUTPUT_LOCATIONS][@sizeOf(zm.F32x4)]u8 = undefined;
|
var outputs = std.mem.zeroes([spv.SPIRV_MAX_OUTPUT_LOCATIONS][@sizeOf(zm.F32x4)]u8);
|
||||||
@memset(std.mem.asBytes(&outputs), 0);
|
|
||||||
|
|
||||||
for (0..spv.SPIRV_MAX_OUTPUT_LOCATIONS) |location| {
|
for (0..spv.SPIRV_MAX_OUTPUT_LOCATIONS) |location| {
|
||||||
var has_split_components = false;
|
var has_split_components = false;
|
||||||
@@ -117,6 +159,10 @@ pub fn shaderInvocation(
|
|||||||
|
|
||||||
try rt.flushDescriptorSets(allocator);
|
try rt.flushDescriptorSets(allocator);
|
||||||
freeOwnedInputs(allocator, fragment_inputs);
|
freeOwnedInputs(allocator, fragment_inputs);
|
||||||
|
if (derivatives) |owned_derivatives| {
|
||||||
|
freeOwnedInputs(allocator, owned_derivatives.dx);
|
||||||
|
freeOwnedInputs(allocator, owned_derivatives.dy);
|
||||||
|
}
|
||||||
|
|
||||||
return outputs;
|
return outputs;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -304,8 +304,7 @@ fn clipTransformAndRasterizePoint(
|
|||||||
if (!common.scissorContainsPixel(draw_call.scissor, px, py))
|
if (!common.scissorContainsPixel(draw_call.scissor, px, py))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var outputs: [spv.SPIRV_MAX_OUTPUT_LOCATIONS][@sizeOf(zm.F32x4)]u8 = undefined;
|
var outputs = std.mem.zeroes([spv.SPIRV_MAX_OUTPUT_LOCATIONS][@sizeOf(zm.F32x4)]u8);
|
||||||
@memset(std.mem.asBytes(&outputs), 0);
|
|
||||||
if (has_fragment_shader) {
|
if (has_fragment_shader) {
|
||||||
outputs = fragment.shaderInvocation(
|
outputs = fragment.shaderInvocation(
|
||||||
allocator,
|
allocator,
|
||||||
@@ -313,6 +312,7 @@ fn clipTransformAndRasterizePoint(
|
|||||||
0,
|
0,
|
||||||
zm.f32x4(@floatFromInt(px), @floatFromInt(py), transformed.position[2], 1.0),
|
zm.f32x4(@floatFromInt(px), @floatFromInt(py), transformed.position[2], 1.0),
|
||||||
try common.interpolateVertexOutputs(allocator, &transformed, &transformed, &transformed, 1.0, 0.0, 0.0),
|
try common.interpolateVertexOutputs(allocator, &transformed, &transformed, &transformed, 1.0, 0.0, 0.0),
|
||||||
|
null,
|
||||||
) catch |err| {
|
) catch |err| {
|
||||||
std.log.scoped(.@"Fragment stage").err("catched a '{s}'", .{@errorName(err)});
|
std.log.scoped(.@"Fragment stage").err("catched a '{s}'", .{@errorName(err)});
|
||||||
if (comptime base.config.logs == .verbose) {
|
if (comptime base.config.logs == .verbose) {
|
||||||
|
|||||||
@@ -152,8 +152,7 @@ inline fn run(data: RunData) !void {
|
|||||||
const t = @as(f32, @floatFromInt(step)) / @as(f32, @floatFromInt(@max(data.d_x, 1)));
|
const t = @as(f32, @floatFromInt(step)) / @as(f32, @floatFromInt(@max(data.d_x, 1)));
|
||||||
const z = ((1.0 - t) * data.start_vertex.position[2]) + (t * data.end_vertex.position[2]);
|
const z = ((1.0 - t) * data.start_vertex.position[2]) + (t * data.end_vertex.position[2]);
|
||||||
|
|
||||||
var outputs: [spv.SPIRV_MAX_OUTPUT_LOCATIONS][@sizeOf(F32x4)]u8 = undefined;
|
var outputs = std.mem.zeroes([spv.SPIRV_MAX_OUTPUT_LOCATIONS][@sizeOf(F32x4)]u8);
|
||||||
@memset(std.mem.asBytes(&outputs), 0);
|
|
||||||
if (data.has_fragment_shader) {
|
if (data.has_fragment_shader) {
|
||||||
outputs = fragment.shaderInvocation(
|
outputs = fragment.shaderInvocation(
|
||||||
data.allocator,
|
data.allocator,
|
||||||
@@ -161,6 +160,7 @@ inline fn run(data: RunData) !void {
|
|||||||
data.batch_id,
|
data.batch_id,
|
||||||
zm.f32x4(@floatFromInt(pixel_x), @floatFromInt(pixel_y), z, 1.0),
|
zm.f32x4(@floatFromInt(pixel_x), @floatFromInt(pixel_y), z, 1.0),
|
||||||
try common.interpolateLineOutputs(data.allocator, data.start_vertex, data.end_vertex, t),
|
try common.interpolateLineOutputs(data.allocator, data.start_vertex, data.end_vertex, t),
|
||||||
|
null,
|
||||||
) catch |err| {
|
) catch |err| {
|
||||||
std.log.scoped(.@"Fragment stage").err("catched a '{s}'", .{@errorName(err)});
|
std.log.scoped(.@"Fragment stage").err("catched a '{s}'", .{@errorName(err)});
|
||||||
if (comptime base.config.logs == .verbose) {
|
if (comptime base.config.logs == .verbose) {
|
||||||
|
|||||||
@@ -226,6 +226,58 @@ pub fn interpolateLineOutputs(
|
|||||||
return interpolateVertexOutputs(allocator, v0, v1, v0, 1.0 - t, t, 0.0);
|
return interpolateVertexOutputs(allocator, v0, v1, v0, 1.0 - t, t, 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn interpolateVertexOutputDerivatives(
|
||||||
|
allocator: std.mem.Allocator,
|
||||||
|
v0: *const Renderer.Vertex,
|
||||||
|
v1: *const Renderer.Vertex,
|
||||||
|
v2: *const Renderer.Vertex,
|
||||||
|
db0: f32,
|
||||||
|
db1: f32,
|
||||||
|
db2: f32,
|
||||||
|
) VkError![spv.SPIRV_MAX_OUTPUT_LOCATIONS]VertexInterpolationLocation {
|
||||||
|
var inputs = [_]VertexInterpolationLocation{[_]VertexInterpolation{.{
|
||||||
|
.blob = &.{},
|
||||||
|
.size = 0,
|
||||||
|
.free_responsability = false,
|
||||||
|
}} ** 4} ** spv.SPIRV_MAX_OUTPUT_LOCATIONS;
|
||||||
|
|
||||||
|
for (0..spv.SPIRV_MAX_OUTPUT_LOCATIONS) |location| {
|
||||||
|
for (0..4) |component| {
|
||||||
|
const out0 = v0.outputs[location][component] orelse continue;
|
||||||
|
const out1 = v1.outputs[location][component] orelse continue;
|
||||||
|
const out2 = v2.outputs[location][component] orelse continue;
|
||||||
|
|
||||||
|
const len = @min(out0.size, out1.size, out2.size);
|
||||||
|
if (len == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const input = allocator.alloc(u8, len + @sizeOf(F32x4)) catch return VkError.OutOfDeviceMemory;
|
||||||
|
@memset(input, 0);
|
||||||
|
|
||||||
|
if (out0.interpolation_type != .flat) {
|
||||||
|
var byte_index: usize = 0;
|
||||||
|
while (byte_index + @sizeOf(F32x4) <= len) : (byte_index += @sizeOf(F32x4)) {
|
||||||
|
const value0 = std.mem.bytesToValue(F32x4, out0.blob[byte_index..]);
|
||||||
|
const value1 = std.mem.bytesToValue(F32x4, out1.blob[byte_index..]);
|
||||||
|
const value2 = std.mem.bytesToValue(F32x4, out2.blob[byte_index..]);
|
||||||
|
base.utils.writePacked(F32x4, input[byte_index..], interpolateF32x4(value0, value1, value2, db0, db1, db2));
|
||||||
|
}
|
||||||
|
|
||||||
|
while (byte_index + @sizeOf(f32) <= len) : (byte_index += @sizeOf(f32)) {
|
||||||
|
const value0 = std.mem.bytesToValue(f32, out0.blob[byte_index..]);
|
||||||
|
const value1 = std.mem.bytesToValue(f32, out1.blob[byte_index..]);
|
||||||
|
const value2 = std.mem.bytesToValue(f32, out2.blob[byte_index..]);
|
||||||
|
base.utils.writePacked(f32, input[byte_index..], (value0 * db0) + (value1 * db1) + (value2 * db2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inputs[location][component] = .{ .blob = input, .size = len, .free_responsability = true };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return inputs;
|
||||||
|
}
|
||||||
|
|
||||||
inline fn interpolateF32x4(value0: F32x4, value1: F32x4, value2: F32x4, b0: f32, b1: f32, b2: f32) F32x4 {
|
inline fn interpolateF32x4(value0: F32x4, value1: F32x4, value2: F32x4, b0: f32, b1: f32, b2: f32) F32x4 {
|
||||||
return (value0 * zm.f32x4s(b0)) + (value1 * zm.f32x4s(b1)) + (value2 * zm.f32x4s(b2));
|
return (value0 * zm.f32x4s(b0)) + (value1 * zm.f32x4s(b1)) + (value2 * zm.f32x4s(b2));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ const RunData = struct {
|
|||||||
stencil_attachment_access: ?*common.RenderTargetAccess,
|
stencil_attachment_access: ?*common.RenderTargetAccess,
|
||||||
front_face: bool,
|
front_face: bool,
|
||||||
has_fragment_shader: bool,
|
has_fragment_shader: bool,
|
||||||
|
fragment_uses_derivatives: bool,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn drawTriangle(
|
pub fn drawTriangle(
|
||||||
@@ -56,6 +57,10 @@ pub fn drawTriangle(
|
|||||||
|
|
||||||
const pipeline = draw_call.renderer.state.pipeline orelse return;
|
const pipeline = draw_call.renderer.state.pipeline orelse return;
|
||||||
const fragment_stage = pipeline.stages.getPtr(.fragment);
|
const fragment_stage = pipeline.stages.getPtr(.fragment);
|
||||||
|
const fragment_uses_derivatives = if (fragment_stage) |stage|
|
||||||
|
fragment.shaderUsesDerivatives(stage.module.module.code)
|
||||||
|
else
|
||||||
|
false;
|
||||||
const runtimes_count = if (fragment_stage) |stage| stage.runtimes.len else 1;
|
const runtimes_count = if (fragment_stage) |stage| stage.runtimes.len else 1;
|
||||||
if (runtimes_count == 0)
|
if (runtimes_count == 0)
|
||||||
return;
|
return;
|
||||||
@@ -106,6 +111,7 @@ pub fn drawTriangle(
|
|||||||
.stencil_attachment_access = stencil_attachment_access,
|
.stencil_attachment_access = stencil_attachment_access,
|
||||||
.front_face = front_face,
|
.front_face = front_face,
|
||||||
.has_fragment_shader = fragment_stage != null,
|
.has_fragment_shader = fragment_stage != null,
|
||||||
|
.fragment_uses_derivatives = fragment_uses_derivatives,
|
||||||
};
|
};
|
||||||
|
|
||||||
draw_call.rasterizer_wait_group.async(io, runWrapper, .{run_data});
|
draw_call.rasterizer_wait_group.async(io, runWrapper, .{run_data});
|
||||||
@@ -171,15 +177,49 @@ inline fn run(data: RunData) !void {
|
|||||||
const b2 = w2 / data.area;
|
const b2 = w2 / data.area;
|
||||||
const z = (b0 * data.v0.position[2]) + (b1 * data.v1.position[2]) + (b2 * data.v2.position[2]);
|
const z = (b0 * data.v0.position[2]) + (b1 * data.v1.position[2]) + (b2 * data.v2.position[2]);
|
||||||
|
|
||||||
var outputs: [spv.SPIRV_MAX_OUTPUT_LOCATIONS][@sizeOf(F32x4)]u8 = undefined;
|
var outputs = std.mem.zeroes([spv.SPIRV_MAX_OUTPUT_LOCATIONS][@sizeOf(F32x4)]u8);
|
||||||
@memset(std.mem.asBytes(&outputs), 0);
|
|
||||||
if (data.has_fragment_shader) {
|
if (data.has_fragment_shader) {
|
||||||
|
const inputs = try common.interpolateVertexOutputs(data.allocator, &data.v0, &data.v1, &data.v2, b0, b1, b2);
|
||||||
|
const derivative_inputs: ?fragment.DerivativeInputs = if (data.fragment_uses_derivatives) blk: {
|
||||||
|
var derivatives: fragment.DerivativeInputs = undefined;
|
||||||
|
|
||||||
|
const p_dx = zm.f32x4(@as(f32, @floatFromInt(x)) + 1.5, @as(f32, @floatFromInt(y)) + 0.5, 0.0, 1.0);
|
||||||
|
const dx_w0 = edgeFunction(data.v1.position, data.v2.position, p_dx);
|
||||||
|
const dx_w1 = edgeFunction(data.v2.position, data.v0.position, p_dx);
|
||||||
|
const dx_w2 = edgeFunction(data.v0.position, data.v1.position, p_dx);
|
||||||
|
derivatives.dx = try common.interpolateVertexOutputDerivatives(
|
||||||
|
data.allocator,
|
||||||
|
&data.v0,
|
||||||
|
&data.v1,
|
||||||
|
&data.v2,
|
||||||
|
(dx_w0 / data.area) - b0,
|
||||||
|
(dx_w1 / data.area) - b1,
|
||||||
|
(dx_w2 / data.area) - b2,
|
||||||
|
);
|
||||||
|
|
||||||
|
const p_dy = zm.f32x4(@as(f32, @floatFromInt(x)) + 0.5, @as(f32, @floatFromInt(y)) + 1.5, 0.0, 1.0);
|
||||||
|
const dy_w0 = edgeFunction(data.v1.position, data.v2.position, p_dy);
|
||||||
|
const dy_w1 = edgeFunction(data.v2.position, data.v0.position, p_dy);
|
||||||
|
const dy_w2 = edgeFunction(data.v0.position, data.v1.position, p_dy);
|
||||||
|
derivatives.dy = try common.interpolateVertexOutputDerivatives(
|
||||||
|
data.allocator,
|
||||||
|
&data.v0,
|
||||||
|
&data.v1,
|
||||||
|
&data.v2,
|
||||||
|
(dy_w0 / data.area) - b0,
|
||||||
|
(dy_w1 / data.area) - b1,
|
||||||
|
(dy_w2 / data.area) - b2,
|
||||||
|
);
|
||||||
|
break :blk derivatives;
|
||||||
|
} else null;
|
||||||
|
|
||||||
outputs = fragment.shaderInvocation(
|
outputs = fragment.shaderInvocation(
|
||||||
data.allocator,
|
data.allocator,
|
||||||
data.draw_call,
|
data.draw_call,
|
||||||
data.batch_id,
|
data.batch_id,
|
||||||
zm.f32x4(@floatFromInt(x), @floatFromInt(y), z, 1.0),
|
zm.f32x4(@floatFromInt(x), @floatFromInt(y), z, 1.0),
|
||||||
try common.interpolateVertexOutputs(data.allocator, &data.v0, &data.v1, &data.v2, b0, b1, b2),
|
inputs,
|
||||||
|
derivative_inputs,
|
||||||
) catch |err| {
|
) catch |err| {
|
||||||
std.log.scoped(.@"Fragment stage").err("catched a '{s}'", .{@errorName(err)});
|
std.log.scoped(.@"Fragment stage").err("catched a '{s}'", .{@errorName(err)});
|
||||||
if (comptime base.config.logs == .verbose) {
|
if (comptime base.config.logs == .verbose) {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ const SpvRuntimeError = spv.Runtime.RuntimeError;
|
|||||||
|
|
||||||
const Renderer = @import("Renderer.zig");
|
const Renderer = @import("Renderer.zig");
|
||||||
const SoftPipeline = @import("../SoftPipeline.zig");
|
const SoftPipeline = @import("../SoftPipeline.zig");
|
||||||
|
const blitter = @import("blitter.zig");
|
||||||
|
|
||||||
const VkError = base.VkError;
|
const VkError = base.VkError;
|
||||||
const INTERFACE_BLOB_PADDING = @sizeOf(F32x4);
|
const INTERFACE_BLOB_PADDING = @sizeOf(F32x4);
|
||||||
@@ -129,6 +130,9 @@ fn setupBuiltins(rt: *spv.Runtime, vertex_index_u32: u32, instance_index: usize)
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn writeVertexInput(rt: *spv.Runtime, allocator: std.mem.Allocator, raw_input: []const u8, format: vk.Format, location: u32) !void {
|
fn writeVertexInput(rt: *spv.Runtime, allocator: std.mem.Allocator, raw_input: []const u8, format: vk.Format, location: u32) !void {
|
||||||
|
var expanded_input: [@sizeOf(F32x4)]u8 = @splat(0);
|
||||||
|
const expanded_slice = expandedVertexInput(raw_input, format, &expanded_input);
|
||||||
|
|
||||||
var has_split_components = false;
|
var has_split_components = false;
|
||||||
for (1..4) |component| {
|
for (1..4) |component| {
|
||||||
_ = rt.getResultByLocationComponent(location, @intCast(component), .input) catch |err| switch (err) {
|
_ = rt.getResultByLocationComponent(location, @intCast(component), .input) catch |err| switch (err) {
|
||||||
@@ -148,8 +152,8 @@ fn writeVertexInput(rt: *spv.Runtime, allocator: std.mem.Allocator, raw_input: [
|
|||||||
const input_memory_size = try rt.getResultMemorySize(result_word);
|
const input_memory_size = try rt.getResultMemorySize(result_word);
|
||||||
const raw_offset = component * @sizeOf(f32);
|
const raw_offset = component * @sizeOf(f32);
|
||||||
|
|
||||||
if (raw_offset + input_memory_size <= raw_input.len) {
|
if (raw_offset + input_memory_size <= expanded_slice.len) {
|
||||||
try rt.writeInput(raw_input[raw_offset .. raw_offset + input_memory_size], result_word);
|
try rt.writeInput(expanded_slice[raw_offset .. raw_offset + input_memory_size], result_word);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,8 +183,8 @@ fn writeVertexInput(rt: *spv.Runtime, allocator: std.mem.Allocator, raw_input: [
|
|||||||
|
|
||||||
const input_memory_size = try rt.getInputLocationMemorySize(location);
|
const input_memory_size = try rt.getInputLocationMemorySize(location);
|
||||||
|
|
||||||
if (raw_input.len >= input_memory_size) {
|
if (expanded_slice.len >= input_memory_size) {
|
||||||
try rt.writeInputLocation(raw_input[0..input_memory_size], location);
|
try rt.writeInputLocation(expanded_slice[0..input_memory_size], location);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,12 +192,24 @@ fn writeVertexInput(rt: *spv.Runtime, allocator: std.mem.Allocator, raw_input: [
|
|||||||
defer allocator.free(input);
|
defer allocator.free(input);
|
||||||
|
|
||||||
@memset(input, 0);
|
@memset(input, 0);
|
||||||
@memcpy(input[0..raw_input.len], raw_input);
|
@memcpy(input[0..expanded_slice.len], expanded_slice);
|
||||||
|
|
||||||
fillMissingVertexComponents(input, raw_input.len, format);
|
fillMissingVertexComponents(input, expanded_slice.len, format);
|
||||||
try rt.writeInputLocation(input, location);
|
try rt.writeInputLocation(input, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn expandedVertexInput(raw_input: []const u8, format: vk.Format, expanded: *[@sizeOf(F32x4)]u8) []const u8 {
|
||||||
|
if (base.format.isUnnormalizedInteger(format)) {
|
||||||
|
const value = blitter.readInt4(raw_input, format);
|
||||||
|
@memcpy(expanded, std.mem.asBytes(&value));
|
||||||
|
return expanded;
|
||||||
|
}
|
||||||
|
|
||||||
|
const value = blitter.readFloat4(raw_input, format);
|
||||||
|
@memcpy(expanded, std.mem.asBytes(&value));
|
||||||
|
return expanded;
|
||||||
|
}
|
||||||
|
|
||||||
fn fillMissingVertexComponents(input: []u8, raw_input_size: usize, format: vk.Format) void {
|
fn fillMissingVertexComponents(input: []u8, raw_input_size: usize, format: vk.Format) void {
|
||||||
if (input.len < @sizeOf(F32x4) or raw_input_size > 3 * @sizeOf(f32))
|
if (input.len < @sizeOf(F32x4) or raw_input_size > 3 * @sizeOf(f32))
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ pub const DRIVER_NAME = "Soft";
|
|||||||
pub const VULKAN_VERSION = vk.makeApiVersion(0, 1, 0, 0);
|
pub const VULKAN_VERSION = vk.makeApiVersion(0, 1, 0, 0);
|
||||||
pub const DRIVER_VERSION = vk.makeApiVersion(0, 0, 0, 1);
|
pub const DRIVER_VERSION = vk.makeApiVersion(0, 0, 0, 1);
|
||||||
pub const DEVICE_ID = 0x600DCAFE;
|
pub const DEVICE_ID = 0x600DCAFE;
|
||||||
|
pub const PIPELINE_CACHE_UUID: [vk.UUID_SIZE]u8 = "ApeSoftCacheUUID".*;
|
||||||
|
|
||||||
/// Generic system memory.
|
/// Generic system memory.
|
||||||
pub const MEMORY_TYPE_GENERIC_BIT = 0;
|
pub const MEMORY_TYPE_GENERIC_BIT = 0;
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ owner: *Device,
|
|||||||
pool: *CommandPool,
|
pool: *CommandPool,
|
||||||
state: State,
|
state: State,
|
||||||
begin_info: ?vk.CommandBufferBeginInfo,
|
begin_info: ?vk.CommandBufferBeginInfo,
|
||||||
|
usage_flags: vk.CommandBufferUsageFlags,
|
||||||
host_allocator: VulkanAllocator,
|
host_allocator: VulkanAllocator,
|
||||||
state_mutex: std.Io.Mutex,
|
state_mutex: std.Io.Mutex,
|
||||||
|
|
||||||
@@ -94,6 +95,7 @@ pub fn init(device: *Device, allocator: std.mem.Allocator, info: *const vk.Comma
|
|||||||
.pool = try NonDispatchable(CommandPool).fromHandleObject(info.command_pool),
|
.pool = try NonDispatchable(CommandPool).fromHandleObject(info.command_pool),
|
||||||
.state = .Initial,
|
.state = .Initial,
|
||||||
.begin_info = null,
|
.begin_info = null,
|
||||||
|
.usage_flags = .{},
|
||||||
.host_allocator = VulkanAllocator.from(allocator).cloneWithScope(.object),
|
.host_allocator = VulkanAllocator.from(allocator).cloneWithScope(.object),
|
||||||
.state_mutex = .init,
|
.state_mutex = .init,
|
||||||
.vtable = undefined,
|
.vtable = undefined,
|
||||||
@@ -120,7 +122,7 @@ pub inline fn destroy(self: *Self, allocator: std.mem.Allocator) void {
|
|||||||
pub fn begin(self: *Self, info: *const vk.CommandBufferBeginInfo) VkError!void {
|
pub fn begin(self: *Self, info: *const vk.CommandBufferBeginInfo) VkError!void {
|
||||||
const implicitly_reset = self.state == .Executable;
|
const implicitly_reset = self.state == .Executable;
|
||||||
|
|
||||||
self.transitionState(.Recording, &.{ .Initial, .Executable }) catch return VkError.ValidationFailed;
|
self.transitionState(.Recording, &.{ .Initial, .Executable, .Invalid }) catch return VkError.ValidationFailed;
|
||||||
if (implicitly_reset) {
|
if (implicitly_reset) {
|
||||||
try self.dispatch_table.reset(self, .{});
|
try self.dispatch_table.reset(self, .{});
|
||||||
self.begin_info = null;
|
self.begin_info = null;
|
||||||
@@ -128,12 +130,12 @@ pub fn begin(self: *Self, info: *const vk.CommandBufferBeginInfo) VkError!void {
|
|||||||
|
|
||||||
try self.dispatch_table.begin(self, info);
|
try self.dispatch_table.begin(self, info);
|
||||||
self.begin_info = info.*;
|
self.begin_info = info.*;
|
||||||
|
self.usage_flags = info.flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn end(self: *Self) VkError!void {
|
pub fn end(self: *Self) VkError!void {
|
||||||
self.transitionState(.Executable, &.{.Recording}) catch return VkError.ValidationFailed;
|
self.transitionState(.Executable, &.{.Recording}) catch return VkError.ValidationFailed;
|
||||||
try self.dispatch_table.end(self);
|
try self.dispatch_table.end(self);
|
||||||
self.begin_info = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reset(self: *Self, flags: vk.CommandBufferResetFlags) VkError!void {
|
pub fn reset(self: *Self, flags: vk.CommandBufferResetFlags) VkError!void {
|
||||||
@@ -141,26 +143,28 @@ pub fn reset(self: *Self, flags: vk.CommandBufferResetFlags) VkError!void {
|
|||||||
return VkError.ValidationFailed;
|
return VkError.ValidationFailed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try self.resetFromPool(flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn resetFromPool(self: *Self, flags: vk.CommandBufferResetFlags) VkError!void {
|
||||||
self.transitionState(.Initial, &.{ .Initial, .Recording, .Executable, .Invalid }) catch return VkError.ValidationFailed;
|
self.transitionState(.Initial, &.{ .Initial, .Recording, .Executable, .Invalid }) catch return VkError.ValidationFailed;
|
||||||
try self.dispatch_table.reset(self, flags);
|
try self.dispatch_table.reset(self, flags);
|
||||||
|
self.begin_info = null;
|
||||||
|
self.usage_flags = .{};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn submit(self: *Self) VkError!void {
|
pub fn submit(self: *Self) VkError!void {
|
||||||
if (self.begin_info) |begin_info| {
|
if (!self.usage_flags.simultaneous_use_bit) {
|
||||||
if (!begin_info.flags.simultaneous_use_bit) {
|
self.transitionState(.Pending, &.{.Executable}) catch return VkError.ValidationFailed;
|
||||||
self.transitionState(.Pending, &.{.Executable}) catch return VkError.ValidationFailed;
|
return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
self.transitionState(.Pending, &.{ .Pending, .Executable }) catch return VkError.ValidationFailed;
|
self.transitionState(.Pending, &.{ .Pending, .Executable }) catch return VkError.ValidationFailed;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn finish(self: *Self) VkError!void {
|
pub fn finish(self: *Self) VkError!void {
|
||||||
if (self.begin_info) |begin_info| {
|
if (self.usage_flags.one_time_submit_bit) {
|
||||||
if (!begin_info.flags.one_time_submit_bit) {
|
self.transitionState(.Invalid, &.{.Pending}) catch return VkError.ValidationFailed;
|
||||||
self.transitionState(.Invalid, &.{.Pending}) catch return VkError.ValidationFailed;
|
return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
self.transitionState(.Executable, &.{.Pending}) catch return VkError.ValidationFailed;
|
self.transitionState(.Executable, &.{.Pending}) catch return VkError.ValidationFailed;
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-10
@@ -55,10 +55,23 @@ pub fn allocateCommandBuffers(self: *Self, info: *const vk.CommandBufferAllocate
|
|||||||
while (self.buffers.capacity < self.buffers.items.len + info.command_buffer_count) {
|
while (self.buffers.capacity < self.buffers.items.len + info.command_buffer_count) {
|
||||||
self.buffers.ensureUnusedCapacity(allocator, BUFFER_POOL_BASE_CAPACITY) catch return VkError.OutOfHostMemory;
|
self.buffers.ensureUnusedCapacity(allocator, BUFFER_POOL_BASE_CAPACITY) catch return VkError.OutOfHostMemory;
|
||||||
}
|
}
|
||||||
|
const original_len = self.buffers.items.len;
|
||||||
|
errdefer {
|
||||||
|
for (self.buffers.items[original_len..]) |dis_cmd| {
|
||||||
|
dis_cmd.intrusiveDestroy(allocator);
|
||||||
|
}
|
||||||
|
self.buffers.shrinkRetainingCapacity(original_len);
|
||||||
|
}
|
||||||
for (0..info.command_buffer_count) |_| {
|
for (0..info.command_buffer_count) |_| {
|
||||||
const cmd = try self.vtable.createCommandBuffer(self, allocator, info);
|
const cmd = try self.vtable.createCommandBuffer(self, allocator, info);
|
||||||
|
var cmd_owned = true;
|
||||||
|
errdefer if (cmd_owned) cmd.destroy(allocator);
|
||||||
const dis_cmd = try Dispatchable(CommandBuffer).wrap(allocator, cmd);
|
const dis_cmd = try Dispatchable(CommandBuffer).wrap(allocator, cmd);
|
||||||
|
cmd_owned = false;
|
||||||
|
var dis_cmd_owned = true;
|
||||||
|
errdefer if (dis_cmd_owned) dis_cmd.intrusiveDestroy(allocator);
|
||||||
self.buffers.appendAssumeCapacity(dis_cmd);
|
self.buffers.appendAssumeCapacity(dis_cmd);
|
||||||
|
dis_cmd_owned = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,15 +110,7 @@ pub fn reset(self: *Self, flags: vk.CommandPoolResetFlags) VkError!void {
|
|||||||
|
|
||||||
self.first_free_buffer_index = 0;
|
self.first_free_buffer_index = 0;
|
||||||
|
|
||||||
if (flags.release_resources_bit) {
|
for (self.buffers.items) |dis_cmd| {
|
||||||
const allocator = self.host_allocator.allocator();
|
_ = dis_cmd.object.resetFromPool(.{ .release_resources_bit = flags.release_resources_bit }) catch {};
|
||||||
for (self.buffers.items) |dis_cmd| {
|
|
||||||
dis_cmd.intrusiveDestroy(allocator);
|
|
||||||
}
|
|
||||||
self.buffers.clearRetainingCapacity();
|
|
||||||
} else {
|
|
||||||
for (self.buffers.items) |dis_cmd| {
|
|
||||||
_ = dis_cmd.object.reset(.{ .release_resources_bit = true }) catch {};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-1
@@ -41,6 +41,7 @@ instance: *Instance,
|
|||||||
physical_device: *const PhysicalDevice,
|
physical_device: *const PhysicalDevice,
|
||||||
queues: std.AutoArrayHashMapUnmanaged(u32, std.ArrayList(*Dispatchable(Queue))),
|
queues: std.AutoArrayHashMapUnmanaged(u32, std.ArrayList(*Dispatchable(Queue))),
|
||||||
host_allocator: VulkanAllocator,
|
host_allocator: VulkanAllocator,
|
||||||
|
khr_swapchain_enabled: bool,
|
||||||
|
|
||||||
dispatch_table: *const DispatchTable,
|
dispatch_table: *const DispatchTable,
|
||||||
vtable: *const VTable,
|
vtable: *const VTable,
|
||||||
@@ -75,17 +76,28 @@ pub const DispatchTable = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub fn init(allocator: std.mem.Allocator, instance: *Instance, physical_device: *const PhysicalDevice, info: *const vk.DeviceCreateInfo) VkError!Self {
|
pub fn init(allocator: std.mem.Allocator, instance: *Instance, physical_device: *const PhysicalDevice, info: *const vk.DeviceCreateInfo) VkError!Self {
|
||||||
_ = info;
|
|
||||||
return .{
|
return .{
|
||||||
.instance = instance,
|
.instance = instance,
|
||||||
.physical_device = physical_device,
|
.physical_device = physical_device,
|
||||||
.queues = .empty,
|
.queues = .empty,
|
||||||
.host_allocator = VulkanAllocator.from(allocator).cloneWithScope(.object),
|
.host_allocator = VulkanAllocator.from(allocator).cloneWithScope(.object),
|
||||||
|
.khr_swapchain_enabled = isExtensionEnabled(info, vk.extensions.khr_swapchain.name),
|
||||||
.dispatch_table = undefined,
|
.dispatch_table = undefined,
|
||||||
.vtable = undefined,
|
.vtable = undefined,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn isExtensionEnabled(info: *const vk.DeviceCreateInfo, extension_name: []const u8) bool {
|
||||||
|
if (info.enabled_extension_count == 0) return false;
|
||||||
|
const names = info.pp_enabled_extension_names orelse return false;
|
||||||
|
for (0..info.enabled_extension_count) |i| {
|
||||||
|
if (std.mem.eql(u8, std.mem.span(names[i]), extension_name)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn createQueues(self: *Self, allocator: std.mem.Allocator, info: *const vk.DeviceCreateInfo) VkError!void {
|
pub fn createQueues(self: *Self, allocator: std.mem.Allocator, info: *const vk.DeviceCreateInfo) VkError!void {
|
||||||
if (info.queue_create_info_count == 0) {
|
if (info.queue_create_info_count == 0) {
|
||||||
return;
|
return;
|
||||||
@@ -102,8 +114,10 @@ pub fn createQueues(self: *Self, allocator: std.mem.Allocator, info: *const vk.D
|
|||||||
}
|
}
|
||||||
|
|
||||||
const queue = try self.vtable.createQueue(allocator, self, queue_info.queue_family_index, @intCast(family_ptr.items.len), queue_info.flags);
|
const queue = try self.vtable.createQueue(allocator, self, queue_info.queue_family_index, @intCast(family_ptr.items.len), queue_info.flags);
|
||||||
|
errdefer self.vtable.destroyQueue(queue, allocator) catch {};
|
||||||
|
|
||||||
const dispatchable_queue = try Dispatchable(Queue).wrap(allocator, queue);
|
const dispatchable_queue = try Dispatchable(Queue).wrap(allocator, queue);
|
||||||
|
errdefer dispatchable_queue.destroy(allocator);
|
||||||
family_ptr.append(allocator, dispatchable_queue) catch return VkError.OutOfHostMemory;
|
family_ptr.append(allocator, dispatchable_queue) catch return VkError.OutOfHostMemory;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ pub inline fn destroy(self: *Self, allocator: std.mem.Allocator) void {
|
|||||||
|
|
||||||
pub 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();
|
const image_size = try self.getTotalSize();
|
||||||
if (offset >= image_size or !self.allowed_memory_types.isSet(memory.memory_type_index)) {
|
if (offset + image_size > memory.size or !self.allowed_memory_types.isSet(memory.memory_type_index)) {
|
||||||
return VkError.ValidationFailed;
|
return VkError.ValidationFailed;
|
||||||
}
|
}
|
||||||
self.memory = memory;
|
self.memory = memory;
|
||||||
|
|||||||
+50
-4
@@ -2,6 +2,7 @@ const std = @import("std");
|
|||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
const vk = @import("vulkan");
|
const vk = @import("vulkan");
|
||||||
const config = @import("lib.zig").config;
|
const config = @import("lib.zig").config;
|
||||||
|
const utils = @import("utils.zig");
|
||||||
|
|
||||||
const VkError = @import("error_set.zig").VkError;
|
const VkError = @import("error_set.zig").VkError;
|
||||||
const Dispatchable = @import("Dispatchable.zig").Dispatchable;
|
const Dispatchable = @import("Dispatchable.zig").Dispatchable;
|
||||||
@@ -50,6 +51,41 @@ pub fn init(allocator: std.mem.Allocator, infos: *const vk.InstanceCreateInfo) V
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn validateCreateInfo(info: *const vk.InstanceCreateInfo) VkError!void {
|
||||||
|
if (info.p_application_info) |application_info| {
|
||||||
|
const requested: vk.Version = @bitCast(application_info.api_version);
|
||||||
|
const supported: vk.Version = if (comptime builtin.is_test)
|
||||||
|
vk.API_VERSION_1_0
|
||||||
|
else
|
||||||
|
@bitCast(root.VULKAN_VERSION);
|
||||||
|
if (requested.variant != 0 or requested.major > supported.major or (requested.major == supported.major and requested.minor > supported.minor)) {
|
||||||
|
return VkError.IncompatibleDriver;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info.enabled_layer_count != 0) {
|
||||||
|
const names = info.pp_enabled_layer_names orelse return VkError.LayerNotPresent;
|
||||||
|
for (0..info.enabled_layer_count) |i| {
|
||||||
|
_ = utils.boundedName(names[i], vk.MAX_EXTENSION_NAME_SIZE) orelse return VkError.LayerNotPresent;
|
||||||
|
return VkError.LayerNotPresent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info.enabled_extension_count != 0) {
|
||||||
|
const names = info.pp_enabled_extension_names orelse return VkError.ExtensionNotPresent;
|
||||||
|
const supported_extensions = if (comptime builtin.is_test)
|
||||||
|
&[_]vk.ExtensionProperties{}
|
||||||
|
else
|
||||||
|
root.Instance.EXTENSIONS[0..];
|
||||||
|
for (0..info.enabled_extension_count) |i| {
|
||||||
|
const name = utils.boundedName(names[i], vk.MAX_EXTENSION_NAME_SIZE) orelse return VkError.ExtensionNotPresent;
|
||||||
|
if (!utils.isSupportedExtension(name, supported_extensions)) {
|
||||||
|
return VkError.ExtensionNotPresent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Dummy to avoid compile error in tests and doc generation
|
/// Dummy to avoid compile error in tests and doc generation
|
||||||
pub fn create(allocator: std.mem.Allocator, infos: *const vk.InstanceCreateInfo) VkError!*Self {
|
pub fn create(allocator: std.mem.Allocator, infos: *const vk.InstanceCreateInfo) VkError!*Self {
|
||||||
_ = allocator;
|
_ = allocator;
|
||||||
@@ -64,11 +100,16 @@ pub fn deinit(self: *Self, allocator: std.mem.Allocator) VkError!void {
|
|||||||
|
|
||||||
pub fn enumerateLayerProperties(count: *u32, p_properties: ?[*]vk.LayerProperties) VkError!void {
|
pub fn enumerateLayerProperties(count: *u32, p_properties: ?[*]vk.LayerProperties) VkError!void {
|
||||||
if (comptime !builtin.is_test and @hasDecl(root.Instance, "LAYERS")) {
|
if (comptime !builtin.is_test and @hasDecl(root.Instance, "LAYERS")) {
|
||||||
count.* = root.Instance.LAYERS.len;
|
const available = root.Instance.LAYERS.len;
|
||||||
if (p_properties) |properties| {
|
if (p_properties) |properties| {
|
||||||
for (root.Instance.LAYERS, properties[0..]) |layer, *prop| {
|
const write_count = @min(count.*, available);
|
||||||
|
for (root.Instance.LAYERS[0..write_count], properties[0..write_count]) |layer, *prop| {
|
||||||
prop.* = layer;
|
prop.* = layer;
|
||||||
}
|
}
|
||||||
|
count.* = @intCast(write_count);
|
||||||
|
if (write_count < available) return VkError.Incomplete;
|
||||||
|
} else {
|
||||||
|
count.* = @intCast(available);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
count.* = 0;
|
count.* = 0;
|
||||||
@@ -81,11 +122,16 @@ pub fn enumerateExtensionProperties(layer_name: ?[]const u8, count: *u32, p_prop
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (comptime !builtin.is_test and @hasDecl(root.Instance, "EXTENSIONS")) {
|
if (comptime !builtin.is_test and @hasDecl(root.Instance, "EXTENSIONS")) {
|
||||||
count.* = root.Instance.EXTENSIONS.len;
|
const available = root.Instance.EXTENSIONS.len;
|
||||||
if (p_properties) |properties| {
|
if (p_properties) |properties| {
|
||||||
for (root.Instance.EXTENSIONS, properties[0..]) |ext, *prop| {
|
const write_count = @min(count.*, available);
|
||||||
|
for (root.Instance.EXTENSIONS[0..write_count], properties[0..write_count]) |ext, *prop| {
|
||||||
prop.* = ext;
|
prop.* = ext;
|
||||||
}
|
}
|
||||||
|
count.* = @intCast(write_count);
|
||||||
|
if (write_count < available) return VkError.Incomplete;
|
||||||
|
} else {
|
||||||
|
count.* = @intCast(available);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
count.* = 0;
|
count.* = 0;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const vk = @import("vulkan");
|
const vk = @import("vulkan");
|
||||||
const root = @import("lib.zig");
|
const root = @import("lib.zig");
|
||||||
|
const utils = @import("utils.zig");
|
||||||
|
|
||||||
const Instance = @import("Instance.zig");
|
const Instance = @import("Instance.zig");
|
||||||
const VkError = @import("error_set.zig").VkError;
|
const VkError = @import("error_set.zig").VkError;
|
||||||
@@ -64,6 +65,43 @@ pub inline fn createDevice(self: *Self, allocator: std.mem.Allocator, infos: *co
|
|||||||
return try self.dispatch_table.createDevice(self, allocator, infos);
|
return try self.dispatch_table.createDevice(self, allocator, infos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn validateCreateInfo(self: *const Self, allocator: std.mem.Allocator, info: *const vk.DeviceCreateInfo) VkError!void {
|
||||||
|
if (info.enabled_layer_count != 0) {
|
||||||
|
const names = info.pp_enabled_layer_names orelse return VkError.LayerNotPresent;
|
||||||
|
for (0..info.enabled_layer_count) |i| {
|
||||||
|
_ = utils.boundedName(names[i], vk.MAX_EXTENSION_NAME_SIZE) orelse return VkError.LayerNotPresent;
|
||||||
|
return VkError.LayerNotPresent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info.enabled_extension_count != 0) {
|
||||||
|
const names = info.pp_enabled_extension_names orelse return VkError.ExtensionNotPresent;
|
||||||
|
|
||||||
|
var available_count: u32 = 0;
|
||||||
|
try self.enumerateExtensionProperties(null, &available_count, null);
|
||||||
|
const supported_extensions = allocator.alloc(vk.ExtensionProperties, available_count) catch return VkError.OutOfHostMemory;
|
||||||
|
defer allocator.free(supported_extensions);
|
||||||
|
|
||||||
|
var written_count = available_count;
|
||||||
|
try self.enumerateExtensionProperties(null, &written_count, supported_extensions.ptr);
|
||||||
|
|
||||||
|
for (0..info.enabled_extension_count) |i| {
|
||||||
|
const name = utils.boundedName(names[i], vk.MAX_EXTENSION_NAME_SIZE) orelse return VkError.ExtensionNotPresent;
|
||||||
|
if (!utils.isSupportedExtension(name, supported_extensions[0..written_count])) {
|
||||||
|
return VkError.ExtensionNotPresent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info.p_enabled_features) |requested_features| {
|
||||||
|
inline for (std.meta.fields(vk.PhysicalDeviceFeatures)) |field| {
|
||||||
|
if (@field(requested_features, field.name) == .true and @field(self.features, field.name) == .false) {
|
||||||
|
return VkError.FeatureNotPresent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub inline 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);
|
return try self.dispatch_table.getFormatProperties(self, format);
|
||||||
}
|
}
|
||||||
|
|||||||
+37
-10
@@ -93,6 +93,21 @@ pub fn initGraphics(device: *Device, allocator: std.mem.Allocator, cache: ?*Pipe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var binding_description: ?[]vk.VertexInputBindingDescription = null;
|
||||||
|
errdefer if (binding_description) |value| allocator.free(value);
|
||||||
|
|
||||||
|
var attribute_description: ?[]vk.VertexInputAttributeDescription = null;
|
||||||
|
errdefer if (attribute_description) |value| allocator.free(value);
|
||||||
|
|
||||||
|
var viewports: ?[]vk.Viewport = null;
|
||||||
|
errdefer if (viewports) |value| allocator.free(value);
|
||||||
|
|
||||||
|
var scissors: ?[]vk.Rect2D = null;
|
||||||
|
errdefer if (scissors) |value| allocator.free(value);
|
||||||
|
|
||||||
|
var color_attachments: ?[]vk.PipelineColorBlendAttachmentState = null;
|
||||||
|
errdefer if (color_attachments) |value| allocator.free(value);
|
||||||
|
|
||||||
return .{
|
return .{
|
||||||
.owner = device,
|
.owner = device,
|
||||||
.vtable = undefined,
|
.vtable = undefined,
|
||||||
@@ -105,7 +120,8 @@ pub fn initGraphics(device: *Device, allocator: std.mem.Allocator, cache: ?*Pipe
|
|||||||
.binding_description = blk: {
|
.binding_description = blk: {
|
||||||
if (info.p_vertex_input_state) |vertex_input_state| {
|
if (info.p_vertex_input_state) |vertex_input_state| {
|
||||||
if (vertex_input_state.p_vertex_binding_descriptions) |vertex_binding_descriptions| {
|
if (vertex_input_state.p_vertex_binding_descriptions) |vertex_binding_descriptions| {
|
||||||
break :blk allocator.dupe(vk.VertexInputBindingDescription, vertex_binding_descriptions[0..vertex_input_state.vertex_binding_description_count]) catch return VkError.OutOfHostMemory;
|
binding_description = allocator.dupe(vk.VertexInputBindingDescription, vertex_binding_descriptions[0..vertex_input_state.vertex_binding_description_count]) catch return VkError.OutOfHostMemory;
|
||||||
|
break :blk binding_description;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return VkError.ValidationFailed;
|
return VkError.ValidationFailed;
|
||||||
@@ -115,7 +131,8 @@ pub fn initGraphics(device: *Device, allocator: std.mem.Allocator, cache: ?*Pipe
|
|||||||
.attribute_description = blk: {
|
.attribute_description = blk: {
|
||||||
if (info.p_vertex_input_state) |vertex_input_state| {
|
if (info.p_vertex_input_state) |vertex_input_state| {
|
||||||
if (vertex_input_state.p_vertex_attribute_descriptions) |vertex_attribute_descriptions| {
|
if (vertex_input_state.p_vertex_attribute_descriptions) |vertex_attribute_descriptions| {
|
||||||
break :blk allocator.dupe(vk.VertexInputAttributeDescription, vertex_attribute_descriptions[0..vertex_input_state.vertex_attribute_description_count]) catch return VkError.OutOfHostMemory;
|
attribute_description = allocator.dupe(vk.VertexInputAttributeDescription, vertex_attribute_descriptions[0..vertex_input_state.vertex_attribute_description_count]) catch return VkError.OutOfHostMemory;
|
||||||
|
break :blk attribute_description;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return VkError.ValidationFailed;
|
return VkError.ValidationFailed;
|
||||||
@@ -128,16 +145,20 @@ pub fn initGraphics(device: *Device, allocator: std.mem.Allocator, cache: ?*Pipe
|
|||||||
.viewport_state = .{
|
.viewport_state = .{
|
||||||
.viewports = blk: {
|
.viewports = blk: {
|
||||||
if (info.p_viewport_state) |viewport_state| {
|
if (info.p_viewport_state) |viewport_state| {
|
||||||
if (viewport_state.p_viewports) |viewports| {
|
if (viewport_state.p_viewports) |p_viewports| {
|
||||||
break :blk allocator.dupe(vk.Viewport, viewports[0..viewport_state.viewport_count]) catch return VkError.OutOfHostMemory;
|
const copy = allocator.dupe(vk.Viewport, p_viewports[0..viewport_state.viewport_count]) catch return VkError.OutOfHostMemory;
|
||||||
|
viewports = copy;
|
||||||
|
break :blk viewports;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break :blk null;
|
break :blk null;
|
||||||
},
|
},
|
||||||
.scissor = blk: {
|
.scissor = blk: {
|
||||||
if (info.p_viewport_state) |viewport_state| {
|
if (info.p_viewport_state) |viewport_state| {
|
||||||
if (viewport_state.p_scissors) |scissors| {
|
if (viewport_state.p_scissors) |p_scissors| {
|
||||||
break :blk allocator.dupe(vk.Rect2D, scissors[0..viewport_state.scissor_count]) catch return VkError.OutOfHostMemory;
|
const copy = allocator.dupe(vk.Rect2D, p_scissors[0..viewport_state.scissor_count]) catch return VkError.OutOfHostMemory;
|
||||||
|
scissors = copy;
|
||||||
|
break :blk scissors;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break :blk null;
|
break :blk null;
|
||||||
@@ -152,10 +173,10 @@ pub fn initGraphics(device: *Device, allocator: std.mem.Allocator, cache: ?*Pipe
|
|||||||
.color_blend = blk: {
|
.color_blend = blk: {
|
||||||
if (info.p_color_blend_state) |state| {
|
if (info.p_color_blend_state) |state| {
|
||||||
break :blk .{
|
break :blk .{
|
||||||
.attachments = if (state.p_attachments) |attachments|
|
.attachments = if (state.p_attachments) |attachments| blk_attachments: {
|
||||||
allocator.dupe(vk.PipelineColorBlendAttachmentState, attachments[0..state.attachment_count]) catch return VkError.OutOfHostMemory
|
color_attachments = allocator.dupe(vk.PipelineColorBlendAttachmentState, attachments[0..state.attachment_count]) catch return VkError.OutOfHostMemory;
|
||||||
else
|
break :blk_attachments color_attachments;
|
||||||
null,
|
} else null,
|
||||||
.constants = state.blend_constants,
|
.constants = state.blend_constants,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -205,6 +226,12 @@ pub inline fn destroy(self: *Self, allocator: std.mem.Allocator) void {
|
|||||||
if (graphics.input_assembly.attribute_description) |attribute_description| {
|
if (graphics.input_assembly.attribute_description) |attribute_description| {
|
||||||
allocator.free(attribute_description);
|
allocator.free(attribute_description);
|
||||||
}
|
}
|
||||||
|
if (graphics.viewport_state.viewports) |viewports| {
|
||||||
|
allocator.free(viewports);
|
||||||
|
}
|
||||||
|
if (graphics.viewport_state.scissor) |scissor| {
|
||||||
|
allocator.free(scissor);
|
||||||
|
}
|
||||||
if (graphics.color_blend.attachments) |attachments| {
|
if (graphics.color_blend.attachments) |attachments| {
|
||||||
allocator.free(attachments);
|
allocator.free(attachments);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ const vk = @import("vulkan");
|
|||||||
const NonDispatchable = @import("NonDispatchable.zig");
|
const NonDispatchable = @import("NonDispatchable.zig");
|
||||||
|
|
||||||
const VkError = @import("error_set.zig").VkError;
|
const VkError = @import("error_set.zig").VkError;
|
||||||
|
const root = @import("lib.zig");
|
||||||
|
|
||||||
const Device = @import("Device.zig");
|
const Device = @import("Device.zig");
|
||||||
|
|
||||||
@@ -11,6 +12,7 @@ const Self = @This();
|
|||||||
pub const ObjectType: vk.ObjectType = .pipeline_cache;
|
pub const ObjectType: vk.ObjectType = .pipeline_cache;
|
||||||
|
|
||||||
owner: *Device,
|
owner: *Device,
|
||||||
|
data_available: bool,
|
||||||
|
|
||||||
vtable: *const VTable,
|
vtable: *const VTable,
|
||||||
|
|
||||||
@@ -18,11 +20,14 @@ pub const VTable = struct {
|
|||||||
destroy: *const fn (*Self, std.mem.Allocator) void,
|
destroy: *const fn (*Self, std.mem.Allocator) void,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const Header = vk.PipelineCacheHeaderVersionOne;
|
||||||
|
|
||||||
pub fn init(device: *Device, allocator: std.mem.Allocator, info: *const vk.PipelineCacheCreateInfo) VkError!Self {
|
pub fn init(device: *Device, allocator: std.mem.Allocator, info: *const vk.PipelineCacheCreateInfo) VkError!Self {
|
||||||
_ = allocator;
|
_ = allocator;
|
||||||
_ = info;
|
const has_initial_data = info.initial_data_size != 0 or info.p_initial_data != null;
|
||||||
return .{
|
return .{
|
||||||
.owner = device,
|
.owner = device,
|
||||||
|
.data_available = !has_initial_data or info.initial_data_size >= dataSize(),
|
||||||
.vtable = undefined,
|
.vtable = undefined,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -30,3 +35,44 @@ pub fn init(device: *Device, allocator: std.mem.Allocator, info: *const vk.Pipel
|
|||||||
pub inline fn destroy(self: *Self, allocator: std.mem.Allocator) void {
|
pub inline fn destroy(self: *Self, allocator: std.mem.Allocator) void {
|
||||||
self.vtable.destroy(self, allocator);
|
self.vtable.destroy(self, allocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn merge(self: *Self) VkError!void {
|
||||||
|
_ = self;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn getData(self: *Self, data: ?[]u8) vk.Result {
|
||||||
|
if (!self.data_available) {
|
||||||
|
return .success;
|
||||||
|
}
|
||||||
|
|
||||||
|
const cache_header = self.header();
|
||||||
|
const bytes = std.mem.asBytes(&cache_header);
|
||||||
|
|
||||||
|
if (data) |dst| {
|
||||||
|
if (dst.len < bytes.len) {
|
||||||
|
return .incomplete;
|
||||||
|
}
|
||||||
|
|
||||||
|
@memcpy(dst[0..bytes.len], bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
return .success;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn dataSize() usize {
|
||||||
|
return @sizeOf(Header);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub inline fn availableDataSize(self: *const Self) usize {
|
||||||
|
return if (self.data_available) dataSize() else 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn header(self: *const Self) Header {
|
||||||
|
return .{
|
||||||
|
.header_size = @sizeOf(Header),
|
||||||
|
.header_version = .one,
|
||||||
|
.vendor_id = @intCast(root.VULKAN_VENDOR_ID),
|
||||||
|
.device_id = self.owner.physical_device.props.device_id,
|
||||||
|
.pipeline_cache_uuid = self.owner.physical_device.props.pipeline_cache_uuid,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
+3
-1
@@ -52,7 +52,9 @@ pub const ShaderModule = @import("ShaderModule.zig");
|
|||||||
pub const SurfaceKHR = @import("wsi/SurfaceKHR.zig");
|
pub const SurfaceKHR = @import("wsi/SurfaceKHR.zig");
|
||||||
pub const SwapchainKHR = @import("wsi/SwapchainKHR.zig");
|
pub const SwapchainKHR = @import("wsi/SwapchainKHR.zig");
|
||||||
|
|
||||||
pub const VULKAN_VENDOR_ID = 0x10008;
|
// To be commented out when spec 1.4.354 is released
|
||||||
|
// pub const VULKAN_VENDOR_ID: i32 = @intFromEnum(vk.VendorId.ape);
|
||||||
|
pub const VULKAN_VENDOR_ID: i32 = 0x10008;
|
||||||
|
|
||||||
/// Default driver name
|
/// Default driver name
|
||||||
pub const DRIVER_NAME = "Unnamed Ape Driver";
|
pub const DRIVER_NAME = "Unnamed Ape Driver";
|
||||||
|
|||||||
+125
-43
@@ -64,6 +64,22 @@ inline fn notImplementedWarning() void {
|
|||||||
logger.fixme("function not yet implemented", .{});
|
logger.fixme("function not yet implemented", .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn isSwapchainDeviceFunction(name: []const u8) bool {
|
||||||
|
return std.mem.eql(u8, name, "vkAcquireNextImageKHR") or
|
||||||
|
std.mem.eql(u8, name, "vkCreateSwapchainKHR") or
|
||||||
|
std.mem.eql(u8, name, "vkDestroySwapchainKHR") or
|
||||||
|
std.mem.eql(u8, name, "vkGetSwapchainImagesKHR") or
|
||||||
|
std.mem.eql(u8, name, "vkQueuePresentKHR");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn wrapNonDispatchable(comptime T: type, allocator: std.mem.Allocator, object: *T, comptime VkT: type) VkError!VkT {
|
||||||
|
const handle = NonDispatchable(T).wrap(allocator, object) catch |err| {
|
||||||
|
object.destroy(allocator);
|
||||||
|
return err;
|
||||||
|
};
|
||||||
|
return handle.toVkHandle(VkT);
|
||||||
|
}
|
||||||
|
|
||||||
fn functionMapEntryPoint(comptime name: []const u8) struct { []const u8, vk.PfnVoidFunction } {
|
fn functionMapEntryPoint(comptime name: []const u8) struct { []const u8, vk.PfnVoidFunction } {
|
||||||
// Mapping 'vkFnName' to 'apeFnName'
|
// Mapping 'vkFnName' to 'apeFnName'
|
||||||
const ape_name = std.fmt.comptimePrint("ape{s}", .{name[2..]});
|
const ape_name = std.fmt.comptimePrint("ape{s}", .{name[2..]});
|
||||||
@@ -94,6 +110,8 @@ const instance_pfn_map = std.StaticStringMap(vk.PfnVoidFunction).initComptime(.{
|
|||||||
functionMapEntryPoint("vkCreateWaylandSurfaceKHR"),
|
functionMapEntryPoint("vkCreateWaylandSurfaceKHR"),
|
||||||
functionMapEntryPoint("vkDestroyInstance"),
|
functionMapEntryPoint("vkDestroyInstance"),
|
||||||
functionMapEntryPoint("vkDestroySurfaceKHR"),
|
functionMapEntryPoint("vkDestroySurfaceKHR"),
|
||||||
|
functionMapEntryPoint("vkEnumeratePhysicalDeviceGroups"),
|
||||||
|
functionMapEntryPoint("vkEnumeratePhysicalDeviceGroupsKHR"),
|
||||||
functionMapEntryPoint("vkEnumeratePhysicalDevices"),
|
functionMapEntryPoint("vkEnumeratePhysicalDevices"),
|
||||||
functionMapEntryPoint("vkGetDeviceProcAddr"),
|
functionMapEntryPoint("vkGetDeviceProcAddr"),
|
||||||
});
|
});
|
||||||
@@ -312,15 +330,23 @@ pub export fn apeCreateInstance(info: *const vk.InstanceCreateInfo, callbacks: ?
|
|||||||
return .error_validation_failed;
|
return .error_validation_failed;
|
||||||
}
|
}
|
||||||
const allocator = VulkanAllocator.init(callbacks, .instance).allocator();
|
const allocator = VulkanAllocator.init(callbacks, .instance).allocator();
|
||||||
|
Instance.validateCreateInfo(info) catch |err| return toVkResult(err);
|
||||||
|
|
||||||
var instance: *lib.Instance = undefined;
|
var instance: *lib.Instance = undefined;
|
||||||
if (!builtin.is_test) {
|
if (!builtin.is_test) {
|
||||||
// Will call impl instead of interface as root refs the impl module
|
// Will call impl instead of interface as root refs the impl module
|
||||||
instance = root.Instance.create(allocator, info) catch |err| return toVkResult(err);
|
instance = root.Instance.create(allocator, info) catch |err| return toVkResult(err);
|
||||||
}
|
}
|
||||||
instance.requestPhysicalDevices(allocator) catch |err| return toVkResult(err);
|
instance.requestPhysicalDevices(allocator) catch |err| {
|
||||||
|
if (!builtin.is_test) instance.deinit(allocator) catch {};
|
||||||
|
return toVkResult(err);
|
||||||
|
};
|
||||||
|
|
||||||
p_instance.* = (Dispatchable(Instance).wrap(allocator, instance) catch |err| return toVkResult(err)).toVkHandle(vk.Instance);
|
const dispatchable = Dispatchable(Instance).wrap(allocator, instance) catch |err| {
|
||||||
|
if (!builtin.is_test) instance.deinit(allocator) catch {};
|
||||||
|
return toVkResult(err);
|
||||||
|
};
|
||||||
|
p_instance.* = dispatchable.toVkHandle(vk.Instance);
|
||||||
return .success;
|
return .success;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -370,15 +396,63 @@ pub export fn apeEnumeratePhysicalDevices(p_instance: vk.Instance, count: *u32,
|
|||||||
defer entryPointEndLogTrace();
|
defer entryPointEndLogTrace();
|
||||||
|
|
||||||
const instance = Dispatchable(Instance).fromHandleObject(p_instance) catch |err| return toVkResult(err);
|
const instance = Dispatchable(Instance).fromHandleObject(p_instance) catch |err| return toVkResult(err);
|
||||||
count.* = @intCast(instance.physical_devices.items.len);
|
const available = instance.physical_devices.items.len;
|
||||||
if (p_devices) |devices| {
|
if (p_devices) |devices| {
|
||||||
for (0..count.*) |i| {
|
const write_count = @min(count.*, available);
|
||||||
|
for (0..write_count) |i| {
|
||||||
devices[i] = instance.physical_devices.items[i].toVkHandle(vk.PhysicalDevice);
|
devices[i] = instance.physical_devices.items[i].toVkHandle(vk.PhysicalDevice);
|
||||||
}
|
}
|
||||||
|
count.* = @intCast(write_count);
|
||||||
|
if (write_count < available) return .incomplete;
|
||||||
|
} else {
|
||||||
|
count.* = @intCast(available);
|
||||||
}
|
}
|
||||||
return .success;
|
return .success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub export fn apeEnumeratePhysicalDeviceGroups(
|
||||||
|
p_instance: vk.Instance,
|
||||||
|
count: *u32,
|
||||||
|
p_groups: ?[*]vk.PhysicalDeviceGroupProperties,
|
||||||
|
) callconv(vk.vulkan_call_conv) vk.Result {
|
||||||
|
entryPointBeginLogTrace(.vkEnumeratePhysicalDeviceGroups);
|
||||||
|
defer entryPointEndLogTrace();
|
||||||
|
|
||||||
|
const instance = Dispatchable(Instance).fromHandleObject(p_instance) catch |err| return toVkResult(err);
|
||||||
|
const available: u32 = 1;
|
||||||
|
|
||||||
|
if (p_groups) |groups| {
|
||||||
|
const write_count = @min(count.*, available);
|
||||||
|
if (write_count == 0) {
|
||||||
|
count.* = 0;
|
||||||
|
return .incomplete;
|
||||||
|
}
|
||||||
|
|
||||||
|
var group = groups[0];
|
||||||
|
group.physical_device_count = @intCast(instance.physical_devices.items.len);
|
||||||
|
group.physical_devices = @splat(.null_handle);
|
||||||
|
for (instance.physical_devices.items, 0..) |physical_device, i| {
|
||||||
|
group.physical_devices[i] = physical_device.toVkHandle(vk.PhysicalDevice);
|
||||||
|
}
|
||||||
|
group.subset_allocation = .false;
|
||||||
|
groups[0] = group;
|
||||||
|
|
||||||
|
count.* = write_count;
|
||||||
|
return .success;
|
||||||
|
}
|
||||||
|
|
||||||
|
count.* = available;
|
||||||
|
return .success;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub export fn apeEnumeratePhysicalDeviceGroupsKHR(
|
||||||
|
p_instance: vk.Instance,
|
||||||
|
count: *u32,
|
||||||
|
p_groups: ?[*]vk.PhysicalDeviceGroupProperties,
|
||||||
|
) callconv(vk.vulkan_call_conv) vk.Result {
|
||||||
|
return apeEnumeratePhysicalDeviceGroups(p_instance, count, p_groups);
|
||||||
|
}
|
||||||
|
|
||||||
// Physical Device functions =================================================================================================================================
|
// Physical Device functions =================================================================================================================================
|
||||||
|
|
||||||
pub export fn apeCreateDevice(p_physical_device: vk.PhysicalDevice, info: *const vk.DeviceCreateInfo, callbacks: ?*const vk.AllocationCallbacks, p_device: *vk.Device) callconv(vk.vulkan_call_conv) vk.Result {
|
pub export fn apeCreateDevice(p_physical_device: vk.PhysicalDevice, info: *const vk.DeviceCreateInfo, callbacks: ?*const vk.AllocationCallbacks, p_device: *vk.Device) callconv(vk.vulkan_call_conv) vk.Result {
|
||||||
@@ -391,11 +465,16 @@ pub export fn apeCreateDevice(p_physical_device: vk.PhysicalDevice, info: *const
|
|||||||
|
|
||||||
const allocator = VulkanAllocator.init(callbacks, .device).allocator();
|
const allocator = VulkanAllocator.init(callbacks, .device).allocator();
|
||||||
const physical_device = Dispatchable(PhysicalDevice).fromHandleObject(p_physical_device) catch |err| return toVkResult(err);
|
const physical_device = Dispatchable(PhysicalDevice).fromHandleObject(p_physical_device) catch |err| return toVkResult(err);
|
||||||
|
physical_device.validateCreateInfo(allocator, info) catch |err| return toVkResult(err);
|
||||||
|
|
||||||
std.log.scoped(.vkCreateDevice).debug("Using VkPhysicalDevice named {s}", .{physical_device.props.device_name});
|
std.log.scoped(.vkCreateDevice).debug("Using VkPhysicalDevice named {s}", .{physical_device.props.device_name});
|
||||||
|
|
||||||
const device = physical_device.createDevice(allocator, info) catch |err| return toVkResult(err);
|
const device = physical_device.createDevice(allocator, info) catch |err| return toVkResult(err);
|
||||||
p_device.* = (Dispatchable(Device).wrap(allocator, device) catch |err| return toVkResult(err)).toVkHandle(vk.Device);
|
const dispatchable = Dispatchable(Device).wrap(allocator, device) catch |err| {
|
||||||
|
device.destroy(allocator) catch {};
|
||||||
|
return toVkResult(err);
|
||||||
|
};
|
||||||
|
p_device.* = dispatchable.toVkHandle(vk.Device);
|
||||||
return .success;
|
return .success;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -679,7 +758,7 @@ pub export fn apeAllocateMemory(p_device: vk.Device, info: *const vk.MemoryAlloc
|
|||||||
const device = Dispatchable(Device).fromHandleObject(p_device) catch |err| return toVkResult(err);
|
const device = Dispatchable(Device).fromHandleObject(p_device) catch |err| return toVkResult(err);
|
||||||
const device_memory = device.allocateMemory(allocator, info) catch |err| return toVkResult(err);
|
const device_memory = device.allocateMemory(allocator, info) catch |err| return toVkResult(err);
|
||||||
|
|
||||||
p_memory.* = (NonDispatchable(DeviceMemory).wrap(allocator, device_memory) catch |err| return toVkResult(err)).toVkHandle(vk.DeviceMemory);
|
p_memory.* = wrapNonDispatchable(DeviceMemory, allocator, device_memory, vk.DeviceMemory) catch |err| return toVkResult(err);
|
||||||
return .success;
|
return .success;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -723,7 +802,7 @@ pub export fn apeCreateBuffer(p_device: vk.Device, info: *const vk.BufferCreateI
|
|||||||
const allocator = VulkanAllocator.init(callbacks, .object).allocator();
|
const allocator = VulkanAllocator.init(callbacks, .object).allocator();
|
||||||
const device = Dispatchable(Device).fromHandleObject(p_device) catch |err| return toVkResult(err);
|
const device = Dispatchable(Device).fromHandleObject(p_device) catch |err| return toVkResult(err);
|
||||||
const buffer = device.createBuffer(allocator, info) catch |err| return toVkResult(err);
|
const buffer = device.createBuffer(allocator, info) catch |err| return toVkResult(err);
|
||||||
p_buffer.* = (NonDispatchable(Buffer).wrap(allocator, buffer) catch |err| return toVkResult(err)).toVkHandle(vk.Buffer);
|
p_buffer.* = wrapNonDispatchable(Buffer, allocator, buffer, vk.Buffer) catch |err| return toVkResult(err);
|
||||||
return .success;
|
return .success;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -737,7 +816,7 @@ pub export fn apeCreateBufferView(p_device: vk.Device, info: *const vk.BufferVie
|
|||||||
const allocator = VulkanAllocator.init(callbacks, .object).allocator();
|
const allocator = VulkanAllocator.init(callbacks, .object).allocator();
|
||||||
const device = Dispatchable(Device).fromHandleObject(p_device) catch |err| return toVkResult(err);
|
const device = Dispatchable(Device).fromHandleObject(p_device) catch |err| return toVkResult(err);
|
||||||
const view = device.createBufferView(allocator, info) catch |err| return toVkResult(err);
|
const view = device.createBufferView(allocator, info) catch |err| return toVkResult(err);
|
||||||
p_view.* = (NonDispatchable(BufferView).wrap(allocator, view) catch |err| return toVkResult(err)).toVkHandle(vk.BufferView);
|
p_view.* = wrapNonDispatchable(BufferView, allocator, view, vk.BufferView) catch |err| return toVkResult(err);
|
||||||
return .success;
|
return .success;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -752,7 +831,7 @@ pub export fn apeCreateCommandPool(p_device: vk.Device, info: *const vk.CommandP
|
|||||||
const allocator = VulkanAllocator.init(callbacks, .object).allocator();
|
const allocator = VulkanAllocator.init(callbacks, .object).allocator();
|
||||||
const device = Dispatchable(Device).fromHandleObject(p_device) catch |err| return toVkResult(err);
|
const device = Dispatchable(Device).fromHandleObject(p_device) catch |err| return toVkResult(err);
|
||||||
const pool = device.createCommandPool(allocator, info) catch |err| return toVkResult(err);
|
const pool = device.createCommandPool(allocator, info) catch |err| return toVkResult(err);
|
||||||
p_pool.* = (NonDispatchable(CommandPool).wrap(allocator, pool) catch |err| return toVkResult(err)).toVkHandle(vk.CommandPool);
|
p_pool.* = wrapNonDispatchable(CommandPool, allocator, pool, vk.CommandPool) catch |err| return toVkResult(err);
|
||||||
return .success;
|
return .success;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -808,7 +887,7 @@ pub export fn apeCreateDescriptorPool(p_device: vk.Device, info: *const vk.Descr
|
|||||||
const allocator = VulkanAllocator.init(callbacks, .object).allocator();
|
const allocator = VulkanAllocator.init(callbacks, .object).allocator();
|
||||||
const device = Dispatchable(Device).fromHandleObject(p_device) catch |err| return toVkResult(err);
|
const device = Dispatchable(Device).fromHandleObject(p_device) catch |err| return toVkResult(err);
|
||||||
const pool = device.createDescriptorPool(allocator, info) catch |err| return toVkResult(err);
|
const pool = device.createDescriptorPool(allocator, info) catch |err| return toVkResult(err);
|
||||||
p_pool.* = (NonDispatchable(DescriptorPool).wrap(allocator, pool) catch |err| return toVkResult(err)).toVkHandle(vk.DescriptorPool);
|
p_pool.* = wrapNonDispatchable(DescriptorPool, allocator, pool, vk.DescriptorPool) catch |err| return toVkResult(err);
|
||||||
return .success;
|
return .success;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -824,7 +903,7 @@ pub export fn apeCreateDescriptorSetLayout(p_device: vk.Device, info: *const vk.
|
|||||||
const allocator = VulkanAllocator.init(callbacks, .device).allocator();
|
const allocator = VulkanAllocator.init(callbacks, .device).allocator();
|
||||||
const device = Dispatchable(Device).fromHandleObject(p_device) catch |err| return toVkResult(err);
|
const device = Dispatchable(Device).fromHandleObject(p_device) catch |err| return toVkResult(err);
|
||||||
const layout = device.createDescriptorSetLayout(allocator, info) catch |err| return toVkResult(err);
|
const layout = device.createDescriptorSetLayout(allocator, info) catch |err| return toVkResult(err);
|
||||||
p_layout.* = (NonDispatchable(DescriptorSetLayout).wrap(allocator, layout) catch |err| return toVkResult(err)).toVkHandle(vk.DescriptorSetLayout);
|
p_layout.* = wrapNonDispatchable(DescriptorSetLayout, allocator, layout, vk.DescriptorSetLayout) catch |err| return toVkResult(err);
|
||||||
return .success;
|
return .success;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -839,7 +918,7 @@ pub export fn apeCreateEvent(p_device: vk.Device, info: *const vk.EventCreateInf
|
|||||||
const allocator = VulkanAllocator.init(callbacks, .object).allocator();
|
const allocator = VulkanAllocator.init(callbacks, .object).allocator();
|
||||||
const device = Dispatchable(Device).fromHandleObject(p_device) catch |err| return toVkResult(err);
|
const device = Dispatchable(Device).fromHandleObject(p_device) catch |err| return toVkResult(err);
|
||||||
const event = device.createEvent(allocator, info) catch |err| return toVkResult(err);
|
const event = device.createEvent(allocator, info) catch |err| return toVkResult(err);
|
||||||
p_event.* = (NonDispatchable(Event).wrap(allocator, event) catch |err| return toVkResult(err)).toVkHandle(vk.Event);
|
p_event.* = wrapNonDispatchable(Event, allocator, event, vk.Event) catch |err| return toVkResult(err);
|
||||||
return .success;
|
return .success;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -854,7 +933,7 @@ pub export fn apeCreateFence(p_device: vk.Device, info: *const vk.FenceCreateInf
|
|||||||
const allocator = VulkanAllocator.init(callbacks, .object).allocator();
|
const allocator = VulkanAllocator.init(callbacks, .object).allocator();
|
||||||
const device = Dispatchable(Device).fromHandleObject(p_device) catch |err| return toVkResult(err);
|
const device = Dispatchable(Device).fromHandleObject(p_device) catch |err| return toVkResult(err);
|
||||||
const fence = device.createFence(allocator, info) catch |err| return toVkResult(err);
|
const fence = device.createFence(allocator, info) catch |err| return toVkResult(err);
|
||||||
p_fence.* = (NonDispatchable(Fence).wrap(allocator, fence) catch |err| return toVkResult(err)).toVkHandle(vk.Fence);
|
p_fence.* = wrapNonDispatchable(Fence, allocator, fence, vk.Fence) catch |err| return toVkResult(err);
|
||||||
return .success;
|
return .success;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -869,7 +948,7 @@ pub export fn apeCreateFramebuffer(p_device: vk.Device, info: *const vk.Framebuf
|
|||||||
const allocator = VulkanAllocator.init(callbacks, .object).allocator();
|
const allocator = VulkanAllocator.init(callbacks, .object).allocator();
|
||||||
const device = Dispatchable(Device).fromHandleObject(p_device) catch |err| return toVkResult(err);
|
const device = Dispatchable(Device).fromHandleObject(p_device) catch |err| return toVkResult(err);
|
||||||
const framebuffer = device.createFramebuffer(allocator, info) catch |err| return toVkResult(err);
|
const framebuffer = device.createFramebuffer(allocator, info) catch |err| return toVkResult(err);
|
||||||
p_framebuffer.* = (NonDispatchable(Framebuffer).wrap(allocator, framebuffer) catch |err| return toVkResult(err)).toVkHandle(vk.Framebuffer);
|
p_framebuffer.* = wrapNonDispatchable(Framebuffer, allocator, framebuffer, vk.Framebuffer) catch |err| return toVkResult(err);
|
||||||
return .success;
|
return .success;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -922,7 +1001,7 @@ pub export fn apeCreateImage(p_device: vk.Device, info: *const vk.ImageCreateInf
|
|||||||
const allocator = VulkanAllocator.init(callbacks, .object).allocator();
|
const allocator = VulkanAllocator.init(callbacks, .object).allocator();
|
||||||
const device = Dispatchable(Device).fromHandleObject(p_device) catch |err| return toVkResult(err);
|
const device = Dispatchable(Device).fromHandleObject(p_device) catch |err| return toVkResult(err);
|
||||||
const image = device.createImage(allocator, info) catch |err| return toVkResult(err);
|
const image = device.createImage(allocator, info) catch |err| return toVkResult(err);
|
||||||
p_image.* = (NonDispatchable(Image).wrap(allocator, image) catch |err| return toVkResult(err)).toVkHandle(vk.Image);
|
p_image.* = wrapNonDispatchable(Image, allocator, image, vk.Image) catch |err| return toVkResult(err);
|
||||||
return .success;
|
return .success;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -936,7 +1015,7 @@ pub export fn apeCreateImageView(p_device: vk.Device, info: *const vk.ImageViewC
|
|||||||
const allocator = VulkanAllocator.init(callbacks, .object).allocator();
|
const allocator = VulkanAllocator.init(callbacks, .object).allocator();
|
||||||
const device = Dispatchable(Device).fromHandleObject(p_device) catch |err| return toVkResult(err);
|
const device = Dispatchable(Device).fromHandleObject(p_device) catch |err| return toVkResult(err);
|
||||||
const image_view = device.createImageView(allocator, info) catch |err| return toVkResult(err);
|
const image_view = device.createImageView(allocator, info) catch |err| return toVkResult(err);
|
||||||
p_image_view.* = (NonDispatchable(ImageView).wrap(allocator, image_view) catch |err| return toVkResult(err)).toVkHandle(vk.ImageView);
|
p_image_view.* = wrapNonDispatchable(ImageView, allocator, image_view, vk.ImageView) catch |err| return toVkResult(err);
|
||||||
return .success;
|
return .success;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -951,7 +1030,7 @@ pub export fn apeCreatePipelineCache(p_device: vk.Device, info: *const vk.Pipeli
|
|||||||
const allocator = VulkanAllocator.init(callbacks, .object).allocator();
|
const allocator = VulkanAllocator.init(callbacks, .object).allocator();
|
||||||
const device = Dispatchable(Device).fromHandleObject(p_device) catch |err| return toVkResult(err);
|
const device = Dispatchable(Device).fromHandleObject(p_device) catch |err| return toVkResult(err);
|
||||||
const cache = device.createPipelineCache(allocator, info) catch |err| return toVkResult(err);
|
const cache = device.createPipelineCache(allocator, info) catch |err| return toVkResult(err);
|
||||||
p_cache.* = (NonDispatchable(PipelineCache).wrap(allocator, cache) catch |err| return toVkResult(err)).toVkHandle(vk.PipelineCache);
|
p_cache.* = wrapNonDispatchable(PipelineCache, allocator, cache, vk.PipelineCache) catch |err| return toVkResult(err);
|
||||||
return .success;
|
return .success;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -967,7 +1046,7 @@ pub export fn apeCreatePipelineLayout(p_device: vk.Device, info: *const vk.Pipel
|
|||||||
const allocator = VulkanAllocator.init(callbacks, .device).allocator();
|
const allocator = VulkanAllocator.init(callbacks, .device).allocator();
|
||||||
const device = Dispatchable(Device).fromHandleObject(p_device) catch |err| return toVkResult(err);
|
const device = Dispatchable(Device).fromHandleObject(p_device) catch |err| return toVkResult(err);
|
||||||
const layout = device.createPipelineLayout(allocator, info) catch |err| return toVkResult(err);
|
const layout = device.createPipelineLayout(allocator, info) catch |err| return toVkResult(err);
|
||||||
p_layout.* = (NonDispatchable(PipelineLayout).wrap(allocator, layout) catch |err| return toVkResult(err)).toVkHandle(vk.PipelineLayout);
|
p_layout.* = wrapNonDispatchable(PipelineLayout, allocator, layout, vk.PipelineLayout) catch |err| return toVkResult(err);
|
||||||
return .success;
|
return .success;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -982,7 +1061,7 @@ pub export fn apeCreateQueryPool(p_device: vk.Device, info: *const vk.QueryPoolC
|
|||||||
const allocator = VulkanAllocator.init(callbacks, .object).allocator();
|
const allocator = VulkanAllocator.init(callbacks, .object).allocator();
|
||||||
const device = Dispatchable(Device).fromHandleObject(p_device) catch |err| return toVkResult(err);
|
const device = Dispatchable(Device).fromHandleObject(p_device) catch |err| return toVkResult(err);
|
||||||
const pool = device.createQueryPool(allocator, info) catch |err| return toVkResult(err);
|
const pool = device.createQueryPool(allocator, info) catch |err| return toVkResult(err);
|
||||||
p_pool.* = (NonDispatchable(QueryPool).wrap(allocator, pool) catch |err| return toVkResult(err)).toVkHandle(vk.QueryPool);
|
p_pool.* = wrapNonDispatchable(QueryPool, allocator, pool, vk.QueryPool) catch |err| return toVkResult(err);
|
||||||
return .success;
|
return .success;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -997,7 +1076,7 @@ pub export fn apeCreateRenderPass(p_device: vk.Device, info: *const vk.RenderPas
|
|||||||
const allocator = VulkanAllocator.init(callbacks, .object).allocator();
|
const allocator = VulkanAllocator.init(callbacks, .object).allocator();
|
||||||
const device = Dispatchable(Device).fromHandleObject(p_device) catch |err| return toVkResult(err);
|
const device = Dispatchable(Device).fromHandleObject(p_device) catch |err| return toVkResult(err);
|
||||||
const pass = device.createRenderPass(allocator, info) catch |err| return toVkResult(err);
|
const pass = device.createRenderPass(allocator, info) catch |err| return toVkResult(err);
|
||||||
p_pass.* = (NonDispatchable(RenderPass).wrap(allocator, pass) catch |err| return toVkResult(err)).toVkHandle(vk.RenderPass);
|
p_pass.* = wrapNonDispatchable(RenderPass, allocator, pass, vk.RenderPass) catch |err| return toVkResult(err);
|
||||||
return .success;
|
return .success;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1012,7 +1091,7 @@ pub export fn apeCreateSampler(p_device: vk.Device, info: *const vk.SamplerCreat
|
|||||||
const allocator = VulkanAllocator.init(callbacks, .object).allocator();
|
const allocator = VulkanAllocator.init(callbacks, .object).allocator();
|
||||||
const device = Dispatchable(Device).fromHandleObject(p_device) catch |err| return toVkResult(err);
|
const device = Dispatchable(Device).fromHandleObject(p_device) catch |err| return toVkResult(err);
|
||||||
const sampler = device.createSampler(allocator, info) catch |err| return toVkResult(err);
|
const sampler = device.createSampler(allocator, info) catch |err| return toVkResult(err);
|
||||||
p_sampler.* = (NonDispatchable(Sampler).wrap(allocator, sampler) catch |err| return toVkResult(err)).toVkHandle(vk.Sampler);
|
p_sampler.* = wrapNonDispatchable(Sampler, allocator, sampler, vk.Sampler) catch |err| return toVkResult(err);
|
||||||
return .success;
|
return .success;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1027,7 +1106,7 @@ pub export fn apeCreateSemaphore(p_device: vk.Device, info: *const vk.SemaphoreC
|
|||||||
const allocator = VulkanAllocator.init(callbacks, .object).allocator();
|
const allocator = VulkanAllocator.init(callbacks, .object).allocator();
|
||||||
const device = Dispatchable(Device).fromHandleObject(p_device) catch |err| return toVkResult(err);
|
const device = Dispatchable(Device).fromHandleObject(p_device) catch |err| return toVkResult(err);
|
||||||
const semaphore = device.createSemaphore(allocator, info) catch |err| return toVkResult(err);
|
const semaphore = device.createSemaphore(allocator, info) catch |err| return toVkResult(err);
|
||||||
p_semaphore.* = (NonDispatchable(BinarySemaphore).wrap(allocator, semaphore) catch |err| return toVkResult(err)).toVkHandle(vk.Semaphore);
|
p_semaphore.* = wrapNonDispatchable(BinarySemaphore, allocator, semaphore, vk.Semaphore) catch |err| return toVkResult(err);
|
||||||
return .success;
|
return .success;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1042,7 +1121,7 @@ pub export fn apeCreateShaderModule(p_device: vk.Device, info: *const vk.ShaderM
|
|||||||
const allocator = VulkanAllocator.init(callbacks, .object).allocator();
|
const allocator = VulkanAllocator.init(callbacks, .object).allocator();
|
||||||
const device = Dispatchable(Device).fromHandleObject(p_device) catch |err| return toVkResult(err);
|
const device = Dispatchable(Device).fromHandleObject(p_device) catch |err| return toVkResult(err);
|
||||||
const module = device.createShaderModule(allocator, info) catch |err| return toVkResult(err);
|
const module = device.createShaderModule(allocator, info) catch |err| return toVkResult(err);
|
||||||
p_module.* = (NonDispatchable(ShaderModule).wrap(allocator, module) catch |err| return toVkResult(err)).toVkHandle(vk.ShaderModule);
|
p_module.* = wrapNonDispatchable(ShaderModule, allocator, module, vk.ShaderModule) catch |err| return toVkResult(err);
|
||||||
return .success;
|
return .success;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1348,6 +1427,8 @@ pub export fn apeGetDeviceProcAddr(p_device: vk.Device, p_name: ?[*:0]const u8)
|
|||||||
const name = std.mem.span(p_name.?);
|
const name = std.mem.span(p_name.?);
|
||||||
|
|
||||||
if (p_device == .null_handle) return null;
|
if (p_device == .null_handle) return null;
|
||||||
|
const device = Dispatchable(Device).fromHandleObject(p_device) catch return null;
|
||||||
|
if (isSwapchainDeviceFunction(name) and !device.khr_swapchain_enabled) return null;
|
||||||
if (device_pfn_map.get(name)) |pfn| return pfn;
|
if (device_pfn_map.get(name)) |pfn| return pfn;
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@@ -1380,7 +1461,7 @@ pub export fn apeGetEventStatus(p_device: vk.Device, p_event: vk.Event) callconv
|
|||||||
|
|
||||||
const event = NonDispatchable(Event).fromHandleObject(p_event) catch |err| return toVkResult(err);
|
const event = NonDispatchable(Event).fromHandleObject(p_event) catch |err| return toVkResult(err);
|
||||||
event.getStatus() catch |err| return toVkResult(err);
|
event.getStatus() catch |err| return toVkResult(err);
|
||||||
return .success;
|
return .event_set;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub export fn apeGetFenceStatus(p_device: vk.Device, p_fence: vk.Fence) callconv(vk.vulkan_call_conv) vk.Result {
|
pub export fn apeGetFenceStatus(p_device: vk.Device, p_fence: vk.Fence) callconv(vk.vulkan_call_conv) vk.Result {
|
||||||
@@ -1391,7 +1472,7 @@ pub export fn apeGetFenceStatus(p_device: vk.Device, p_fence: vk.Fence) callconv
|
|||||||
|
|
||||||
const fence = NonDispatchable(Fence).fromHandleObject(p_fence) catch |err| return toVkResult(err);
|
const fence = NonDispatchable(Fence).fromHandleObject(p_fence) catch |err| return toVkResult(err);
|
||||||
fence.getStatus() catch |err| return toVkResult(err);
|
fence.getStatus() catch |err| return toVkResult(err);
|
||||||
return .event_set;
|
return .success;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub export fn apeGetImageMemoryRequirements(p_device: vk.Device, p_image: vk.Image, requirements: *vk.MemoryRequirements) callconv(vk.vulkan_call_conv) void {
|
pub export fn apeGetImageMemoryRequirements(p_device: vk.Device, p_image: vk.Image, requirements: *vk.MemoryRequirements) callconv(vk.vulkan_call_conv) void {
|
||||||
@@ -1428,19 +1509,20 @@ pub export fn apeGetImageSubresourceLayout(p_device: vk.Device, p_image: vk.Imag
|
|||||||
layout.* = image.getSubresourceLayout(subresource.*) catch |err| return errorLogger(err);
|
layout.* = image.getSubresourceLayout(subresource.*) catch |err| return errorLogger(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub export fn apeGetPipelineCacheData(p_device: vk.Device, p_cache: vk.PipelineCache, size: *usize, data: *anyopaque) callconv(vk.vulkan_call_conv) vk.Result {
|
pub export fn apeGetPipelineCacheData(p_device: vk.Device, p_cache: vk.PipelineCache, size: *usize, data: ?*anyopaque) callconv(vk.vulkan_call_conv) vk.Result {
|
||||||
entryPointBeginLogTrace(.vkGetPipelineCacheData);
|
entryPointBeginLogTrace(.vkGetPipelineCacheData);
|
||||||
defer entryPointEndLogTrace();
|
defer entryPointEndLogTrace();
|
||||||
|
|
||||||
Dispatchable(Device).checkHandleValidity(p_device) catch |err| return toVkResult(err);
|
Dispatchable(Device).checkHandleValidity(p_device) catch |err| return toVkResult(err);
|
||||||
|
const cache = NonDispatchable(PipelineCache).fromHandleObject(p_cache) catch |err| return toVkResult(err);
|
||||||
|
|
||||||
notImplementedWarning();
|
const available = cache.availableDataSize();
|
||||||
|
const result = if (data) |ptr| blk: {
|
||||||
_ = p_cache;
|
const bytes = @as([*]u8, @ptrCast(ptr))[0..size.*];
|
||||||
_ = size;
|
break :blk cache.getData(bytes);
|
||||||
_ = data;
|
} else cache.getData(null);
|
||||||
|
size.* = if (result == .incomplete) 0 else available;
|
||||||
return .success;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub export fn apeGetQueryPoolResults(
|
pub export fn apeGetQueryPoolResults(
|
||||||
@@ -1503,14 +1585,14 @@ pub export fn apeMergePipelineCaches(p_device: vk.Device, p_dst: vk.PipelineCach
|
|||||||
defer entryPointEndLogTrace();
|
defer entryPointEndLogTrace();
|
||||||
|
|
||||||
Dispatchable(Device).checkHandleValidity(p_device) catch |err| return toVkResult(err);
|
Dispatchable(Device).checkHandleValidity(p_device) catch |err| return toVkResult(err);
|
||||||
|
const dst = NonDispatchable(PipelineCache).fromHandleObject(p_dst) catch |err| return toVkResult(err);
|
||||||
|
|
||||||
notImplementedWarning();
|
for (0..count) |i| {
|
||||||
|
_ = NonDispatchable(PipelineCache).fromHandleObject(p_srcs[i]) catch |err| return toVkResult(err);
|
||||||
|
}
|
||||||
|
|
||||||
_ = p_dst;
|
dst.merge() catch |err| return toVkResult(err);
|
||||||
_ = count;
|
return .success;
|
||||||
_ = p_srcs;
|
|
||||||
|
|
||||||
return .error_unknown;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub export fn apeResetCommandPool(p_device: vk.Device, p_pool: vk.CommandPool, flags: vk.CommandPoolResetFlags) callconv(vk.vulkan_call_conv) vk.Result {
|
pub export fn apeResetCommandPool(p_device: vk.Device, p_pool: vk.CommandPool, flags: vk.CommandPoolResetFlags) callconv(vk.vulkan_call_conv) vk.Result {
|
||||||
@@ -1533,7 +1615,7 @@ pub export fn apeResetDescriptorPool(p_device: vk.Device, p_pool: vk.DescriptorP
|
|||||||
return .success;
|
return .success;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub export fn apeResetEvent(p_device: vk.Device, p_event: vk.Fence) callconv(vk.vulkan_call_conv) vk.Result {
|
pub export fn apeResetEvent(p_device: vk.Device, p_event: vk.Event) callconv(vk.vulkan_call_conv) vk.Result {
|
||||||
entryPointBeginLogTrace(.vkResetEvent);
|
entryPointBeginLogTrace(.vkResetEvent);
|
||||||
defer entryPointEndLogTrace();
|
defer entryPointEndLogTrace();
|
||||||
|
|
||||||
@@ -1557,7 +1639,7 @@ pub export fn apeResetFences(p_device: vk.Device, count: u32, p_fences: [*]const
|
|||||||
return .success;
|
return .success;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub export fn apeSetEvent(p_device: vk.Device, p_event: vk.Fence) callconv(vk.vulkan_call_conv) vk.Result {
|
pub export fn apeSetEvent(p_device: vk.Device, p_event: vk.Event) callconv(vk.vulkan_call_conv) vk.Result {
|
||||||
entryPointBeginLogTrace(.vkSetEvent);
|
entryPointBeginLogTrace(.vkSetEvent);
|
||||||
defer entryPointEndLogTrace();
|
defer entryPointEndLogTrace();
|
||||||
|
|
||||||
@@ -2168,7 +2250,7 @@ pub export fn apeCreateSwapchainKHR(p_device: vk.Device, info: *const vk.Swapcha
|
|||||||
const device = Dispatchable(Device).fromHandleObject(p_device) catch |err| return toVkResult(err);
|
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 surface = NonDispatchable(SurfaceKHR).fromHandleObject(info.surface) catch |err| return toVkResult(err);
|
||||||
const swapchain = SwapchainKHR.create(device, allocator, surface, info) catch |err| return toVkResult(err);
|
const swapchain = SwapchainKHR.create(device, allocator, surface, info) catch |err| return toVkResult(err);
|
||||||
p_swapchain.* = (NonDispatchable(SwapchainKHR).wrap(allocator, swapchain) catch |err| return toVkResult(err)).toVkHandle(vk.SwapchainKHR);
|
p_swapchain.* = wrapNonDispatchable(SwapchainKHR, allocator, swapchain, vk.SwapchainKHR) catch |err| return toVkResult(err);
|
||||||
return .success;
|
return .success;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2183,7 +2265,7 @@ pub export fn apeCreateWaylandSurfaceKHR(p_instance: vk.Instance, info: *const v
|
|||||||
const allocator = VulkanAllocator.init(callbacks, .object).allocator();
|
const allocator = VulkanAllocator.init(callbacks, .object).allocator();
|
||||||
const instance = Dispatchable(Instance).fromHandleObject(p_instance) catch |err| return toVkResult(err);
|
const instance = Dispatchable(Instance).fromHandleObject(p_instance) catch |err| return toVkResult(err);
|
||||||
const surface = WaylandSurfaceKHR.create(instance, allocator, info) 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);
|
p_surface.* = wrapNonDispatchable(SurfaceKHR, allocator, surface, vk.SurfaceKHR) catch |err| return toVkResult(err);
|
||||||
return .success;
|
return .success;
|
||||||
} else {
|
} else {
|
||||||
return .error_unknown;
|
return .error_unknown;
|
||||||
|
|||||||
@@ -1,3 +1,29 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const vk = @import("vulkan");
|
||||||
|
|
||||||
|
pub fn boundedName(name: [*:0]const u8, max_len: usize) ?[]const u8 {
|
||||||
|
const bytes = name[0..max_len];
|
||||||
|
const len = std.mem.indexOfScalar(u8, bytes, 0) orelse return null;
|
||||||
|
return bytes[0..len];
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn propertyName(comptime max_len: usize, name: *const [max_len]u8) []const u8 {
|
||||||
|
return std.mem.sliceTo(name[0..], 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn extensionName(name: *const [vk.MAX_EXTENSION_NAME_SIZE]u8) []const u8 {
|
||||||
|
return propertyName(vk.MAX_EXTENSION_NAME_SIZE, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn isSupportedExtension(name: []const u8, extensions: []const vk.ExtensionProperties) bool {
|
||||||
|
for (extensions) |extension| {
|
||||||
|
if (std.mem.eql(u8, name, extensionName(&extension.extension_name))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn writePacked(comptime T: type, bytes: []u8, value: T) void {
|
pub fn writePacked(comptime T: type, bytes: []u8, value: T) void {
|
||||||
const raw: [@sizeOf(T)]u8 = @bitCast(value);
|
const raw: [@sizeOf(T)]u8 = @bitCast(value);
|
||||||
@memcpy(bytes[0..@sizeOf(T)], raw[0..]);
|
@memcpy(bytes[0..@sizeOf(T)], raw[0..]);
|
||||||
|
|||||||
@@ -68,8 +68,8 @@ pub fn getNextImage(self: *const Self, timeout: u64, semaphore: ?*BinarySemaphor
|
|||||||
if (image.state == .Available) {
|
if (image.state == .Available) {
|
||||||
image.state = .Drawing;
|
image.state = .Drawing;
|
||||||
index.* = @intCast(i);
|
index.* = @intCast(i);
|
||||||
// TODO: signal semaphore
|
if (semaphore) |s|
|
||||||
_ = semaphore;
|
try s.signal();
|
||||||
if (fence) |f|
|
if (fence) |f|
|
||||||
try f.signal();
|
try f.signal();
|
||||||
return;
|
return;
|
||||||
|
|||||||
Reference in New Issue
Block a user