fixing all image operation tests
Test / build_and_test (push) Successful in 26s
Build / build (push) Successful in 1m3s

This commit is contained in:
2026-06-01 22:13:43 +02:00
parent 19c8d84e05
commit 6dc82d4a68
14 changed files with 514 additions and 132 deletions
+84 -4
View File
@@ -106,8 +106,28 @@ inline fn run(data: RunData) !void {
const rt = &shader.runtimes[data.batch_id].rt;
const entry = try rt.getEntryPointByName(shader.entry);
const uses_control_barrier = hasControlBarrier(rt.mod.code);
try ExecutionDevice.writeDescriptorSets(data.self.state, rt);
var barrier_runtimes: []spv.Runtime = &.{};
var barrier_statuses: []spv.Runtime.EntryPointStatus = &.{};
if (uses_control_barrier) {
barrier_runtimes = try allocator.alloc(spv.Runtime, data.invocations_per_workgroup);
barrier_statuses = try allocator.alloc(spv.Runtime.EntryPointStatus, data.invocations_per_workgroup);
for (barrier_runtimes) |*barrier_rt| {
barrier_rt.* = try spv.Runtime.init(allocator, rt.mod, rt.image_api);
try barrier_rt.copySpecializationConstantsFrom(allocator, rt);
}
}
defer {
for (barrier_runtimes) |*barrier_rt| {
barrier_rt.deinit(allocator);
}
allocator.free(barrier_runtimes);
allocator.free(barrier_statuses);
}
if (!uses_control_barrier)
try ExecutionDevice.writeDescriptorSets(data.self.state, rt);
var group_index: usize = data.batch_id;
while (group_index < data.group_count) : (group_index += data.self.batch_size) {
@@ -121,15 +141,23 @@ inline fn run(data: RunData) !void {
modulo -= group_y * data.group_count_x;
const group_x = modulo;
try setupWorkgroupBuiltins(data.self, rt, .{
const group_count_vec = @Vector(3, u32){
@as(u32, @intCast(data.group_count_x)),
@as(u32, @intCast(data.group_count_y)),
@as(u32, @intCast(data.group_count_z)),
}, .{
};
const group_id_vec = @Vector(3, u32){
@as(u32, @intCast(group_x)),
@as(u32, @intCast(group_y)),
@as(u32, @intCast(group_z)),
});
};
if (uses_control_barrier) {
try runBarrierWorkgroup(data, barrier_runtimes, barrier_statuses, entry, group_count_vec, group_id_vec);
continue;
}
try setupWorkgroupBuiltins(data.self, rt, group_count_vec, group_id_vec);
for (0..data.invocations_per_workgroup) |i| {
const invocation_index = data.self.invocation_index.fetchAdd(1, .monotonic);
@@ -163,6 +191,58 @@ inline fn run(data: RunData) !void {
}
}
fn runBarrierWorkgroup(
data: RunData,
runtimes: []spv.Runtime,
statuses: []spv.Runtime.EntryPointStatus,
entry: spv.SpvWord,
group_count: @Vector(3, u32),
group_id: @Vector(3, u32),
) !void {
const allocator = data.self.device.device_allocator.allocator();
for (runtimes, 0..) |*rt, i| {
try ExecutionDevice.writeDescriptorSets(data.self.state, rt);
try setupWorkgroupBuiltins(data.self, rt, group_count, group_id);
try setupSubgroupBuiltins(data.self, rt, group_id, i);
statuses[i] = try rt.beginEntryPoint(allocator, entry);
try rt.flushDescriptorSets(allocator);
}
while (true) {
var pending = false;
for (statuses) |status| {
if (status == .barrier) {
pending = true;
break;
}
}
if (!pending)
break;
for (runtimes, 0..) |*rt, i| {
if (statuses[i] == .completed)
continue;
statuses[i] = try rt.continueEntryPoint(allocator);
try rt.flushDescriptorSets(allocator);
}
}
}
/// TODO: Move this in the SPIR-V Interpreter
fn hasControlBarrier(code: []const spv.SpvWord) bool {
var i: usize = 5;
while (i < code.len) {
const opcode_data = code[i];
const word_count = (opcode_data & (~spv.spv.SpvOpCodeMask)) >> spv.spv.SpvWordCountShift;
const opcode: spv.spv.SpvOp = @enumFromInt(opcode_data & spv.spv.SpvOpCodeMask);
if (opcode == .ControlBarrier)
return true;
i += @max(word_count, 1);
}
return false;
}
inline fn dumpResultsTable(allocator: std.mem.Allocator, io: std.Io, rt: *spv.Runtime, is_early: bool) !void {
@branchHint(.cold);
const file = try std.Io.Dir.cwd().createFile(
+1 -1
View File
@@ -71,7 +71,7 @@ pub fn writeDescriptorSets(state: *PipelineState, rt: *spv.Runtime) !void {
switch (binding) {
.buffer => |buffer_data_array| for (buffer_data_array, 0..) |buffer_data, descriptor_index| {
if (buffer_data.object) |buffer| {
const map = buffer.mapAsSliceWithOffset(u8, buffer_data.offset, buffer_data.size) catch continue :bindings;
const map = buffer.mapAsSliceWithAddedOffset(u8, buffer_data.offset, buffer_data.size) catch continue :bindings;
try rt.writeDescriptorSet(
map,
@as(u32, @intCast(set_index)),
+98 -33
View File
@@ -286,6 +286,17 @@ fn sample(src: []const u8, pos: F32x4, dim: F32x4, slice_bytes: usize, pitch_byt
}
pub fn blitRegion(src: *const SoftImage, dst: *SoftImage, region: vk.ImageBlit, filter: vk.Filter) VkError!void {
try blitRegionWithFormats(
src,
dst,
region,
filter,
base.format.fromAspect(src.interface.format, region.src_subresource.aspect_mask),
base.format.fromAspect(dst.interface.format, region.dst_subresource.aspect_mask),
);
}
pub fn blitRegionWithFormats(src: *const SoftImage, dst: *SoftImage, region: vk.ImageBlit, filter: vk.Filter, src_format: vk.Format, dst_format: vk.Format) VkError!void {
const io = dst.interface.owner.io();
const timer = std.Io.Timestamp.now(io, .real);
defer if (comptime base.config.logs != .none) {
@@ -323,13 +334,10 @@ pub fn blitRegion(src: *const SoftImage, dst: *SoftImage, region: vk.ImageBlit,
const y0 = @as(f32, @floatFromInt(src_offset_0.y)) + (0.5 - @as(f32, @floatFromInt(dst_offset_0.y))) * height_ratio;
const z0 = @as(f32, @floatFromInt(src_offset_0.z)) + (0.5 - @as(f32, @floatFromInt(dst_offset_0.z))) * depth_ratio;
const src_slice_pitch_bytes = src.interface.getSliceMemSizeForMipLevel(region.src_subresource.aspect_mask, region.src_subresource.mip_level);
const src_row_pitch_bytes = src.interface.getRowPitchMemSizeForMipLevel(region.src_subresource.aspect_mask, region.src_subresource.mip_level);
const dst_slice_pitch_bytes = dst.interface.getSliceMemSizeForMipLevel(region.dst_subresource.aspect_mask, region.dst_subresource.mip_level);
const dst_row_pitch_bytes = dst.interface.getRowPitchMemSizeForMipLevel(region.dst_subresource.aspect_mask, region.dst_subresource.mip_level);
const src_format = base.format.fromAspect(src.interface.format, region.src_subresource.aspect_mask);
const dst_format = base.format.fromAspect(dst.interface.format, region.dst_subresource.aspect_mask);
const src_slice_pitch_bytes = src.getSliceMemSizeForMipLevelWithFormat(region.src_subresource.aspect_mask, region.src_subresource.mip_level, src_format);
const src_row_pitch_bytes = src.getRowPitchMemSizeForMipLevelWithFormat(region.src_subresource.aspect_mask, region.src_subresource.mip_level, src_format);
const dst_slice_pitch_bytes = dst.getSliceMemSizeForMipLevelWithFormat(region.dst_subresource.aspect_mask, region.dst_subresource.mip_level, dst_format);
const dst_row_pitch_bytes = dst.getRowPitchMemSizeForMipLevelWithFormat(region.dst_subresource.aspect_mask, region.dst_subresource.mip_level, dst_format);
const apply_filter = (filter != .nearest);
const allow_srgb_conversion = apply_filter or base.format.isSrgb(src_format) != base.format.isSrgb(dst_format);
@@ -485,6 +493,16 @@ fn blit(state: State, data: BlitData) void {
/// Using image blitting to resolve
pub inline fn resolve(src: *const SoftImage, dst: *SoftImage, region: vk.ImageResolve) VkError!void {
try resolveWithFormats(
src,
dst,
region,
base.format.fromAspect(src.interface.format, region.src_subresource.aspect_mask),
base.format.fromAspect(dst.interface.format, region.dst_subresource.aspect_mask),
);
}
pub inline fn resolveWithFormats(src: *const SoftImage, dst: *SoftImage, region: vk.ImageResolve, src_format: vk.Format, dst_format: vk.Format) VkError!void {
var blit_region: vk.ImageBlit = .{
.src_offsets = .{ region.src_offset, region.src_offset },
.src_subresource = region.src_subresource,
@@ -500,7 +518,7 @@ pub inline fn resolve(src: *const SoftImage, dst: *SoftImage, region: vk.ImageRe
blit_region.dst_offsets[1].y += @intCast(region.extent.height);
blit_region.dst_offsets[1].z += @intCast(region.extent.depth);
try blitRegion(src, dst, blit_region, .nearest);
try blitRegionWithFormats(src, dst, blit_region, .nearest, src_format, dst_format);
}
fn applyScaleAndClamp(base_color: F32x4, state: State, apply_srgb_convertion: bool) F32x4 {
@@ -532,6 +550,16 @@ fn applyScaleAndClamp(base_color: F32x4, state: State, apply_srgb_convertion: bo
return color;
}
inline fn normalizedI8(value: u8) f32 {
const signed: i8 = @bitCast(value);
return @max(@as(f32, @floatFromInt(signed)) / @as(f32, @floatFromInt(std.math.maxInt(i8))), -1.0);
}
inline fn normalizedI16(value: u16) f32 {
const signed: i16 = @bitCast(value);
return @max(@as(f32, @floatFromInt(signed)) / @as(f32, @floatFromInt(std.math.maxInt(i16))), -1.0);
}
pub fn readFloat4(map: []const u8, src_format: vk.Format) F32x4 {
var c: F32x4 = .{ 0.0, 0.0, 0.0, 1.0 };
@@ -543,9 +571,9 @@ pub fn readFloat4(map: []const u8, src_format: vk.Format) F32x4 {
.r8_sint,
.r8_snorm,
=> c[0] = @as(f32, @floatFromInt(map[0])) / std.math.maxInt(i8),
=> c[0] = normalizedI8(map[0]),
.r16_snorm => c[0] = @as(f32, @floatFromInt(std.mem.bytesToValue(u16, map))) / std.math.maxInt(i16),
.r16_snorm => c[0] = normalizedI16(std.mem.bytesToValue(u16, map)),
.r16_unorm => c[0] = @as(f32, @floatFromInt(std.mem.bytesToValue(u16, map))) / std.math.maxInt(u16),
.r8g8b8a8_sint,
@@ -570,15 +598,15 @@ pub fn readFloat4(map: []const u8, src_format: vk.Format) F32x4 {
.r8g8_sint,
.r8g8_snorm,
=> {
c[0] = @as(f32, @floatFromInt(map[0])) / std.math.maxInt(i8);
c[1] = @as(f32, @floatFromInt(map[1])) / std.math.maxInt(i8);
c[0] = normalizedI8(map[0]);
c[1] = normalizedI8(map[1]);
},
.r8g8b8a8_snorm => {
c[0] = @as(f32, @floatFromInt(map[0])) / std.math.maxInt(i8);
c[1] = @as(f32, @floatFromInt(map[1])) / std.math.maxInt(i8);
c[2] = @as(f32, @floatFromInt(map[2])) / std.math.maxInt(i8);
c[3] = @as(f32, @floatFromInt(map[3])) / std.math.maxInt(i8);
c[0] = normalizedI8(map[0]);
c[1] = normalizedI8(map[1]);
c[2] = normalizedI8(map[2]);
c[3] = normalizedI8(map[3]);
},
.r4g4b4a4_unorm_pack16 => {
@@ -627,8 +655,8 @@ pub fn readFloat4(map: []const u8, src_format: vk.Format) F32x4 {
},
.r16g16_snorm => {
c[0] = @as(f32, @floatFromInt(std.mem.bytesToValue(u16, map[0..]))) / std.math.maxInt(i16);
c[1] = @as(f32, @floatFromInt(std.mem.bytesToValue(u16, map[2..]))) / std.math.maxInt(i16);
c[0] = normalizedI16(std.mem.bytesToValue(u16, map[0..]));
c[1] = normalizedI16(std.mem.bytesToValue(u16, map[2..]));
},
.r16g16_unorm => {
@@ -666,10 +694,10 @@ pub fn readFloat4(map: []const u8, src_format: vk.Format) F32x4 {
.r16g16b16a16_sint,
.r16g16b16a16_snorm,
=> {
c[0] = @as(f32, @floatFromInt(std.mem.bytesToValue(u16, map[0..]))) / std.math.maxInt(i16);
c[1] = @as(f32, @floatFromInt(std.mem.bytesToValue(u16, map[2..]))) / std.math.maxInt(i16);
c[2] = @as(f32, @floatFromInt(std.mem.bytesToValue(u16, map[4..]))) / std.math.maxInt(i16);
c[3] = @as(f32, @floatFromInt(std.mem.bytesToValue(u16, map[6..]))) / std.math.maxInt(i16);
c[0] = normalizedI16(std.mem.bytesToValue(u16, map[0..]));
c[1] = normalizedI16(std.mem.bytesToValue(u16, map[2..]));
c[2] = normalizedI16(std.mem.bytesToValue(u16, map[4..]));
c[3] = normalizedI16(std.mem.bytesToValue(u16, map[6..]));
},
.r16g16b16a16_sfloat => c = std.mem.bytesToValue(@Vector(4, f16), map),
@@ -704,10 +732,10 @@ pub fn readFloat4(map: []const u8, src_format: vk.Format) F32x4 {
.a8b8g8r8_snorm_pack32,
=> {
const pack = std.mem.bytesToValue(@Vector(4, u8), map);
c[0] = @as(f32, @floatFromInt(pack[0])) / std.math.maxInt(i8);
c[1] = @as(f32, @floatFromInt(pack[1])) / std.math.maxInt(i8);
c[2] = @as(f32, @floatFromInt(pack[2])) / std.math.maxInt(i8);
c[3] = @as(f32, @floatFromInt(pack[3])) / std.math.maxInt(i8);
c[0] = normalizedI8(pack[0]);
c[1] = normalizedI8(pack[1]);
c[2] = normalizedI8(pack[2]);
c[3] = normalizedI8(pack[3]);
},
.a2b10g10r10_uint_pack32,
@@ -1093,37 +1121,55 @@ pub fn writeFloat4(c: F32x4, map: []u8, dst_format: vk.Format) void {
}
}
inline fn signExtendI8(value: u8) u32 {
return @bitCast(@as(i32, @as(i8, @bitCast(value))));
}
inline fn signExtendI16(value: u16) u32 {
return @bitCast(@as(i32, @as(i16, @bitCast(value))));
}
pub fn readInt4(map: []const u8, src_format: vk.Format) U32x4 {
var c: U32x4 = .{ 0, 0, 0, 1 };
switch (src_format) {
.r8_sint,
.r8_uint,
.s8_uint,
=> c[0] = map[0],
.r16_sint,
.r8_sint => c[0] = signExtendI8(map[0]),
.r16_uint,
=> c[0] = std.mem.bytesToValue(u16, map),
.r16_sint => c[0] = signExtendI16(std.mem.bytesToValue(u16, map)),
.r32_sint,
.r32_uint,
=> c[0] = std.mem.bytesToValue(u32, map),
.r8g8_sint,
.r8g8_uint,
=> {
c[0] = map[0];
c[1] = map[1];
},
.r16g16_sint,
.r8g8_sint => {
c[0] = signExtendI8(map[0]);
c[1] = signExtendI8(map[1]);
},
.r16g16_uint,
=> {
c[0] = std.mem.bytesToValue(u16, map[0..]);
c[1] = std.mem.bytesToValue(u16, map[2..]);
},
.r16g16_sint => {
c[0] = signExtendI16(std.mem.bytesToValue(u16, map[0..]));
c[1] = signExtendI16(std.mem.bytesToValue(u16, map[2..]));
},
.r32g32_sint,
.r32g32_uint,
=> {
@@ -1131,7 +1177,6 @@ pub fn readInt4(map: []const u8, src_format: vk.Format) U32x4 {
c[1] = std.mem.bytesToValue(u32, map[4..]);
},
.r8g8b8a8_sint,
.r8g8b8a8_uint,
=> {
c[0] = map[0];
@@ -1140,7 +1185,13 @@ pub fn readInt4(map: []const u8, src_format: vk.Format) U32x4 {
c[3] = map[3];
},
.r16g16b16a16_sint,
.r8g8b8a8_sint => {
c[0] = signExtendI8(map[0]);
c[1] = signExtendI8(map[1]);
c[2] = signExtendI8(map[2]);
c[3] = signExtendI8(map[3]);
},
.r16g16b16a16_uint,
=> {
c[0] = std.mem.bytesToValue(u16, map[0..2]);
@@ -1149,12 +1200,18 @@ pub fn readInt4(map: []const u8, src_format: vk.Format) U32x4 {
c[3] = std.mem.bytesToValue(u16, map[6..8]);
},
.r16g16b16a16_sint => {
c[0] = signExtendI16(std.mem.bytesToValue(u16, map[0..2]));
c[1] = signExtendI16(std.mem.bytesToValue(u16, map[2..4]));
c[2] = signExtendI16(std.mem.bytesToValue(u16, map[4..6]));
c[3] = signExtendI16(std.mem.bytesToValue(u16, map[6..8]));
},
.r32g32b32a32_sint,
.r32g32b32a32_uint,
=> c = std.mem.bytesToValue(U32x4, map),
.a8b8g8r8_uint_pack32,
.a8b8g8r8_sint_pack32,
.a8b8g8r8_unorm_pack32,
.a8b8g8r8_snorm_pack32,
=> {
@@ -1165,6 +1222,14 @@ pub fn readInt4(map: []const u8, src_format: vk.Format) U32x4 {
c[3] = pack[3];
},
.a8b8g8r8_sint_pack32 => {
const pack = std.mem.bytesToValue(@Vector(4, u8), map);
c[0] = signExtendI8(pack[0]);
c[1] = signExtendI8(pack[1]);
c[2] = signExtendI8(pack[2]);
c[3] = signExtendI8(pack[3]);
},
.a2b10g10r10_unorm_pack32,
.a2b10g10r10_uint_pack32,
=> {
+10 -2
View File
@@ -32,8 +32,9 @@ pub fn shaderInvocation(
mutex.lock(io) catch return SpvRuntimeError.Unknown;
defer mutex.unlock(io);
try rt.populatePushConstants(draw_call.renderer.state.push_constant_blob[0..]);
const entry = try rt.getEntryPointByName(shader.entry);
const output_result = try rt.getResultByLocation(0, .output);
for (0..spv.SPIRV_MAX_OUTPUT_LOCATIONS) |location| {
const result_word = rt.getResultByLocation(@intCast(location), .input) catch |err| switch (err) {
@@ -54,8 +55,15 @@ pub fn shaderInvocation(
};
var outputs: [spv.SPIRV_MAX_OUTPUT_LOCATIONS][@sizeOf(zm.F32x4)]u8 = undefined;
@memset(std.mem.asBytes(&outputs), 0);
try rt.readOutput(std.mem.asBytes(&outputs), output_result);
for (0..spv.SPIRV_MAX_OUTPUT_LOCATIONS) |location| {
const result_word = rt.getResultByLocation(@intCast(location), .output) catch |err| switch (err) {
SpvRuntimeError.NotFound => continue,
else => return err,
};
try rt.readOutput(&outputs[location], result_word);
}
try rt.flushDescriptorSets(allocator);
+37 -28
View File
@@ -1,4 +1,5 @@
const std = @import("std");
const vk = @import("vulkan");
const base = @import("base");
const clip = @import("clip.zig");
@@ -20,26 +21,34 @@ pub fn processThenFragmentStage(renderer: *Renderer, allocator: std.mem.Allocato
const pipeline_data = (renderer.state.pipeline orelse return VkError.InvalidHandleDrv).interface.mode.graphics;
const topology = pipeline_data.input_assembly.topology;
const color_attachment = if (draw_call.render_pass.interface.subpasses[renderer.subpass_index].color_attachments) |attachments| attachments[0].attachment else return VkError.InvalidAttachmentDrv;
const render_target_view: *base.ImageView = draw_call.color_attachments[color_attachment];
const render_target: *SoftImage = @alignCast(@fieldParentPtr("interface", render_target_view.image));
const color_attachments = draw_call.render_pass.interface.subpasses[renderer.subpass_index].color_attachments orelse return VkError.InvalidAttachmentDrv;
const color_attachment_access = allocator.alloc(?common.RenderTargetAccess, color_attachments.len) catch return VkError.OutOfDeviceMemory;
@memset(color_attachment_access, null);
const color_range = render_target_view.subresource_range;
const color_format = render_target_view.format;
for (color_attachments, color_attachment_access) |attachment_ref, *access| {
if (attachment_ref.attachment == vk.ATTACHMENT_UNUSED)
continue;
const color_attachment_subresource_offset = try render_target.getSubresourceOffset(
color_range.aspect_mask,
color_range.base_mip_level,
color_range.base_array_layer,
);
const color_attachment_subresource_size = render_target.getLayerSize(color_range.aspect_mask);
const color_attachment_access: common.RenderTargetAccess = .{
.mutex = undefined,
.base = try render_target.mapAsSliceWithAddedOffset(u8, color_attachment_subresource_offset, color_attachment_subresource_size),
.row_pitch = render_target.getRowPitchMemSizeForMipLevelWithFormat(color_range.aspect_mask, color_range.base_mip_level, color_format),
.texel_size = base.format.texelSize(color_format),
.format = color_format,
};
const render_target_view: *base.ImageView = draw_call.color_attachments[attachment_ref.attachment];
const render_target: *SoftImage = @alignCast(@fieldParentPtr("interface", render_target_view.image));
const color_range = render_target_view.subresource_range;
const color_format = render_target_view.format;
const color_attachment_subresource_offset = try render_target.getSubresourceOffset(
color_range.aspect_mask,
color_range.base_mip_level,
color_range.base_array_layer,
);
const color_attachment_subresource_size = render_target.getLayerSize(color_range.aspect_mask);
access.* = .{
.mutex = undefined,
.base = try render_target.mapAsSliceWithAddedOffset(u8, color_attachment_subresource_offset, color_attachment_subresource_size),
.row_pitch = render_target.getRowPitchMemSizeForMipLevelWithFormat(color_range.aspect_mask, color_range.base_mip_level, color_format),
.texel_size = base.format.texelSize(color_format),
.format = color_format,
};
}
const depth_attachment_view: ?*base.ImageView = if (draw_call.depth_attachment) |view| view else null;
const depth_attachment: ?*SoftImage = if (depth_attachment_view) |view| @alignCast(@fieldParentPtr("interface", view.image)) else null;
@@ -60,7 +69,7 @@ pub fn processThenFragmentStage(renderer: *Renderer, allocator: std.mem.Allocato
break :blk .{
.mutex = .init,
.base = try depth_attachment.?.mapAsSliceWithAddedOffset(u8, attachment_subresource_offset, attachment_subresource_size),
.row_pitch = render_target.getRowPitchMemSizeForMipLevelWithFormat(depth_range.aspect_mask, depth_range.base_mip_level, depth_format),
.row_pitch = depth_attachment.?.getRowPitchMemSizeForMipLevelWithFormat(depth_range.aspect_mask, depth_range.base_mip_level, depth_format),
.texel_size = base.format.texelSize(depth_format),
.format = depth_format,
};
@@ -80,7 +89,7 @@ pub fn processThenFragmentStage(renderer: *Renderer, allocator: std.mem.Allocato
v0,
v1,
v2,
&color_attachment_access,
color_attachment_access,
if (depth_attachment_access) |*access| access else null,
);
},
@@ -97,7 +106,7 @@ pub fn processThenFragmentStage(renderer: *Renderer, allocator: std.mem.Allocato
v0,
v1,
v2,
&color_attachment_access,
color_attachment_access,
if (depth_attachment_access) |*access| access else null,
);
}
@@ -116,7 +125,7 @@ pub fn processThenFragmentStage(renderer: *Renderer, allocator: std.mem.Allocato
v0,
v1,
v2,
&color_attachment_access,
color_attachment_access,
if (depth_attachment_access) |*access| access else null,
);
} else {
@@ -127,7 +136,7 @@ pub fn processThenFragmentStage(renderer: *Renderer, allocator: std.mem.Allocato
v1,
v0,
v2,
&color_attachment_access,
color_attachment_access,
if (depth_attachment_access) |*access| access else null,
);
}
@@ -143,7 +152,7 @@ pub fn processThenFragmentStage(renderer: *Renderer, allocator: std.mem.Allocato
draw_call,
v0,
v1,
&color_attachment_access,
color_attachment_access,
if (depth_attachment_access) |*access| access else null,
);
},
@@ -157,7 +166,7 @@ pub fn processThenFragmentStage(renderer: *Renderer, allocator: std.mem.Allocato
draw_call,
v0,
v1,
&color_attachment_access,
color_attachment_access,
if (depth_attachment_access) |*access| access else null,
);
}
@@ -173,7 +182,7 @@ fn clipTransformAndRasterizeLine(
draw_call: *DrawCall,
v0: *Vertex,
v1: *Vertex,
color_attachment_access: *const common.RenderTargetAccess,
color_attachment_access: []const ?common.RenderTargetAccess,
depth_attachment_access: ?*common.RenderTargetAccess,
) VkError!void {
const clipped_line = (try clip.clipLine(allocator, v0, v1)) orelse return;
@@ -201,7 +210,7 @@ fn clipTransformAndRasterizeTriangle(
v0: *Vertex,
v1: *Vertex,
v2: *Vertex,
color_attachment_access: *const common.RenderTargetAccess,
color_attachment_access: []const ?common.RenderTargetAccess,
depth_attachment_access: ?*common.RenderTargetAccess,
) VkError!void {
const clipped_polygon = try clip.clipTriangle(allocator, v0, v1, v2);
@@ -238,7 +247,7 @@ fn rasterizeTriangle(
v0: *Vertex,
v1: *Vertex,
v2: *Vertex,
color_attachment_access: *const common.RenderTargetAccess,
color_attachment_access: []const ?common.RenderTargetAccess,
depth_attachment_access: ?*common.RenderTargetAccess,
) VkError!void {
if (try triangleIsCulled(renderer, v0, v1, v2))
+2 -2
View File
@@ -28,7 +28,7 @@ const RunData = struct {
end_vertex: *Renderer.Vertex,
start_step: usize,
end_step: usize,
color_attachment_access: *const common.RenderTargetAccess,
color_attachment_access: []const ?common.RenderTargetAccess,
depth_attachment_access: ?*common.RenderTargetAccess,
};
@@ -37,7 +37,7 @@ pub fn drawLine(
draw_call: *Renderer.DrawCall,
v0: *Renderer.Vertex,
v1: *Renderer.Vertex,
color_attachment_access: *const common.RenderTargetAccess,
color_attachment_access: []const ?common.RenderTargetAccess,
depth_attachment_access: ?*common.RenderTargetAccess,
) VkError!void {
const io = draw_call.renderer.device.interface.io();
+14 -13
View File
@@ -101,10 +101,15 @@ inline fn interpolateF32x4(value0: F32x4, value1: F32x4, value2: F32x4, b0: f32,
return (value0 * zm.f32x4s(b0)) + (value1 * zm.f32x4s(b1)) + (value2 * zm.f32x4s(b2));
}
inline fn fragmentOutputFloat4(output: [@sizeOf(F32x4)]u8, format: vk.Format) F32x4 {
const color = std.mem.bytesToValue(F32x4, &output);
return if (base.format.isSrgb(format)) zm.rgbToSrgb(color) else color;
}
pub fn writeToTargets(
outputs: [spv.SPIRV_MAX_OUTPUT_LOCATIONS][@sizeOf(F32x4)]u8,
draw_call: *Renderer.DrawCall,
color_attachment_access: *const RenderTargetAccess,
color_attachment_access: []const ?RenderTargetAccess,
depth_attachment_access: ?*RenderTargetAccess,
x: usize,
y: usize,
@@ -112,8 +117,6 @@ pub fn writeToTargets(
) VkError!void {
const io = draw_call.renderer.device.interface.io();
const color_offset = @as(usize, @intCast(x)) * color_attachment_access.texel_size + @as(usize, @intCast(y)) * color_attachment_access.row_pitch;
// After work depth test to avoid overwritten depth pixels during fragment invocations
if (depth_attachment_access) |depth| {
const depth_offset = @as(usize, @intCast(x)) * depth.texel_size + @as(usize, @intCast(y)) * depth.row_pitch;
@@ -125,18 +128,16 @@ pub fn writeToTargets(
if (z >= depth_value[0])
return;
blitter.writeFloat4(zm.f32x4s(z), depth.base[depth_offset..], depth.format);
}
// Doubled line to stay inside the critical section
if (base.format.isUnnormalizedInteger(color_attachment_access.format)) {
blitter.writeInt4(std.mem.bytesToValue(U32x4, &outputs[0]), color_attachment_access.base[color_offset..], color_attachment_access.format);
for (color_attachment_access, 0..) |maybe_color, location| {
const color = maybe_color orelse continue;
const color_offset = @as(usize, @intCast(x)) * color.texel_size + @as(usize, @intCast(y)) * color.row_pitch;
if (base.format.isUnnormalizedInteger(color.format)) {
blitter.writeInt4(std.mem.bytesToValue(U32x4, &outputs[location]), color.base[color_offset..], color.format);
} else {
blitter.writeFloat4(std.mem.bytesToValue(F32x4, &outputs[0]), color_attachment_access.base[color_offset..], color_attachment_access.format);
}
} else {
if (base.format.isUnnormalizedInteger(color_attachment_access.format)) {
blitter.writeInt4(std.mem.bytesToValue(U32x4, &outputs[0]), color_attachment_access.base[color_offset..], color_attachment_access.format);
} else {
blitter.writeFloat4(std.mem.bytesToValue(F32x4, &outputs[0]), color_attachment_access.base[color_offset..], color_attachment_access.format);
blitter.writeFloat4(fragmentOutputFloat4(outputs[location], color.format), color.base[color_offset..], color.format);
}
}
}
+2 -2
View File
@@ -26,7 +26,7 @@ const RunData = struct {
v0: Renderer.Vertex,
v1: Renderer.Vertex,
v2: Renderer.Vertex,
color_attachment_access: *const common.RenderTargetAccess,
color_attachment_access: []const ?common.RenderTargetAccess,
depth_attachment_access: ?*common.RenderTargetAccess,
};
@@ -36,7 +36,7 @@ pub fn drawTriangle(
v0: *Renderer.Vertex,
v1: *Renderer.Vertex,
v2: *Renderer.Vertex,
color_attachment_access: *const common.RenderTargetAccess,
color_attachment_access: []const ?common.RenderTargetAccess,
depth_attachment_access: ?*common.RenderTargetAccess,
) VkError!void {
const io = draw_call.renderer.device.interface.io();