adding software blitter base
This commit is contained in:
@@ -2,6 +2,8 @@ const std = @import("std");
|
|||||||
const vk = @import("vulkan");
|
const vk = @import("vulkan");
|
||||||
const base = @import("base");
|
const base = @import("base");
|
||||||
|
|
||||||
|
const SoftImage = @import("SoftImage.zig");
|
||||||
|
|
||||||
const cmd = base.commands;
|
const cmd = base.commands;
|
||||||
const VkError = base.VkError;
|
const VkError = base.VkError;
|
||||||
|
|
||||||
@@ -27,22 +29,8 @@ pub fn dispatch(self: *Self, command: *const cmd.Command) VkError!void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn clearColorImage(data: *const cmd.CommandClearColorImage) VkError!void {
|
fn clearColorImage(data: *const cmd.CommandClearColorImage) VkError!void {
|
||||||
// TODO: use a blitter
|
const soft_image: *SoftImage = @alignCast(@fieldParentPtr("interface", data.image));
|
||||||
|
soft_image.clearRange(data.clear_color, data.range);
|
||||||
const image = data.image;
|
|
||||||
for (data.ranges) |range| {
|
|
||||||
const image_size = image.getTotalSize();
|
|
||||||
|
|
||||||
const memory = if (image.memory) |memory| memory else return VkError.ValidationFailed;
|
|
||||||
var memory_map: []u32 = @as([*]u32, @ptrCast(@alignCast(try memory.map(0, image_size))))[0..image_size];
|
|
||||||
|
|
||||||
_ = range;
|
|
||||||
_ = &memory_map;
|
|
||||||
|
|
||||||
base.logger.fixme("Implement image clear", .{});
|
|
||||||
|
|
||||||
memory.unmap();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn copyBuffer(data: *const cmd.CommandCopyBuffer) VkError!void {
|
fn copyBuffer(data: *const cmd.CommandCopyBuffer) VkError!void {
|
||||||
|
|||||||
@@ -63,13 +63,13 @@ pub fn reset(interface: *Interface, flags: vk.CommandBufferResetFlags) VkError!v
|
|||||||
|
|
||||||
// Commands ====================================================================================================
|
// Commands ====================================================================================================
|
||||||
|
|
||||||
pub fn clearColorImage(interface: *Interface, image: *base.Image, layout: vk.ImageLayout, color: *const vk.ClearColorValue, ranges: []const vk.ImageSubresourceRange) VkError!void {
|
pub fn clearColorImage(interface: *Interface, image: *base.Image, layout: vk.ImageLayout, color: *const vk.ClearColorValue, range: vk.ImageSubresourceRange) VkError!void {
|
||||||
// No-op
|
// No-op
|
||||||
_ = interface;
|
_ = interface;
|
||||||
_ = image;
|
_ = image;
|
||||||
_ = layout;
|
_ = layout;
|
||||||
_ = color;
|
_ = color;
|
||||||
_ = ranges;
|
_ = range;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fillBuffer(interface: *Interface, buffer: *base.Buffer, offset: vk.DeviceSize, size: vk.DeviceSize, data: u32) VkError!void {
|
pub fn fillBuffer(interface: *Interface, buffer: *base.Buffer, offset: vk.DeviceSize, size: vk.DeviceSize, data: u32) VkError!void {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ const builtin = @import("builtin");
|
|||||||
const Debug = std.builtin.OptimizeMode.Debug;
|
const Debug = std.builtin.OptimizeMode.Debug;
|
||||||
|
|
||||||
const SoftQueue = @import("SoftQueue.zig");
|
const SoftQueue = @import("SoftQueue.zig");
|
||||||
|
const Blitter = @import("device/Blitter.zig");
|
||||||
|
|
||||||
pub const SoftBinarySemaphore = @import("SoftBinarySemaphore.zig");
|
pub const SoftBinarySemaphore = @import("SoftBinarySemaphore.zig");
|
||||||
pub const SoftBuffer = @import("SoftBuffer.zig");
|
pub const SoftBuffer = @import("SoftBuffer.zig");
|
||||||
@@ -38,6 +39,7 @@ const SpawnError = std.Thread.SpawnError;
|
|||||||
interface: Interface,
|
interface: Interface,
|
||||||
device_allocator: if (builtin.mode == Debug) std.heap.DebugAllocator(.{}) else std.heap.ThreadSafeAllocator,
|
device_allocator: if (builtin.mode == Debug) std.heap.DebugAllocator(.{}) else std.heap.ThreadSafeAllocator,
|
||||||
workers: std.Thread.Pool,
|
workers: std.Thread.Pool,
|
||||||
|
blitter: Blitter,
|
||||||
|
|
||||||
pub fn create(physical_device: *base.PhysicalDevice, allocator: std.mem.Allocator, info: *const vk.DeviceCreateInfo) VkError!*Self {
|
pub fn create(physical_device: *base.PhysicalDevice, allocator: std.mem.Allocator, info: *const vk.DeviceCreateInfo) VkError!*Self {
|
||||||
const self = allocator.create(Self) catch return VkError.OutOfHostMemory;
|
const self = allocator.create(Self) catch return VkError.OutOfHostMemory;
|
||||||
@@ -78,6 +80,7 @@ pub fn create(physical_device: *base.PhysicalDevice, allocator: std.mem.Allocato
|
|||||||
.interface = interface,
|
.interface = interface,
|
||||||
.device_allocator = if (builtin.mode == Debug) .init else .{ .child_allocator = std.heap.c_allocator }, // TODO: better device allocator
|
.device_allocator = if (builtin.mode == Debug) .init else .{ .child_allocator = std.heap.c_allocator }, // TODO: better device allocator
|
||||||
.workers = undefined,
|
.workers = undefined,
|
||||||
|
.blitter = .init,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.workers.init(.{ .allocator = self.device_allocator.allocator() }) catch |err| return switch (err) {
|
self.workers.init(.{ .allocator = self.device_allocator.allocator() }) catch |err| return switch (err) {
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ const lib = @import("lib.zig");
|
|||||||
const VkError = base.VkError;
|
const VkError = base.VkError;
|
||||||
const Device = base.Device;
|
const Device = base.Device;
|
||||||
|
|
||||||
|
const SoftDevice = @import("SoftDevice.zig");
|
||||||
|
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
pub const Interface = base.Image;
|
pub const Interface = base.Image;
|
||||||
|
|
||||||
@@ -38,3 +40,20 @@ pub fn getMemoryRequirements(interface: *Interface, requirements: *vk.MemoryRequ
|
|||||||
_ = interface;
|
_ = interface;
|
||||||
requirements.alignment = lib.MEMORY_REQUIREMENTS_IMAGE_ALIGNMENT;
|
requirements.alignment = lib.MEMORY_REQUIREMENTS_IMAGE_ALIGNMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline fn clear(self: *Self, pixel: *const anyopaque, format: vk.Format, view_format: vk.Format, range: vk.ImageSubresourceRange, area: ?vk.Rect2D) void {
|
||||||
|
const soft_device: *SoftDevice = @alignCast(@fieldParentPtr("interface", self.interface.owner));
|
||||||
|
soft_device.blitter.clear(pixel, format, self, view_format, range, area);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clearRange(self: *Self, color: vk.ClearColorValue, range: vk.ImageSubresourceRange) void {
|
||||||
|
std.debug.assert(range.aspect_mask == vk.ImageAspectFlags{ .color_bit = true });
|
||||||
|
|
||||||
|
const clear_format: vk.Format = if (base.vku.vkuFormatIsSINT(@intCast(@intFromEnum(self.interface.format))))
|
||||||
|
.r32g32b32a32_sint
|
||||||
|
else if (base.vku.vkuFormatIsUINT(@intCast(@intFromEnum(self.interface.format))))
|
||||||
|
.r32g32b32a32_uint
|
||||||
|
else
|
||||||
|
.r32g32b32a32_sfloat;
|
||||||
|
self.clear(@ptrCast(&color.float_32), clear_format, self.interface.format, range, null);
|
||||||
|
}
|
||||||
|
|||||||
27
src/soft/device/Blitter.zig
git.filemode.normal_file
27
src/soft/device/Blitter.zig
git.filemode.normal_file
@@ -0,0 +1,27 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const vk = @import("vulkan");
|
||||||
|
const base = @import("base");
|
||||||
|
|
||||||
|
pub const SoftImage = @import("../SoftImage.zig");
|
||||||
|
pub const SoftImageView = @import("../SoftImageView.zig");
|
||||||
|
|
||||||
|
const Self = @This();
|
||||||
|
|
||||||
|
blit_mutex: std.Thread.Mutex,
|
||||||
|
|
||||||
|
pub const init: Self = .{
|
||||||
|
.blit_mutex = .{},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn clear(self: *Self, pixel: *const anyopaque, format: vk.Format, dest: *SoftImage, view_format: vk.Format, range: vk.ImageSubresourceRange, area: ?vk.Rect2D) void {
|
||||||
|
const dst_format = base.Image.formatFromAspect(view_format, range.aspect_mask);
|
||||||
|
if (dst_format == .undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = self;
|
||||||
|
_ = pixel;
|
||||||
|
_ = format;
|
||||||
|
_ = dest;
|
||||||
|
_ = area;
|
||||||
|
}
|
||||||
@@ -40,7 +40,7 @@ dispatch_table: *const DispatchTable,
|
|||||||
|
|
||||||
pub const DispatchTable = struct {
|
pub const DispatchTable = struct {
|
||||||
begin: *const fn (*Self, *const vk.CommandBufferBeginInfo) VkError!void,
|
begin: *const fn (*Self, *const vk.CommandBufferBeginInfo) VkError!void,
|
||||||
clearColorImage: *const fn (*Self, *Image, vk.ImageLayout, *const vk.ClearColorValue, []const vk.ImageSubresourceRange) VkError!void,
|
clearColorImage: *const fn (*Self, *Image, vk.ImageLayout, *const vk.ClearColorValue, vk.ImageSubresourceRange) VkError!void,
|
||||||
copyBuffer: *const fn (*Self, *Buffer, *Buffer, []const vk.BufferCopy) VkError!void,
|
copyBuffer: *const fn (*Self, *Buffer, *Buffer, []const vk.BufferCopy) VkError!void,
|
||||||
copyImage: *const fn (*Self, *Image, vk.ImageLayout, *Image, vk.ImageLayout, []const vk.ImageCopy) VkError!void,
|
copyImage: *const fn (*Self, *Image, vk.ImageLayout, *Image, vk.ImageLayout, []const vk.ImageCopy) VkError!void,
|
||||||
end: *const fn (*Self) VkError!void,
|
end: *const fn (*Self) VkError!void,
|
||||||
@@ -122,7 +122,6 @@ fn cleanCommandList(self: *Self) void {
|
|||||||
const allocator = self.host_allocator.allocator();
|
const allocator = self.host_allocator.allocator();
|
||||||
for (self.commands.items) |command| {
|
for (self.commands.items) |command| {
|
||||||
switch (command) {
|
switch (command) {
|
||||||
.ClearColorImage => |data| allocator.free(data.ranges),
|
|
||||||
.CopyBuffer => |data| allocator.free(data.regions),
|
.CopyBuffer => |data| allocator.free(data.regions),
|
||||||
.CopyImage => |data| allocator.free(data.regions),
|
.CopyImage => |data| allocator.free(data.regions),
|
||||||
else => {},
|
else => {},
|
||||||
@@ -134,13 +133,15 @@ fn cleanCommandList(self: *Self) void {
|
|||||||
|
|
||||||
pub inline fn clearColorImage(self: *Self, image: *Image, layout: vk.ImageLayout, color: *const vk.ClearColorValue, ranges: []const vk.ImageSubresourceRange) VkError!void {
|
pub inline fn clearColorImage(self: *Self, image: *Image, layout: vk.ImageLayout, color: *const vk.ClearColorValue, ranges: []const vk.ImageSubresourceRange) VkError!void {
|
||||||
const allocator = self.host_allocator.allocator();
|
const allocator = self.host_allocator.allocator();
|
||||||
|
for (ranges) |range| {
|
||||||
self.commands.append(allocator, .{ .ClearColorImage = .{
|
self.commands.append(allocator, .{ .ClearColorImage = .{
|
||||||
.image = image,
|
.image = image,
|
||||||
.layout = layout,
|
.layout = layout,
|
||||||
.clear_color = color.*,
|
.clear_color = color.*,
|
||||||
.ranges = allocator.dupe(vk.ImageSubresourceRange, ranges) catch return VkError.OutOfHostMemory,
|
.range = range,
|
||||||
} }) catch return VkError.OutOfHostMemory;
|
} }) catch return VkError.OutOfHostMemory;
|
||||||
try self.dispatch_table.clearColorImage(self, image, layout, color, ranges);
|
try self.dispatch_table.clearColorImage(self, image, layout, color, range);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub inline fn copyBuffer(self: *Self, src: *Buffer, dst: *Buffer, regions: []const vk.BufferCopy) VkError!void {
|
pub inline fn copyBuffer(self: *Self, src: *Buffer, dst: *Buffer, regions: []const vk.BufferCopy) VkError!void {
|
||||||
|
|||||||
@@ -125,3 +125,23 @@ pub fn formatSupportsColorAttachemendBlend(format: vk.Format) bool {
|
|||||||
else => false,
|
else => false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn formatFromAspect(base_format: vk.Format, aspect: vk.ImageAspectFlags) vk.Format {
|
||||||
|
if (aspect.color_bit or (aspect.color_bit and aspect.stencil_bit)) {
|
||||||
|
return base_format;
|
||||||
|
} else if (aspect.depth_bit) {
|
||||||
|
if (base_format == .d16_unorm or base_format == .d16_unorm_s8_uint) {
|
||||||
|
return .d16_unorm;
|
||||||
|
} else if (base_format == .d24_unorm_s8_uint) {
|
||||||
|
return .x8_d24_unorm_pack32;
|
||||||
|
} else if (base_format == .d32_sfloat or base_format == .d32_sfloat_s8_uint) {
|
||||||
|
return .d32_sfloat;
|
||||||
|
}
|
||||||
|
} else if (aspect.stencil_bit) {
|
||||||
|
if (base_format == .s8_uint or base_format == .d16_unorm_s8_uint or base_format == .d24_unorm_s8_uint or base_format == .d32_sfloat_s8_uint) {
|
||||||
|
return .s8_uint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lib.unsupported("format {d}", .{@intFromEnum(base_format)});
|
||||||
|
return base_format;
|
||||||
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ pub const CommandClearColorImage = struct {
|
|||||||
image: *Image,
|
image: *Image,
|
||||||
layout: vk.ImageLayout,
|
layout: vk.ImageLayout,
|
||||||
clear_color: vk.ClearColorValue,
|
clear_color: vk.ClearColorValue,
|
||||||
ranges: []const vk.ImageSubresourceRange,
|
range: vk.ImageSubresourceRange,
|
||||||
};
|
};
|
||||||
pub const CommandCopyBuffer = struct {
|
pub const CommandCopyBuffer = struct {
|
||||||
src: *Buffer,
|
src: *Buffer,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
//! Here lies the documentation of the common internal API that backends need to implement
|
//! Here lies the documentation of the common internal API that backends need to implement
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const builtin = @import("builtin");
|
||||||
const vk = @import("vulkan");
|
const vk = @import("vulkan");
|
||||||
pub const vku = @cImport({
|
pub const vku = @cImport({
|
||||||
@cInclude("vulkan/utility/vk_format_utils.h");
|
@cInclude("vulkan/utility/vk_format_utils.h");
|
||||||
@@ -79,6 +80,14 @@ pub inline fn getLogVerboseLevel() LogVerboseLevel {
|
|||||||
.Standard;
|
.Standard;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn unsupported(comptime fmt: []const u8, args: anytype) void {
|
||||||
|
if (builtin.mode == std.builtin.OptimizeMode.Debug) {
|
||||||
|
std.debug.panic("UNSUPPORTED " ++ fmt, args);
|
||||||
|
} else {
|
||||||
|
std.log.scoped(.UNSUPPORTED).warn(fmt, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
comptime {
|
comptime {
|
||||||
_ = lib_vulkan;
|
_ = lib_vulkan;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user