adding descriptor bindings
This commit is contained in:
@@ -22,6 +22,7 @@ pub fn create(device: *base.Device, allocator: std.mem.Allocator, info: *const v
|
|||||||
|
|
||||||
interface.dispatch_table = &.{
|
interface.dispatch_table = &.{
|
||||||
.begin = begin,
|
.begin = begin,
|
||||||
|
.bindDescriptorSets = bindDescriptorSets,
|
||||||
.bindPipeline = bindPipeline,
|
.bindPipeline = bindPipeline,
|
||||||
.clearColorImage = clearColorImage,
|
.clearColorImage = clearColorImage,
|
||||||
.copyBuffer = copyBuffer,
|
.copyBuffer = copyBuffer,
|
||||||
@@ -65,6 +66,15 @@ pub fn reset(interface: *Interface, flags: vk.CommandBufferResetFlags) VkError!v
|
|||||||
|
|
||||||
// Commands ====================================================================================================
|
// Commands ====================================================================================================
|
||||||
|
|
||||||
|
pub fn bindDescriptorSets(interface: *Interface, bind_point: vk.PipelineBindPoint, first_set: u32, sets: [base.VULKAN_MAX_DESCRIPTOR_SETS]?*base.DescriptorSet, dynamic_offsets: []const u32) VkError!void {
|
||||||
|
// No-op
|
||||||
|
_ = interface;
|
||||||
|
_ = bind_point;
|
||||||
|
_ = first_set;
|
||||||
|
_ = sets;
|
||||||
|
_ = dynamic_offsets;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn bindPipeline(interface: *Interface, bind_point: vk.PipelineBindPoint, pipeline: *base.Pipeline) VkError!void {
|
pub fn bindPipeline(interface: *Interface, bind_point: vk.PipelineBindPoint, pipeline: *base.Pipeline) VkError!void {
|
||||||
_ = interface;
|
_ = interface;
|
||||||
_ = pipeline;
|
_ = pipeline;
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ pub fn create(allocator: std.mem.Allocator, instance: *const base.Instance) VkEr
|
|||||||
.max_sampler_allocation_count = 4096,
|
.max_sampler_allocation_count = 4096,
|
||||||
.buffer_image_granularity = 131072,
|
.buffer_image_granularity = 131072,
|
||||||
.sparse_address_space_size = 0,
|
.sparse_address_space_size = 0,
|
||||||
.max_bound_descriptor_sets = 4,
|
.max_bound_descriptor_sets = base.VULKAN_MAX_DESCRIPTOR_SETS,
|
||||||
.max_per_stage_descriptor_samplers = 16,
|
.max_per_stage_descriptor_samplers = 16,
|
||||||
.max_per_stage_descriptor_uniform_buffers = 12,
|
.max_per_stage_descriptor_uniform_buffers = 12,
|
||||||
.max_per_stage_descriptor_storage_buffers = 4,
|
.max_per_stage_descriptor_storage_buffers = 4,
|
||||||
|
|||||||
@@ -6,11 +6,19 @@ const spv = @import("spv");
|
|||||||
const VkError = base.VkError;
|
const VkError = base.VkError;
|
||||||
const Device = base.Device;
|
const Device = base.Device;
|
||||||
|
|
||||||
|
const NonDispatchable = base.NonDispatchable;
|
||||||
|
const ShaderModule = base.ShaderModule;
|
||||||
|
|
||||||
|
const SoftDevice = @import("SoftDevice.zig");
|
||||||
|
const SoftShaderModule = @import("SoftShaderModule.zig");
|
||||||
|
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
pub const Interface = base.Pipeline;
|
pub const Interface = base.Pipeline;
|
||||||
|
|
||||||
interface: Interface,
|
interface: Interface,
|
||||||
|
|
||||||
|
runtimes: []spv.Runtime,
|
||||||
|
|
||||||
pub fn createCompute(device: *base.Device, allocator: std.mem.Allocator, cache: ?*base.PipelineCache, info: *const vk.ComputePipelineCreateInfo) VkError!*Self {
|
pub fn createCompute(device: *base.Device, allocator: std.mem.Allocator, cache: ?*base.PipelineCache, info: *const vk.ComputePipelineCreateInfo) VkError!*Self {
|
||||||
const self = allocator.create(Self) catch return VkError.OutOfHostMemory;
|
const self = allocator.create(Self) catch return VkError.OutOfHostMemory;
|
||||||
errdefer allocator.destroy(self);
|
errdefer allocator.destroy(self);
|
||||||
@@ -21,8 +29,23 @@ pub fn createCompute(device: *base.Device, allocator: std.mem.Allocator, cache:
|
|||||||
.destroy = destroy,
|
.destroy = destroy,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const soft_device: *SoftDevice = @alignCast(@fieldParentPtr("interface", device));
|
||||||
|
const module = try NonDispatchable(ShaderModule).fromHandleObject(info.stage.module);
|
||||||
|
const soft_module: *SoftShaderModule = @alignCast(@fieldParentPtr("interface", module));
|
||||||
|
|
||||||
|
const runtimes = allocator.alloc(spv.Runtime, soft_device.workers.getIdCount()) catch return VkError.OutOfHostMemory;
|
||||||
|
errdefer allocator.free(runtimes);
|
||||||
|
|
||||||
|
for (runtimes) |*runtime| {
|
||||||
|
runtime.* = spv.Runtime.init(allocator, &soft_module.module) catch |err| {
|
||||||
|
std.log.scoped(.SpvRuntimeInit).err("SPIR-V Runtime failed to initialize, {s}", .{@errorName(err)});
|
||||||
|
return VkError.Unknown;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
self.* = .{
|
self.* = .{
|
||||||
.interface = interface,
|
.interface = interface,
|
||||||
|
.runtimes = runtimes,
|
||||||
};
|
};
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
@@ -37,13 +60,30 @@ pub fn createGraphics(device: *base.Device, allocator: std.mem.Allocator, cache:
|
|||||||
.destroy = destroy,
|
.destroy = destroy,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const soft_device: *SoftDevice = @alignCast(@fieldParentPtr("interface", device));
|
||||||
|
|
||||||
|
const runtimes = allocator.alloc(spv.Runtime, soft_device.workers.getIdCount()) catch return VkError.OutOfHostMemory;
|
||||||
|
errdefer allocator.free(runtimes);
|
||||||
|
|
||||||
|
//for (runtimes) |*runtime| {
|
||||||
|
// runtime.* = spv.Runtime.init() catch |err| {
|
||||||
|
// std.log.scoped(.SpvRuntimeInit).err("SPIR-V Runtime failed to initialize, {s}", .{@errorName(err)});
|
||||||
|
// return VkError.Unknown;
|
||||||
|
// };
|
||||||
|
//}
|
||||||
|
|
||||||
self.* = .{
|
self.* = .{
|
||||||
.interface = interface,
|
.interface = interface,
|
||||||
|
.runtimes = runtimes,
|
||||||
};
|
};
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn destroy(interface: *Interface, allocator: std.mem.Allocator) void {
|
pub fn destroy(interface: *Interface, allocator: std.mem.Allocator) void {
|
||||||
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
|
const self: *Self = @alignCast(@fieldParentPtr("interface", interface));
|
||||||
|
for (self.runtimes) |*runtime| {
|
||||||
|
runtime.deinit(allocator);
|
||||||
|
}
|
||||||
|
allocator.free(self.runtimes);
|
||||||
allocator.destroy(self);
|
allocator.destroy(self);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ pub fn submit(interface: *Interface, infos: []Interface.SubmitInfo, p_fence: ?*b
|
|||||||
defer self.lock.unlockShared();
|
defer self.lock.unlockShared();
|
||||||
|
|
||||||
for (infos) |info| {
|
for (infos) |info| {
|
||||||
// Cloning info to keep them alive until commands dispatch end
|
// Cloning info to keep them alive until command execution ends
|
||||||
const cloned_info: Interface.SubmitInfo = .{
|
const cloned_info: Interface.SubmitInfo = .{
|
||||||
.command_buffers = info.command_buffers.clone(allocator) catch return VkError.OutOfDeviceMemory,
|
.command_buffers = info.command_buffers.clone(allocator) catch return VkError.OutOfDeviceMemory,
|
||||||
};
|
};
|
||||||
@@ -100,10 +100,10 @@ fn taskRunner(self: *Self, info: Interface.SubmitInfo, p_fence: ?*base.Fence, ru
|
|||||||
var device = Device.init(soft_device);
|
var device = Device.init(soft_device);
|
||||||
defer device.deinit();
|
defer device.deinit();
|
||||||
|
|
||||||
loop: for (info.command_buffers.items) |command_buffer| {
|
for (info.command_buffers.items) |command_buffer| {
|
||||||
command_buffer.submit() catch continue :loop;
|
command_buffer.submit() catch continue;
|
||||||
for (command_buffer.commands.items) |command| {
|
for (command_buffer.commands.items) |command| {
|
||||||
device.dispatch(&command) catch |err| base.errors.errorLoggerContext(err, "the software command dispatcher");
|
device.execute(&command) catch |err| base.errors.errorLoggerContext(err, "the software command dispatcher");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ const vk = @import("vulkan");
|
|||||||
const base = @import("base");
|
const base = @import("base");
|
||||||
const spv = @import("spv");
|
const spv = @import("spv");
|
||||||
|
|
||||||
|
const PipelineState = @import("PipelineState.zig");
|
||||||
|
|
||||||
const SoftDevice = @import("../SoftDevice.zig");
|
const SoftDevice = @import("../SoftDevice.zig");
|
||||||
const SoftPipeline = @import("../SoftPipeline.zig");
|
const SoftPipeline = @import("../SoftPipeline.zig");
|
||||||
|
|
||||||
@@ -11,19 +13,15 @@ const VkError = base.VkError;
|
|||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
|
||||||
device: *SoftDevice,
|
device: *SoftDevice,
|
||||||
pipeline: ?*SoftPipeline,
|
state: *PipelineState,
|
||||||
|
|
||||||
pub fn init(device: *SoftDevice) Self {
|
pub fn init(device: *SoftDevice, state: *PipelineState) Self {
|
||||||
return .{
|
return .{
|
||||||
.device = device,
|
.device = device,
|
||||||
.pipeline = null,
|
.state = state,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn destroy(self: *Self) void {
|
pub fn destroy(self: *Self) void {
|
||||||
_ = self;
|
_ = self;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bindPipeline(self: *Self, pipeline: *SoftPipeline) void {
|
|
||||||
self.pipeline = pipeline;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -2,11 +2,14 @@ const std = @import("std");
|
|||||||
const vk = @import("vulkan");
|
const vk = @import("vulkan");
|
||||||
const base = @import("base");
|
const base = @import("base");
|
||||||
|
|
||||||
|
const copy_routines = @import("copy_routines.zig");
|
||||||
|
|
||||||
|
const SoftDescriptorSet = @import("../SoftDescriptorSet.zig");
|
||||||
const SoftDevice = @import("../SoftDevice.zig");
|
const SoftDevice = @import("../SoftDevice.zig");
|
||||||
const SoftImage = @import("../SoftImage.zig");
|
|
||||||
const SoftPipeline = @import("../SoftPipeline.zig");
|
const SoftPipeline = @import("../SoftPipeline.zig");
|
||||||
|
|
||||||
const ComputeRoutines = @import("ComputeRoutines.zig");
|
const ComputeRoutines = @import("ComputeRoutines.zig");
|
||||||
|
const PipelineState = @import("PipelineState.zig");
|
||||||
|
|
||||||
const cmd = base.commands;
|
const cmd = base.commands;
|
||||||
const VkError = base.VkError;
|
const VkError = base.VkError;
|
||||||
@@ -15,108 +18,43 @@ const Self = @This();
|
|||||||
|
|
||||||
compute_routine: ComputeRoutines,
|
compute_routine: ComputeRoutines,
|
||||||
|
|
||||||
|
/// .graphics = 0
|
||||||
|
/// .compute = 1
|
||||||
|
pipeline_states: [2]PipelineState,
|
||||||
|
|
||||||
pub fn init(device: *SoftDevice) Self {
|
pub fn init(device: *SoftDevice) Self {
|
||||||
return .{
|
var self: Self = undefined;
|
||||||
.compute_routine = .init(device),
|
|
||||||
|
for (self.pipeline_states[0..]) |*state| {
|
||||||
|
state.* = .{
|
||||||
|
.pipeline = null,
|
||||||
|
.sets = [_]?*SoftDescriptorSet{null} ** base.VULKAN_MAX_DESCRIPTOR_SETS,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.compute_routine = .init(device, &self.pipeline_states[@intFromEnum(vk.PipelineBindPoint.compute)]);
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *Self) void {
|
pub fn deinit(self: *Self) void {
|
||||||
self.compute_routine.destroy();
|
self.compute_routine.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dispatch(self: *Self, command: *const cmd.Command) VkError!void {
|
pub fn execute(self: *Self, command: *const cmd.Command) VkError!void {
|
||||||
switch (command.*) {
|
switch (command.*) {
|
||||||
.BindPipeline => |data| {
|
.BindDescriptorSets => |data| {
|
||||||
if (data.bind_point == .compute) {
|
for (data.first_set.., data.sets[0..]) |i, set| {
|
||||||
self.compute_routine.bindPipeline(@alignCast(@fieldParentPtr("interface", data.pipeline)));
|
if (set == null) break;
|
||||||
} else {
|
self.pipeline_states[@intCast(@intFromEnum(data.bind_point))].sets[i] = @alignCast(@fieldParentPtr("interface", set.?));
|
||||||
// TODO
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.ClearColorImage => |data| try clearColorImage(&data),
|
.BindPipeline => |data| self.pipeline_states[@intCast(@intFromEnum(data.bind_point))].pipeline = @alignCast(@fieldParentPtr("interface", data.pipeline)),
|
||||||
.CopyBuffer => |data| try copyBuffer(&data),
|
.ClearColorImage => |data| try copy_routines.clearColorImage(&data),
|
||||||
.CopyImage => |data| try copyImage(&data),
|
.CopyBuffer => |data| try copy_routines.copyBuffer(&data),
|
||||||
.CopyImageToBuffer => |data| try copyImageToBuffer(&data),
|
.CopyImage => |data| try copy_routines.copyImage(&data),
|
||||||
.FillBuffer => |data| try fillBuffer(&data),
|
.CopyImageToBuffer => |data| try copy_routines.copyImageToBuffer(&data),
|
||||||
|
.FillBuffer => |data| try copy_routines.fillBuffer(&data),
|
||||||
else => {},
|
else => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clearColorImage(data: *const cmd.CommandClearColorImage) VkError!void {
|
|
||||||
const soft_image: *SoftImage = @alignCast(@fieldParentPtr("interface", data.image));
|
|
||||||
soft_image.clearRange(data.clear_color, data.range);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn copyBuffer(data: *const cmd.CommandCopyBuffer) VkError!void {
|
|
||||||
for (data.regions) |region| {
|
|
||||||
const src_memory = if (data.src.memory) |memory| memory else return VkError.ValidationFailed;
|
|
||||||
const dst_memory = if (data.dst.memory) |memory| memory else return VkError.ValidationFailed;
|
|
||||||
|
|
||||||
const src_map: []u8 = @as([*]u8, @ptrCast(try src_memory.map(region.src_offset, region.size)))[0..region.size];
|
|
||||||
const dst_map: []u8 = @as([*]u8, @ptrCast(try dst_memory.map(region.dst_offset, region.size)))[0..region.size];
|
|
||||||
|
|
||||||
@memcpy(dst_map, src_map);
|
|
||||||
|
|
||||||
src_memory.unmap();
|
|
||||||
dst_memory.unmap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn copyImage(data: *const cmd.CommandCopyImage) VkError!void {
|
|
||||||
_ = data;
|
|
||||||
std.log.scoped(.commandExecutor).warn("FIXME: implement image to image copy", .{});
|
|
||||||
}
|
|
||||||
|
|
||||||
fn copyImageToBuffer(data: *const cmd.CommandCopyImageToBuffer) VkError!void {
|
|
||||||
for (data.regions) |region| {
|
|
||||||
const src_memory = if (data.src.memory) |memory| memory else return VkError.ValidationFailed;
|
|
||||||
const dst_memory = if (data.dst.memory) |memory| memory else return VkError.ValidationFailed;
|
|
||||||
|
|
||||||
const pixel_size: u32 = @intCast(data.src.getPixelSize());
|
|
||||||
const image_row_pitch: u32 = data.src.extent.width * pixel_size;
|
|
||||||
const image_size: u32 = @intCast(data.src.getTotalSize());
|
|
||||||
|
|
||||||
const buffer_row_length: u32 = if (region.buffer_row_length != 0) region.buffer_row_length else region.image_extent.width;
|
|
||||||
const buffer_row_pitch: u32 = buffer_row_length * pixel_size;
|
|
||||||
const buffer_size: u32 = buffer_row_pitch * region.image_extent.height * region.image_extent.depth;
|
|
||||||
|
|
||||||
const src_map: []u8 = @as([*]u8, @ptrCast(try src_memory.map(0, image_size)))[0..image_size];
|
|
||||||
const dst_map: []u8 = @as([*]u8, @ptrCast(try dst_memory.map(region.buffer_offset, buffer_size)))[0..buffer_size];
|
|
||||||
|
|
||||||
const row_size = region.image_extent.width * pixel_size;
|
|
||||||
for (0..data.src.extent.depth) |z| {
|
|
||||||
for (0..data.src.extent.height) |y| {
|
|
||||||
const z_as_u32: u32 = @intCast(z);
|
|
||||||
const y_as_u32: u32 = @intCast(y);
|
|
||||||
|
|
||||||
const src_offset = ((@as(u32, @intCast(region.image_offset.z)) + z_as_u32) * data.src.extent.height + @as(u32, @intCast(region.image_offset.y)) + y_as_u32) * image_row_pitch + @as(u32, @intCast(region.image_offset.x)) * pixel_size;
|
|
||||||
const dst_offset = (z_as_u32 * buffer_row_length * region.image_extent.height + y_as_u32 * buffer_row_length) * pixel_size;
|
|
||||||
|
|
||||||
const src_slice = src_map[src_offset..(src_offset + row_size)];
|
|
||||||
const dst_slice = dst_map[dst_offset..(dst_offset + row_size)];
|
|
||||||
@memcpy(dst_slice, src_slice);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
src_memory.unmap();
|
|
||||||
dst_memory.unmap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fillBuffer(data: *const cmd.CommandFillBuffer) VkError!void {
|
|
||||||
const memory = if (data.buffer.memory) |memory| memory else return VkError.ValidationFailed;
|
|
||||||
var memory_map: []u32 = @as([*]u32, @ptrCast(@alignCast(try memory.map(data.offset, data.size))))[0..data.size];
|
|
||||||
|
|
||||||
var bytes = if (data.size == vk.WHOLE_SIZE) memory.size - data.offset else data.size;
|
|
||||||
|
|
||||||
var i: usize = 0;
|
|
||||||
while (bytes >= 4) : ({
|
|
||||||
bytes -= 4;
|
|
||||||
i += 1;
|
|
||||||
}) {
|
|
||||||
memory_map[i] = data.data;
|
|
||||||
}
|
|
||||||
|
|
||||||
memory.unmap();
|
|
||||||
}
|
|
||||||
|
|||||||
9
src/soft/device/PipelineState.zig
git.filemode.normal_file
9
src/soft/device/PipelineState.zig
git.filemode.normal_file
@@ -0,0 +1,9 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const vk = @import("vulkan");
|
||||||
|
const base = @import("base");
|
||||||
|
|
||||||
|
const SoftDescriptorSet = @import("../SoftDescriptorSet.zig");
|
||||||
|
const SoftPipeline = @import("../SoftPipeline.zig");
|
||||||
|
|
||||||
|
pipeline: ?*SoftPipeline,
|
||||||
|
sets: [base.VULKAN_MAX_DESCRIPTOR_SETS]?*SoftDescriptorSet,
|
||||||
86
src/soft/device/copy_routines.zig
git.filemode.normal_file
86
src/soft/device/copy_routines.zig
git.filemode.normal_file
@@ -0,0 +1,86 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const vk = @import("vulkan");
|
||||||
|
const base = @import("base");
|
||||||
|
|
||||||
|
const cmd = base.commands;
|
||||||
|
const VkError = base.VkError;
|
||||||
|
|
||||||
|
const SoftImage = @import("../SoftImage.zig");
|
||||||
|
|
||||||
|
pub fn clearColorImage(data: *const cmd.CommandClearColorImage) VkError!void {
|
||||||
|
const soft_image: *SoftImage = @alignCast(@fieldParentPtr("interface", data.image));
|
||||||
|
soft_image.clearRange(data.clear_color, data.range);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn copyBuffer(data: *const cmd.CommandCopyBuffer) VkError!void {
|
||||||
|
for (data.regions) |region| {
|
||||||
|
const src_memory = if (data.src.memory) |memory| memory else return VkError.ValidationFailed;
|
||||||
|
const dst_memory = if (data.dst.memory) |memory| memory else return VkError.ValidationFailed;
|
||||||
|
|
||||||
|
const src_map: []u8 = @as([*]u8, @ptrCast(try src_memory.map(region.src_offset, region.size)))[0..region.size];
|
||||||
|
const dst_map: []u8 = @as([*]u8, @ptrCast(try dst_memory.map(region.dst_offset, region.size)))[0..region.size];
|
||||||
|
|
||||||
|
@memcpy(dst_map, src_map);
|
||||||
|
|
||||||
|
src_memory.unmap();
|
||||||
|
dst_memory.unmap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn copyImage(data: *const cmd.CommandCopyImage) VkError!void {
|
||||||
|
_ = data;
|
||||||
|
std.log.scoped(.commandExecutor).warn("FIXME: implement image to image copy", .{});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn copyImageToBuffer(data: *const cmd.CommandCopyImageToBuffer) VkError!void {
|
||||||
|
for (data.regions) |region| {
|
||||||
|
const src_memory = if (data.src.memory) |memory| memory else return VkError.ValidationFailed;
|
||||||
|
const dst_memory = if (data.dst.memory) |memory| memory else return VkError.ValidationFailed;
|
||||||
|
|
||||||
|
const pixel_size: u32 = @intCast(data.src.getPixelSize());
|
||||||
|
const image_row_pitch: u32 = data.src.extent.width * pixel_size;
|
||||||
|
const image_size: u32 = @intCast(data.src.getTotalSize());
|
||||||
|
|
||||||
|
const buffer_row_length: u32 = if (region.buffer_row_length != 0) region.buffer_row_length else region.image_extent.width;
|
||||||
|
const buffer_row_pitch: u32 = buffer_row_length * pixel_size;
|
||||||
|
const buffer_size: u32 = buffer_row_pitch * region.image_extent.height * region.image_extent.depth;
|
||||||
|
|
||||||
|
const src_map: []u8 = @as([*]u8, @ptrCast(try src_memory.map(0, image_size)))[0..image_size];
|
||||||
|
const dst_map: []u8 = @as([*]u8, @ptrCast(try dst_memory.map(region.buffer_offset, buffer_size)))[0..buffer_size];
|
||||||
|
|
||||||
|
const row_size = region.image_extent.width * pixel_size;
|
||||||
|
for (0..data.src.extent.depth) |z| {
|
||||||
|
for (0..data.src.extent.height) |y| {
|
||||||
|
const z_as_u32: u32 = @intCast(z);
|
||||||
|
const y_as_u32: u32 = @intCast(y);
|
||||||
|
|
||||||
|
const src_offset = ((@as(u32, @intCast(region.image_offset.z)) + z_as_u32) * data.src.extent.height + @as(u32, @intCast(region.image_offset.y)) + y_as_u32) * image_row_pitch + @as(u32, @intCast(region.image_offset.x)) * pixel_size;
|
||||||
|
const dst_offset = (z_as_u32 * buffer_row_length * region.image_extent.height + y_as_u32 * buffer_row_length) * pixel_size;
|
||||||
|
|
||||||
|
const src_slice = src_map[src_offset..(src_offset + row_size)];
|
||||||
|
const dst_slice = dst_map[dst_offset..(dst_offset + row_size)];
|
||||||
|
@memcpy(dst_slice, src_slice);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
src_memory.unmap();
|
||||||
|
dst_memory.unmap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fillBuffer(data: *const cmd.CommandFillBuffer) VkError!void {
|
||||||
|
const memory = if (data.buffer.memory) |memory| memory else return VkError.ValidationFailed;
|
||||||
|
var memory_map: []u32 = @as([*]u32, @ptrCast(@alignCast(try memory.map(data.offset, data.size))))[0..data.size];
|
||||||
|
|
||||||
|
var bytes = if (data.size == vk.WHOLE_SIZE) memory.size - data.offset else data.size;
|
||||||
|
|
||||||
|
var i: usize = 0;
|
||||||
|
while (bytes >= 4) : ({
|
||||||
|
bytes -= 4;
|
||||||
|
i += 1;
|
||||||
|
}) {
|
||||||
|
memory_map[i] = data.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
memory.unmap();
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const vk = @import("vulkan");
|
const vk = @import("vulkan");
|
||||||
|
const lib = @import("lib.zig");
|
||||||
|
|
||||||
const cmd = @import("commands.zig");
|
const cmd = @import("commands.zig");
|
||||||
|
|
||||||
@@ -14,6 +15,7 @@ const CommandPool = @import("CommandPool.zig");
|
|||||||
const Event = @import("Event.zig");
|
const Event = @import("Event.zig");
|
||||||
const Image = @import("Image.zig");
|
const Image = @import("Image.zig");
|
||||||
const Pipeline = @import("Pipeline.zig");
|
const Pipeline = @import("Pipeline.zig");
|
||||||
|
const DescriptorSet = @import("DescriptorSet.zig");
|
||||||
|
|
||||||
const COMMAND_BUFFER_BASE_CAPACITY = 256;
|
const COMMAND_BUFFER_BASE_CAPACITY = 256;
|
||||||
|
|
||||||
@@ -40,6 +42,7 @@ vtable: *const VTable,
|
|||||||
dispatch_table: *const DispatchTable,
|
dispatch_table: *const DispatchTable,
|
||||||
|
|
||||||
pub const DispatchTable = struct {
|
pub const DispatchTable = struct {
|
||||||
|
bindDescriptorSets: *const fn (*Self, vk.PipelineBindPoint, u32, [lib.VULKAN_MAX_DESCRIPTOR_SETS]?*DescriptorSet, []const u32) VkError!void,
|
||||||
bindPipeline: *const fn (*Self, vk.PipelineBindPoint, *Pipeline) VkError!void,
|
bindPipeline: *const fn (*Self, vk.PipelineBindPoint, *Pipeline) VkError!void,
|
||||||
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, vk.ImageSubresourceRange) VkError!void,
|
clearColorImage: *const fn (*Self, *Image, vk.ImageLayout, *const vk.ClearColorValue, vk.ImageSubresourceRange) VkError!void,
|
||||||
@@ -135,6 +138,23 @@ fn cleanCommandList(self: *Self) void {
|
|||||||
|
|
||||||
// Commands ====================================================================================================
|
// Commands ====================================================================================================
|
||||||
|
|
||||||
|
pub inline fn bindDescriptorSets(self: *Self, bind_point: vk.PipelineBindPoint, first_set: u32, sets: []const vk.DescriptorSet, dynamic_offsets: []const u32) VkError!void {
|
||||||
|
const allocator = self.host_allocator.allocator();
|
||||||
|
|
||||||
|
var inner_sets = [_]?*DescriptorSet{null} ** lib.VULKAN_MAX_DESCRIPTOR_SETS;
|
||||||
|
for (sets, inner_sets[0..sets.len]) |set, *inner_set| {
|
||||||
|
inner_set.* = try NonDispatchable(DescriptorSet).fromHandleObject(set);
|
||||||
|
}
|
||||||
|
|
||||||
|
try self.dispatch_table.bindDescriptorSets(self, bind_point, first_set, inner_sets, dynamic_offsets);
|
||||||
|
self.commands.append(allocator, .{ .BindDescriptorSets = .{
|
||||||
|
.bind_point = bind_point,
|
||||||
|
.first_set = first_set,
|
||||||
|
.sets = inner_sets,
|
||||||
|
.dynamic_offsets = dynamic_offsets,
|
||||||
|
} }) catch return VkError.OutOfHostMemory;
|
||||||
|
}
|
||||||
|
|
||||||
pub inline fn bindPipeline(self: *Self, bind_point: vk.PipelineBindPoint, pipeline: *Pipeline) VkError!void {
|
pub inline fn bindPipeline(self: *Self, bind_point: vk.PipelineBindPoint, pipeline: *Pipeline) VkError!void {
|
||||||
const allocator = self.host_allocator.allocator();
|
const allocator = self.host_allocator.allocator();
|
||||||
try self.dispatch_table.bindPipeline(self, bind_point, pipeline);
|
try self.dispatch_table.bindPipeline(self, bind_point, pipeline);
|
||||||
|
|||||||
@@ -1,24 +1,18 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const vk = @import("vulkan");
|
const vk = @import("vulkan");
|
||||||
|
const lib = @import("lib.zig");
|
||||||
|
|
||||||
const Buffer = @import("Buffer.zig");
|
const Buffer = @import("Buffer.zig");
|
||||||
const Image = @import("Image.zig");
|
const Image = @import("Image.zig");
|
||||||
const Pipeline = @import("Pipeline.zig");
|
const Pipeline = @import("Pipeline.zig");
|
||||||
|
const DescriptorSet = @import("DescriptorSet.zig");
|
||||||
|
|
||||||
pub const CommandType = enum {
|
pub const CommandBindDescriptorSets = struct {
|
||||||
BindPipeline,
|
bind_point: vk.PipelineBindPoint,
|
||||||
BindVertexBuffer,
|
first_set: u32,
|
||||||
ClearColorImage,
|
sets: [lib.VULKAN_MAX_DESCRIPTOR_SETS]?*DescriptorSet,
|
||||||
CopyBuffer,
|
dynamic_offsets: []const u32,
|
||||||
CopyImage,
|
|
||||||
CopyImageToBuffer,
|
|
||||||
Draw,
|
|
||||||
DrawIndexed,
|
|
||||||
DrawIndexedIndirect,
|
|
||||||
DrawIndirect,
|
|
||||||
FillBuffer,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const CommandBindPipeline = struct {
|
pub const CommandBindPipeline = struct {
|
||||||
bind_point: vk.PipelineBindPoint,
|
bind_point: vk.PipelineBindPoint,
|
||||||
pipeline: *Pipeline,
|
pipeline: *Pipeline,
|
||||||
@@ -84,7 +78,8 @@ pub const CommandFillBuffer = struct {
|
|||||||
data: u32,
|
data: u32,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Command = union(CommandType) {
|
pub const Command = union(enum) {
|
||||||
|
BindDescriptorSets: CommandBindDescriptorSets,
|
||||||
BindPipeline: CommandBindPipeline,
|
BindPipeline: CommandBindPipeline,
|
||||||
BindVertexBuffer: CommandBindVertexBuffer,
|
BindVertexBuffer: CommandBindVertexBuffer,
|
||||||
ClearColorImage: CommandClearColorImage,
|
ClearColorImage: CommandClearColorImage,
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ pub const DRIVER_NAME = "Unnamed Stroll Driver";
|
|||||||
pub const VULKAN_VERSION = vk.makeApiVersion(0, 1, 0, 0);
|
pub const VULKAN_VERSION = vk.makeApiVersion(0, 1, 0, 0);
|
||||||
|
|
||||||
/// Maximum number of descriptor sets per pipeline
|
/// Maximum number of descriptor sets per pipeline
|
||||||
pub const VULKAN_MAX_DESCRIPTOR_SETS = 32;
|
pub const VULKAN_MAX_DESCRIPTOR_SETS = 4;
|
||||||
|
|
||||||
/// The number of push constant ranges is effectively bounded
|
/// The number of push constant ranges is effectively bounded
|
||||||
/// by the number of possible shader stages. Not the number of stages that can
|
/// by the number of possible shader stages. Not the number of stages that can
|
||||||
|
|||||||
@@ -1674,17 +1674,9 @@ pub export fn strollCmdBindDescriptorSets(
|
|||||||
defer entryPointEndLogTrace();
|
defer entryPointEndLogTrace();
|
||||||
|
|
||||||
const cmd = Dispatchable(CommandBuffer).fromHandleObject(p_cmd) catch |err| return errorLogger(err);
|
const cmd = Dispatchable(CommandBuffer).fromHandleObject(p_cmd) catch |err| return errorLogger(err);
|
||||||
|
cmd.bindDescriptorSets(bind_point, first, sets[0..count], dynamic_offsets[0..dynamic_offset_count]) catch |err| return errorLogger(err);
|
||||||
|
|
||||||
notImplementedWarning();
|
|
||||||
|
|
||||||
_ = cmd;
|
|
||||||
_ = bind_point;
|
|
||||||
_ = layout;
|
_ = layout;
|
||||||
_ = first;
|
|
||||||
_ = count;
|
|
||||||
_ = sets;
|
|
||||||
_ = dynamic_offsets;
|
|
||||||
_ = dynamic_offset_count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub export fn strollCmdBindIndexBuffer(p_cmd: vk.CommandBuffer, p_buffer: vk.Buffer, offset: vk.DeviceSize, index_type: vk.IndexType) callconv(vk.vulkan_call_conv) void {
|
pub export fn strollCmdBindIndexBuffer(p_cmd: vk.CommandBuffer, p_buffer: vk.Buffer, offset: vk.DeviceSize, index_type: vk.IndexType) callconv(vk.vulkan_call_conv) void {
|
||||||
|
|||||||
Reference in New Issue
Block a user