fixing vertex outputs
This commit is contained in:
@@ -88,10 +88,12 @@ pub fn build(b: *std.Build) !void {
|
|||||||
const drm = b.dependency("drm", .{}).module("drm");
|
const drm = b.dependency("drm", .{}).module("drm");
|
||||||
|
|
||||||
const logs_option: LogType = b.option(LogType, "logs", "Driver logs") orelse .none;
|
const logs_option: LogType = b.option(LogType, "logs", "Driver logs") orelse .none;
|
||||||
|
const debug_allocator_option = b.option(bool, "device-debug-allocator", "Debug device allocator") orelse false;
|
||||||
|
|
||||||
const options = b.addOptions();
|
const options = b.addOptions();
|
||||||
options.addOption(std.SemanticVersion, "driver_version", driver_version);
|
options.addOption(std.SemanticVersion, "driver_version", driver_version);
|
||||||
options.addOption(LogType, "logs", logs_option);
|
options.addOption(LogType, "logs", logs_option);
|
||||||
|
options.addOption(bool, "device_debug_allocator", debug_allocator_option);
|
||||||
|
|
||||||
base_mod.addImport("vulkan", vulkan);
|
base_mod.addImport("vulkan", vulkan);
|
||||||
base_mod.addImport("zmath", zmath);
|
base_mod.addImport("zmath", zmath);
|
||||||
@@ -274,14 +276,12 @@ fn customSoft(
|
|||||||
|
|
||||||
fn optionsSoft(b: *std.Build, options: *Step.Options) !void {
|
fn optionsSoft(b: *std.Build, options: *Step.Options) !void {
|
||||||
const single_threaded_option = b.option(bool, "soft-single-threaded", "Single threaded runtime mode") orelse false;
|
const single_threaded_option = b.option(bool, "soft-single-threaded", "Single threaded runtime mode") orelse false;
|
||||||
const debug_allocator_option = b.option(bool, "soft-debug-allocator", "Debug device allocator") orelse false;
|
|
||||||
const shaders_simd_option = b.option(bool, "soft-shader-simd", "Shaders SIMD acceleration") orelse true;
|
const shaders_simd_option = b.option(bool, "soft-shader-simd", "Shaders SIMD acceleration") orelse true;
|
||||||
const compute_dump_early_results_table_option = b.option(u32, "soft-compute-dump-early-results-table", "Dump compute shaders results table before invocation");
|
const compute_dump_early_results_table_option = b.option(u32, "soft-compute-dump-early-results-table", "Dump compute shaders results table before invocation");
|
||||||
const compute_dump_final_results_table_option = b.option(u32, "soft-compute-dump-final-results-table", "Dump compute shaders results table after invocation");
|
const compute_dump_final_results_table_option = b.option(u32, "soft-compute-dump-final-results-table", "Dump compute shaders results table after invocation");
|
||||||
const approxiamte_rgb_option = b.option(bool, "soft-approximates-rgb", "Approximate sRGB <-> RGB conversions") orelse true;
|
const approxiamte_rgb_option = b.option(bool, "soft-approximates-rgb", "Approximate sRGB <-> RGB conversions") orelse true;
|
||||||
|
|
||||||
options.addOption(bool, "soft_single_threaded", single_threaded_option);
|
options.addOption(bool, "soft_single_threaded", single_threaded_option);
|
||||||
options.addOption(bool, "soft_debug_allocator", debug_allocator_option);
|
|
||||||
options.addOption(bool, "soft_shaders_simd", shaders_simd_option);
|
options.addOption(bool, "soft_shaders_simd", shaders_simd_option);
|
||||||
options.addOption(?u32, "soft_compute_dump_early_results_table", compute_dump_early_results_table_option);
|
options.addOption(?u32, "soft_compute_dump_early_results_table", compute_dump_early_results_table_option);
|
||||||
options.addOption(?u32, "soft_compute_dump_final_results_table", compute_dump_final_results_table_option);
|
options.addOption(?u32, "soft_compute_dump_final_results_table", compute_dump_final_results_table_option);
|
||||||
|
|||||||
+2
-2
@@ -32,8 +32,8 @@
|
|||||||
|
|
||||||
// Soft dependencies
|
// Soft dependencies
|
||||||
.SPIRV_Interpreter = .{
|
.SPIRV_Interpreter = .{
|
||||||
.url = "git+https://github.com/Kbz-8/SPIRV-Interpreter#445bb93296bd6da4a74aa40152aaa779170887cf",
|
.url = "git+https://github.com/Kbz-8/SPIRV-Interpreter#53da7f93154086574bf41a13130299d1bc6df670",
|
||||||
.hash = "SPIRV_Interpreter-0.0.1-ajmpn113CQDBhtMXf88no5gcMJhlricW5G_rWc7AvRS5",
|
.hash = "SPIRV_Interpreter-0.0.1-ajmpn95-CQCUUA6EfT9id_Y50N7kjcKftj0VrGLyi751",
|
||||||
.lazy = true,
|
.lazy = true,
|
||||||
},
|
},
|
||||||
//.SPIRV_Interpreter = .{
|
//.SPIRV_Interpreter = .{
|
||||||
|
|||||||
@@ -76,7 +76,20 @@ fn requestPhysicalDevices(interface: *Interface, allocator: std.mem.Allocator, d
|
|||||||
drm_device.device_info.pci.vendor_id != lib.INTEL_PCI_VENDOR_ID)
|
drm_device.device_info.pci.vendor_id != lib.INTEL_PCI_VENDOR_ID)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const physical_device = try FlintPhysicalDevice.create(allocator, interface, &drm_device);
|
const version = device.getVersion(io_var, allocator) catch continue;
|
||||||
|
defer version.deinit(allocator);
|
||||||
|
|
||||||
|
const kmd_type: lib.KmdType = if (std.mem.eql(u8, version.name, "i915"))
|
||||||
|
.I915
|
||||||
|
else if (std.mem.eql(u8, version.name, "xe"))
|
||||||
|
.Xe
|
||||||
|
else
|
||||||
|
.Invalid;
|
||||||
|
|
||||||
|
if (kmd_type == .Invalid)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const physical_device = try FlintPhysicalDevice.create(allocator, interface, &drm_device, kmd_type);
|
||||||
errdefer physical_device.interface.release(allocator) catch {};
|
errdefer physical_device.interface.release(allocator) catch {};
|
||||||
|
|
||||||
const dispatchable = try Dispatchable(base.PhysicalDevice).wrap(allocator, &physical_device.interface);
|
const dispatchable = try Dispatchable(base.PhysicalDevice).wrap(allocator, &physical_device.interface);
|
||||||
|
|||||||
@@ -30,8 +30,9 @@ pub const EXTENSIONS = [_]vk.ExtensionProperties{
|
|||||||
};
|
};
|
||||||
|
|
||||||
interface: Interface,
|
interface: Interface,
|
||||||
|
kmd_type: lib.KmdType,
|
||||||
|
|
||||||
pub fn create(allocator: std.mem.Allocator, instance: *base.Instance, drm_device: *const base.drm.Device) VkError!*Self {
|
pub fn create(allocator: std.mem.Allocator, instance: *base.Instance, drm_device: *const base.drm.Device, kmd_type: lib.KmdType) VkError!*Self {
|
||||||
const self = allocator.create(Self) catch return VkError.OutOfHostMemory;
|
const self = allocator.create(Self) catch return VkError.OutOfHostMemory;
|
||||||
errdefer allocator.destroy(self);
|
errdefer allocator.destroy(self);
|
||||||
|
|
||||||
@@ -223,6 +224,7 @@ pub fn create(allocator: std.mem.Allocator, instance: *base.Instance, drm_device
|
|||||||
|
|
||||||
self.* = .{
|
self.* = .{
|
||||||
.interface = interface,
|
.interface = interface,
|
||||||
|
.kmd_type = kmd_type,
|
||||||
};
|
};
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
|
|||||||
@@ -31,14 +31,7 @@ const VkError = base.VkError;
|
|||||||
const Self = @This();
|
const Self = @This();
|
||||||
pub const Interface = base.Device;
|
pub const Interface = base.Device;
|
||||||
|
|
||||||
const DeviceAllocator = struct {
|
|
||||||
pub inline fn allocator(_: @This()) std.mem.Allocator {
|
|
||||||
return base.fallback_host_allocator;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
interface: Interface,
|
interface: Interface,
|
||||||
allocator: DeviceAllocator,
|
|
||||||
|
|
||||||
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;
|
||||||
@@ -80,7 +73,6 @@ pub fn create(instance: *base.Instance, physical_device: *base.PhysicalDevice, a
|
|||||||
|
|
||||||
self.* = .{
|
self.* = .{
|
||||||
.interface = interface,
|
.interface = interface,
|
||||||
.allocator = .{},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
try self.interface.createQueues(allocator, info);
|
try self.interface.createQueues(allocator, info);
|
||||||
|
|||||||
@@ -195,7 +195,7 @@ pub fn beginQuery(interface: *Interface, pool: *base.QueryPool, query: u32, _: v
|
|||||||
if (active.pool == impl.pool and active.query == impl.query)
|
if (active.pool == impl.pool and active.query == impl.query)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
device.active_occlusion_queries.append(device.renderer.device.device_allocator.allocator(), .{
|
device.active_occlusion_queries.append(device.renderer.device.interface.device_allocator.allocator(), .{
|
||||||
.pool = impl.pool,
|
.pool = impl.pool,
|
||||||
.query = impl.query,
|
.query = impl.query,
|
||||||
}) catch return VkError.OutOfDeviceMemory;
|
}) catch return VkError.OutOfDeviceMemory;
|
||||||
|
|||||||
@@ -35,14 +35,7 @@ pub const Interface = base.Device;
|
|||||||
|
|
||||||
const SpawnError = std.Thread.SpawnError;
|
const SpawnError = std.Thread.SpawnError;
|
||||||
|
|
||||||
const DeviceAllocator = struct {
|
|
||||||
pub inline fn allocator(_: @This()) std.mem.Allocator {
|
|
||||||
return base.fallback_host_allocator;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
interface: Interface,
|
interface: Interface,
|
||||||
device_allocator: if (config.soft_debug_allocator) std.heap.DebugAllocator(.{}) else DeviceAllocator,
|
|
||||||
|
|
||||||
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;
|
||||||
@@ -91,7 +84,6 @@ pub fn create(instance: *base.Instance, physical_device: *base.PhysicalDevice, a
|
|||||||
|
|
||||||
self.* = .{
|
self.* = .{
|
||||||
.interface = interface,
|
.interface = interface,
|
||||||
.device_allocator = if (config.soft_debug_allocator) .init else .{},
|
|
||||||
};
|
};
|
||||||
initialized = true;
|
initialized = true;
|
||||||
|
|
||||||
@@ -102,16 +94,6 @@ pub fn create(instance: *base.Instance, physical_device: *base.PhysicalDevice, a
|
|||||||
pub fn destroy(interface: *Interface, allocator: std.mem.Allocator) VkError!void {
|
pub fn destroy(interface: *Interface, allocator: std.mem.Allocator) VkError!void {
|
||||||
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
|
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
|
||||||
|
|
||||||
if (config.soft_debug_allocator) {
|
|
||||||
// All device memory allocations should've been freed by now
|
|
||||||
const leaks = self.device_allocator.detectLeaks();
|
|
||||||
if (leaks != 0)
|
|
||||||
std.log.scoped(.vkDestroyDevice).err("Device was destroyed leaking {d:.3}KB", .{@as(f32, @floatFromInt(leaks)) / 1000})
|
|
||||||
else
|
|
||||||
std.log.scoped(.vkDestroyDevice).debug("No device memory leaks detected", .{});
|
|
||||||
self.device_allocator.deinitWithoutLeakChecks();
|
|
||||||
}
|
|
||||||
|
|
||||||
allocator.destroy(self);
|
allocator.destroy(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,15 +28,14 @@ pub fn create(device: *SoftDevice, allocator: std.mem.Allocator, size: vk.Device
|
|||||||
|
|
||||||
self.* = .{
|
self.* = .{
|
||||||
.interface = interface,
|
.interface = interface,
|
||||||
.data = device.device_allocator.allocator().alloc(u8, size) catch return VkError.OutOfDeviceMemory,
|
.data = device.interface.device_allocator.allocator().alloc(u8, size) catch return VkError.OutOfDeviceMemory,
|
||||||
};
|
};
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
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 soft_device: *SoftDevice = @alignCast(@fieldParentPtr("interface", interface.owner));
|
interface.owner.device_allocator.allocator().free(self.data);
|
||||||
soft_device.device_allocator.allocator().free(self.data);
|
|
||||||
allocator.destroy(self);
|
allocator.destroy(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -79,11 +79,10 @@ pub fn createCompute(device: *base.Device, allocator: std.mem.Allocator, cache:
|
|||||||
.destroy = destroy,
|
.destroy = destroy,
|
||||||
};
|
};
|
||||||
|
|
||||||
const soft_device: *SoftDevice = @alignCast(@fieldParentPtr("interface", device));
|
|
||||||
const module = try NonDispatchable(ShaderModule).fromHandleObject(info.stage.module);
|
const module = try NonDispatchable(ShaderModule).fromHandleObject(info.stage.module);
|
||||||
const soft_module: *SoftShaderModule = @alignCast(@fieldParentPtr("interface", module));
|
const soft_module: *SoftShaderModule = @alignCast(@fieldParentPtr("interface", module));
|
||||||
|
|
||||||
const device_allocator = soft_device.device_allocator.allocator();
|
const device_allocator = device.device_allocator.allocator();
|
||||||
const soft_cache: ?*SoftPipelineCache = if (cache) |pipeline_cache|
|
const soft_cache: ?*SoftPipelineCache = if (cache) |pipeline_cache|
|
||||||
@alignCast(@fieldParentPtr("interface", pipeline_cache))
|
@alignCast(@fieldParentPtr("interface", pipeline_cache))
|
||||||
else
|
else
|
||||||
@@ -123,8 +122,7 @@ pub fn createGraphics(device: *base.Device, allocator: std.mem.Allocator, cache:
|
|||||||
.destroy = destroy,
|
.destroy = destroy,
|
||||||
};
|
};
|
||||||
|
|
||||||
const soft_device: *SoftDevice = @alignCast(@fieldParentPtr("interface", device));
|
const device_allocator = device.device_allocator.allocator();
|
||||||
const device_allocator = soft_device.device_allocator.allocator();
|
|
||||||
const soft_cache: ?*SoftPipelineCache = if (cache) |pipeline_cache|
|
const soft_cache: ?*SoftPipelineCache = if (cache) |pipeline_cache|
|
||||||
@alignCast(@fieldParentPtr("interface", pipeline_cache))
|
@alignCast(@fieldParentPtr("interface", pipeline_cache))
|
||||||
else
|
else
|
||||||
@@ -185,8 +183,7 @@ pub fn createGraphics(device: *base.Device, allocator: std.mem.Allocator, cache:
|
|||||||
|
|
||||||
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 soft_device: *SoftDevice = @alignCast(@fieldParentPtr("interface", interface.owner));
|
const device_allocator = interface.owner.device_allocator.allocator();
|
||||||
const device_allocator = soft_device.device_allocator.allocator();
|
|
||||||
|
|
||||||
var it = self.stages.iterator();
|
var it = self.stages.iterator();
|
||||||
while (it.next()) |entry| {
|
while (it.next()) |entry| {
|
||||||
@@ -486,10 +483,22 @@ fn readImageFloat4(context: *anyopaque, dim: spv.SpvDim, x: i32, y: i32, z: i32,
|
|||||||
.@"2d", .@"2d_array", .cube, .cube_array => .{ .x = x, .y = y, .z = 0 },
|
.@"2d", .@"2d_array", .cube, .cube_array => .{ .x = x, .y = y, .z = 0 },
|
||||||
else => .{ .x = x, .y = y, .z = z },
|
else => .{ .x = x, .y = y, .z = z },
|
||||||
};
|
};
|
||||||
|
const sample_count = image.interface.samples.toInt();
|
||||||
|
const sample_index: u32 = if (sample_count > 1) blk: {
|
||||||
|
if (image_view.interface.view_type == .@"2d_array" or image_view.interface.view_type == .cube_array)
|
||||||
|
break :blk @intCast(@mod(z, @as(i32, @intCast(sample_count))));
|
||||||
|
break :blk @intCast(z);
|
||||||
|
} else 0;
|
||||||
|
const array_z: i32 = if (sample_count > 1 and
|
||||||
|
(image_view.interface.view_type == .@"2d_array" or image_view.interface.view_type == .cube_array))
|
||||||
|
@divFloor(z, @as(i32, @intCast(sample_count)))
|
||||||
|
else
|
||||||
|
z;
|
||||||
const array_layer = image_view.interface.subresource_range.base_array_layer + switch (image_view.interface.view_type) {
|
const array_layer = image_view.interface.subresource_range.base_array_layer + switch (image_view.interface.view_type) {
|
||||||
.@"1d_array" => @as(u32, @intCast(y)),
|
.@"1d_array" => @as(u32, @intCast(y)),
|
||||||
.@"2d_array" => @as(u32, @intCast(z)),
|
.@"2d_array" => @as(u32, @intCast(array_z)),
|
||||||
.cube => cube_face,
|
.cube => cube_face,
|
||||||
|
.cube_array => @as(u32, @intCast(array_z)),
|
||||||
else => 0,
|
else => 0,
|
||||||
};
|
};
|
||||||
const aspect_mask = imageReadAspect(image_view, false);
|
const aspect_mask = imageReadAspect(image_view, false);
|
||||||
@@ -498,7 +507,6 @@ fn readImageFloat4(context: *anyopaque, dim: spv.SpvDim, x: i32, y: i32, z: i32,
|
|||||||
.mip_level = mip_level,
|
.mip_level = mip_level,
|
||||||
.array_layer = array_layer,
|
.array_layer = array_layer,
|
||||||
};
|
};
|
||||||
const sample_index: u32 = if (image.interface.samples.toInt() > 1) @intCast(z) else 0;
|
|
||||||
const format = base.format.fromAspect(image_view.interface.format, aspect_mask);
|
const format = base.format.fromAspect(image_view.interface.format, aspect_mask);
|
||||||
const raw_pixel = if (dim == .SubpassData) blk: {
|
const raw_pixel = if (dim == .SubpassData) blk: {
|
||||||
if (findInputAttachmentSnapshot(image_view, subresource)) |snapshot| {
|
if (findInputAttachmentSnapshot(image_view, subresource)) |snapshot| {
|
||||||
@@ -541,10 +549,22 @@ fn readImageInt4(context: *anyopaque, dim: spv.SpvDim, x: i32, y: i32, z: i32, l
|
|||||||
.@"2d", .@"2d_array", .cube, .cube_array => .{ .x = x, .y = y, .z = 0 },
|
.@"2d", .@"2d_array", .cube, .cube_array => .{ .x = x, .y = y, .z = 0 },
|
||||||
else => .{ .x = x, .y = y, .z = z },
|
else => .{ .x = x, .y = y, .z = z },
|
||||||
};
|
};
|
||||||
|
const sample_count = image.interface.samples.toInt();
|
||||||
|
const sample_index: u32 = if (sample_count > 1) blk: {
|
||||||
|
if (image_view.interface.view_type == .@"2d_array" or image_view.interface.view_type == .cube_array)
|
||||||
|
break :blk @intCast(@mod(z, @as(i32, @intCast(sample_count))));
|
||||||
|
break :blk @intCast(z);
|
||||||
|
} else 0;
|
||||||
|
const array_z: i32 = if (sample_count > 1 and
|
||||||
|
(image_view.interface.view_type == .@"2d_array" or image_view.interface.view_type == .cube_array))
|
||||||
|
@divFloor(z, @as(i32, @intCast(sample_count)))
|
||||||
|
else
|
||||||
|
z;
|
||||||
const array_layer = image_view.interface.subresource_range.base_array_layer + switch (image_view.interface.view_type) {
|
const array_layer = image_view.interface.subresource_range.base_array_layer + switch (image_view.interface.view_type) {
|
||||||
.@"1d_array" => @as(u32, @intCast(y)),
|
.@"1d_array" => @as(u32, @intCast(y)),
|
||||||
.@"2d_array" => @as(u32, @intCast(z)),
|
.@"2d_array" => @as(u32, @intCast(array_z)),
|
||||||
.cube => cube_face,
|
.cube => cube_face,
|
||||||
|
.cube_array => @as(u32, @intCast(array_z)),
|
||||||
else => 0,
|
else => 0,
|
||||||
};
|
};
|
||||||
const aspect_mask = imageReadAspect(image_view, true);
|
const aspect_mask = imageReadAspect(image_view, true);
|
||||||
@@ -553,7 +573,6 @@ fn readImageInt4(context: *anyopaque, dim: spv.SpvDim, x: i32, y: i32, z: i32, l
|
|||||||
.mip_level = mip_level,
|
.mip_level = mip_level,
|
||||||
.array_layer = array_layer,
|
.array_layer = array_layer,
|
||||||
};
|
};
|
||||||
const sample_index: u32 = if (image.interface.samples.toInt() > 1) @intCast(z) else 0;
|
|
||||||
const format = base.format.fromAspect(image_view.interface.format, aspect_mask);
|
const format = base.format.fromAspect(image_view.interface.format, aspect_mask);
|
||||||
const raw_pixel = if (dim == .SubpassData) blk: {
|
const raw_pixel = if (dim == .SubpassData) blk: {
|
||||||
if (findInputAttachmentSnapshot(image_view, subresource)) |snapshot| {
|
if (findInputAttachmentSnapshot(image_view, subresource)) |snapshot| {
|
||||||
|
|||||||
@@ -67,8 +67,7 @@ pub fn create(device: *base.Device, allocator: std.mem.Allocator, info: *const v
|
|||||||
|
|
||||||
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 soft_device: *SoftDevice = @alignCast(@fieldParentPtr("interface", interface.owner));
|
const data_allocator = interface.owner.device_allocator.allocator();
|
||||||
const data_allocator = soft_device.device_allocator.allocator();
|
|
||||||
|
|
||||||
for (self.shaders.items) |*shader| {
|
for (self.shaders.items) |*shader| {
|
||||||
shader.deinit(allocator, data_allocator);
|
shader.deinit(allocator, data_allocator);
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ pub fn submit(interface: *Interface, infos: []Interface.SubmitInfo, p_fence: ?*b
|
|||||||
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 io = interface.owner.io();
|
const io = interface.owner.io();
|
||||||
const allocator = soft_device.device_allocator.allocator();
|
const allocator = interface.owner.device_allocator.allocator();
|
||||||
|
|
||||||
const data = allocator.create(TaskData) catch return VkError.OutOfDeviceMemory;
|
const data = allocator.create(TaskData) catch return VkError.OutOfDeviceMemory;
|
||||||
errdefer allocator.destroy(data);
|
errdefer allocator.destroy(data);
|
||||||
@@ -111,7 +111,7 @@ fn executeSubmitInfo(soft_device: *SoftDevice, info: Interface.SubmitInfo) VkErr
|
|||||||
|
|
||||||
var execution_device: ExecutionDevice = undefined;
|
var execution_device: ExecutionDevice = undefined;
|
||||||
execution_device.setup(soft_device);
|
execution_device.setup(soft_device);
|
||||||
defer execution_device.deinit(soft_device.device_allocator.allocator());
|
defer execution_device.deinit(soft_device.interface.device_allocator.allocator());
|
||||||
|
|
||||||
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));
|
||||||
@@ -125,7 +125,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.interface.device_allocator.allocator();
|
||||||
|
|
||||||
defer {
|
defer {
|
||||||
deinitSubmitInfos(allocator, &data.infos);
|
deinitSubmitInfos(allocator, &data.infos);
|
||||||
|
|||||||
@@ -276,7 +276,6 @@ pub fn queryImageLod(image: *SoftImage, image_view: *SoftImageView, sampler: *Se
|
|||||||
const clamped_lod = std.math.clamp(biased_lod, sampler.interface.min_lod, sampler.interface.max_lod);
|
const clamped_lod = std.math.clamp(biased_lod, sampler.interface.min_lod, sampler.interface.max_lod);
|
||||||
const max_level: f32 = @floatFromInt(viewMipCount(image_view) - 1);
|
const max_level: f32 = @floatFromInt(viewMipCount(image_view) - 1);
|
||||||
const level = std.math.clamp(mipmapModeLevel(sampler, clamped_lod), 0.0, max_level);
|
const level = std.math.clamp(mipmapModeLevel(sampler, clamped_lod), 0.0, max_level);
|
||||||
|
|
||||||
return .{ level, lod, 0.0, 0.0 };
|
return .{ level, lod, 0.0, 0.0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,8 +25,7 @@ pub fn create(device: *base.Device, allocator: std.mem.Allocator, info: *const v
|
|||||||
|
|
||||||
var interface = try Interface.init(device, allocator, info);
|
var interface = try Interface.init(device, allocator, info);
|
||||||
|
|
||||||
const soft_device: *SoftDevice = @alignCast(@fieldParentPtr("interface", device));
|
const device_allocator = device.device_allocator.allocator();
|
||||||
const device_allocator = soft_device.device_allocator.allocator();
|
|
||||||
|
|
||||||
interface.vtable = &.{
|
interface.vtable = &.{
|
||||||
.destroy = destroy,
|
.destroy = destroy,
|
||||||
@@ -62,8 +61,7 @@ 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 {
|
||||||
const soft_device: *SoftDevice = @alignCast(@fieldParentPtr("interface", self.interface.owner));
|
const device_allocator = self.interface.owner.device_allocator.allocator();
|
||||||
const device_allocator = soft_device.device_allocator.allocator();
|
|
||||||
|
|
||||||
self.module.deinit(device_allocator);
|
self.module.deinit(device_allocator);
|
||||||
|
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ pub fn dispatchBase(self: *Self, base_group_x: u32, base_group_y: u32, base_grou
|
|||||||
const spv_module = &shader.module.module;
|
const spv_module = &shader.module.module;
|
||||||
self.batch_size = if (spv_module.reflection_infos.has_atomics) 1 else shader.runtimes.len;
|
self.batch_size = if (spv_module.reflection_infos.has_atomics) 1 else shader.runtimes.len;
|
||||||
|
|
||||||
const allocator = self.device.device_allocator.allocator();
|
const allocator = self.device.interface.device_allocator.allocator();
|
||||||
const local_size = try getLocalSize(&shader.runtimes[0].rt, allocator, spv_module);
|
const local_size = try getLocalSize(&shader.runtimes[0].rt, allocator, spv_module);
|
||||||
const local_size_xy = std.math.mul(usize, local_size[0], local_size[1]) catch return VkError.ValidationFailed;
|
const local_size_xy = std.math.mul(usize, local_size[0], local_size[1]) catch return VkError.ValidationFailed;
|
||||||
const invocations_per_workgroup = std.math.mul(usize, local_size_xy, local_size[2]) catch return VkError.ValidationFailed;
|
const invocations_per_workgroup = std.math.mul(usize, local_size_xy, local_size[2]) catch return VkError.ValidationFailed;
|
||||||
@@ -124,7 +124,7 @@ fn runWrapper(data: RunData) void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline fn run(data: RunData) !void {
|
inline fn run(data: RunData) !void {
|
||||||
const allocator = data.self.device.device_allocator.allocator();
|
const allocator = data.self.device.interface.device_allocator.allocator();
|
||||||
const io = data.self.device.interface.io();
|
const io = data.self.device.interface.io();
|
||||||
|
|
||||||
const shader = data.pipeline.stages.getPtrAssertContains(.compute);
|
const shader = data.pipeline.stages.getPtrAssertContains(.compute);
|
||||||
@@ -233,7 +233,8 @@ fn runBarrierWorkgroup(
|
|||||||
group_count: @Vector(3, u32),
|
group_count: @Vector(3, u32),
|
||||||
group_id: @Vector(3, u32),
|
group_id: @Vector(3, u32),
|
||||||
) !void {
|
) !void {
|
||||||
const allocator = data.self.device.device_allocator.allocator();
|
const allocator = data.self.device.interface.device_allocator.allocator();
|
||||||
|
|
||||||
const workgroup_memory = try runtimes[0].createWorkgroupMemory(allocator);
|
const workgroup_memory = try runtimes[0].createWorkgroupMemory(allocator);
|
||||||
defer runtimes[0].destroyWorkgroupMemory(allocator, workgroup_memory);
|
defer runtimes[0].destroyWorkgroupMemory(allocator, workgroup_memory);
|
||||||
for (runtimes, 0..) |*rt, i| {
|
for (runtimes, 0..) |*rt, i| {
|
||||||
@@ -292,21 +293,25 @@ fn dumpResultsTable(allocator: std.mem.Allocator, io: std.Io, rt: *spv.Runtime,
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn setupWorkgroupBuiltins(self: *Self, rt: *spv.Runtime, local_size: @Vector(3, u32), group_count: @Vector(3, u32), group_id: @Vector(3, u32)) spv.Runtime.RuntimeError!void {
|
fn setupWorkgroupBuiltins(self: *Self, rt: *spv.Runtime, local_size: @Vector(3, u32), group_count: @Vector(3, u32), group_id: @Vector(3, u32)) spv.Runtime.RuntimeError!void {
|
||||||
rt.writeBuiltIn(self.device.device_allocator.allocator(), std.mem.asBytes(&local_size), .WorkgroupSize) catch |err| switch (err) {
|
const allocator = self.device.interface.device_allocator.allocator();
|
||||||
|
|
||||||
|
rt.writeBuiltIn(allocator, std.mem.asBytes(&local_size), .WorkgroupSize) catch |err| switch (err) {
|
||||||
SpvRuntimeError.NotFound => {},
|
SpvRuntimeError.NotFound => {},
|
||||||
else => return err,
|
else => return err,
|
||||||
};
|
};
|
||||||
rt.writeBuiltIn(self.device.device_allocator.allocator(), std.mem.asBytes(&group_count), .NumWorkgroups) catch |err| switch (err) {
|
rt.writeBuiltIn(allocator, std.mem.asBytes(&group_count), .NumWorkgroups) catch |err| switch (err) {
|
||||||
SpvRuntimeError.NotFound => {},
|
SpvRuntimeError.NotFound => {},
|
||||||
else => return err,
|
else => return err,
|
||||||
};
|
};
|
||||||
rt.writeBuiltIn(self.device.device_allocator.allocator(), std.mem.asBytes(&group_id), .WorkgroupId) catch |err| switch (err) {
|
rt.writeBuiltIn(allocator, std.mem.asBytes(&group_id), .WorkgroupId) catch |err| switch (err) {
|
||||||
SpvRuntimeError.NotFound => {},
|
SpvRuntimeError.NotFound => {},
|
||||||
else => return err,
|
else => return err,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setupSubgroupBuiltins(self: *Self, rt: *spv.Runtime, local_size: @Vector(3, u32), group_id: @Vector(3, u32), local_invocation_index: usize) spv.Runtime.RuntimeError!void {
|
fn setupSubgroupBuiltins(self: *Self, rt: *spv.Runtime, local_size: @Vector(3, u32), group_id: @Vector(3, u32), local_invocation_index: usize) spv.Runtime.RuntimeError!void {
|
||||||
|
const allocator = self.device.interface.device_allocator.allocator();
|
||||||
|
|
||||||
const local_base = local_size * group_id;
|
const local_base = local_size * group_id;
|
||||||
var local_invocation = @Vector(3, u32){ 0, 0, 0 };
|
var local_invocation = @Vector(3, u32){ 0, 0, 0 };
|
||||||
|
|
||||||
@@ -320,15 +325,15 @@ fn setupSubgroupBuiltins(self: *Self, rt: *spv.Runtime, local_size: @Vector(3, u
|
|||||||
const global_invocation_index = local_base + local_invocation;
|
const global_invocation_index = local_base + local_invocation;
|
||||||
const local_invocation_index_u32: u32 = @intCast(local_invocation_index);
|
const local_invocation_index_u32: u32 = @intCast(local_invocation_index);
|
||||||
|
|
||||||
rt.writeBuiltIn(self.device.device_allocator.allocator(), std.mem.asBytes(&local_invocation), .LocalInvocationId) catch |err| switch (err) {
|
rt.writeBuiltIn(allocator, std.mem.asBytes(&local_invocation), .LocalInvocationId) catch |err| switch (err) {
|
||||||
SpvRuntimeError.NotFound => {},
|
SpvRuntimeError.NotFound => {},
|
||||||
else => return err,
|
else => return err,
|
||||||
};
|
};
|
||||||
rt.writeBuiltIn(self.device.device_allocator.allocator(), std.mem.asBytes(&local_invocation_index_u32), .LocalInvocationIndex) catch |err| switch (err) {
|
rt.writeBuiltIn(allocator, std.mem.asBytes(&local_invocation_index_u32), .LocalInvocationIndex) catch |err| switch (err) {
|
||||||
SpvRuntimeError.NotFound => {},
|
SpvRuntimeError.NotFound => {},
|
||||||
else => return err,
|
else => return err,
|
||||||
};
|
};
|
||||||
rt.writeBuiltIn(self.device.device_allocator.allocator(), std.mem.asBytes(&global_invocation_index), .GlobalInvocationId) catch |err| switch (err) {
|
rt.writeBuiltIn(allocator, std.mem.asBytes(&global_invocation_index), .GlobalInvocationId) catch |err| switch (err) {
|
||||||
SpvRuntimeError.NotFound => {},
|
SpvRuntimeError.NotFound => {},
|
||||||
else => return err,
|
else => return err,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -187,7 +187,7 @@ pub fn init(device: *SoftDevice, state: *PipelineState, active_occlusion_queries
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn resetInputAttachmentSnapshots(self: *Self) void {
|
pub fn resetInputAttachmentSnapshots(self: *Self) void {
|
||||||
const allocator = self.device.device_allocator.allocator();
|
const allocator = self.device.interface.device_allocator.allocator();
|
||||||
for (self.input_attachment_snapshots) |snapshot| {
|
for (self.input_attachment_snapshots) |snapshot| {
|
||||||
allocator.free(snapshot.data);
|
allocator.free(snapshot.data);
|
||||||
}
|
}
|
||||||
@@ -196,12 +196,12 @@ pub fn resetInputAttachmentSnapshots(self: *Self) void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw(self: *Self, vertex_count: usize, instance_count: usize, first_vertex: usize, first_instance: usize) VkError!void {
|
pub fn draw(self: *Self, vertex_count: usize, instance_count: usize, first_vertex: usize, first_instance: usize) VkError!void {
|
||||||
var bounded_allocator: BoundedAllocator = .init(self.device.device_allocator.allocator(), 4 * @"1GiB");
|
var bounded_allocator: BoundedAllocator = .init(self.device.interface.device_allocator.allocator(), 4 * @"1GiB");
|
||||||
try self.drawCall(&bounded_allocator, vertex_count, instance_count, first_vertex, first_instance, null, null);
|
try self.drawCall(&bounded_allocator, vertex_count, instance_count, first_vertex, first_instance, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn drawIndexed(self: *Self, index_count: usize, instance_count: usize, first_index: usize, first_instance: usize, vertex_offset: i32) VkError!void {
|
pub fn drawIndexed(self: *Self, index_count: usize, instance_count: usize, first_index: usize, first_instance: usize, vertex_offset: i32) VkError!void {
|
||||||
var bounded_allocator: BoundedAllocator = .init(self.device.device_allocator.allocator(), 4 * @"1GiB");
|
var bounded_allocator: BoundedAllocator = .init(self.device.interface.device_allocator.allocator(), 4 * @"1GiB");
|
||||||
const allocator = bounded_allocator.allocator();
|
const allocator = bounded_allocator.allocator();
|
||||||
|
|
||||||
const indexed_draw = try self.readIndexBuffer(allocator, index_count, first_index, vertex_offset);
|
const indexed_draw = try self.readIndexBuffer(allocator, index_count, first_index, vertex_offset);
|
||||||
@@ -266,6 +266,9 @@ fn drawCall(self: *Self, bounded_allocator: *BoundedAllocator, vertex_count: usi
|
|||||||
return VkError.Unknown;
|
return VkError.Unknown;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (pipeline.interface.mode.graphics.rasterization.rasterizer_discard_enable)
|
||||||
|
return;
|
||||||
|
|
||||||
draw_call.viewport = try self.resolveViewport(0);
|
draw_call.viewport = try self.resolveViewport(0);
|
||||||
draw_call.scissor = try self.resolveScissor(0);
|
draw_call.scissor = try self.resolveScissor(0);
|
||||||
|
|
||||||
|
|||||||
@@ -67,10 +67,8 @@ pub fn shaderInvocation(
|
|||||||
else => return err,
|
else => return err,
|
||||||
};
|
};
|
||||||
if (rt.getBuiltinResult(.FragCoord)) |frag_coord_word| {
|
if (rt.getBuiltinResult(.FragCoord)) |frag_coord_word| {
|
||||||
const frag_x: i32 = @intFromFloat(position[0]);
|
const frag_coord_dx = zm.f32x4(1.0, 0.0, 0.0, 0.0);
|
||||||
const frag_y: i32 = @intFromFloat(position[1]);
|
const frag_coord_dy = zm.f32x4(0.0, 1.0, 0.0, 0.0);
|
||||||
const frag_coord_dx = zm.f32x4(if (@mod(frag_x, 2) == 0) 1.0 else -1.0, 0.0, 0.0, 0.0);
|
|
||||||
const frag_coord_dy = zm.f32x4(0.0, if (@mod(frag_y, 2) == 0) 1.0 else -1.0, 0.0, 0.0);
|
|
||||||
try rt.setDerivativeFromMemory(allocator, frag_coord_word, std.mem.asBytes(&frag_coord_dx), std.mem.asBytes(&frag_coord_dy));
|
try rt.setDerivativeFromMemory(allocator, frag_coord_word, std.mem.asBytes(&frag_coord_dx), std.mem.asBytes(&frag_coord_dy));
|
||||||
}
|
}
|
||||||
if (point_coord) |coord| {
|
if (point_coord) |coord| {
|
||||||
@@ -170,7 +168,9 @@ pub fn shaderInvocation(
|
|||||||
|
|
||||||
if (input.size != 0) {
|
if (input.size != 0) {
|
||||||
const input_bytes = input.blob[0..input.size];
|
const input_bytes = input.blob[0..input.size];
|
||||||
if (!has_result_value or input.size < memory_size)
|
if (has_result_value and input.size < memory_size)
|
||||||
|
try writeAggregateInputLocations(allocator, rt, fragment_inputs, result_word, location, component, memory_size)
|
||||||
|
else if (!has_result_value)
|
||||||
try rt.writeInputLocation(input_bytes, @intCast(location))
|
try rt.writeInputLocation(input_bytes, @intCast(location))
|
||||||
else
|
else
|
||||||
try rt.writeInput(allocator, input_bytes, result_word);
|
try rt.writeInput(allocator, input_bytes, result_word);
|
||||||
@@ -262,6 +262,70 @@ pub fn shaderInvocation(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn writeAggregateInputLocations(
|
||||||
|
allocator: std.mem.Allocator,
|
||||||
|
rt: *spv.Runtime,
|
||||||
|
inputs: [spv.SPIRV_MAX_OUTPUT_LOCATIONS]VertexInterpolationLocation,
|
||||||
|
result_word: spv.SpvWord,
|
||||||
|
location: usize,
|
||||||
|
component: usize,
|
||||||
|
memory_size: usize,
|
||||||
|
) SpvRuntimeError!void {
|
||||||
|
const value = try rt.results[result_word].getConstValue();
|
||||||
|
switch (value.*) {
|
||||||
|
.Array, .Matrix => {},
|
||||||
|
else => {
|
||||||
|
const input = inputs[location][component];
|
||||||
|
if (input.size != 0)
|
||||||
|
try rt.writeInputLocation(input.blob[0..input.size], @intCast(location));
|
||||||
|
return;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const bytes = allocator.alloc(u8, memory_size + INTERFACE_BLOB_PADDING) catch return SpvRuntimeError.OutOfMemory;
|
||||||
|
defer allocator.free(bytes);
|
||||||
|
@memset(bytes, 0);
|
||||||
|
|
||||||
|
var source_location = location;
|
||||||
|
var offset: usize = 0;
|
||||||
|
try copyAggregateInputLocations(value, inputs, &source_location, component, bytes[0..memory_size], &offset);
|
||||||
|
try rt.writeInput(allocator, bytes[0..memory_size], result_word);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn copyAggregateInputLocations(
|
||||||
|
value: anytype,
|
||||||
|
inputs: [spv.SPIRV_MAX_OUTPUT_LOCATIONS]VertexInterpolationLocation,
|
||||||
|
source_location: *usize,
|
||||||
|
component: usize,
|
||||||
|
bytes: []u8,
|
||||||
|
offset: *usize,
|
||||||
|
) SpvRuntimeError!void {
|
||||||
|
switch (value.*) {
|
||||||
|
.Array => |array| {
|
||||||
|
for (array.values) |*element|
|
||||||
|
try copyAggregateInputLocations(element, inputs, source_location, component, bytes, offset);
|
||||||
|
},
|
||||||
|
.Matrix => |columns| {
|
||||||
|
for (columns) |*column|
|
||||||
|
try copyAggregateInputLocations(column, inputs, source_location, component, bytes, offset);
|
||||||
|
},
|
||||||
|
else => {
|
||||||
|
if (source_location.* >= inputs.len or component >= 4)
|
||||||
|
return SpvRuntimeError.OutOfBounds;
|
||||||
|
const input = inputs[source_location.*][component];
|
||||||
|
const element_size = try value.getPlainMemorySize();
|
||||||
|
if (offset.* > bytes.len or element_size > bytes.len - offset.*)
|
||||||
|
return SpvRuntimeError.OutOfBounds;
|
||||||
|
if (input.size != 0) {
|
||||||
|
const copy_size = @min(element_size, input.size);
|
||||||
|
@memcpy(bytes[offset.* .. offset.* + copy_size], input.blob[0..copy_size]);
|
||||||
|
}
|
||||||
|
offset.* += element_size;
|
||||||
|
source_location.* += 1;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn readFragmentOutput(
|
fn readFragmentOutput(
|
||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
rt: anytype,
|
rt: anytype,
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ pub fn processThenFragmentStage(renderer: *Renderer, allocator: std.mem.Allocato
|
|||||||
const pipeline_data = (renderer.state.pipeline orelse return VkError.InvalidHandleDrv).interface.mode.graphics;
|
const pipeline_data = (renderer.state.pipeline orelse return VkError.InvalidHandleDrv).interface.mode.graphics;
|
||||||
const topology = pipeline_data.input_assembly.topology;
|
const topology = pipeline_data.input_assembly.topology;
|
||||||
if (renderer.input_attachment_snapshots.len == 0) {
|
if (renderer.input_attachment_snapshots.len == 0) {
|
||||||
renderer.input_attachment_snapshots = try snapshotInputAttachments(renderer.device.device_allocator.allocator(), draw_call);
|
renderer.input_attachment_snapshots = try snapshotInputAttachments(renderer.device.interface.device_allocator.allocator(), draw_call);
|
||||||
}
|
}
|
||||||
draw_call.input_attachment_snapshots = renderer.input_attachment_snapshots;
|
draw_call.input_attachment_snapshots = renderer.input_attachment_snapshots;
|
||||||
|
|
||||||
|
|||||||
@@ -612,7 +612,8 @@ pub fn writeToTargets(
|
|||||||
const color = maybe_color orelse continue;
|
const color = maybe_color orelse continue;
|
||||||
const color_offset = targetSampleOffset(color, x, y, sample_index) orelse continue;
|
const color_offset = targetSampleOffset(color, x, y, sample_index) orelse continue;
|
||||||
if (base.format.isUnnormalizedInteger(color.format)) {
|
if (base.format.isUnnormalizedInteger(color.format)) {
|
||||||
blitter.writeInt4(std.mem.bytesToValue(U32x4, &outputs[location]), color.base[color_offset..], color.format);
|
const value = std.mem.bytesToValue(U32x4, &outputs[location]);
|
||||||
|
blitter.writeInt4(value, color.base[color_offset..], color.format);
|
||||||
} else {
|
} else {
|
||||||
const src = fragmentOutputFloat4(outputs[location], color.format);
|
const src = fragmentOutputFloat4(outputs[location], color.format);
|
||||||
const encoded_dst = blitter.readFloat4(color.base[color_offset..], color.format);
|
const encoded_dst = blitter.readFloat4(color.base[color_offset..], color.format);
|
||||||
|
|||||||
@@ -381,7 +381,7 @@ inline fn run(data: RunData) !void {
|
|||||||
if (early_depth.mask == 0)
|
if (early_depth.mask == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const interpolation_barycentrics = if (data.sample_count > 1) blk: {
|
const interpolation_barycentrics = if (data.sample_count > 1 and data.fragment_uses_centroid) blk: {
|
||||||
const sample_pos = firstCoveredSamplePosition(data.sample_count, early_depth.mask);
|
const sample_pos = firstCoveredSamplePosition(data.sample_count, early_depth.mask);
|
||||||
const centroid_p = zm.f32x4(
|
const centroid_p = zm.f32x4(
|
||||||
@as(f32, @floatFromInt(x)) + sample_pos.x,
|
@as(f32, @floatFromInt(x)) + sample_pos.x,
|
||||||
|
|||||||
@@ -115,6 +115,7 @@ inline fn run(data: RunData) !void {
|
|||||||
|
|
||||||
try readPosition(rt, std.mem.asBytes(&output.position));
|
try readPosition(rt, std.mem.asBytes(&output.position));
|
||||||
try readPointSize(rt, &output.point_size);
|
try readPointSize(rt, &output.point_size);
|
||||||
|
try readActiveInterfaceOutputs(data, output, rt, entry);
|
||||||
|
|
||||||
for (0..spv.SPIRV_MAX_OUTPUT_LOCATIONS) |location| {
|
for (0..spv.SPIRV_MAX_OUTPUT_LOCATIONS) |location| {
|
||||||
const location_result = rt.getResultByLocation(@intCast(location), .output) catch |err| switch (err) {
|
const location_result = rt.getResultByLocation(@intCast(location), .output) catch |err| switch (err) {
|
||||||
@@ -122,7 +123,8 @@ inline fn run(data: RunData) !void {
|
|||||||
else => return err,
|
else => return err,
|
||||||
};
|
};
|
||||||
|
|
||||||
try readVertexOutput(data, output, rt, location, 0, location_result);
|
if (output.outputs[location][0] == null)
|
||||||
|
try readVertexOutput(data, output, rt, location, 0, location_result);
|
||||||
|
|
||||||
for (1..4) |component| {
|
for (1..4) |component| {
|
||||||
const component_result = rt.getResultByLocationComponent(@intCast(location), @intCast(component), .output) catch |err| switch (err) {
|
const component_result = rt.getResultByLocationComponent(@intCast(location), @intCast(component), .output) catch |err| switch (err) {
|
||||||
@@ -133,12 +135,11 @@ inline fn run(data: RunData) !void {
|
|||||||
if (component_result == location_result)
|
if (component_result == location_result)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
try readVertexOutput(data, output, rt, location, component, component_result);
|
if (output.outputs[location][component] == null)
|
||||||
|
try readVertexOutput(data, output, rt, location, component, component_result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try readActiveInterfaceOutputs(data, output, rt, entry);
|
|
||||||
|
|
||||||
try rt.flushDescriptorSets(data.allocator);
|
try rt.flushDescriptorSets(data.allocator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -170,9 +171,8 @@ fn readActiveInterfaceOutputs(data: RunData, output: *Renderer.Vertex, rt: *spv.
|
|||||||
if (rt.results[type_word].variant) |type_variant| switch (type_variant) {
|
if (rt.results[type_word].variant) |type_variant| switch (type_variant) {
|
||||||
.Type => |t| switch (t) {
|
.Type => |t| switch (t) {
|
||||||
.Structure => |structure| {
|
.Structure => |structure| {
|
||||||
const base_location = location orelse continue;
|
|
||||||
for (structure.members_type_word, 0..) |_, member_index| {
|
for (structure.members_type_word, 0..) |_, member_index| {
|
||||||
const member_location = interfaceMemberLocation(rt, type_word, base_location, @intCast(member_index));
|
const member_location = explicitInterfaceMemberLocation(rt, type_word, @intCast(member_index)) orelse continue;
|
||||||
if (member_location >= spv.SPIRV_MAX_OUTPUT_LOCATIONS)
|
if (member_location >= spv.SPIRV_MAX_OUTPUT_LOCATIONS)
|
||||||
continue;
|
continue;
|
||||||
if (output.outputs[member_location][component] != null)
|
if (output.outputs[member_location][component] != null)
|
||||||
@@ -199,8 +199,16 @@ fn readActiveInterfaceOutputs(data: RunData, output: *Renderer.Vertex, rt: *spv.
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn readVertexOutput(data: RunData, output: *Renderer.Vertex, rt: *spv.Runtime, location: usize, component: usize, result_word: spv.SpvWord) !void {
|
fn readVertexOutput(data: RunData, output: *Renderer.Vertex, rt: *spv.Runtime, location: usize, component: usize, result_word: spv.SpvWord) !void {
|
||||||
|
const value = try rt.results[result_word].getConstValue();
|
||||||
const memory_size = try rt.getResultMemorySize(result_word);
|
const memory_size = try rt.getResultMemorySize(result_word);
|
||||||
const interpolation_type = vertexOutputInterpolationType(data, rt, location, component, result_word);
|
const interpolation_type = vertexOutputInterpolationType(data, rt, location, component, result_word);
|
||||||
|
switch (value.*) {
|
||||||
|
.Array, .Matrix => {
|
||||||
|
try readVertexOutputAggregate(data, output, value, location, component, interpolation_type);
|
||||||
|
return;
|
||||||
|
},
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
|
||||||
output.outputs[location][component] = .{
|
output.outputs[location][component] = .{
|
||||||
.interpolation_type = interpolation_type,
|
.interpolation_type = interpolation_type,
|
||||||
@@ -211,6 +219,66 @@ fn readVertexOutput(data: RunData, output: *Renderer.Vertex, rt: *spv.Runtime, l
|
|||||||
try rt.readOutput(output.outputs[location][component].?.blob, result_word);
|
try rt.readOutput(output.outputs[location][component].?.blob, result_word);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn readVertexOutputAggregate(
|
||||||
|
data: RunData,
|
||||||
|
output: *Renderer.Vertex,
|
||||||
|
value: anytype,
|
||||||
|
location: usize,
|
||||||
|
component: usize,
|
||||||
|
interpolation_type: Renderer.InterpolationType,
|
||||||
|
) !void {
|
||||||
|
var target_location = location;
|
||||||
|
switch (value.*) {
|
||||||
|
.Array => |array| {
|
||||||
|
for (array.values) |*element| {
|
||||||
|
try readVertexOutputAggregate(data, output, element, target_location, component, interpolation_type);
|
||||||
|
target_location += vertexOutputValueLocationCount(element);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.Matrix => |columns| {
|
||||||
|
for (columns) |*column| {
|
||||||
|
try writeVertexOutputValue(data, output, column, target_location, component, interpolation_type);
|
||||||
|
target_location += 1;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
else => try writeVertexOutputValue(data, output, value, location, component, interpolation_type),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn writeVertexOutputValue(
|
||||||
|
data: RunData,
|
||||||
|
output: *Renderer.Vertex,
|
||||||
|
value: anytype,
|
||||||
|
location: usize,
|
||||||
|
component: usize,
|
||||||
|
interpolation_type: Renderer.InterpolationType,
|
||||||
|
) !void {
|
||||||
|
if (location >= spv.SPIRV_MAX_OUTPUT_LOCATIONS or component >= 4)
|
||||||
|
return VkError.ValidationFailed;
|
||||||
|
|
||||||
|
const memory_size = try value.getPlainMemorySize();
|
||||||
|
output.outputs[location][component] = .{
|
||||||
|
.interpolation_type = interpolation_type,
|
||||||
|
.blob = data.allocator.alloc(u8, memory_size + INTERFACE_BLOB_PADDING) catch return VkError.OutOfDeviceMemory,
|
||||||
|
.size = memory_size,
|
||||||
|
};
|
||||||
|
@memset(output.outputs[location][component].?.blob, 0);
|
||||||
|
_ = try value.read(output.outputs[location][component].?.blob[0..memory_size]);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn vertexOutputValueLocationCount(value: anytype) usize {
|
||||||
|
return switch (value.*) {
|
||||||
|
.Array => |array| count: {
|
||||||
|
var location_count: usize = 0;
|
||||||
|
for (array.values) |*element|
|
||||||
|
location_count += vertexOutputValueLocationCount(element);
|
||||||
|
break :count location_count;
|
||||||
|
},
|
||||||
|
.Matrix => |columns| columns.len,
|
||||||
|
else => 1,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
fn vertexOutputInterpolationType(data: RunData, rt: *spv.Runtime, location: usize, component: usize, result_word: spv.SpvWord) Renderer.InterpolationType {
|
fn vertexOutputInterpolationType(data: RunData, rt: *spv.Runtime, location: usize, component: usize, result_word: spv.SpvWord) Renderer.InterpolationType {
|
||||||
const result_is_integer = resultIsInteger(rt, result_word);
|
const result_is_integer = resultIsInteger(rt, result_word);
|
||||||
|
|
||||||
@@ -259,7 +327,7 @@ fn interfaceLocationMemberHasDecoration(rt: *const spv.Runtime, location: usize,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
const type_word = pointerTargetType(rt, variable.type_word) orelse continue;
|
const type_word = pointerTargetType(rt, variable.type_word) orelse continue;
|
||||||
const base_location = resultLocation(rt, @intCast(id)) orelse continue;
|
const base_location = resultLocation(rt, @intCast(id));
|
||||||
const type_result = rt.results[type_word];
|
const type_result = rt.results[type_word];
|
||||||
const type_variant = type_result.variant orelse continue;
|
const type_variant = type_result.variant orelse continue;
|
||||||
switch (type_variant) {
|
switch (type_variant) {
|
||||||
@@ -292,14 +360,21 @@ fn resultLocation(rt: *const spv.Runtime, result_word: spv.SpvWord) ?usize {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn interfaceMemberLocation(rt: *const spv.Runtime, type_word: spv.SpvWord, base_location: usize, member_index: spv.SpvWord) usize {
|
fn interfaceMemberLocation(rt: *const spv.Runtime, type_word: spv.SpvWord, base_location: ?usize, member_index: spv.SpvWord) ?usize {
|
||||||
|
if (explicitInterfaceMemberLocation(rt, type_word, member_index)) |location|
|
||||||
|
return location;
|
||||||
|
|
||||||
|
return if (base_location) |location| location + @as(usize, @intCast(member_index)) else null;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn explicitInterfaceMemberLocation(rt: *const spv.Runtime, type_word: spv.SpvWord, member_index: spv.SpvWord) ?usize {
|
||||||
if (type_word < rt.results.len) {
|
if (type_word < rt.results.len) {
|
||||||
for (rt.results[type_word].decorations.items) |decoration| {
|
for (rt.results[type_word].decorations.items) |decoration| {
|
||||||
if (decoration.rtype == .Location and decoration.index == member_index)
|
if (decoration.rtype == .Location and decoration.index == member_index)
|
||||||
return decoration.literal_1;
|
return decoration.literal_1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return base_location + @as(usize, @intCast(member_index));
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn interfaceMemberHasDecoration(rt: *const spv.Runtime, variable_word: spv.SpvWord, member_index: spv.SpvWord, decoration: anytype) bool {
|
fn interfaceMemberHasDecoration(rt: *const spv.Runtime, variable_word: spv.SpvWord, member_index: spv.SpvWord, decoration: anytype) bool {
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const vk = @import("vulkan");
|
const vk = @import("vulkan");
|
||||||
|
const lib = @import("lib.zig");
|
||||||
|
const config = lib.config;
|
||||||
|
|
||||||
const Dispatchable = @import("Dispatchable.zig").Dispatchable;
|
const Dispatchable = @import("Dispatchable.zig").Dispatchable;
|
||||||
const NonDispatchable = @import("NonDispatchable.zig").NonDispatchable;
|
const NonDispatchable = @import("NonDispatchable.zig").NonDispatchable;
|
||||||
@@ -37,10 +39,17 @@ const SwapchainKHR = @import("wsi/SwapchainKHR.zig");
|
|||||||
const Self = @This();
|
const Self = @This();
|
||||||
pub const ObjectType: vk.ObjectType = .device;
|
pub const ObjectType: vk.ObjectType = .device;
|
||||||
|
|
||||||
|
const DeviceAllocator = struct {
|
||||||
|
pub inline fn allocator(_: @This()) std.mem.Allocator {
|
||||||
|
return lib.fallback_host_allocator;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
instance: *Instance,
|
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,
|
||||||
|
device_allocator: if (config.device_debug_allocator) std.heap.DebugAllocator(.{}) else DeviceAllocator,
|
||||||
enabled_khr_swapchain: bool,
|
enabled_khr_swapchain: bool,
|
||||||
enabled_khr_device_group: bool,
|
enabled_khr_device_group: bool,
|
||||||
|
|
||||||
@@ -110,6 +119,7 @@ pub fn init(allocator: std.mem.Allocator, instance: *Instance, physical_device:
|
|||||||
.host_allocator = VulkanAllocator.from(allocator).cloneWithScope(.object),
|
.host_allocator = VulkanAllocator.from(allocator).cloneWithScope(.object),
|
||||||
.enabled_khr_swapchain = enabled_khr_swapchain,
|
.enabled_khr_swapchain = enabled_khr_swapchain,
|
||||||
.enabled_khr_device_group = enabled_khr_device_group,
|
.enabled_khr_device_group = enabled_khr_device_group,
|
||||||
|
.device_allocator = if (config.device_debug_allocator) .init else .{},
|
||||||
.dispatch_table = undefined,
|
.dispatch_table = undefined,
|
||||||
.vtable = undefined,
|
.vtable = undefined,
|
||||||
};
|
};
|
||||||
@@ -154,6 +164,17 @@ pub inline fn destroy(self: *Self, allocator: std.mem.Allocator) VkError!void {
|
|||||||
family.deinit(allocator);
|
family.deinit(allocator);
|
||||||
}
|
}
|
||||||
self.queues.deinit(allocator);
|
self.queues.deinit(allocator);
|
||||||
|
|
||||||
|
if (config.device_debug_allocator) {
|
||||||
|
// All device memory allocations should've been freed by now
|
||||||
|
const leaks = self.device_allocator.detectLeaks();
|
||||||
|
if (leaks != 0)
|
||||||
|
std.log.scoped(.vkDestroyDevice).err("Device was destroyed leaking {d:.3}KB", .{@as(f32, @floatFromInt(leaks)) / 1000})
|
||||||
|
else
|
||||||
|
std.log.scoped(.vkDestroyDevice).debug("No device memory leaks detected", .{});
|
||||||
|
self.device_allocator.deinitWithoutLeakChecks();
|
||||||
|
}
|
||||||
|
|
||||||
try self.dispatch_table.destroy(self, allocator);
|
try self.dispatch_table.destroy(self, allocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ mode: union(enum) {
|
|||||||
scissor: ?[]vk.Rect2D,
|
scissor: ?[]vk.Rect2D,
|
||||||
},
|
},
|
||||||
rasterization: struct {
|
rasterization: struct {
|
||||||
|
rasterizer_discard_enable: bool,
|
||||||
polygon_mode: vk.PolygonMode,
|
polygon_mode: vk.PolygonMode,
|
||||||
cull_mode: vk.CullModeFlags,
|
cull_mode: vk.CullModeFlags,
|
||||||
front_face: vk.FrontFace,
|
front_face: vk.FrontFace,
|
||||||
@@ -194,6 +195,7 @@ pub fn initGraphics(device: *Device, allocator: std.mem.Allocator, cache: ?*Pipe
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
.rasterization = .{
|
.rasterization = .{
|
||||||
|
.rasterizer_discard_enable = rasterizer_discard_enable,
|
||||||
.polygon_mode = if (info.p_rasterization_state) |state| state.polygon_mode else return VkError.ValidationFailed,
|
.polygon_mode = if (info.p_rasterization_state) |state| state.polygon_mode else return VkError.ValidationFailed,
|
||||||
.cull_mode = if (info.p_rasterization_state) |state| state.cull_mode else return VkError.ValidationFailed,
|
.cull_mode = if (info.p_rasterization_state) |state| state.cull_mode else return VkError.ValidationFailed,
|
||||||
.front_face = if (info.p_rasterization_state) |state| state.front_face else return VkError.ValidationFailed,
|
.front_face = if (info.p_rasterization_state) |state| state.front_face else return VkError.ValidationFailed,
|
||||||
|
|||||||
Reference in New Issue
Block a user