fixing synchronization issues, implementing missing entrypoints
This commit is contained in:
@@ -89,11 +89,11 @@ vkCmdResetEvent | ✅ Implemented
|
||||
vkCmdResetQueryPool | ✅ Implemented
|
||||
vkCmdResolveImage | ✅ Implemented
|
||||
vkCmdSetBlendConstants | ✅ Implemented
|
||||
vkCmdSetDepthBias | ⚙️ WIP
|
||||
vkCmdSetDepthBounds | ⚙️ WIP
|
||||
vkCmdSetDepthBias | ✅ Implemented
|
||||
vkCmdSetDepthBounds | ✅ Implemented
|
||||
vkCmdSetDeviceMaskKHR | ✅ Implemented
|
||||
vkCmdSetEvent | ✅ Implemented
|
||||
vkCmdSetLineWidth | ⚙️ WIP
|
||||
vkCmdSetLineWidth | ✅ Implemented
|
||||
vkCmdSetScissor | ✅ Implemented
|
||||
vkCmdSetStencilCompareMask | ✅ Implemented
|
||||
vkCmdSetStencilReference | ✅ Implemented
|
||||
@@ -101,7 +101,7 @@ vkCmdSetStencilWriteMask | ✅ Implemented
|
||||
vkCmdSetViewport | ✅ Implemented
|
||||
vkCmdUpdateBuffer | ✅ Implemented
|
||||
vkCmdWaitEvents | ✅ Implemented
|
||||
vkCmdWriteTimestamp | ⚙️ WIP
|
||||
vkCmdWriteTimestamp | ✅ Implemented
|
||||
vkCreateBuffer | ✅ Implemented
|
||||
vkCreateBufferView | ✅ Implemented
|
||||
vkCreateCommandPool | ✅ Implemented
|
||||
@@ -169,7 +169,7 @@ vkGetBufferMemoryRequirements | ✅ Implemented
|
||||
vkGetDeviceGroupPeerMemoryFeaturesKHR | ✅ Implemented
|
||||
vkGetDeviceGroupPresentCapabilitiesKHR | ✅ Implemented
|
||||
vkGetDeviceGroupSurfacePresentModesKHR | ✅ Implemented
|
||||
vkGetDeviceMemoryCommitment | ⚙️ WIP
|
||||
vkGetDeviceMemoryCommitment | ✅ Implemented
|
||||
vkGetDeviceProcAddr | ✅ Implemented
|
||||
vkGetDeviceQueue | ✅ Implemented
|
||||
vkGetEventStatus | ✅ Implemented
|
||||
|
||||
@@ -53,7 +53,10 @@ pub fn create(device: *base.Device, allocator: std.mem.Allocator, info: *const v
|
||||
.resolveImage = resolveImage,
|
||||
.setEvent = setEvent,
|
||||
.setBlendConstants = setBlendConstants,
|
||||
.setDepthBias = setDepthBias,
|
||||
.setDepthBounds = setDepthBounds,
|
||||
.setDeviceMask = setDeviceMask,
|
||||
.setLineWidth = setLineWidth,
|
||||
.setScissor = setScissor,
|
||||
.setStencilCompareMask = setStencilCompareMask,
|
||||
.setStencilReference = setStencilReference,
|
||||
@@ -61,6 +64,7 @@ pub fn create(device: *base.Device, allocator: std.mem.Allocator, info: *const v
|
||||
.setViewport = setViewport,
|
||||
.updateBuffer = updateBuffer,
|
||||
.waitEvent = waitEvent,
|
||||
.writeTimestamp = writeTimestamp,
|
||||
};
|
||||
|
||||
self.* = .{ .interface = interface };
|
||||
@@ -363,6 +367,24 @@ pub fn setBlendConstants(interface: *Interface, constants: [4]f32) VkError!void
|
||||
_ = constants;
|
||||
}
|
||||
|
||||
pub fn setDepthBias(interface: *Interface, constant_factor: f32, clamp: f32, slope_factor: f32) VkError!void {
|
||||
_ = interface;
|
||||
_ = constant_factor;
|
||||
_ = clamp;
|
||||
_ = slope_factor;
|
||||
}
|
||||
|
||||
pub fn setDepthBounds(interface: *Interface, min: f32, max: f32) VkError!void {
|
||||
_ = interface;
|
||||
_ = min;
|
||||
_ = max;
|
||||
}
|
||||
|
||||
pub fn setLineWidth(interface: *Interface, width: f32) VkError!void {
|
||||
_ = interface;
|
||||
_ = width;
|
||||
}
|
||||
|
||||
pub fn setStencilCompareMask(interface: *Interface, face_mask: vk.StencilFaceFlags, compare_mask: u32) VkError!void {
|
||||
_ = interface;
|
||||
_ = face_mask;
|
||||
@@ -390,3 +412,9 @@ pub fn waitEvent(interface: *Interface, event: *base.Event, src_stage: vk.Pipeli
|
||||
_ = buffer_barriers;
|
||||
_ = image_barriers;
|
||||
}
|
||||
|
||||
pub fn writeTimestamp(interface: *Interface, stage: vk.PipelineStageFlags, pool: *base.QueryPool, query: u32) VkError!void {
|
||||
_ = interface;
|
||||
_ = stage;
|
||||
try pool.writeTimestamp(query, 0);
|
||||
}
|
||||
|
||||
@@ -113,7 +113,10 @@ pub fn create(device: *base.Device, allocator: std.mem.Allocator, info: *const v
|
||||
.resolveImage = resolveImage,
|
||||
.setEvent = setEvent,
|
||||
.setBlendConstants = setBlendConstants,
|
||||
.setDepthBias = setDepthBias,
|
||||
.setDepthBounds = setDepthBounds,
|
||||
.setDeviceMask = setDeviceMask,
|
||||
.setLineWidth = setLineWidth,
|
||||
.setScissor = setScissor,
|
||||
.setStencilCompareMask = setStencilCompareMask,
|
||||
.setStencilReference = setStencilReference,
|
||||
@@ -121,6 +124,7 @@ pub fn create(device: *base.Device, allocator: std.mem.Allocator, info: *const v
|
||||
.setViewport = setViewport,
|
||||
.updateBuffer = updateBuffer,
|
||||
.waitEvent = waitEvent,
|
||||
.writeTimestamp = writeTimestamp,
|
||||
};
|
||||
|
||||
self.* = .{
|
||||
@@ -283,6 +287,36 @@ pub fn resetQueryPool(interface: *Interface, pool: *base.QueryPool, first: u32,
|
||||
self.commands.append(allocator, .{ .ptr = cmd, .vtable = &.{ .execute = CommandImpl.execute } }) catch return VkError.OutOfHostMemory;
|
||||
}
|
||||
|
||||
pub fn writeTimestamp(interface: *Interface, stage: vk.PipelineStageFlags, pool: *base.QueryPool, query: u32) VkError!void {
|
||||
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
|
||||
const allocator = self.command_allocator.allocator();
|
||||
|
||||
const CommandImpl = struct {
|
||||
const Impl = @This();
|
||||
|
||||
stage: vk.PipelineStageFlags,
|
||||
pool: *base.QueryPool,
|
||||
query: u32,
|
||||
|
||||
pub fn execute(context: *anyopaque, device: *ExecutionDevice) VkError!void {
|
||||
const impl: *Impl = @ptrCast(@alignCast(context));
|
||||
_ = impl.stage;
|
||||
const io = device.renderer.device.interface.io();
|
||||
const now = std.Io.Timestamp.now(io, .real).toNanoseconds();
|
||||
try impl.pool.writeTimestamp(impl.query, if (now > 0) @intCast(now) else 0);
|
||||
}
|
||||
};
|
||||
|
||||
const cmd = allocator.create(CommandImpl) catch return VkError.OutOfHostMemory;
|
||||
errdefer allocator.destroy(cmd);
|
||||
cmd.* = .{
|
||||
.stage = stage,
|
||||
.pool = pool,
|
||||
.query = query,
|
||||
};
|
||||
self.commands.append(allocator, .{ .ptr = cmd, .vtable = &.{ .execute = CommandImpl.execute } }) catch return VkError.OutOfHostMemory;
|
||||
}
|
||||
|
||||
pub fn beginRenderPass(interface: *Interface, render_pass: *base.RenderPass, framebuffer: *base.Framebuffer, render_area: vk.Rect2D, clear_values: ?[]const vk.ClearValue) VkError!void {
|
||||
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
|
||||
const allocator = self.command_allocator.allocator();
|
||||
@@ -1330,6 +1364,75 @@ pub fn setBlendConstants(interface: *Interface, constants: [4]f32) VkError!void
|
||||
self.commands.append(allocator, .{ .ptr = cmd, .vtable = &.{ .execute = CommandImpl.execute } }) catch return VkError.OutOfHostMemory;
|
||||
}
|
||||
|
||||
pub fn setDepthBias(interface: *Interface, constant_factor: f32, clamp: f32, slope_factor: f32) VkError!void {
|
||||
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
|
||||
const allocator = self.command_allocator.allocator();
|
||||
|
||||
const CommandImpl = struct {
|
||||
const Impl = @This();
|
||||
|
||||
depth_bias: @import("device/Renderer.zig").DepthBias,
|
||||
|
||||
pub fn execute(context: *anyopaque, device: *ExecutionDevice) VkError!void {
|
||||
const impl: *Impl = @ptrCast(@alignCast(context));
|
||||
device.renderer.dynamic_state.depth_bias = impl.depth_bias;
|
||||
}
|
||||
};
|
||||
|
||||
const cmd = allocator.create(CommandImpl) catch return VkError.OutOfHostMemory;
|
||||
errdefer allocator.destroy(cmd);
|
||||
cmd.* = .{
|
||||
.depth_bias = .{
|
||||
.constant_factor = constant_factor,
|
||||
.clamp = clamp,
|
||||
.slope_factor = slope_factor,
|
||||
},
|
||||
};
|
||||
self.commands.append(allocator, .{ .ptr = cmd, .vtable = &.{ .execute = CommandImpl.execute } }) catch return VkError.OutOfHostMemory;
|
||||
}
|
||||
|
||||
pub fn setDepthBounds(interface: *Interface, min: f32, max: f32) VkError!void {
|
||||
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
|
||||
const allocator = self.command_allocator.allocator();
|
||||
|
||||
const CommandImpl = struct {
|
||||
const Impl = @This();
|
||||
|
||||
depth_bounds: @import("device/Renderer.zig").DepthBounds,
|
||||
|
||||
pub fn execute(context: *anyopaque, device: *ExecutionDevice) VkError!void {
|
||||
const impl: *Impl = @ptrCast(@alignCast(context));
|
||||
device.renderer.dynamic_state.depth_bounds = impl.depth_bounds;
|
||||
}
|
||||
};
|
||||
|
||||
const cmd = allocator.create(CommandImpl) catch return VkError.OutOfHostMemory;
|
||||
errdefer allocator.destroy(cmd);
|
||||
cmd.* = .{ .depth_bounds = .{ .min = min, .max = max } };
|
||||
self.commands.append(allocator, .{ .ptr = cmd, .vtable = &.{ .execute = CommandImpl.execute } }) catch return VkError.OutOfHostMemory;
|
||||
}
|
||||
|
||||
pub fn setLineWidth(interface: *Interface, width: f32) VkError!void {
|
||||
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
|
||||
const allocator = self.command_allocator.allocator();
|
||||
|
||||
const CommandImpl = struct {
|
||||
const Impl = @This();
|
||||
|
||||
width: f32,
|
||||
|
||||
pub fn execute(context: *anyopaque, device: *ExecutionDevice) VkError!void {
|
||||
const impl: *Impl = @ptrCast(@alignCast(context));
|
||||
device.renderer.dynamic_state.line_width = impl.width;
|
||||
}
|
||||
};
|
||||
|
||||
const cmd = allocator.create(CommandImpl) catch return VkError.OutOfHostMemory;
|
||||
errdefer allocator.destroy(cmd);
|
||||
cmd.* = .{ .width = width };
|
||||
self.commands.append(allocator, .{ .ptr = cmd, .vtable = &.{ .execute = CommandImpl.execute } }) catch return VkError.OutOfHostMemory;
|
||||
}
|
||||
|
||||
pub fn setStencilCompareMask(interface: *Interface, face_mask: vk.StencilFaceFlags, compare_mask: u32) VkError!void {
|
||||
try setStencilDynamicState(interface, face_mask, compare_mask, .compare_mask);
|
||||
}
|
||||
|
||||
@@ -43,6 +43,11 @@ pub fn destroy(interface: *Interface, allocator: std.mem.Allocator) void {
|
||||
|
||||
pub fn getStatus(interface: *Interface) VkError!void {
|
||||
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
|
||||
const io = interface.owner.io();
|
||||
|
||||
self.mutex.lock(io) catch return VkError.DeviceLost;
|
||||
defer self.mutex.unlock(io);
|
||||
|
||||
if (!self.is_signaled) {
|
||||
return VkError.NotReady;
|
||||
}
|
||||
@@ -50,6 +55,11 @@ pub fn getStatus(interface: *Interface) VkError!void {
|
||||
|
||||
pub fn reset(interface: *Interface) VkError!void {
|
||||
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
|
||||
const io = interface.owner.io();
|
||||
|
||||
self.mutex.lock(io) catch return VkError.DeviceLost;
|
||||
defer self.mutex.unlock(io);
|
||||
|
||||
self.is_signaled = false;
|
||||
}
|
||||
|
||||
@@ -68,18 +78,34 @@ pub fn wait(interface: *Interface, timeout: u64) VkError!void {
|
||||
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
|
||||
const io = interface.owner.io();
|
||||
|
||||
if (timeout == std.math.maxInt(@TypeOf(timeout))) {
|
||||
self.mutex.lock(io) catch return VkError.DeviceLost;
|
||||
defer self.mutex.unlock(io);
|
||||
|
||||
while (!self.is_signaled) {
|
||||
self.condition.wait(io, &self.mutex) catch return VkError.DeviceLost;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const deadline = std.Io.Clock.Timestamp.fromNow(io, .{
|
||||
.raw = .fromNanoseconds(@intCast(timeout)),
|
||||
.clock = .awake,
|
||||
});
|
||||
while (true) {
|
||||
{
|
||||
self.mutex.lock(io) catch return VkError.DeviceLost;
|
||||
defer self.mutex.unlock(io);
|
||||
|
||||
if (self.is_signaled) return;
|
||||
if (timeout == 0) return VkError.Timeout;
|
||||
|
||||
if (timeout != std.math.maxInt(@TypeOf(timeout))) {
|
||||
const duration: std.Io.Clock.Duration = .{
|
||||
.raw = .fromNanoseconds(@intCast(timeout)),
|
||||
.clock = .cpu_process,
|
||||
};
|
||||
duration.sleep(io) catch return VkError.DeviceLost;
|
||||
}
|
||||
self.condition.wait(io, &self.mutex) catch return VkError.DeviceLost;
|
||||
|
||||
const remaining = deadline.durationFromNow(io);
|
||||
if (remaining.raw.nanoseconds <= 0) return VkError.Timeout;
|
||||
|
||||
(std.Io.Clock.Duration{
|
||||
.raw = .fromNanoseconds(@min(remaining.raw.nanoseconds, std.time.ns_per_ms)),
|
||||
.clock = .awake,
|
||||
}).sleep(io) catch return VkError.DeviceLost;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,7 +184,6 @@ inline fn run(data: RunData) !void {
|
||||
const workgroup_memory = try rt.createWorkgroupMemory(allocator);
|
||||
defer rt.destroyWorkgroupMemory(allocator, workgroup_memory);
|
||||
|
||||
for (0..data.invocations_per_workgroup) |i| {
|
||||
rt.resetInvocation(allocator);
|
||||
if (rt.specialization_constants.count() != 0)
|
||||
try rt.applySpecializationInvocationLayout(allocator);
|
||||
@@ -193,6 +192,9 @@ inline fn run(data: RunData) !void {
|
||||
try rt.bindWorkgroupMemory(workgroup_memory);
|
||||
try setupWorkgroupBuiltins(data.self, rt, data.local_size, group_count_vec, group_id_vec);
|
||||
|
||||
for (0..data.invocations_per_workgroup) |i| {
|
||||
rt.resetInvocation(allocator);
|
||||
|
||||
const invocation_index = data.self.invocation_index.fetchAdd(1, .monotonic);
|
||||
|
||||
try setupSubgroupBuiltins(data.self, rt, data.local_size, .{
|
||||
|
||||
@@ -45,6 +45,8 @@ pub const DynamicState = struct {
|
||||
viewports: ?[]const vk.Viewport,
|
||||
scissor: ?[]const vk.Rect2D,
|
||||
line_width: ?f32,
|
||||
depth_bias: ?DepthBias,
|
||||
depth_bounds: ?DepthBounds,
|
||||
blend_constants: ?[4]f32,
|
||||
stencil_front_compare_mask: ?u32,
|
||||
stencil_back_compare_mask: ?u32,
|
||||
@@ -54,6 +56,17 @@ pub const DynamicState = struct {
|
||||
stencil_back_reference: ?u32,
|
||||
};
|
||||
|
||||
pub const DepthBias = struct {
|
||||
constant_factor: f32,
|
||||
clamp: f32,
|
||||
slope_factor: f32,
|
||||
};
|
||||
|
||||
pub const DepthBounds = struct {
|
||||
min: f32,
|
||||
max: f32,
|
||||
};
|
||||
|
||||
pub const Vertex = struct {
|
||||
primitive_restart: bool,
|
||||
position: F32x4,
|
||||
@@ -158,6 +171,8 @@ pub fn init(device: *SoftDevice, state: *PipelineState, active_occlusion_queries
|
||||
.viewports = null,
|
||||
.scissor = null,
|
||||
.line_width = null,
|
||||
.depth_bias = null,
|
||||
.depth_bounds = null,
|
||||
.blend_constants = null,
|
||||
.stencil_front_compare_mask = null,
|
||||
.stencil_back_compare_mask = null,
|
||||
|
||||
@@ -271,7 +271,7 @@ pub fn processThenFragmentStage(renderer: *Renderer, allocator: std.mem.Allocato
|
||||
v0,
|
||||
v1,
|
||||
v2,
|
||||
v0,
|
||||
v1,
|
||||
color_attachment_access,
|
||||
if (depth_attachment_access) |*access| access else null,
|
||||
if (stencil_attachment_access) |*access| access else null,
|
||||
|
||||
@@ -26,6 +26,7 @@ const RunData = struct {
|
||||
steep: bool,
|
||||
start_vertex: *Renderer.Vertex,
|
||||
end_vertex: *Renderer.Vertex,
|
||||
provoking_vertex: *Renderer.Vertex,
|
||||
start_step: usize,
|
||||
end_step: usize,
|
||||
color_attachment_access: []const ?common.RenderTargetAccess,
|
||||
@@ -68,78 +69,183 @@ fn drawLineWithEndpointMode(
|
||||
stencil_attachment_access: ?*common.RenderTargetAccess,
|
||||
include_last_endpoint: bool,
|
||||
) VkError!void {
|
||||
const io = draw_call.renderer.device.interface.io();
|
||||
|
||||
var x0: i32 = @intFromFloat(v0.position[0]);
|
||||
var y0: i32 = @intFromFloat(@floor(v0.position[1] - 0.5));
|
||||
var x1: i32 = @intFromFloat(v1.position[0]);
|
||||
var y1: i32 = @intFromFloat(@floor(v1.position[1] - 0.5));
|
||||
|
||||
const steep = blk: {
|
||||
if (@abs(y1 - y0) > @abs(x1 - x0)) {
|
||||
std.mem.swap(i32, &x0, &y0);
|
||||
std.mem.swap(i32, &x1, &y1);
|
||||
break :blk true;
|
||||
}
|
||||
break :blk false;
|
||||
};
|
||||
|
||||
var start_vertex = v0;
|
||||
var end_vertex = v1;
|
||||
if (x0 > x1) {
|
||||
std.mem.swap(i32, &x0, &x1);
|
||||
std.mem.swap(i32, &y0, &y1);
|
||||
std.mem.swap(*Renderer.Vertex, &start_vertex, &end_vertex);
|
||||
}
|
||||
|
||||
const d_err: i32 = @intCast(@abs(y1 - y0));
|
||||
const d_x = x1 - x0;
|
||||
const y_step: i32 = if (y0 > y1) -1 else 1;
|
||||
try drawLineDiamond(
|
||||
allocator,
|
||||
draw_call,
|
||||
v0,
|
||||
v1,
|
||||
color_attachment_access,
|
||||
depth_attachment_access,
|
||||
stencil_attachment_access,
|
||||
include_last_endpoint,
|
||||
);
|
||||
}
|
||||
|
||||
fn drawLineDiamond(
|
||||
allocator: std.mem.Allocator,
|
||||
draw_call: *Renderer.DrawCall,
|
||||
v0: *Renderer.Vertex,
|
||||
v1: *Renderer.Vertex,
|
||||
color_attachment_access: []const ?common.RenderTargetAccess,
|
||||
depth_attachment_access: ?*common.RenderTargetAccess,
|
||||
stencil_attachment_access: ?*common.RenderTargetAccess,
|
||||
include_last_endpoint: bool,
|
||||
) VkError!void {
|
||||
const pipeline = draw_call.renderer.state.pipeline orelse return;
|
||||
const fragment_stage = pipeline.stages.getPtr(.fragment);
|
||||
const runtimes_count = if (fragment_stage) |stage| stage.runtimes.len else 1;
|
||||
if (runtimes_count == 0)
|
||||
return;
|
||||
const has_fragment_shader = fragment_stage != null;
|
||||
const batch_id: usize = 0;
|
||||
|
||||
const step_count: usize = @intCast(if (include_last_endpoint) @max(d_x, 0) + 1 else @max(d_x, 1));
|
||||
const runs_count = @min(runtimes_count, step_count);
|
||||
const steps_per_run = @divTrunc(step_count + runs_count - 1, runs_count);
|
||||
const min_x: i32 = @intFromFloat(@floor(@min(v0.position[0], v1.position[0]) - 1.0));
|
||||
const max_x: i32 = @intFromFloat(@ceil(@max(v0.position[0], v1.position[0]) + 1.0));
|
||||
const min_y: i32 = @intFromFloat(@floor(@min(v0.position[1], v1.position[1]) - 1.0));
|
||||
const max_y: i32 = @intFromFloat(@ceil(@max(v0.position[1], v1.position[1]) + 1.0));
|
||||
|
||||
var batch_id: usize = 0;
|
||||
for (0..runs_count) |run_index| {
|
||||
defer batch_id = @mod(batch_id + 1, runtimes_count);
|
||||
|
||||
const start_step = run_index * steps_per_run;
|
||||
if (start_step >= step_count)
|
||||
var y = min_y;
|
||||
while (y <= max_y) : (y += 1) {
|
||||
var x = min_x;
|
||||
while (x <= max_x) : (x += 1) {
|
||||
if (!common.scissorContainsPixel(draw_call.scissor, x, y))
|
||||
continue;
|
||||
|
||||
const end_step = @min(start_step + steps_per_run - 1, step_count - 1);
|
||||
const coverage = diamondCoverage(v0.position, v1.position, x, y, include_last_endpoint);
|
||||
const t = coverage orelse continue;
|
||||
const z = ((1.0 - t) * v0.position[2]) + (t * v1.position[2]);
|
||||
const frag_w = ((1.0 - t) / v0.position[3]) + (t / v1.position[3]);
|
||||
|
||||
const run_data: RunData = .{
|
||||
.allocator = allocator,
|
||||
.draw_call = draw_call,
|
||||
.batch_id = batch_id,
|
||||
.x0 = x0,
|
||||
.y0 = y0,
|
||||
.d_x = d_x,
|
||||
.d_err = d_err,
|
||||
.y_step = y_step,
|
||||
.steep = steep,
|
||||
.start_vertex = start_vertex,
|
||||
.end_vertex = end_vertex,
|
||||
.start_step = start_step,
|
||||
.end_step = end_step,
|
||||
.color_attachment_access = color_attachment_access,
|
||||
.depth_attachment_access = depth_attachment_access,
|
||||
.stencil_attachment_access = stencil_attachment_access,
|
||||
.has_fragment_shader = fragment_stage != null,
|
||||
var fragment_result: fragment.InvocationResult = .{
|
||||
.outputs = std.mem.zeroes([spv.SPIRV_MAX_OUTPUT_LOCATIONS][@sizeOf(F32x4)]u8),
|
||||
.depth = null,
|
||||
.sample_mask = null,
|
||||
};
|
||||
if (has_fragment_shader) {
|
||||
fragment_result = fragment.shaderInvocation(
|
||||
allocator,
|
||||
draw_call,
|
||||
batch_id,
|
||||
zm.f32x4(@as(f32, @floatFromInt(x)) + 0.5, @as(f32, @floatFromInt(y)) + 0.5, z, frag_w),
|
||||
null,
|
||||
null,
|
||||
true,
|
||||
try common.interpolateLineOutputs(allocator, v0, v1, v0, t),
|
||||
null,
|
||||
) catch |err| {
|
||||
if (err == SpvRuntimeError.Killed)
|
||||
continue;
|
||||
|
||||
draw_call.rasterizer_wait_group.async(io, runWrapper, .{run_data});
|
||||
std.log.scoped(.@"Fragment stage").err("catched a '{s}'", .{@errorName(err)});
|
||||
if (comptime base.config.logs == .verbose) {
|
||||
if (@errorReturnTrace()) |trace| {
|
||||
std.debug.dumpErrorReturnTrace(trace);
|
||||
}
|
||||
}
|
||||
return;
|
||||
};
|
||||
}
|
||||
|
||||
draw_call.rasterizer_wait_group.await(io) catch return VkError.DeviceLost;
|
||||
try common.writeToTargets(
|
||||
fragment_result.outputs,
|
||||
draw_call,
|
||||
color_attachment_access,
|
||||
depth_attachment_access,
|
||||
stencil_attachment_access,
|
||||
true,
|
||||
@intCast(x),
|
||||
@intCast(y),
|
||||
fragment_result.depth orelse z,
|
||||
lineCoverageMaskFloat(
|
||||
v0.position,
|
||||
v1.position,
|
||||
x,
|
||||
y,
|
||||
pipeline.interface.mode.graphics.multisample.rasterization_samples.toInt(),
|
||||
),
|
||||
fragment_result.sample_mask,
|
||||
false,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn diamondCoverage(a: F32x4, b: F32x4, pixel_x: i32, pixel_y: i32, include_last_endpoint: bool) ?f32 {
|
||||
const cx = @as(f32, @floatFromInt(pixel_x)) + 0.5;
|
||||
const cy = @as(f32, @floatFromInt(pixel_y)) + 0.5;
|
||||
const clipped = clipSegmentToDiamond(a[0], a[1], b[0], b[1], cx, cy) orelse return null;
|
||||
if (!include_last_endpoint and a[3] == 1.0 and b[3] == 1.0 and clipped.min_t <= 0.0)
|
||||
return null;
|
||||
if (!include_last_endpoint and clipped.min_t >= 1.0)
|
||||
return null;
|
||||
return std.math.clamp((clipped.min_t + clipped.max_t) * 0.5, 0.0, 1.0);
|
||||
}
|
||||
|
||||
fn clipSegmentToDiamond(ax: f32, ay: f32, bx: f32, by: f32, cx: f32, cy: f32) ?struct { min_t: f32, max_t: f32 } {
|
||||
var min_t: f32 = 0.0;
|
||||
var max_t: f32 = 1.0;
|
||||
const dx = bx - ax;
|
||||
const dy = by - ay;
|
||||
|
||||
const normals = [_]struct { nx: f32, ny: f32 }{
|
||||
.{ .nx = 1.0, .ny = 1.0 },
|
||||
.{ .nx = 1.0, .ny = -1.0 },
|
||||
.{ .nx = -1.0, .ny = 1.0 },
|
||||
.{ .nx = -1.0, .ny = -1.0 },
|
||||
};
|
||||
|
||||
for (normals) |normal| {
|
||||
const origin_distance = normal.nx * (ax - cx) + normal.ny * (ay - cy) - 0.5;
|
||||
const delta_distance = normal.nx * dx + normal.ny * dy;
|
||||
if (delta_distance == 0.0) {
|
||||
if (origin_distance > 0.0)
|
||||
return null;
|
||||
continue;
|
||||
}
|
||||
|
||||
const t = -origin_distance / delta_distance;
|
||||
if (delta_distance > 0.0) {
|
||||
max_t = @min(max_t, t);
|
||||
} else {
|
||||
min_t = @max(min_t, t);
|
||||
}
|
||||
if (min_t > max_t)
|
||||
return null;
|
||||
}
|
||||
|
||||
return .{ .min_t = min_t, .max_t = max_t };
|
||||
}
|
||||
|
||||
fn lineCoverageMaskFloat(a: F32x4, b: F32x4, pixel_x: i32, pixel_y: i32, sample_count: usize) vk.SampleMask {
|
||||
if (sample_count <= 1)
|
||||
return 1;
|
||||
|
||||
const ab_x = b[0] - a[0];
|
||||
const ab_y = b[1] - a[1];
|
||||
const ab_len2 = ab_x * ab_x + ab_y * ab_y;
|
||||
if (ab_len2 == 0.0)
|
||||
return 1;
|
||||
|
||||
var mask: vk.SampleMask = 0;
|
||||
for (0..sample_count) |sample_index| {
|
||||
if (sample_index >= @bitSizeOf(vk.SampleMask))
|
||||
break;
|
||||
|
||||
const sample_pos = standardSamplePosition(sample_count, sample_index);
|
||||
const sample_x = @as(f32, @floatFromInt(pixel_x)) + sample_pos.x;
|
||||
const sample_y = @as(f32, @floatFromInt(pixel_y)) + sample_pos.y;
|
||||
const ap_x = sample_x - a[0];
|
||||
const ap_y = sample_y - a[1];
|
||||
const t = std.math.clamp(((ap_x * ab_x) + (ap_y * ab_y)) / ab_len2, 0.0, 1.0);
|
||||
const closest_x = a[0] + ab_x * t;
|
||||
const closest_y = a[1] + ab_y * t;
|
||||
const dx = sample_x - closest_x;
|
||||
const dy = sample_y - closest_y;
|
||||
|
||||
if (dx * dx + dy * dy <= 0.25) {
|
||||
const bit_index: u5 = @intCast(sample_index);
|
||||
mask |= @as(vk.SampleMask, 1) << bit_index;
|
||||
}
|
||||
}
|
||||
|
||||
return if (mask == 0) 1 else mask;
|
||||
}
|
||||
|
||||
fn bresenhamYAtStep(y0: i32, d_x: i32, d_err: i32, y_step: i32, step: usize) i32 {
|
||||
@@ -249,7 +355,7 @@ inline fn run(data: RunData) !void {
|
||||
null,
|
||||
null,
|
||||
true,
|
||||
try common.interpolateLineOutputs(data.allocator, data.start_vertex, data.end_vertex, t),
|
||||
try common.interpolateLineOutputs(data.allocator, data.start_vertex, data.end_vertex, data.provoking_vertex, t),
|
||||
null,
|
||||
) catch |err| {
|
||||
if (err == SpvRuntimeError.Killed)
|
||||
|
||||
@@ -31,6 +31,27 @@ pub const VertexInterpolation = struct {
|
||||
|
||||
pub const VertexInterpolationLocation = [4]VertexInterpolation;
|
||||
|
||||
pub fn depthBiasConstantUnit(format: vk.Format, z: f32) f32 {
|
||||
return switch (format) {
|
||||
.d16_unorm => 1.0 / @as(f32, @floatFromInt(std.math.maxInt(u16))),
|
||||
.x8_d24_unorm_pack32,
|
||||
.d24_unorm_s8_uint,
|
||||
=> 1.0 / @as(f32, @floatFromInt(0x00ff_ffff)),
|
||||
.d32_sfloat,
|
||||
.d32_sfloat_s8_uint,
|
||||
=> if (z > 0.0) std.math.pow(f32, 2.0, @floor(@log2(z)) - 23.0) else 0.0,
|
||||
else => 0.0,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn clampDepthBias(bias: f32, clamp: f32) f32 {
|
||||
if (clamp > 0.0)
|
||||
return @min(bias, clamp);
|
||||
if (clamp < 0.0)
|
||||
return @max(bias, clamp);
|
||||
return bias;
|
||||
}
|
||||
|
||||
pub fn scissorContainsPixel(scissor: vk.Rect2D, x: i32, y: i32) bool {
|
||||
const min_x: i64 = @as(i64, scissor.offset.x);
|
||||
const min_y: i64 = @as(i64, scissor.offset.y);
|
||||
@@ -172,6 +193,20 @@ pub fn depthTestAndUpdate(depth: *RenderTargetAccess, x: usize, y: usize, z: f32
|
||||
return depthTestAndUpdateAtOffset(depth, offset, z, state);
|
||||
}
|
||||
|
||||
pub fn resolveDepthStencilState(draw_call: *Renderer.DrawCall, state: vk.PipelineDepthStencilStateCreateInfo) vk.PipelineDepthStencilStateCreateInfo {
|
||||
var resolved = state;
|
||||
const pipeline_data = draw_call.renderer.state.pipeline.?.interface.mode.graphics;
|
||||
if (pipeline_data.dynamic_state.depth_bounds) {
|
||||
const bounds = draw_call.renderer.dynamic_state.depth_bounds orelse Renderer.DepthBounds{
|
||||
.min = 0.0,
|
||||
.max = 1.0,
|
||||
};
|
||||
resolved.min_depth_bounds = bounds.min;
|
||||
resolved.max_depth_bounds = bounds.max;
|
||||
}
|
||||
return resolved;
|
||||
}
|
||||
|
||||
pub fn depthTestSampleAndUpdate(
|
||||
io: std.Io,
|
||||
depth: *RenderTargetAccess,
|
||||
@@ -198,10 +233,14 @@ pub fn depthTestSampleAndUpdate(
|
||||
}
|
||||
|
||||
fn depthTestAndUpdateAtOffset(depth: *RenderTargetAccess, offset: usize, z: f32, state: vk.PipelineDepthStencilStateCreateInfo) bool {
|
||||
const reference = quantizeDepthForFormat(depth.format, z);
|
||||
if (state.depth_bounds_test_enable == .true and
|
||||
(reference < state.min_depth_bounds or reference > state.max_depth_bounds))
|
||||
return false;
|
||||
|
||||
if (state.depth_test_enable == .false)
|
||||
return true;
|
||||
|
||||
const reference = quantizeDepthForFormat(depth.format, z);
|
||||
const depth_value = blitter.readFloat4(depth.base[offset..], depth.format);
|
||||
const passed = compare(f32, state.depth_compare_op, reference, depth_value[0]);
|
||||
if (passed and state.depth_write_enable == .true)
|
||||
@@ -287,9 +326,10 @@ pub fn interpolateLineOutputs(
|
||||
allocator: std.mem.Allocator,
|
||||
v0: *const Renderer.Vertex,
|
||||
v1: *const Renderer.Vertex,
|
||||
provoking_vertex: *const Renderer.Vertex,
|
||||
t: f32,
|
||||
) VkError![spv.SPIRV_MAX_OUTPUT_LOCATIONS]VertexInterpolationLocation {
|
||||
return interpolateVertexOutputs(allocator, v0, v1, v0, v0, 1.0 - t, t, 0.0);
|
||||
return interpolateVertexOutputs(allocator, v0, v1, v0, provoking_vertex, 1.0 - t, t, 0.0);
|
||||
}
|
||||
|
||||
pub fn interpolateVertexOutputDerivatives(
|
||||
@@ -506,7 +546,7 @@ pub fn writeToTargets(
|
||||
) VkError!void {
|
||||
const io = draw_call.renderer.device.interface.io();
|
||||
const pipeline_data = draw_call.renderer.state.pipeline.?.interface.mode.graphics;
|
||||
const depth_stencil_state = pipeline_data.depth_stencil;
|
||||
const depth_stencil_state = if (pipeline_data.depth_stencil) |state| resolveDepthStencilState(draw_call, state) else null;
|
||||
const effective_fragment_sample_mask = alphaToCoverageMask(
|
||||
pipeline_data.multisample,
|
||||
outputs,
|
||||
|
||||
@@ -40,6 +40,7 @@ const RunData = struct {
|
||||
fragment_uses_derivatives: bool,
|
||||
fragment_uses_sample_id: bool,
|
||||
fragment_uses_centroid: bool,
|
||||
depth_bias_slope: f32,
|
||||
};
|
||||
|
||||
pub fn drawTriangle(
|
||||
@@ -64,6 +65,16 @@ pub fn drawTriangle(
|
||||
const area = edgeFunction(v0.position, v1.position, v2.position);
|
||||
if (area == 0.0)
|
||||
return;
|
||||
const inv_area = 1.0 / area;
|
||||
const dz_dx =
|
||||
(v0.position[2] * ((v1.position[1] - v2.position[1]) * inv_area)) +
|
||||
(v1.position[2] * ((v2.position[1] - v0.position[1]) * inv_area)) +
|
||||
(v2.position[2] * ((v0.position[1] - v1.position[1]) * inv_area));
|
||||
const dz_dy =
|
||||
(v0.position[2] * ((v2.position[0] - v1.position[0]) * inv_area)) +
|
||||
(v1.position[2] * ((v0.position[0] - v2.position[0]) * inv_area)) +
|
||||
(v2.position[2] * ((v1.position[0] - v0.position[0]) * inv_area));
|
||||
const depth_bias_slope = @max(@abs(dz_dx), @abs(dz_dy));
|
||||
|
||||
const pipeline = draw_call.renderer.state.pipeline orelse return;
|
||||
const fragment_stage = pipeline.stages.getPtr(.fragment);
|
||||
@@ -139,6 +150,7 @@ pub fn drawTriangle(
|
||||
.fragment_uses_derivatives = fragment_uses_derivatives,
|
||||
.fragment_uses_sample_id = fragment_uses_sample_id,
|
||||
.fragment_uses_centroid = fragment_uses_centroid,
|
||||
.depth_bias_slope = depth_bias_slope,
|
||||
};
|
||||
|
||||
draw_call.rasterizer_wait_group.async(io, runWrapper, .{run_data});
|
||||
@@ -250,6 +262,7 @@ fn applyEarlyDepth(data: RunData, coverage_sample_mask: vk.SampleMask, x: i32, y
|
||||
|
||||
const depth = data.depth_attachment_access orelse return .{ .mask = coverage_sample_mask, .applied = false };
|
||||
const pipeline_data = data.draw_call.renderer.state.pipeline.?.interface.mode.graphics;
|
||||
const depth_stencil_state = if (pipeline_data.depth_stencil) |state| common.resolveDepthStencilState(data.draw_call, state) else null;
|
||||
const io = data.draw_call.renderer.device.interface.io();
|
||||
|
||||
var passed_mask: vk.SampleMask = 0;
|
||||
@@ -261,13 +274,38 @@ fn applyEarlyDepth(data: RunData, coverage_sample_mask: vk.SampleMask, x: i32, y
|
||||
if ((coverage_sample_mask & bit) == 0)
|
||||
continue;
|
||||
|
||||
if (try common.depthTestSampleAndUpdate(io, depth, @intCast(x), @intCast(y), sample_index, z, pipeline_data.depth_stencil))
|
||||
if (try common.depthTestSampleAndUpdate(io, depth, @intCast(x), @intCast(y), sample_index, z, depth_stencil_state))
|
||||
passed_mask |= bit;
|
||||
}
|
||||
|
||||
return .{ .mask = passed_mask, .applied = true };
|
||||
}
|
||||
|
||||
fn biasedDepth(data: RunData, z: f32) f32 {
|
||||
const pipeline_data = data.draw_call.renderer.state.pipeline.?.interface.mode.graphics;
|
||||
if (pipeline_data.rasterization.depth_bias_enable == .false)
|
||||
return z;
|
||||
|
||||
const depth = data.depth_attachment_access orelse return z;
|
||||
const bias_state: Renderer.DepthBias = if (pipeline_data.dynamic_state.depth_bias)
|
||||
data.draw_call.renderer.dynamic_state.depth_bias orelse Renderer.DepthBias{
|
||||
.constant_factor = 0.0,
|
||||
.clamp = 0.0,
|
||||
.slope_factor = 0.0,
|
||||
}
|
||||
else
|
||||
Renderer.DepthBias{
|
||||
.constant_factor = pipeline_data.rasterization.depth_bias_constant_factor,
|
||||
.clamp = pipeline_data.rasterization.depth_bias_clamp,
|
||||
.slope_factor = pipeline_data.rasterization.depth_bias_slope_factor,
|
||||
};
|
||||
|
||||
const bias =
|
||||
bias_state.constant_factor * common.depthBiasConstantUnit(depth.format, z) +
|
||||
bias_state.slope_factor * data.depth_bias_slope;
|
||||
return z + common.clampDepthBias(bias, bias_state.clamp);
|
||||
}
|
||||
|
||||
fn runWrapper(data: RunData) void {
|
||||
@call(.always_inline, run, .{data}) catch |err| {
|
||||
std.log.scoped(.@"Rasterization stage").err("triangle fill mode catched a '{s}'", .{@errorName(err)});
|
||||
@@ -304,8 +342,9 @@ inline fn run(data: RunData) !void {
|
||||
const b1 = w1 / 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 depth_z = biasedDepth(data, z);
|
||||
const frag_w = (b0 / data.v0.position[3]) + (b1 / data.v1.position[3]) + (b2 / data.v2.position[3]);
|
||||
const early_depth = try applyEarlyDepth(data, coverage_sample_mask, x, y, z, sample_count);
|
||||
const early_depth = try applyEarlyDepth(data, coverage_sample_mask, x, y, depth_z, sample_count);
|
||||
if (early_depth.mask == 0)
|
||||
continue;
|
||||
|
||||
@@ -378,7 +417,7 @@ inline fn run(data: RunData) !void {
|
||||
data.front_face,
|
||||
@intCast(x),
|
||||
@intCast(y),
|
||||
sample_result.depth orelse z,
|
||||
sample_result.depth orelse depth_z,
|
||||
sample_coverage_mask,
|
||||
sample_result.sample_mask,
|
||||
early_depth.applied,
|
||||
@@ -460,7 +499,7 @@ inline fn run(data: RunData) !void {
|
||||
data.front_face,
|
||||
@intCast(x),
|
||||
@intCast(y),
|
||||
fragment_result.depth orelse z,
|
||||
fragment_result.depth orelse depth_z,
|
||||
early_depth.mask,
|
||||
fragment_result.sample_mask,
|
||||
early_depth.applied,
|
||||
|
||||
@@ -78,7 +78,10 @@ pub const DispatchTable = struct {
|
||||
resolveImage: *const fn (*Self, *Image, vk.ImageLayout, *Image, vk.ImageLayout, vk.ImageResolve) VkError!void,
|
||||
setEvent: *const fn (*Self, *Event, vk.PipelineStageFlags) VkError!void,
|
||||
setBlendConstants: *const fn (*Self, [4]f32) VkError!void,
|
||||
setDepthBias: *const fn (*Self, f32, f32, f32) VkError!void,
|
||||
setDepthBounds: *const fn (*Self, f32, f32) VkError!void,
|
||||
setDeviceMask: *const fn (*Self, u32) VkError!void,
|
||||
setLineWidth: *const fn (*Self, f32) VkError!void,
|
||||
setScissor: *const fn (*Self, u32, []const vk.Rect2D) VkError!void,
|
||||
setStencilCompareMask: *const fn (*Self, vk.StencilFaceFlags, u32) VkError!void,
|
||||
setStencilReference: *const fn (*Self, vk.StencilFaceFlags, u32) VkError!void,
|
||||
@@ -86,6 +89,7 @@ pub const DispatchTable = struct {
|
||||
setViewport: *const fn (*Self, u32, []const vk.Viewport) VkError!void,
|
||||
updateBuffer: *const fn (*Self, *Buffer, vk.DeviceSize, []const u8) VkError!void,
|
||||
waitEvent: *const fn (*Self, *Event, vk.PipelineStageFlags, vk.PipelineStageFlags, []const vk.MemoryBarrier, []const vk.BufferMemoryBarrier, []const vk.ImageMemoryBarrier) VkError!void,
|
||||
writeTimestamp: *const fn (*Self, vk.PipelineStageFlags, *QueryPool, u32) VkError!void,
|
||||
};
|
||||
|
||||
pub const VTable = struct {
|
||||
@@ -338,6 +342,14 @@ pub inline fn setBlendConstants(self: *Self, constants: [4]f32) VkError!void {
|
||||
try self.dispatch_table.setBlendConstants(self, constants);
|
||||
}
|
||||
|
||||
pub inline fn setDepthBias(self: *Self, constant_factor: f32, clamp: f32, slope_factor: f32) VkError!void {
|
||||
try self.dispatch_table.setDepthBias(self, constant_factor, clamp, slope_factor);
|
||||
}
|
||||
|
||||
pub inline fn setDepthBounds(self: *Self, min: f32, max: f32) VkError!void {
|
||||
try self.dispatch_table.setDepthBounds(self, min, max);
|
||||
}
|
||||
|
||||
pub inline fn setDeviceMask(self: *Self, device_mask: u32) VkError!void {
|
||||
if (device_mask != 1)
|
||||
return VkError.ValidationFailed;
|
||||
@@ -345,6 +357,10 @@ pub inline fn setDeviceMask(self: *Self, device_mask: u32) VkError!void {
|
||||
try self.dispatch_table.setDeviceMask(self, device_mask);
|
||||
}
|
||||
|
||||
pub inline fn setLineWidth(self: *Self, width: f32) VkError!void {
|
||||
try self.dispatch_table.setLineWidth(self, width);
|
||||
}
|
||||
|
||||
pub inline fn setScissor(self: *Self, first: u32, scissor: []const vk.Rect2D) VkError!void {
|
||||
try self.dispatch_table.setScissor(self, first, scissor);
|
||||
}
|
||||
@@ -376,3 +392,7 @@ pub inline fn waitEvent(
|
||||
) VkError!void {
|
||||
try self.dispatch_table.waitEvent(self, event, src_stage, dst_stage, memory_barriers, buffer_barriers, image_barriers);
|
||||
}
|
||||
|
||||
pub inline fn writeTimestamp(self: *Self, stage: vk.PipelineStageFlags, pool: *QueryPool, query: u32) VkError!void {
|
||||
try self.dispatch_table.writeTimestamp(self, stage, pool, query);
|
||||
}
|
||||
|
||||
@@ -48,3 +48,41 @@ pub inline fn signal(self: *Self) VkError!void {
|
||||
pub inline fn wait(self: *Self, timeout: u64) VkError!void {
|
||||
try self.vtable.wait(self, timeout);
|
||||
}
|
||||
|
||||
pub fn waitMany(device: *Device, fences: []const *Self, wait_for_all: vk.Bool32, timeout: u64) VkError!void {
|
||||
const forever = timeout == std.math.maxInt(@TypeOf(timeout));
|
||||
const io = device.io();
|
||||
const deadline = if (forever) null else std.Io.Clock.Timestamp.fromNow(io, .{
|
||||
.raw = .fromNanoseconds(@intCast(timeout)),
|
||||
.clock = .awake,
|
||||
});
|
||||
|
||||
while (true) {
|
||||
var signaled_count: usize = 0;
|
||||
for (fences) |fence| {
|
||||
if (fence.owner != device) return VkError.InvalidHandleDrv;
|
||||
|
||||
fence.getStatus() catch |err| switch (err) {
|
||||
VkError.NotReady => continue,
|
||||
else => return err,
|
||||
};
|
||||
|
||||
if (wait_for_all == .false) return;
|
||||
signaled_count += 1;
|
||||
}
|
||||
|
||||
if (signaled_count == fences.len) return;
|
||||
if (timeout == 0) return VkError.Timeout;
|
||||
|
||||
const sleep_ns = if (deadline) |value| blk: {
|
||||
const remaining = value.durationFromNow(io);
|
||||
if (remaining.raw.nanoseconds <= 0) return VkError.Timeout;
|
||||
break :blk @min(remaining.raw.nanoseconds, std.time.ns_per_ms);
|
||||
} else std.time.ns_per_ms;
|
||||
|
||||
(std.Io.Clock.Duration{
|
||||
.raw = .fromNanoseconds(sleep_ns),
|
||||
.clock = .awake,
|
||||
}).sleep(io) catch return VkError.DeviceLost;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,6 +49,10 @@ mode: union(enum) {
|
||||
cull_mode: vk.CullModeFlags,
|
||||
front_face: vk.FrontFace,
|
||||
line_width: f32,
|
||||
depth_bias_enable: vk.Bool32,
|
||||
depth_bias_constant_factor: f32,
|
||||
depth_bias_clamp: f32,
|
||||
depth_bias_slope_factor: f32,
|
||||
},
|
||||
multisample: struct {
|
||||
rasterization_samples: vk.SampleCountFlags,
|
||||
@@ -194,6 +198,10 @@ pub fn initGraphics(device: *Device, allocator: std.mem.Allocator, cache: ?*Pipe
|
||||
.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,
|
||||
.line_width = if (info.p_rasterization_state) |state| state.line_width else return VkError.ValidationFailed,
|
||||
.depth_bias_enable = if (info.p_rasterization_state) |state| state.depth_bias_enable else return VkError.ValidationFailed,
|
||||
.depth_bias_constant_factor = if (info.p_rasterization_state) |state| state.depth_bias_constant_factor else return VkError.ValidationFailed,
|
||||
.depth_bias_clamp = if (info.p_rasterization_state) |state| state.depth_bias_clamp else return VkError.ValidationFailed,
|
||||
.depth_bias_slope_factor = if (info.p_rasterization_state) |state| state.depth_bias_slope_factor else return VkError.ValidationFailed,
|
||||
},
|
||||
.multisample = blk: {
|
||||
if (rasterizer_discard_enable) {
|
||||
|
||||
@@ -69,6 +69,16 @@ pub fn end(self: *Self, query: u32) VkError!void {
|
||||
q.available = true;
|
||||
}
|
||||
|
||||
pub fn writeTimestamp(self: *Self, query: u32, value: u64) VkError!void {
|
||||
if (self.query_type != .timestamp)
|
||||
return VkError.ValidationFailed;
|
||||
|
||||
const q = try self.queryAt(query);
|
||||
q.value.store(value, .seq_cst);
|
||||
q.available = true;
|
||||
q.active = false;
|
||||
}
|
||||
|
||||
pub fn addSamples(self: *Self, query: u32, samples: u64) VkError!void {
|
||||
const q = try self.queryAt(query);
|
||||
if (q.active)
|
||||
|
||||
+18
-36
@@ -1434,13 +1434,11 @@ pub export fn apeGetDeviceMemoryCommitment(p_device: vk.Device, p_memory: vk.Dev
|
||||
defer entryPointEndLogTrace();
|
||||
|
||||
const device = Dispatchable(Device).fromHandleObject(p_device) catch |err| return errorLogger(err);
|
||||
const memory = Dispatchable(DeviceMemory).fromHandleObject(p_memory) catch |err| return errorLogger(err);
|
||||
const memory = NonDispatchable(DeviceMemory).fromHandleObject(p_memory) catch |err| return errorLogger(err);
|
||||
if (memory.owner != device)
|
||||
return errorLogger(VkError.InvalidHandleDrv);
|
||||
|
||||
notImplementedWarning();
|
||||
|
||||
_ = device;
|
||||
_ = memory;
|
||||
_ = committed_memory;
|
||||
committed_memory.* = memory.size;
|
||||
}
|
||||
|
||||
pub export fn apeGetDeviceGroupPeerMemoryFeatures(
|
||||
@@ -1759,13 +1757,17 @@ pub export fn apeWaitForFences(p_device: vk.Device, count: u32, p_fences: [*]con
|
||||
entryPointBeginLogTrace(.vkWaitForFences);
|
||||
defer entryPointEndLogTrace();
|
||||
|
||||
Dispatchable(Device).checkHandleValidity(p_device) catch |err| return toVkResult(err);
|
||||
const device = Dispatchable(Device).fromHandleObject(p_device) catch |err| return toVkResult(err);
|
||||
|
||||
for (p_fences, 0..count) |p_fence, _| {
|
||||
const fence = NonDispatchable(Fence).fromHandleObject(p_fence) catch |err| return toVkResult(err);
|
||||
fence.wait(timeout) catch |err| return toVkResult(err);
|
||||
if (waitForAll == .false) break;
|
||||
const allocator = VulkanAllocator.init(null, .command).allocator();
|
||||
const fences = allocator.alloc(*Fence, count) catch return toVkResult(VkError.OutOfHostMemory);
|
||||
defer allocator.free(fences);
|
||||
|
||||
for (p_fences[0..count], fences) |p_fence, *fence| {
|
||||
fence.* = NonDispatchable(Fence).fromHandleObject(p_fence) catch |err| return toVkResult(err);
|
||||
}
|
||||
|
||||
Fence.waitMany(device, fences, waitForAll, timeout) catch |err| return toVkResult(err);
|
||||
return .success;
|
||||
}
|
||||
|
||||
@@ -2152,13 +2154,7 @@ pub export fn apeCmdSetDepthBias(p_cmd: vk.CommandBuffer, constant_factor: f32,
|
||||
defer entryPointEndLogTrace();
|
||||
|
||||
const cmd = Dispatchable(CommandBuffer).fromHandleObject(p_cmd) catch |err| return errorLogger(err);
|
||||
|
||||
notImplementedWarning();
|
||||
|
||||
_ = cmd;
|
||||
_ = constant_factor;
|
||||
_ = clamp;
|
||||
_ = slope_factor;
|
||||
cmd.setDepthBias(constant_factor, clamp, slope_factor) catch |err| return errorLogger(err);
|
||||
}
|
||||
|
||||
pub export fn apeCmdSetDepthBounds(p_cmd: vk.CommandBuffer, min: f32, max: f32) callconv(vk.vulkan_call_conv) void {
|
||||
@@ -2166,12 +2162,7 @@ pub export fn apeCmdSetDepthBounds(p_cmd: vk.CommandBuffer, min: f32, max: f32)
|
||||
defer entryPointEndLogTrace();
|
||||
|
||||
const cmd = Dispatchable(CommandBuffer).fromHandleObject(p_cmd) catch |err| return errorLogger(err);
|
||||
|
||||
notImplementedWarning();
|
||||
|
||||
_ = cmd;
|
||||
_ = min;
|
||||
_ = max;
|
||||
cmd.setDepthBounds(min, max) catch |err| return errorLogger(err);
|
||||
}
|
||||
|
||||
pub export fn apeCmdSetDeviceMask(p_cmd: vk.CommandBuffer, device_mask: u32) callconv(vk.vulkan_call_conv) void {
|
||||
@@ -2200,11 +2191,7 @@ pub export fn apeCmdSetLineWidth(p_cmd: vk.CommandBuffer, width: f32) callconv(v
|
||||
defer entryPointEndLogTrace();
|
||||
|
||||
const cmd = Dispatchable(CommandBuffer).fromHandleObject(p_cmd) catch |err| return errorLogger(err);
|
||||
|
||||
notImplementedWarning();
|
||||
|
||||
_ = cmd;
|
||||
_ = width;
|
||||
cmd.setLineWidth(width) catch |err| return errorLogger(err);
|
||||
}
|
||||
|
||||
pub export fn apeCmdSetScissor(p_cmd: vk.CommandBuffer, first: u32, count: u32, scissors: [*]const vk.Rect2D) callconv(vk.vulkan_call_conv) void {
|
||||
@@ -2292,13 +2279,8 @@ pub export fn apeCmdWriteTimestamp(p_cmd: vk.CommandBuffer, stage: vk.PipelineSt
|
||||
defer entryPointEndLogTrace();
|
||||
|
||||
const cmd = Dispatchable(CommandBuffer).fromHandleObject(p_cmd) catch |err| return errorLogger(err);
|
||||
|
||||
notImplementedWarning();
|
||||
|
||||
_ = cmd;
|
||||
_ = stage;
|
||||
_ = p_pool;
|
||||
_ = query;
|
||||
const pool = NonDispatchable(QueryPool).fromHandleObject(p_pool) catch |err| return errorLogger(err);
|
||||
cmd.writeTimestamp(stage, pool, query) catch |err| return errorLogger(err);
|
||||
}
|
||||
|
||||
pub export fn apeEndCommandBuffer(p_cmd: vk.CommandBuffer) callconv(vk.vulkan_call_conv) vk.Result {
|
||||
|
||||
Reference in New Issue
Block a user