adding proper subpass management and image resolve
Test / build_and_test (push) Successful in 29s
Build / build (push) Successful in 1m5s

This commit is contained in:
2026-05-27 23:31:05 +02:00
parent 6edb856d06
commit fe391bc678
13 changed files with 257 additions and 116 deletions
+75 -24
View File
@@ -68,10 +68,12 @@ pub fn create(device: *base.Device, allocator: std.mem.Allocator, info: *const v
.endRenderPass = endRenderPass,
.executeCommands = executeCommands,
.fillBuffer = fillBuffer,
.nextSubpass = nextSubpass,
.pipelineBarrier = pipelineBarrier,
.pushConstants = pushConstants,
.reset = reset,
.resetEvent = resetEvent,
.resolveImage = resolveImage,
.setEvent = setEvent,
.setScissor = setScissor,
.setViewport = setViewport,
@@ -144,6 +146,7 @@ pub fn beginRenderPass(interface: *Interface, render_pass: *base.RenderPass, fra
const impl: *Impl = @ptrCast(@alignCast(context));
device.renderer.render_pass = impl.render_pass;
device.renderer.framebuffer = impl.framebuffer;
device.renderer.subpass_index = 0;
for (impl.render_pass.interface.attachments, impl.framebuffer.interface.attachments, 0..) |desc, attachment, index| {
const image: *SoftImage = @alignCast(@fieldParentPtr("interface", attachment.image));
@@ -378,20 +381,44 @@ pub fn clearAttachment(interface: *Interface, attachment: vk.ClearAttachment, re
pub fn execute(context: *anyopaque, device: *ExecutionDevice) VkError!void {
const impl: *Impl = @ptrCast(@alignCast(context));
if (device.renderer.framebuffer) |framebuffer| {
const image_view = framebuffer.interface.attachments[impl.attachment.color_attachment];
const image: *SoftImage = @alignCast(@fieldParentPtr("interface", image_view.image));
const clear_format = try image.getClearFormat();
const framebuffer = device.renderer.framebuffer orelse return;
const render_pass = device.renderer.render_pass orelse return;
const subpass = render_pass.interface.subpasses[device.renderer.subpass_index];
try blitter.clear(
impl.attachment.clear_value,
clear_format,
image,
image_view.format,
image_view.subresource_range,
null,
);
}
const image_view = blk: {
if (impl.attachment.aspect_mask.toInt() == (vk.ImageAspectFlags{ .color_bit = true }).toInt()) {
const fb_attachment_index = (subpass.color_attachments orelse return)[impl.attachment.color_attachment].attachment;
if (fb_attachment_index != vk.ATTACHMENT_UNUSED)
break :blk framebuffer.interface.attachments[impl.attachment.color_attachment];
} else if (impl.attachment.aspect_mask.depth_bit or impl.attachment.aspect_mask.stencil_bit) {
if (render_pass.interface.subpasses[device.renderer.subpass_index].depth_stencil_attachments) |desc| {
if (desc.attachment != vk.ATTACHMENT_UNUSED)
break :blk framebuffer.interface.attachments[desc.attachment];
}
}
return;
};
const image: *SoftImage = @alignCast(@fieldParentPtr("interface", image_view.image));
const clear_format = try image.getClearFormat();
const range: vk.ImageSubresourceRange = .{
.aspect_mask = impl.attachment.aspect_mask,
.base_mip_level = image_view.subresource_range.base_mip_level,
.level_count = image_view.subresource_range.level_count,
.base_array_layer = impl.rect.base_array_layer + image_view.subresource_range.base_array_layer,
.layer_count = impl.rect.layer_count,
};
try blitter.clear(
impl.attachment.clear_value,
clear_format,
image,
image_view.format,
range,
impl.rect.rect,
);
}
};
@@ -821,27 +848,26 @@ pub fn fillBuffer(interface: *Interface, buffer: *base.Buffer, offset: vk.Device
self.commands.append(allocator, .{ .ptr = cmd, .vtable = &.{ .execute = CommandImpl.execute } }) catch return VkError.OutOfHostMemory;
}
pub fn pipelineBarrier(interface: *Interface, src_stage: vk.PipelineStageFlags, dst_stage: vk.PipelineStageFlags, dependency: vk.DependencyFlags, memory_barriers: []const vk.MemoryBarrier, buffer_barriers: []const vk.BufferMemoryBarrier, image_barriers: []const vk.ImageMemoryBarrier) VkError!void {
pub fn nextSubpass(interface: *Interface, _: vk.SubpassContents) VkError!void {
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
const allocator = self.command_allocator.allocator();
const CommandImpl = struct {
const Impl = @This();
pub fn execute(_: *anyopaque, _: *ExecutionDevice) VkError!void {}
pub fn execute(_: *anyopaque, device: *ExecutionDevice) VkError!void {
device.renderer.subpass_index += 1;
}
};
const cmd = allocator.create(CommandImpl) catch return VkError.OutOfHostMemory;
errdefer allocator.destroy(cmd);
cmd.* = .{};
self.commands.append(allocator, .{ .ptr = cmd, .vtable = &.{ .execute = CommandImpl.execute } }) catch return VkError.OutOfHostMemory;
}
_ = src_stage;
_ = dst_stage;
_ = dependency;
_ = memory_barriers;
_ = buffer_barriers;
_ = image_barriers;
pub fn pipelineBarrier(_: *Interface, _: vk.PipelineStageFlags, _: vk.PipelineStageFlags, _: vk.DependencyFlags, _: []const vk.MemoryBarrier, _: []const vk.BufferMemoryBarrier, _: []const vk.ImageMemoryBarrier) VkError!void {
// No-op
}
pub fn pushConstants(interface: *Interface, stages: vk.ShaderStageFlags, offset: u32, blob: []const u8) VkError!void {
@@ -880,12 +906,10 @@ pub fn pushConstants(interface: *Interface, stages: vk.ShaderStageFlags, offset:
self.commands.append(allocator, .{ .ptr = cmd, .vtable = &.{ .execute = CommandImpl.execute } }) catch return VkError.OutOfHostMemory;
}
pub fn resetEvent(interface: *Interface, event: *base.Event, stage: vk.PipelineStageFlags) VkError!void {
pub fn resetEvent(interface: *Interface, event: *base.Event, _: vk.PipelineStageFlags) VkError!void {
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
const allocator = self.command_allocator.allocator();
_ = stage;
const CommandImpl = struct {
const Impl = @This();
@@ -905,6 +929,33 @@ pub fn resetEvent(interface: *Interface, event: *base.Event, stage: vk.PipelineS
self.commands.append(allocator, .{ .ptr = cmd, .vtable = &.{ .execute = CommandImpl.execute } }) catch return VkError.OutOfHostMemory;
}
pub fn resolveImage(interface: *Interface, src: *base.Image, _: vk.ImageLayout, dst: *base.Image, _: vk.ImageLayout, region: vk.ImageResolve) VkError!void {
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
const allocator = self.command_allocator.allocator();
const CommandImpl = struct {
const Impl = @This();
src: *const SoftImage,
dst: *SoftImage,
region: vk.ImageResolve,
pub fn execute(context: *anyopaque, _: *ExecutionDevice) VkError!void {
const impl: *Impl = @ptrCast(@alignCast(context));
try blitter.resolve(impl.src, impl.dst, impl.region);
}
};
const cmd = allocator.create(CommandImpl) catch return VkError.OutOfHostMemory;
errdefer allocator.destroy(cmd);
cmd.* = .{
.src = @alignCast(@fieldParentPtr("interface", src)),
.dst = @alignCast(@fieldParentPtr("interface", dst)),
.region = region,
};
self.commands.append(allocator, .{ .ptr = cmd, .vtable = &.{ .execute = CommandImpl.execute } }) catch return VkError.OutOfHostMemory;
}
pub fn setEvent(interface: *Interface, event: *base.Event, stage: vk.PipelineStageFlags) VkError!void {
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
const allocator = self.command_allocator.allocator();
+80 -22
View File
@@ -1,8 +1,8 @@
const std = @import("std");
const builtin = @import("builtin");
const vk = @import("vulkan");
const base = @import("base");
const lib = @import("lib.zig");
const cpuinfo = lib.c;
const SoftDevice = @import("SoftDevice.zig");
@@ -189,9 +189,6 @@ pub fn create(allocator: std.mem.Allocator, instance: *base.Instance) VkError!*S
.shader_float_64 = .true,
.shader_int_64 = .true,
.shader_int_16 = .true,
.texture_compression_etc2 = .false,
.texture_compression_bc = .false,
.texture_compression_astc_ldr = .false,
};
var queue_family_props = [_]vk.QueueFamilyProperties{
@@ -201,30 +198,47 @@ pub fn create(allocator: std.mem.Allocator, instance: *base.Instance) VkError!*S
.timestamp_valid_bits = 0,
.min_image_transfer_granularity = .{ .width = 1, .height = 1, .depth = 1 },
},
.{
.queue_flags = .{ .graphics_bit = true },
.queue_count = 1,
.timestamp_valid_bits = 0,
.min_image_transfer_granularity = .{ .width = 1, .height = 1, .depth = 1 },
},
.{
.queue_flags = .{ .transfer_bit = true },
.queue_count = 1,
.timestamp_valid_bits = 0,
.min_image_transfer_granularity = .{ .width = 1, .height = 1, .depth = 1 },
},
// TODO: maybe add a compute specialized queue
};
interface.queue_family_props.appendSlice(allocator, queue_family_props[0..]) catch return VkError.OutOfHostMemory;
if (device_name[0] == 0) {
const name = blk: {
if (cpuinfo.cpuinfo_initialize()) {
const package = cpuinfo.cpuinfo_get_package(0).*;
const non_sentinel_name = package.name[0..(std.mem.len(@as([*:0]const u8, @ptrCast(&package.name))))];
break :blk std.fmt.allocPrint(command_allocator, "{s} ({d} threads)", .{ non_sentinel_name, package.processor_count }) catch return VkError.OutOfHostMemory;
// If arch is x86 we try to get precise CPU name through CPUID
// and fallback to vendor name if not available
if (comptime builtin.cpu.arch.isX86()) {
const max_extended_leaf = cpuid(0x80000000, 0).eax;
if (max_extended_leaf >= 0x80000004) {
var brand: [49]u8 = @splat(0);
for (0..3) |i| {
const regs = cpuid(0x80000002 + @as(u32, @intCast(i)), 0);
const offset = i * 16;
writeU32Le(brand[0..], offset + 0, regs.eax);
writeU32Le(brand[0..], offset + 4, regs.ebx);
writeU32Le(brand[0..], offset + 8, regs.ecx);
writeU32Le(brand[0..], offset + 12, regs.edx);
}
const brand_str = std.mem.trim(u8, brand[0..48], " \x00");
break :blk command_allocator.dupe(u8, brand_str) catch return VkError.OutOfHostMemory;
} else {
var vendor: [13]u8 = @splat(0);
const leaf0 = cpuid(0, 0);
writeU32Le(vendor[0..], 0, leaf0.ebx);
writeU32Le(vendor[0..], 4, leaf0.edx);
writeU32Le(vendor[0..], 8, leaf0.ecx);
const vendor_str = std.mem.trim(u8, vendor[0..12], " \x00");
break :blk command_allocator.dupe(u8, vendor_str) catch return VkError.OutOfHostMemory;
}
}
break :blk command_allocator.dupe(u8, "Unkown") catch return VkError.OutOfHostMemory;
break :blk command_allocator.dupe(u8, lib.PHYSICAL_DEVICE_DEFAULT_NAME) catch return VkError.OutOfHostMemory;
};
defer command_allocator.free(name);
@@ -857,3 +871,47 @@ fn checkFormatUsage(usage: vk.ImageUsageFlags, features: vk.FormatFeatureFlags)
pub fn getSurfaceSupportKHR(_: *Interface, _: u32, _: *SurfaceKHR) VkError!bool {
return true;
}
const CpuidRegs = packed struct {
eax: u32,
ebx: u32,
ecx: u32,
edx: u32,
};
fn cpuid(leaf_id: u32, subleaf_id: u32) CpuidRegs {
comptime {
switch (builtin.cpu.arch) {
.x86, .x86_64 => {},
else => @compileError("cpuid is only available on x86/x86_64"),
}
}
var eax: u32 = undefined;
var ebx: u32 = undefined;
var ecx: u32 = undefined;
var edx: u32 = undefined;
asm volatile ("cpuid"
: [_] "={eax}" (eax),
[_] "={ebx}" (ebx),
[_] "={ecx}" (ecx),
[_] "={edx}" (edx),
: [_] "{eax}" (leaf_id),
[_] "{ecx}" (subleaf_id),
);
return .{
.eax = eax,
.ebx = ebx,
.ecx = ecx,
.edx = edx,
};
}
fn writeU32Le(dst: []u8, offset: usize, value: u32) void {
dst[offset + 0] = @truncate(value);
dst[offset + 1] = @truncate(value >> 8);
dst[offset + 2] = @truncate(value >> 16);
dst[offset + 3] = @truncate(value >> 24);
}
-1
View File
@@ -1 +0,0 @@
#include <cpuinfo.h>
+4 -1
View File
@@ -82,7 +82,7 @@ pub const DrawCall = struct {
.viewport = undefined,
.scissor = undefined,
.color_attachments = framebuffer.interface.attachments[0..],
.depth_attachment = if (render_pass.interface.subpasses[0].depth_stencil_attachments) |desc| framebuffer.interface.attachments[desc.attachment] else null,
.depth_attachment = if (render_pass.interface.subpasses[renderer.subpass_index].depth_stencil_attachments) |desc| framebuffer.interface.attachments[desc.attachment] else null,
.render_pass = render_pass,
.framebuffer = framebuffer,
.rasterizer_wait_group = .init,
@@ -117,6 +117,8 @@ render_pass: ?*SoftRenderPass,
framebuffer: ?*SoftFramebuffer,
dynamic_state: DynamicState,
subpass_index: usize,
pub fn init(device: *SoftDevice, state: *PipelineState) Self {
return .{
.device = device,
@@ -128,6 +130,7 @@ pub fn init(device: *SoftDevice, state: *PipelineState) Self {
.scissor = null,
.line_width = null,
},
.subpass_index = 0,
};
}
+62 -17
View File
@@ -50,6 +50,18 @@ fn computeOffset3D(x: usize, y: usize, z: usize, slice_bytes: usize, pitch_bytes
}
pub fn clear(pixel: vk.ClearValue, format: vk.Format, dst: *SoftImage, view_format: vk.Format, range: vk.ImageSubresourceRange, render_area: ?vk.Rect2D) VkError!void {
if (range.aspect_mask.depth_bit and range.aspect_mask.stencil_bit) {
var depth_range = range;
depth_range.aspect_mask = .{ .depth_bit = true };
try clear(pixel, format, dst, view_format, depth_range, render_area);
var stencil_range = range;
stencil_range.aspect_mask = .{ .stencil_bit = true };
try clear(pixel, format, dst, view_format, stencil_range, render_area);
return;
}
const dst_format = base.format.fromAspect(view_format, range.aspect_mask);
if (dst_format == .undefined) {
return;
@@ -64,23 +76,38 @@ pub fn clear(pixel: vk.ClearValue, format: vk.Format, dst: *SoftImage, view_form
};
var clamped_pixel: vk.ClearValue = pixel;
if (base.format.isSnorm(view_format) or base.format.isUnorm(view_format)) {
if (range.aspect_mask.color_bit and (base.format.isSnorm(view_format) or base.format.isUnorm(view_format))) {
const min_value: f32 = if (base.format.isSnorm(view_format)) -1.0 else 0.0;
if (range.aspect_mask.color_bit) {
clamped_pixel.color.float_32[0] = std.math.clamp(pixel.color.float_32[0], min_value, 1.0);
clamped_pixel.color.float_32[1] = std.math.clamp(pixel.color.float_32[1], min_value, 1.0);
clamped_pixel.color.float_32[2] = std.math.clamp(pixel.color.float_32[2], min_value, 1.0);
clamped_pixel.color.float_32[3] = std.math.clamp(pixel.color.float_32[3], min_value, 1.0);
}
if (range.aspect_mask.depth_bit) {
clamped_pixel.depth_stencil.depth = std.math.clamp(pixel.depth_stencil.depth, min_value, 1.0);
}
clamped_pixel.color.float_32[0] = std.math.clamp(pixel.color.float_32[0], min_value, 1.0);
clamped_pixel.color.float_32[1] = std.math.clamp(pixel.color.float_32[1], min_value, 1.0);
clamped_pixel.color.float_32[2] = std.math.clamp(pixel.color.float_32[2], min_value, 1.0);
clamped_pixel.color.float_32[3] = std.math.clamp(pixel.color.float_32[3], min_value, 1.0);
}
if (range.aspect_mask.depth_bit) {
clamped_pixel.depth_stencil.depth = std.math.clamp(pixel.depth_stencil.depth, 0.0, 1.0);
}
const depth_clear: F32x4 = @splat(clamped_pixel.depth_stencil.depth);
const stencil_clear: U32x4 = @splat(clamped_pixel.depth_stencil.stencil);
const src_format: vk.Format = if (range.aspect_mask.stencil_bit)
.r32g32b32a32_uint
else if (range.aspect_mask.depth_bit)
.r32g32b32a32_sfloat
else
format;
const src_map: []const u8 = if (range.aspect_mask.stencil_bit)
std.mem.asBytes(&stencil_clear)
else if (range.aspect_mask.depth_bit)
std.mem.asBytes(&depth_clear)
else
std.mem.asBytes(&clamped_pixel);
const state: State = .{
.src_format = format,
.src_format = src_format,
.dst_format = dst_format,
.filter = .nearest,
.allow_srgb_conversion = true,
@@ -120,10 +147,10 @@ pub fn clear(pixel: vk.ClearValue, format: vk.Format, dst: *SoftImage, view_form
const dst_map = try dst.mapAsSliceWithAddedOffset(u8, dst_texel_offset, vk.WHOLE_SIZE);
blit(state, .{
.src_map = std.mem.asBytes(&clamped_pixel),
.src_map = src_map,
.dst_map = dst_map,
.src_slice_pitch_bytes = base.format.texelSize(format),
.src_slice_pitch_bytes = base.format.texelSize(src_format),
.src_row_pitch_bytes = 0,
.dst_slice_pitch_bytes = dst.interface.getSliceMemSizeForMipLevel(subresource.aspect_mask, subresource.mip_level),
.dst_row_pitch_bytes = dst.interface.getRowPitchMemSizeForMipLevel(subresource.aspect_mask, subresource.mip_level),
@@ -456,6 +483,26 @@ 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 {
var blit_region: vk.ImageBlit = .{
.src_offsets = .{ region.src_offset, region.src_offset },
.src_subresource = region.src_subresource,
.dst_offsets = .{ region.dst_offset, region.dst_offset },
.dst_subresource = region.dst_subresource,
};
blit_region.src_offsets[1].x += @intCast(region.extent.width);
blit_region.src_offsets[1].y += @intCast(region.extent.height);
blit_region.src_offsets[1].z += @intCast(region.extent.depth);
blit_region.dst_offsets[1].x += @intCast(region.extent.width);
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);
}
fn applyScaleAndClamp(base_color: F32x4, state: State, apply_srgb_convertion: bool) F32x4 {
var color: F32x4 = base_color;
@@ -764,8 +811,7 @@ pub fn writeFloat4(color: F32x4, map: []u8, dst_format: vk.Format) void {
.s8_uint,
=> map[0] = @intFromFloat(@round(color[0] * std.math.maxInt(u8))),
.r8_snorm,
=> map[0] = @intFromFloat(@round(color[0] * std.math.maxInt(i8))),
.r8_snorm => map[0] = @intFromFloat(@round(color[0] * std.math.maxInt(i8))),
.r16_sint,
.r16_uint,
@@ -1150,7 +1196,6 @@ pub fn writeInt4(c: U32x4, map: []u8, dst_format: vk.Format) void {
.r8g8b8_uscaled,
.r8g8_uscaled,
.r8_uscaled,
.s8_uint,
=> color = @min(color, U32x4{ 0xFF, 0xFF, 0xFF, 0xFF }),
.r16g16b16a16_uint,
+1 -1
View File
@@ -20,7 +20,7 @@ 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[0].color_attachments) |attachments| attachments[0].attachment else return VkError.InvalidAttachmentDrv;
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));
+1 -1
View File
@@ -121,7 +121,7 @@ fn runWrapper(data: RunData) void {
}
inline fn run(data: RunData) !void {
const color_attachment = if (data.draw_call.render_pass.interface.subpasses[0].color_attachments) |attachments| attachments[0].attachment else return VkError.InvalidAttachmentDrv;
const color_attachment = if (data.draw_call.render_pass.interface.subpasses[data.draw_call.renderer.subpass_index].color_attachments) |attachments| attachments[0].attachment else return VkError.InvalidAttachmentDrv;
const render_target_view: *base.ImageView = data.draw_call.color_attachments[color_attachment];
const render_target: *SoftImage = @alignCast(@fieldParentPtr("interface", render_target_view.image));
+1
View File
@@ -68,6 +68,7 @@ pub const MAX_IMAGE_LEVELS_3D = 12;
pub const MAX_IMAGE_LEVELS_CUBE = 15;
pub const MAX_IMAGE_ARRAY_LAYERS = 2048;
pub const PHYSICAL_DEVICE_DEFAULT_NAME = "StrollSoft device";
pub const PHYSICAL_DEVICE_FALLBACK_HEAP_SIZE = 0x10000000; // 256MB
pub const std_options = base.std_options;
+12
View File
@@ -62,10 +62,12 @@ pub const DispatchTable = struct {
endRenderPass: *const fn (*Self) VkError!void,
executeCommands: *const fn (*Self, *Self) VkError!void,
fillBuffer: *const fn (*Self, *Buffer, vk.DeviceSize, vk.DeviceSize, u32) VkError!void,
nextSubpass: *const fn (*Self, vk.SubpassContents) VkError!void,
pipelineBarrier: *const fn (*Self, vk.PipelineStageFlags, vk.PipelineStageFlags, vk.DependencyFlags, []const vk.MemoryBarrier, []const vk.BufferMemoryBarrier, []const vk.ImageMemoryBarrier) VkError!void,
pushConstants: *const fn (*Self, vk.ShaderStageFlags, u32, []const u8) VkError!void,
reset: *const fn (*Self, vk.CommandBufferResetFlags) VkError!void,
resetEvent: *const fn (*Self, *Event, vk.PipelineStageFlags) VkError!void,
resolveImage: *const fn (*Self, *Image, vk.ImageLayout, *Image, vk.ImageLayout, vk.ImageResolve) VkError!void,
setEvent: *const fn (*Self, *Event, vk.PipelineStageFlags) VkError!void,
setScissor: *const fn (*Self, u32, []const vk.Rect2D) VkError!void,
setViewport: *const fn (*Self, u32, []const vk.Viewport) VkError!void,
@@ -250,6 +252,10 @@ pub inline fn fillBuffer(self: *Self, buffer: *Buffer, offset: vk.DeviceSize, si
try self.dispatch_table.fillBuffer(self, buffer, offset, size, data);
}
pub inline fn nextSubpass(self: *Self, contents: vk.SubpassContents) VkError!void {
try self.dispatch_table.nextSubpass(self, contents);
}
pub inline fn pipelineBarrier(
self: *Self,
src_stage: vk.PipelineStageFlags,
@@ -270,6 +276,12 @@ pub inline fn resetEvent(self: *Self, event: *Event, stage: vk.PipelineStageFlag
try self.dispatch_table.resetEvent(self, event, stage);
}
pub inline fn resolveImage(self: *Self, src: *Image, src_layout: vk.ImageLayout, dst: *Image, dst_layout: vk.ImageLayout, regions: []const vk.ImageResolve) VkError!void {
for (regions[0..]) |region| {
try self.dispatch_table.resolveImage(self, src, src_layout, dst, dst_layout, region);
}
}
pub inline fn setEvent(self: *Self, event: *Event, stage: vk.PipelineStageFlags) VkError!void {
try self.dispatch_table.setEvent(self, event, stage);
}
+4 -17
View File
@@ -1912,11 +1912,7 @@ pub export fn strollCmdNextSubpass(p_cmd: vk.CommandBuffer, contents: vk.Subpass
defer entryPointEndLogTrace();
const cmd = Dispatchable(CommandBuffer).fromHandleObject(p_cmd) catch |err| return errorLogger(err);
notImplementedWarning();
_ = cmd;
_ = contents;
cmd.nextSubpass(contents) catch |err| return errorLogger(err);
}
pub export fn strollCmdPipelineBarrier(
@@ -1991,18 +1987,9 @@ pub export fn strollCmdResolveImage(
defer entryPointEndLogTrace();
const cmd = Dispatchable(CommandBuffer).fromHandleObject(p_cmd) catch |err| return errorLogger(err);
const src = Dispatchable(Image).fromHandleObject(p_src) catch |err| return errorLogger(err);
const dst = Dispatchable(Image).fromHandleObject(p_dst) catch |err| return errorLogger(err);
notImplementedWarning();
_ = cmd;
_ = src;
_ = src_layout;
_ = dst;
_ = dst_layout;
_ = count;
_ = regions;
const src = NonDispatchable(Image).fromHandleObject(p_src) catch |err| return errorLogger(err);
const dst = NonDispatchable(Image).fromHandleObject(p_dst) catch |err| return errorLogger(err);
cmd.resolveImage(src, src_layout, dst, dst_layout, regions[0..count]) catch |err| return errorLogger(err);
}
pub export fn strollCmdSetBlendConstants(p_cmd: vk.CommandBuffer, p_constants: [*]f32) callconv(vk.vulkan_call_conv) void {