2022-07-08 07:46:55 +00:00
|
|
|
const std = @import("std");
|
|
|
|
const vk = @import("vulkan");
|
|
|
|
const vkd = @import("device.zig").DeviceDispatch;
|
|
|
|
const Image = @import("image.zig").Image;
|
2022-07-09 00:56:30 +00:00
|
|
|
const renderpass = @import("render_pass.zig");
|
2022-07-08 07:46:55 +00:00
|
|
|
const Device = @import("device.zig").Device;
|
|
|
|
|
|
|
|
// TODO memory
|
|
|
|
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
|
|
|
const allocator = gpa.allocator();
|
|
|
|
|
|
|
|
const num_attachments = 8;
|
|
|
|
|
|
|
|
const Key = struct {
|
|
|
|
attachments: [num_attachments]vk.ImageView,
|
|
|
|
formats: [num_attachments]vk.Format,
|
|
|
|
width: u16,
|
|
|
|
height: u16,
|
|
|
|
};
|
|
|
|
|
|
|
|
const Value = struct {
|
|
|
|
handle: vk.Framebuffer,
|
|
|
|
};
|
|
|
|
|
|
|
|
const Self = @This();
|
|
|
|
|
|
|
|
const HashMap = std.HashMap(Key, Value);
|
|
|
|
const s_fbufs = undefined;
|
|
|
|
|
|
|
|
pub fn init() !void {
|
|
|
|
s_fbufs = try HashMap.init(allocator);
|
|
|
|
try s_fbufs.ensureTotalCapacity(16);
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn deinit(device: *Device) void {
|
|
|
|
const it = s_fbufs.iterator();
|
|
|
|
{
|
|
|
|
while (it.next()) |entry| {
|
|
|
|
vkd.destroyFramebuffer(device.dev, entry.handle, null);
|
|
|
|
entry.handle = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
s_fbufs.deinit();
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn getOrAdd(attachments: []*const Image, width: i32, height: i32) !*Framebuffer {
|
|
|
|
std.debug.assert(attachments.len >= 1);
|
|
|
|
std.debug.assert(attachments.len <= num_attachments);
|
|
|
|
|
|
|
|
const key = Key{
|
|
|
|
.width = width,
|
|
|
|
.height = height,
|
|
|
|
};
|
|
|
|
|
|
|
|
for (attachments) |attachment, i| {
|
|
|
|
if (attachment.view) |view| {
|
|
|
|
key.attachments[i] = view;
|
|
|
|
key.formats[i] = attachment.format;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const result = s_fbufs.getOrPutAssumeCapacity(key);
|
|
|
|
if (!result.found_existing) {
|
|
|
|
const value = Value{
|
|
|
|
.handle = try Framebuffer.init(key.attachments, key.formats, key.width, key.height),
|
|
|
|
};
|
|
|
|
result.value_ptr.* = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
return result.value_ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
fn containsView(key: *const Key, view: vk.ImageView) bool {
|
|
|
|
for (key.attachments) |attachment| {
|
|
|
|
if (attachment == view) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
const Framebuffer = struct {
|
|
|
|
pub fn init(device: *Device, attachments: []const vk.ImageView, formats: []const vk.Format, width: i32, height: i32) !Self {
|
|
|
|
const pass_desc: renderpass.Description = .{
|
|
|
|
.src_access_mask = .shader_read_bit,
|
|
|
|
.dst_access_mask = .color_attachment_write_bit,
|
|
|
|
.src_stage_mask = .fragment_shader_bit,
|
|
|
|
.dst_stage_mask = .color_attachment_output_bit,
|
|
|
|
};
|
|
|
|
|
|
|
|
for (formats) |format, i| {
|
|
|
|
pass_desc.attachments[i].format = format;
|
|
|
|
const layout = if (i == 0 and format >= .d16_unorm and format <= .d32_sfloat_s8_uint)
|
|
|
|
.depth_stencil_attachment_optimal
|
|
|
|
else
|
|
|
|
.color_attachment_optimal;
|
|
|
|
pass_desc.attachments[i].layout = layout;
|
|
|
|
}
|
|
|
|
|
|
|
|
const pass = try renderpass.get(&pass_desc);
|
|
|
|
vkd.createFramebuffer(device.dev, .{
|
|
|
|
.s_type = .framebuffer_create_info,
|
|
|
|
.render_pass = pass,
|
|
|
|
.attachment_count = attachments.len,
|
|
|
|
.p_attachments = attachments.ptr,
|
|
|
|
.width = width,
|
|
|
|
.height = height,
|
|
|
|
.layers = 1,
|
|
|
|
}, null);
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn deinit(self: *Self, device: *Device) !void {
|
|
|
|
vkd.destroyFramebuffer(device.dev, self.handle, null);
|
|
|
|
}
|
|
|
|
};
|