fixing wsi crashes
This commit is contained in:
@@ -432,7 +432,8 @@ fn addMultithreadedCTS(b: *std.Build, target: std.Build.ResolvedTarget, impl: *c
|
|||||||
}
|
}
|
||||||
|
|
||||||
run.addArg("run");
|
run.addArg("run");
|
||||||
run.addArg("--verbose");
|
run.addArg("--timeout");
|
||||||
|
run.addArg("300");
|
||||||
run.addArg("--deqp");
|
run.addArg("--deqp");
|
||||||
run.addArg(cts_exe_path);
|
run.addArg(cts_exe_path);
|
||||||
run.addArg("--caselist");
|
run.addArg("--caselist");
|
||||||
|
|||||||
+2
-2
@@ -32,8 +32,8 @@
|
|||||||
|
|
||||||
// Soft dependencies
|
// Soft dependencies
|
||||||
.SPIRV_Interpreter = .{
|
.SPIRV_Interpreter = .{
|
||||||
.url = "git+https://github.com/Kbz-8/SPIRV-Interpreter#18f910f38a6a9c8a00294947ac545bbffdc55477",
|
.url = "git+https://github.com/Kbz-8/SPIRV-Interpreter#9b6f409bffdbb9105d32d73fa3c3025134b0e7f0",
|
||||||
.hash = "SPIRV_Interpreter-0.0.1-ajmpn9wmCQAuq_IL_yvnqUJgHnWyGAtYomv0x8HjTaRh",
|
.hash = "SPIRV_Interpreter-0.0.1-ajmpn_U2CQArCKl6BQ5HxvEE9bslrF21gzZVufvTHkJe",
|
||||||
.lazy = true,
|
.lazy = true,
|
||||||
},
|
},
|
||||||
//.SPIRV_Interpreter = .{
|
//.SPIRV_Interpreter = .{
|
||||||
|
|||||||
@@ -42,36 +42,75 @@ pub inline fn queryPeakFootprint(self: *Self) usize {
|
|||||||
return self.peak_concurrent_bytes_allocated.load(.monotonic);
|
return self.peak_concurrent_bytes_allocated.load(.monotonic);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn reserve(self: *Self, len: usize) bool {
|
||||||
|
while (true) {
|
||||||
|
const current = self.current_bytes_allocated.load(.monotonic);
|
||||||
|
if (len > self.bound -| current)
|
||||||
|
return false;
|
||||||
|
const new_current = current + len;
|
||||||
|
if (self.current_bytes_allocated.cmpxchgWeak(current, new_current, .monotonic, .monotonic) == null) {
|
||||||
|
_ = self.total_bytes_allocated.fetchAdd(len, .monotonic);
|
||||||
|
while (true) {
|
||||||
|
const peak = self.peak_concurrent_bytes_allocated.load(.monotonic);
|
||||||
|
if (new_current <= peak)
|
||||||
|
break;
|
||||||
|
if (self.peak_concurrent_bytes_allocated.cmpxchgWeak(peak, new_current, .monotonic, .monotonic) == null)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn release(self: *Self, len: usize) void {
|
||||||
|
while (true) {
|
||||||
|
const current = self.current_bytes_allocated.load(.monotonic);
|
||||||
|
const new_current = current -| len;
|
||||||
|
if (self.current_bytes_allocated.cmpxchgWeak(current, new_current, .monotonic, .monotonic) == null)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn alloc(context: *anyopaque, len: usize, alignment: Alignment, ret_addr: usize) ?[*]u8 {
|
fn alloc(context: *anyopaque, len: usize, alignment: Alignment, ret_addr: usize) ?[*]u8 {
|
||||||
const self: *Self = @ptrCast(@alignCast(context));
|
const self: *Self = @ptrCast(@alignCast(context));
|
||||||
if (self.current_bytes_allocated.fetchAdd(len, .monotonic) >= self.bound)
|
if (!self.reserve(len))
|
||||||
return null;
|
return null;
|
||||||
_ = self.total_bytes_allocated.fetchAdd(len, .monotonic);
|
return self.child_allocator.rawAlloc(len, alignment, ret_addr) orelse {
|
||||||
if (self.current_bytes_allocated.load(.monotonic) > self.peak_concurrent_bytes_allocated.load(.monotonic))
|
self.release(len);
|
||||||
self.peak_concurrent_bytes_allocated.store(self.current_bytes_allocated.load(.monotonic), .monotonic);
|
return null;
|
||||||
return self.child_allocator.rawAlloc(len, alignment, ret_addr);
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resize(context: *anyopaque, ptr: []u8, alignment: Alignment, new_len: usize, ret_addr: usize) bool {
|
fn resize(context: *anyopaque, ptr: []u8, alignment: Alignment, new_len: usize, ret_addr: usize) bool {
|
||||||
const self: *Self = @ptrCast(@alignCast(context));
|
const self: *Self = @ptrCast(@alignCast(context));
|
||||||
_ = self.current_bytes_allocated.fetchSub(ptr.len, .monotonic);
|
if (new_len > ptr.len) {
|
||||||
if (self.current_bytes_allocated.fetchAdd(new_len, .monotonic) >= self.bound)
|
const delta = new_len - ptr.len;
|
||||||
|
if (!self.reserve(delta))
|
||||||
|
return false;
|
||||||
|
if (self.child_allocator.rawResize(ptr, alignment, new_len, ret_addr))
|
||||||
|
return true;
|
||||||
|
self.release(delta);
|
||||||
return false;
|
return false;
|
||||||
_ = self.total_bytes_allocated.fetchAdd(new_len, .monotonic);
|
}
|
||||||
return self.child_allocator.rawResize(ptr, alignment, new_len, ret_addr);
|
return self.child_allocator.rawResize(ptr, alignment, new_len, ret_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remap(context: *anyopaque, ptr: []u8, alignment: Alignment, new_len: usize, ret_addr: usize) ?[*]u8 {
|
fn remap(context: *anyopaque, ptr: []u8, alignment: Alignment, new_len: usize, ret_addr: usize) ?[*]u8 {
|
||||||
const self: *Self = @ptrCast(@alignCast(context));
|
const self: *Self = @ptrCast(@alignCast(context));
|
||||||
_ = self.current_bytes_allocated.fetchSub(ptr.len, .monotonic);
|
if (new_len > ptr.len) {
|
||||||
if (self.current_bytes_allocated.fetchAdd(new_len, .monotonic) >= self.bound)
|
const delta = new_len - ptr.len;
|
||||||
return null;
|
if (!self.reserve(delta))
|
||||||
_ = self.total_bytes_allocated.fetchAdd(new_len, .monotonic);
|
return null;
|
||||||
return self.child_allocator.rawRemap(ptr, alignment, new_len, ret_addr);
|
return self.child_allocator.rawRemap(ptr, alignment, new_len, ret_addr) orelse {
|
||||||
|
self.release(delta);
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return self.child_allocator.rawRemap(ptr, alignment, new_len, ret_addr) orelse null;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn free(context: *anyopaque, ptr: []u8, alignment: Alignment, ret_addr: usize) void {
|
fn free(context: *anyopaque, ptr: []u8, alignment: Alignment, ret_addr: usize) void {
|
||||||
const self: *Self = @ptrCast(@alignCast(context));
|
const self: *Self = @ptrCast(@alignCast(context));
|
||||||
_ = self.current_bytes_allocated.fetchSub(ptr.len, .monotonic);
|
self.release(ptr.len);
|
||||||
return self.child_allocator.rawFree(ptr, alignment, ret_addr);
|
return self.child_allocator.rawFree(ptr, alignment, ret_addr);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -118,11 +118,10 @@ fn writeDescriptorSet(rt: *spv.Runtime, payload: DescriptorPayload, set: u32, bi
|
|||||||
for (rt.mod.bindings.items) |entry| {
|
for (rt.mod.bindings.items) |entry| {
|
||||||
if (entry.set != set or entry.binding != binding)
|
if (entry.set != set or entry.binding != binding)
|
||||||
continue;
|
continue;
|
||||||
|
const variable = if (rt.results[entry.result].variant) |*variant| switch (variant.*) {
|
||||||
const variable = switch (rt.results[entry.result].variant orelse continue) {
|
|
||||||
.Variable => |*variable| variable,
|
.Variable => |*variable| variable,
|
||||||
else => continue,
|
else => continue,
|
||||||
};
|
} else continue;
|
||||||
|
|
||||||
writeDescriptorValue(&variable.value, payload, descriptor_index) catch |err| switch (err) {
|
writeDescriptorValue(&variable.value, payload, descriptor_index) catch |err| switch (err) {
|
||||||
spv.Runtime.RuntimeError.InvalidValueType,
|
spv.Runtime.RuntimeError.InvalidValueType,
|
||||||
|
|||||||
@@ -82,6 +82,11 @@ pub fn shaderInvocation(
|
|||||||
SpvRuntimeError.NotFound => {},
|
SpvRuntimeError.NotFound => {},
|
||||||
else => return err,
|
else => return err,
|
||||||
};
|
};
|
||||||
|
const helper_invocation = false;
|
||||||
|
rt.writeBuiltIn(allocator, std.mem.asBytes(&helper_invocation), .HelperInvocation) catch |err| switch (err) {
|
||||||
|
SpvRuntimeError.NotFound => {},
|
||||||
|
else => return err,
|
||||||
|
};
|
||||||
|
|
||||||
const SoftPipeline = @import("../SoftPipeline.zig");
|
const SoftPipeline = @import("../SoftPipeline.zig");
|
||||||
const previous_fragment_coord = SoftPipeline.current_fragment_coord;
|
const previous_fragment_coord = SoftPipeline.current_fragment_coord;
|
||||||
@@ -157,6 +162,10 @@ pub fn shaderInvocation(
|
|||||||
},
|
},
|
||||||
else => return err,
|
else => return err,
|
||||||
};
|
};
|
||||||
|
if (rt.helper_invocation) {
|
||||||
|
try rt.flushDescriptorSets(allocator);
|
||||||
|
return SpvRuntimeError.Killed;
|
||||||
|
}
|
||||||
|
|
||||||
var outputs = std.mem.zeroes([spv.SPIRV_MAX_OUTPUT_LOCATIONS][@sizeOf(zm.F32x4)]u8);
|
var outputs = std.mem.zeroes([spv.SPIRV_MAX_OUTPUT_LOCATIONS][@sizeOf(zm.F32x4)]u8);
|
||||||
|
|
||||||
|
|||||||
@@ -216,20 +216,13 @@ pub fn depthTestSampleAndUpdate(
|
|||||||
z: f32,
|
z: f32,
|
||||||
state: ?vk.PipelineDepthStencilStateCreateInfo,
|
state: ?vk.PipelineDepthStencilStateCreateInfo,
|
||||||
) VkError!bool {
|
) VkError!bool {
|
||||||
|
const depth_state = state orelse return true;
|
||||||
const depth_offset = targetSampleOffset(depth.*, x, y, sample_index) orelse return false;
|
const depth_offset = targetSampleOffset(depth.*, x, y, sample_index) orelse return false;
|
||||||
|
|
||||||
depth.mutex.lock(io) catch return VkError.DeviceLost;
|
depth.mutex.lock(io) catch return VkError.DeviceLost;
|
||||||
defer depth.mutex.unlock(io);
|
defer depth.mutex.unlock(io);
|
||||||
|
|
||||||
if (state) |depth_state| {
|
return depthTestAndUpdateAtOffset(depth, depth_offset, z, depth_state);
|
||||||
return depthTestAndUpdateAtOffset(depth, depth_offset, z, depth_state);
|
|
||||||
}
|
|
||||||
|
|
||||||
const depth_value = blitter.readFloat4(depth.base[depth_offset..], depth.format);
|
|
||||||
if (z >= depth_value[0])
|
|
||||||
return false;
|
|
||||||
blitter.writeFloat4(zm.f32x4s(z), depth.base[depth_offset..], depth.format);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn depthTestAndUpdateAtOffset(depth: *RenderTargetAccess, offset: usize, z: f32, state: vk.PipelineDepthStencilStateCreateInfo) bool {
|
fn depthTestAndUpdateAtOffset(depth: *RenderTargetAccess, offset: usize, z: f32, state: vk.PipelineDepthStencilStateCreateInfo) bool {
|
||||||
@@ -589,24 +582,16 @@ pub fn writeToTargets(
|
|||||||
|
|
||||||
// After work depth test to avoid overwritten depth pixels during fragment invocations.
|
// After work depth test to avoid overwritten depth pixels during fragment invocations.
|
||||||
var depth_passed: ?bool = null;
|
var depth_passed: ?bool = null;
|
||||||
if (!depth_already_applied and depth_attachment_access != null) {
|
if (!depth_already_applied and depth_attachment_access != null and depth_stencil_state != null) {
|
||||||
const depth = depth_attachment_access.?;
|
const depth = depth_attachment_access.?;
|
||||||
const depth_offset = targetSampleOffset(depth.*, x, y, sample_index) orelse continue;
|
const depth_offset = targetSampleOffset(depth.*, x, y, sample_index) orelse continue;
|
||||||
|
|
||||||
depth.mutex.lock(io) catch return VkError.DeviceLost;
|
depth.mutex.lock(io) catch return VkError.DeviceLost;
|
||||||
defer depth.mutex.unlock(io);
|
defer depth.mutex.unlock(io);
|
||||||
|
|
||||||
if (depth_stencil_state) |state| {
|
depth_passed = depthTestAndUpdateAtOffset(depth, depth_offset, z, depth_stencil_state.?);
|
||||||
depth_passed = depthTestAndUpdateAtOffset(depth, depth_offset, z, state);
|
if (!depth_passed.? and stencil_state == null)
|
||||||
if (!depth_passed.? and stencil_state == null)
|
continue;
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
const depth_value = blitter.readFloat4(depth.base[depth_offset..], depth.format);
|
|
||||||
if (z >= depth_value[0])
|
|
||||||
continue;
|
|
||||||
blitter.writeFloat4(zm.f32x4s(z), depth.base[depth_offset..], depth.format);
|
|
||||||
depth_passed = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stencil_attachment_access) |stencil| {
|
if (stencil_attachment_access) |stencil| {
|
||||||
|
|||||||
@@ -164,21 +164,29 @@ pub fn getSurfaceCapabilitiesKHR(_: *Self, surface: *SurfaceKHR, capabilities: *
|
|||||||
|
|
||||||
pub fn getSurfaceFormatsKHR(_: *Self, _: *SurfaceKHR, count: *u32, p_formats: ?[*]vk.SurfaceFormatKHR) VkError!void {
|
pub fn getSurfaceFormatsKHR(_: *Self, _: *SurfaceKHR, count: *u32, p_formats: ?[*]vk.SurfaceFormatKHR) VkError!void {
|
||||||
const surface_formats = SurfaceKHR.getFormats();
|
const surface_formats = SurfaceKHR.getFormats();
|
||||||
count.* = surface_formats.len;
|
|
||||||
if (p_formats) |formats| {
|
if (p_formats) |formats| {
|
||||||
for (formats[0..], surface_formats[0..]) |*format, surface_format| {
|
const write_count = @min(count.*, surface_formats.len);
|
||||||
|
for (formats[0..write_count], surface_formats[0..write_count]) |*format, surface_format| {
|
||||||
format.* = surface_format;
|
format.* = surface_format;
|
||||||
}
|
}
|
||||||
|
count.* = @intCast(write_count);
|
||||||
|
if (write_count < surface_formats.len) return VkError.Incomplete;
|
||||||
|
} else {
|
||||||
|
count.* = @intCast(surface_formats.len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getSurfacePresentModesKHR(_: *Self, _: *SurfaceKHR, count: *u32, p_modes: ?[*]vk.PresentModeKHR) VkError!void {
|
pub fn getSurfacePresentModesKHR(_: *Self, _: *SurfaceKHR, count: *u32, p_modes: ?[*]vk.PresentModeKHR) VkError!void {
|
||||||
const surface_modes = SurfaceKHR.getPresentModes();
|
const surface_modes = SurfaceKHR.getPresentModes();
|
||||||
count.* = surface_modes.len;
|
|
||||||
if (p_modes) |modes| {
|
if (p_modes) |modes| {
|
||||||
for (modes[0..], surface_modes[0..]) |*mode, surface_mode| {
|
const write_count = @min(count.*, surface_modes.len);
|
||||||
|
for (modes[0..write_count], surface_modes[0..write_count]) |*mode, surface_mode| {
|
||||||
mode.* = surface_mode;
|
mode.* = surface_mode;
|
||||||
}
|
}
|
||||||
|
count.* = @intCast(write_count);
|
||||||
|
if (write_count < surface_modes.len) return VkError.Incomplete;
|
||||||
|
} else {
|
||||||
|
count.* = @intCast(surface_modes.len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -149,7 +149,11 @@ pub fn presentKHR(_: *Self, info: *const vk.PresentInfoKHR) VkError!void {
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
cmd_err = err;
|
cmd_err = err;
|
||||||
|
continue;
|
||||||
};
|
};
|
||||||
|
if (info.p_results) |results| {
|
||||||
|
results[i] = .success;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cmd_err) |err|
|
if (cmd_err) |err|
|
||||||
|
|||||||
@@ -2458,11 +2458,15 @@ pub export fn apeGetSwapchainImagesKHR(p_device: vk.Device, p_swapchain: vk.Swap
|
|||||||
Dispatchable(Device).checkHandleValidity(p_device) catch |err| return toVkResult(err);
|
Dispatchable(Device).checkHandleValidity(p_device) catch |err| return toVkResult(err);
|
||||||
|
|
||||||
const swapchain = NonDispatchable(SwapchainKHR).fromHandleObject(p_swapchain) catch |err| return toVkResult(err);
|
const swapchain = NonDispatchable(SwapchainKHR).fromHandleObject(p_swapchain) catch |err| return toVkResult(err);
|
||||||
count.* = @intCast(swapchain.images.len);
|
|
||||||
if (p_images) |images| {
|
if (p_images) |images| {
|
||||||
for (images[0..], swapchain.images[0..]) |*image, *swapchain_image| {
|
const write_count = @min(count.*, swapchain.images.len);
|
||||||
|
for (images[0..write_count], swapchain.images[0..write_count]) |*image, *swapchain_image| {
|
||||||
image.* = swapchain_image.non_dispatchable_image.toVkHandle(vk.Image);
|
image.* = swapchain_image.non_dispatchable_image.toVkHandle(vk.Image);
|
||||||
}
|
}
|
||||||
|
count.* = @intCast(write_count);
|
||||||
|
if (write_count < swapchain.images.len) return .incomplete;
|
||||||
|
} else {
|
||||||
|
count.* = @intCast(swapchain.images.len);
|
||||||
}
|
}
|
||||||
|
|
||||||
return .success;
|
return .success;
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ const formats = [_]vk.SurfaceFormatKHR{
|
|||||||
};
|
};
|
||||||
|
|
||||||
const present_modes = [_]vk.PresentModeKHR{
|
const present_modes = [_]vk.PresentModeKHR{
|
||||||
|
.fifo_khr,
|
||||||
.immediate_khr,
|
.immediate_khr,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,19 @@ owner: *Device,
|
|||||||
surface: ?*SurfaceKHR,
|
surface: ?*SurfaceKHR,
|
||||||
images: []PresentImage,
|
images: []PresentImage,
|
||||||
|
|
||||||
|
fn validateImageAllocationSize(info: *const vk.SwapchainCreateInfoKHR) VkError!void {
|
||||||
|
if (info.image_extent.width == 0 or info.image_extent.height == 0 or info.image_array_layers == 0)
|
||||||
|
return VkError.OutOfDeviceMemory;
|
||||||
|
|
||||||
|
const texel_size = lib.format.texelSize(info.image_format);
|
||||||
|
var size = std.math.mul(usize, texel_size, info.image_extent.width) catch return VkError.OutOfDeviceMemory;
|
||||||
|
size = std.math.mul(usize, size, info.image_extent.height) catch return VkError.OutOfDeviceMemory;
|
||||||
|
_ = std.math.mul(usize, size, info.image_array_layers) catch return VkError.OutOfDeviceMemory;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn create(device: *Device, allocator: std.mem.Allocator, surface: *SurfaceKHR, info: *const vk.SwapchainCreateInfoKHR) VkError!*Self {
|
pub fn create(device: *Device, allocator: std.mem.Allocator, surface: *SurfaceKHR, info: *const vk.SwapchainCreateInfoKHR) VkError!*Self {
|
||||||
|
try validateImageAllocationSize(info);
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
@@ -27,6 +39,14 @@ pub fn create(device: *Device, allocator: std.mem.Allocator, surface: *SurfaceKH
|
|||||||
allocator.free(images);
|
allocator.free(images);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var initialized_image_count: usize = 0;
|
||||||
|
errdefer {
|
||||||
|
for (images[0..initialized_image_count]) |*image| {
|
||||||
|
surface.detachImage(allocator, image) catch {};
|
||||||
|
image.deinit(allocator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (images) |*image| {
|
for (images) |*image| {
|
||||||
image.* = try .init(device, allocator, &.{
|
image.* = try .init(device, allocator, &.{
|
||||||
.format = info.image_format,
|
.format = info.image_format,
|
||||||
@@ -46,6 +66,7 @@ pub fn create(device: *Device, allocator: std.mem.Allocator, surface: *SurfaceKH
|
|||||||
.queue_family_index_count = info.queue_family_index_count,
|
.queue_family_index_count = info.queue_family_index_count,
|
||||||
.initial_layout = .general,
|
.initial_layout = .general,
|
||||||
});
|
});
|
||||||
|
initialized_image_count += 1;
|
||||||
|
|
||||||
try surface.attachImage(allocator, image);
|
try surface.attachImage(allocator, image);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user