lots more goodies and compiling again
This commit is contained in:
parent
dd30befb3c
commit
4b59b2d387
|
@ -1 +1,88 @@
|
|||
pub const Float4 = @Vector(4, f32);
|
||||
const std = @import("std");
|
||||
|
||||
pub const Float4 = packed struct {
|
||||
const Self = @This();
|
||||
|
||||
x: f32 = 0,
|
||||
y: f32 = 0,
|
||||
z: f32 = 0,
|
||||
w: f32 = 0,
|
||||
|
||||
pub inline fn add(lhs: Self, rhs: Self) Self {
|
||||
return Self{
|
||||
.x = lhs.x + rhs.x,
|
||||
.y = lhs.y + rhs.y,
|
||||
.z = lhs.z + rhs.z,
|
||||
.w = lhs.w + rhs.w,
|
||||
};
|
||||
}
|
||||
|
||||
pub inline fn sub(lhs: Self, rhs: Self) Self {
|
||||
return Self{
|
||||
.x = lhs.x - rhs.x,
|
||||
.y = lhs.y - rhs.y,
|
||||
.z = lhs.z - rhs.z,
|
||||
.w = lhs.w - rhs.w,
|
||||
};
|
||||
}
|
||||
|
||||
pub inline fn mul(lhs: Self, rhs: Self) Self {
|
||||
return Self{
|
||||
.x = lhs.x * rhs.x,
|
||||
.y = lhs.y * rhs.y,
|
||||
.z = lhs.z * rhs.z,
|
||||
.w = lhs.w * rhs.w,
|
||||
};
|
||||
}
|
||||
|
||||
pub inline fn mulvs(lhs: Self, rhs: f32) Self {
|
||||
return Self{
|
||||
.x = lhs.x * rhs,
|
||||
.y = lhs.y * rhs,
|
||||
.z = lhs.z * rhs,
|
||||
.w = lhs.w * rhs,
|
||||
};
|
||||
}
|
||||
|
||||
pub inline fn divvs(lhs: Self, rhs: f32) Self {
|
||||
return lhs.mulvs(1.0 / rhs);
|
||||
}
|
||||
|
||||
pub inline fn sum3(self: Self) f32 {
|
||||
return self.x + self.y + self.z;
|
||||
}
|
||||
|
||||
pub inline fn dot3(a: Self, b: Self) f32 {
|
||||
return a.mul(b).sum3();
|
||||
}
|
||||
|
||||
pub inline fn zxy(self: Self) Self {
|
||||
return Self{
|
||||
.x = self.z,
|
||||
.y = self.x,
|
||||
.z = self.y,
|
||||
.w = 0,
|
||||
};
|
||||
}
|
||||
|
||||
pub inline fn cross3(a: Self, b: Self) Self {
|
||||
return zxy(sub(mul(zxy(a), b), mul(a, zxy(b))));
|
||||
}
|
||||
|
||||
pub inline fn max(a: Self, b: Self) Self {
|
||||
return Self{
|
||||
.x = @maximum(a.x, b.x),
|
||||
.y = @maximum(a.y, b.y),
|
||||
.z = @maximum(a.z, b.z),
|
||||
.w = @maximum(a.w, b.w),
|
||||
};
|
||||
}
|
||||
|
||||
pub inline fn length3(self: Self) f32 {
|
||||
return @sqrt(@maximum(std.math.f32_epsilon, self.dot3(self)));
|
||||
}
|
||||
|
||||
pub inline fn normalize3(self: Self) Self {
|
||||
return self.divvs(self.length3());
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,9 +1,64 @@
|
|||
const std = @import("std");
|
||||
const Float4 = @import("float4.zig").Float4;
|
||||
|
||||
// TODO: comptime magic?
|
||||
pub const Float4x4 = packed struct {
|
||||
c0: Float4,
|
||||
c1: Float4,
|
||||
c2: Float4,
|
||||
c3: Float4,
|
||||
const Self = @This();
|
||||
|
||||
const zero = Self{};
|
||||
|
||||
c0: Float4 = Float4{},
|
||||
c1: Float4 = Float4{},
|
||||
c2: Float4 = Float4{},
|
||||
c3: Float4 = Float4{},
|
||||
|
||||
pub inline fn mulCol(self: Self, col: Float4) Float4 {
|
||||
const a = self.c0.mulvs(col.x);
|
||||
const b = self.c1.mulvs(col.y);
|
||||
const c = self.c2.mulvs(col.z);
|
||||
const d = self.c0.mulvs(col.w);
|
||||
return a.add(b).add(c.add(d));
|
||||
}
|
||||
|
||||
pub inline fn mul(a: Self, b: Self) Self {
|
||||
return Self{
|
||||
.c0 = a.mulCol(b.c0),
|
||||
.c1 = a.mulCol(b.c1),
|
||||
.c2 = a.mulCol(b.c2),
|
||||
.c3 = a.mulCol(b.c3),
|
||||
};
|
||||
}
|
||||
|
||||
pub inline fn lookAt(eye: Float4, at: Float4, up: Float4) Float4x4 {
|
||||
// right-handed (ew)
|
||||
const f = at.sub(eye).normalize3();
|
||||
const s = f.cross3(up).normalize3();
|
||||
const u = s.cross3(f).normalize3();
|
||||
|
||||
const tx = -s.dot3(eye);
|
||||
const ty = -u.dot3(eye);
|
||||
const tz = f.dot3(eye);
|
||||
return Float4x4{
|
||||
.c0 = .{ .x = s.x, .y = u.x, .z = -f.x, .w = 0 },
|
||||
.c1 = .{ .x = s.y, .y = u.y, .z = -f.y, .w = 0 },
|
||||
.c2 = .{ .x = s.z, .y = u.z, .z = -f.z, .w = 0 },
|
||||
.c3 = .{ .x = tx, .y = ty, .z = tz, .w = 1 },
|
||||
};
|
||||
}
|
||||
|
||||
pub inline fn glPerspective(fov_y: f32, aspect: f32, z_near: f32, z_far: f32) Self {
|
||||
const t = std.math.tan(fov_y * 0.5);
|
||||
var m = zero;
|
||||
m.c0.x = 1.0 / (aspect * t);
|
||||
m.c1.y = 1.0 / t;
|
||||
m.c2.z = -1.0 * (z_far * z_near) / (z_far - z_near);
|
||||
m.c3.z = -2.0 * (z_far * z_near) / (z_far - z_near);
|
||||
return m;
|
||||
}
|
||||
|
||||
pub inline fn vkPerspective(fov_y: f32, aspect: f32, z_near: f32, z_far: f32) Self {
|
||||
var m = glPerspective(fov_y, aspect, z_near, z_far);
|
||||
m.c1.y *= -1.0;
|
||||
return m;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
const Float4 = @import("float4.zig").Float4;
|
||||
|
||||
pub const Quat = struct {
|
||||
const Self = @This();
|
||||
|
||||
v: Float4,
|
||||
|
||||
pub inline fn mulDir(q: Self, dir: Float4) Float4 {
|
||||
const uv = q.v.cross3(dir);
|
||||
const uuv = q.v.cross3(uv);
|
||||
|
||||
var y = uv.mulvs(q.v.w);
|
||||
y = y.add(uuv);
|
||||
y = y.mulvs(2);
|
||||
y = y.add(dir);
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
pub inline fn fwd(q: Self) Float4 {
|
||||
const dir = Float4{ .x = 0, .y = 0, .z = -1, .w = 0 };
|
||||
return q.mulDir(dir);
|
||||
}
|
||||
|
||||
pub inline fn up(q: Self) Float4 {
|
||||
const dir = Float4{ .x = 0, .y = 1, .z = 0, .w = 0 };
|
||||
return q.mulDir(dir);
|
||||
}
|
||||
};
|
|
@ -0,0 +1,32 @@
|
|||
const std = @import("std");
|
||||
const Float4 = @import("../math/float4.zig").Float4;
|
||||
const Float4x4 = @import("../math/float4x4.zig").Float4x4;
|
||||
const Quat = @import("../math/quat.zig").Quat;
|
||||
|
||||
const Self = @This();
|
||||
|
||||
var s_camera: Self = std.mem.zeroes(Self);
|
||||
|
||||
position: Float4,
|
||||
rotation: Quat,
|
||||
z_near: f32,
|
||||
z_far: f32,
|
||||
fov_y: f32,
|
||||
|
||||
pub fn get() Self {
|
||||
return s_camera;
|
||||
}
|
||||
|
||||
pub inline fn getProj(self: *const Self, aspect: f32) Float4x4 {
|
||||
return Float4x4.vkPerspective(std.math.degreesToRadians(f32, self.fov_y), aspect, self.z_near, self.z_far);
|
||||
}
|
||||
|
||||
pub inline fn getView(self: *const Self) Float4x4 {
|
||||
const pos = self.position;
|
||||
const rot = self.rotation;
|
||||
return Float4x4.lookAt(pos, pos.add(rot.fwd()), rot.up());
|
||||
}
|
||||
|
||||
pub inline fn getWorldToClip(self: *const Self, aspect: f32) Float4x4 {
|
||||
return self.getProj(aspect).mul(self.getView());
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
const vk = @import("vulkan");
|
||||
|
||||
const Device = @import("device.zig").Device;
|
||||
const ProfileMark = @import("../../common/profiler.zig").ProfileMark;
|
||||
const settings = @import("settings.zig");
|
||||
const Swapchain = @import("swapchain.zig").Swapchain;
|
||||
|
||||
var s_sets = std.mem.zeroes([settings.resource_sets]vk.DescriptorSet);
|
||||
var s_writes = std.mem.zeroes([settings.Bid.Count]vk.WriteDescriptorSet);
|
||||
var s_bindings = std.mem.zeroes([settings.Bid.Count]Binding);
|
||||
var s_dirty = std.mem.zeroes([settings.Bid.Count]i32);
|
||||
|
||||
const pm_update = ProfileMark.init("Bindings.update");
|
||||
pub fn update(device: *const Device, swapchain: *const Swapchain) void {
|
||||
pm_update.begin();
|
||||
defer pm_update.end();
|
||||
|
||||
// kara says: why do validation layers think there is a command buffer in flight using this desc set?
|
||||
// submit.awaitAll();
|
||||
|
||||
//const set = getSet(swapchain);
|
||||
// TexTable.write(set);
|
||||
flush(device, swapchain);
|
||||
}
|
||||
|
||||
pub fn getSet(swapchain: *const Swapchain) vk.DescriptorSet {
|
||||
const sync_index = swapchain.sync_index;
|
||||
assert(sync_index < s_sets.len);
|
||||
assert(s_sets[sync_index] != .null_handle);
|
||||
return s_sets[sync_index];
|
||||
}
|
||||
|
||||
const pm_flush = ProfileMark.init("Bindings.flush");
|
||||
pub fn flush(device: *const Device, swapchain: *const Swapchain) void {
|
||||
pm_flush.begin();
|
||||
defer pm_flush.end();
|
||||
|
||||
const set = getSet(swapchain);
|
||||
var write_count: i32 = 0;
|
||||
for (s_bindings) |binding, i| {
|
||||
assert(s_dirty[i] >= 0);
|
||||
if (s_dirty[i] <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
s_dirty[i] -= 1;
|
||||
|
||||
var write = &s_writes[write_count];
|
||||
write_count += 1;
|
||||
write.* = .{
|
||||
.s_type = .write_descriptor_set,
|
||||
.descriptor_type = binding.desc_type,
|
||||
.dst_set = set,
|
||||
.dst_binding = i,
|
||||
.dst_array_element = 0,
|
||||
.descriptor_count = 1,
|
||||
};
|
||||
|
||||
switch (binding.info) {
|
||||
.buffer => |*buffer| {
|
||||
switch (binding.desc_type) {
|
||||
.uniform_buffer, .storage_buffer, .uniform_buffer_dynamic, .storage_buffer_dynamic => {
|
||||
write.p_buffer_info = buffer;
|
||||
},
|
||||
else => {
|
||||
assert(false);
|
||||
},
|
||||
}
|
||||
},
|
||||
.image => |*image| {
|
||||
switch (binding.desc_type) {
|
||||
.sampler, .combined_image_sampler, .sampled_image, .storage_image, .input_attachment => {
|
||||
write.p_image_info = image;
|
||||
},
|
||||
else => {
|
||||
assert(false);
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
if (write_count > 0) {
|
||||
device.dispatch.updateDescriptorSets(device.handle, write_count, s_writes, 0, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub const Binding = struct {
|
||||
const Type = enum {
|
||||
buffer,
|
||||
image,
|
||||
};
|
||||
const Union = union(Type) {
|
||||
buffer: vk.DescriptorBufferInfo,
|
||||
image: vk.DescriptorImageInfo,
|
||||
};
|
||||
|
||||
desc_type: vk.DescriptorType,
|
||||
info: Union,
|
||||
};
|
|
@ -14,6 +14,7 @@ const Renderer = @import("Renderer.zig");
|
|||
const SubmitId = @import("submit_id.zig").SubmitId;
|
||||
const Fence = @import("sync.zig").Fence;
|
||||
const Semaphore = @import("sync.zig").Semaphore;
|
||||
const Bindings = @import("Bindings.zig");
|
||||
|
||||
const queues = @import("queues.zig");
|
||||
|
||||
|
@ -210,18 +211,36 @@ pub const Buffer = struct {
|
|||
self.ended = false;
|
||||
}
|
||||
|
||||
pub fn bindDescSets(self: *Self, device: *const Device, bindpoint: vk.PipelineBindPoint, layout: vk.PipelineLayout, set_count: u32, sets: [*]const vk.DescriptorSet) void {
|
||||
assert(self.handle != .null_handle);
|
||||
assert(self.gfx or self.comp);
|
||||
assert(layout != .null_handle);
|
||||
if (set_count > 0) {
|
||||
device.dispatch.cmdBindDescriptorSets(self.handle, bindpoint, layout, 0, set_count, sets, 0, undefined);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bindPass(self: *Self, device: *const Device, swapchain: *const Swapchain, pass: *const Pass) void {
|
||||
assert(self.handle != .null_handle);
|
||||
assert(self.gfx or self.comp);
|
||||
assert(pass.pipeline != .null_handle);
|
||||
device.dispatch.cmdBindPipeline(self.handle, pass.bindpoint, pass.pipeline);
|
||||
const set = Bindings.getSet(swapchain);
|
||||
self.bindDescSets(device, pass.bindpoint, pass.layout, 1, @ptrCast([*]const vk.DescriptorSet, &set));
|
||||
}
|
||||
|
||||
const pm_buffer_beginrenderpass = ProfileMark.init("Command.Buffer.beginRenderPass");
|
||||
pub fn beginRenderPass(self: *Self, device: *const Device, pass: vk.RenderPass, framebuf: vk.Framebuffer, rect: vk.Rect2D, clear_values: []*const vk.ClearValue) void {
|
||||
pub fn beginRenderPass(self: *Self, device: *const Device, pass: vk.RenderPass, framebuf: vk.Framebuffer, rect: vk.Rect2D, clear_values: []const vk.ClearValue) void {
|
||||
pm_buffer_beginrenderpass.begin();
|
||||
defer pm_buffer_beginrenderpass.end();
|
||||
|
||||
assert(self.handle != .null_handle);
|
||||
assert(!self.in_render_pass);
|
||||
device.dispatch.beginRenderPass(self.handle, &.{
|
||||
device.dispatch.cmdBeginRenderPass(self.handle, &.{
|
||||
.render_pass = pass,
|
||||
.framebuffer = framebuf,
|
||||
.render_area = rect,
|
||||
.clear_value_count = clear_values.len,
|
||||
.clear_value_count = @intCast(u32, clear_values.len),
|
||||
.p_clear_values = clear_values.ptr,
|
||||
}, .@"inline");
|
||||
self.in_render_pass = true;
|
||||
|
@ -239,7 +258,7 @@ pub const Buffer = struct {
|
|||
assert(self.handle != .null_handle);
|
||||
assert(self.in_render_pass);
|
||||
device.dispatch.cmdEndRenderPass(self.handle);
|
||||
self.in_render_pass = 0;
|
||||
self.in_render_pass = false;
|
||||
self.subpass = 0;
|
||||
}
|
||||
|
||||
|
@ -262,19 +281,19 @@ pub const Buffer = struct {
|
|||
assert(self.handle != .null_handle);
|
||||
assert(self.gfx or self.comp);
|
||||
assert(size == pass.push_constant_bytes);
|
||||
assert(pass.layout.toInt() != 0);
|
||||
assert(pass.layout != .null_handle);
|
||||
assert(pass.stage_flags.toInt() != 0);
|
||||
device.dispatch.cmdPushConstants(self.handle, pass.layout, pass.stage_flags, 0, size, constants);
|
||||
}
|
||||
|
||||
pub fn viewport(self: *Self, device: *const Device, vp: vk.Viewport, scissor: vk.Rect2D) void {
|
||||
assert(self.handle != .null_handle);
|
||||
device.dispatch.cmdSetViewport(self.handle, 0, 1, &vp);
|
||||
device.dispatch.cmdSetScissor(self.handle, 0, 1, &scissor);
|
||||
device.dispatch.cmdSetViewport(self.handle, 0, 1, @ptrCast([*]const vk.Viewport, &vp));
|
||||
device.dispatch.cmdSetScissor(self.handle, 0, 1, @ptrCast([*]const vk.Rect2D, &scissor));
|
||||
}
|
||||
|
||||
pub fn defaultViewport(self: *Self) void {
|
||||
self.viewport(Swapchain.getViewport(), Swapchain.getRect());
|
||||
pub fn defaultViewport(self: *Self, device: *const Device, swapchain: *const Swapchain) void {
|
||||
self.viewport(device, swapchain.getViewport(), swapchain.getRect());
|
||||
}
|
||||
|
||||
pub fn draw(self: *Self, device: *const Device, vertex_count: i32, first_vertex: i32) void {
|
||||
|
@ -303,6 +322,10 @@ pub const Buffer = struct {
|
|||
pm_buffer_submit.begin();
|
||||
defer pm_buffer_submit.end();
|
||||
|
||||
_ = wait_sema;
|
||||
_ = signal_sema;
|
||||
_ = wait_mask;
|
||||
|
||||
assert(self.began);
|
||||
assert(!self.ended);
|
||||
assert(!self.submitted);
|
||||
|
|
|
@ -12,9 +12,8 @@ const Self = @This();
|
|||
|
||||
pub var context: Self = Self{};
|
||||
|
||||
pub fn init() Self {
|
||||
pub fn init() void {
|
||||
context = std.mem.zeroes(@This());
|
||||
return context;
|
||||
}
|
||||
|
||||
pub fn deinit() void {
|
||||
|
|
|
@ -10,7 +10,7 @@ const Camera = @import("../Camera.zig");
|
|||
const Shader = @import("Shader.zig");
|
||||
const Pass = @import("Pass.zig");
|
||||
const framebuffer = @import("framebuffer.zig");
|
||||
const DepthBuffer = @import("DepthBuffer.zig");
|
||||
const Targets = @import("Targets.zig");
|
||||
const RenderPass = @import("RenderPass.zig");
|
||||
const Float4 = @import("../../math/float4.zig").Float4;
|
||||
const Float4x4 = @import("../../math/float4x4.zig").Float4x4;
|
||||
|
@ -19,14 +19,14 @@ const PushConstants = struct {
|
|||
local_to_clip: Float4x4,
|
||||
};
|
||||
|
||||
pub fn init() !void {
|
||||
pub fn init(device: *const Device, swapchain: *Swapchain) !void {
|
||||
errdefer {
|
||||
std.debug.print("Failed to init MainPass");
|
||||
std.debug.print("Failed to init MainPass", .{});
|
||||
deinit();
|
||||
}
|
||||
|
||||
// try ScreenBlit.init()
|
||||
try DepthPass.init();
|
||||
try DepthPass.init(device, swapchain);
|
||||
try OpaquePass.init();
|
||||
// try Exposure.init();
|
||||
// try UIPass.init();
|
||||
|
@ -52,12 +52,12 @@ pub fn setup() void {
|
|||
}
|
||||
|
||||
const pm_execute = ProfileMark.init("MainPass.execute");
|
||||
pub fn execute() void {
|
||||
pub fn execute(device: *const Device, swapchain: *Swapchain) !void {
|
||||
pm_execute.begin();
|
||||
defer pm_execute.end();
|
||||
|
||||
// todo: pt_trace convar check
|
||||
DepthPass.execute();
|
||||
try DepthPass.execute(device, swapchain);
|
||||
OpaquePass.execute();
|
||||
|
||||
// Exposure.execute();
|
||||
|
@ -68,10 +68,10 @@ const DepthPass = struct {
|
|||
var s_render_pass: vk.RenderPass = undefined;
|
||||
var s_pass: Pass = undefined;
|
||||
|
||||
pub fn init() !void {
|
||||
pub fn init(device: *const Device, swapchain: *Swapchain) !void {
|
||||
errdefer DepthPass.deinit();
|
||||
|
||||
const depth_buffer = DepthBuffer.get();
|
||||
const depth_buffer = swapchain.getDepthBuffer();
|
||||
|
||||
var info = RenderPass.Description{
|
||||
.src_stage_mask = .{ .early_fragment_tests_bit = true },
|
||||
|
@ -83,51 +83,49 @@ const DepthPass = struct {
|
|||
info.attachments[0] = .{
|
||||
.format = depth_buffer.format,
|
||||
.layout = .depth_stencil_attachment_optimal,
|
||||
.load = vk.VK_ATTACHMENT_LOAD_OP_CLEAR,
|
||||
.store = vk.VK_ATTACHMENT_LOAD_OP_STORE,
|
||||
.load = .clear,
|
||||
.store = .store,
|
||||
};
|
||||
s_render_pass = try RenderPass.get(&info);
|
||||
s_render_pass = try RenderPass.get(device, info);
|
||||
|
||||
var shaders = std.mem.zeroes([2]vk.PipelineShaderStageCreateInfo);
|
||||
var shaders: [2]vk.PipelineShaderStageCreateInfo = undefined;
|
||||
try Shader.init(&shaders[0], "DepthOnly.hlsl", "VSMain", .vertex);
|
||||
errdefer Shader.deinit(&shaders[0]);
|
||||
try Shader.init(&shaders[1], "DepthOnly.hlsl", "PSMain", .fragment);
|
||||
errdefer Shader.deinit(&shaders[1]);
|
||||
|
||||
const vert_bindings = []vk.VertexInputBindingDescription{
|
||||
var vert_bindings = [_]vk.VertexInputBindingDescription{
|
||||
.{
|
||||
.binding = 0,
|
||||
.stride = @sizeOf(Float4),
|
||||
.input_rate = .vertex,
|
||||
},
|
||||
};
|
||||
const vert_attributes = []vk.VertexInputAtttributeDescription{
|
||||
var vert_attributes = [_]vk.VertexInputAttributeDescription{
|
||||
.{
|
||||
.binding = 0,
|
||||
.format = .r32g32b32a32_sfloat,
|
||||
.location = 0,
|
||||
.offset = 0,
|
||||
},
|
||||
};
|
||||
|
||||
try Pass.new(&s_pass, &.{
|
||||
const createInfo = Pass.Description{
|
||||
.push_constant_bytes = @sizeOf(PushConstants),
|
||||
.shader_count = shaders.len,
|
||||
.shaders = shaders,
|
||||
.shaders = &shaders,
|
||||
.render_pass = s_render_pass,
|
||||
.subpass = 0,
|
||||
.subpass = -1,
|
||||
.vert_layout = .{
|
||||
.binding_count = vert_bindings.len,
|
||||
.bindings = vert_bindings.ptr,
|
||||
.attribute_count = vert_attributes.len,
|
||||
.attributes = vert_attributes.ptr,
|
||||
.bindings = &vert_bindings,
|
||||
.attributes = &vert_attributes,
|
||||
},
|
||||
.fixed_funcs = .{
|
||||
.viewport = Swapchain.getViewport(),
|
||||
.scissor = Swapchain.getRect(),
|
||||
.viewport = swapchain.getViewport(),
|
||||
.scissor = swapchain.getRect(),
|
||||
.topology = .triangle_list,
|
||||
.polygon_mode = .fill,
|
||||
.front_face = .counter_clockwise,
|
||||
.cull_mode = .back_bit,
|
||||
.cull_mode = .{ .back_bit = true },
|
||||
.depth_compare_op = .less,
|
||||
.scissor_on = false,
|
||||
.depth_clamp = false,
|
||||
|
@ -135,7 +133,8 @@ const DepthPass = struct {
|
|||
.depth_write_enable = true,
|
||||
.attachment_count = 0,
|
||||
},
|
||||
});
|
||||
};
|
||||
try Pass.init(&s_pass, &createInfo);
|
||||
}
|
||||
|
||||
pub fn deinit() void {
|
||||
|
@ -145,15 +144,15 @@ const DepthPass = struct {
|
|||
pub fn setup() void {}
|
||||
|
||||
const pm_depth_execute = ProfileMark.init("DepthPass.execute");
|
||||
pub fn execute(device: *const Device) void {
|
||||
pub fn execute(device: *const Device, swapchain: *Swapchain) !void {
|
||||
pm_depth_execute.begin();
|
||||
defer pm_depth_execute.end();
|
||||
|
||||
const camera = Camera.get();
|
||||
|
||||
const world_to_clip = camera.getWorldToClip(Swapchain.getAspect());
|
||||
const world_to_clip = camera.getWorldToClip(swapchain.getAspect());
|
||||
|
||||
const attachments = []Image{DepthBuffer.get()};
|
||||
const attachments = &[_]*Image{swapchain.getDepthBuffer()};
|
||||
const rect = vk.Rect2D{
|
||||
.offset = std.mem.zeroes(vk.Offset2D),
|
||||
.extent = .{
|
||||
|
@ -162,14 +161,14 @@ const DepthPass = struct {
|
|||
},
|
||||
};
|
||||
|
||||
const fbuf = framebuffer.get(attachments, rect.extent.width, rect.extent.height);
|
||||
const fbuf = try framebuffer.getOrAdd(device, attachments, rect.extent.width, rect.extent.height);
|
||||
const cmd = try Command.Buffer.get(.graphics, device);
|
||||
|
||||
Image.State.depthAttachWrite(cmd, attachments[0]);
|
||||
_ = try Image.State.depthAttachWrite(device, cmd, attachments[0]);
|
||||
|
||||
cmd.defaultViewport(device);
|
||||
cmd.bindPass(device, &s_pass);
|
||||
cmd.beginRenderPass(device, s_render_pass, fbuf, rect, .{
|
||||
cmd.defaultViewport(device, swapchain);
|
||||
cmd.bindPass(device, swapchain, &s_pass);
|
||||
cmd.beginRenderPass(device, s_render_pass, fbuf, rect, &.{
|
||||
.{
|
||||
.depth_stencil = .{ .depth = 1.0, .stencil = 0.0 },
|
||||
},
|
||||
|
@ -184,4 +183,12 @@ const DepthPass = struct {
|
|||
}
|
||||
};
|
||||
|
||||
const OpaquePass = struct {};
|
||||
const OpaquePass = struct {
|
||||
pub fn init() !void {}
|
||||
|
||||
pub fn deinit() void {}
|
||||
|
||||
pub fn setup() void {}
|
||||
|
||||
pub fn execute() void {}
|
||||
};
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
const vk = @import("vulkan");
|
||||
|
||||
const Self = @This();
|
||||
|
||||
pipeline: vk.Pipeline,
|
||||
layout: vk.PipelineLayout,
|
||||
bindpoint: vk.PipelineBindPoint,
|
||||
stage_flags: vk.ShaderStageFlags,
|
||||
push_constant_bytes: i32,
|
||||
|
||||
const VertexLayout = struct {
|
||||
bindings: []vk.VertexInputBindingDescription,
|
||||
attributes: []vk.VertexInputAttributeDescription,
|
||||
};
|
||||
|
||||
const BlendState = struct {
|
||||
color_wite_mask: vk.ColorComponentFlags,
|
||||
blend_enable: bool,
|
||||
src_color_blend_factor: vk.BlendFactor,
|
||||
dst_color_blend_factor: vk.BlendFactor,
|
||||
color_blend_op: vk.BlendOp,
|
||||
src_alpha_blend_factor: vk.BlendFactor,
|
||||
dst_alpha_blend_factor: vk.BlendFactor,
|
||||
alpha_blend_op: vk.BlendOp,
|
||||
};
|
||||
|
||||
const FixedFuncs = struct {
|
||||
viewport: vk.Viewport,
|
||||
scissor: vk.Rect2D,
|
||||
topology: vk.PrimitiveTopology,
|
||||
polygon_mode: vk.PolygonMode,
|
||||
cull_mode: vk.CullModeFlags,
|
||||
front_face: vk.FrontFace,
|
||||
depth_compare_op: vk.CompareOp,
|
||||
scissor_on: bool,
|
||||
depth_clamp: bool,
|
||||
depth_test_enable: bool,
|
||||
depth_write_enable: bool,
|
||||
attachment_count: u3,
|
||||
attachments: ?[8]BlendState = null,
|
||||
};
|
||||
|
||||
pub const Description = struct {
|
||||
// Graphics and compute
|
||||
push_constant_bytes: i32,
|
||||
shaders: []vk.PipelineShaderStageCreateInfo,
|
||||
// Graphics only
|
||||
render_pass: vk.RenderPass,
|
||||
subpass: i32,
|
||||
vert_layout: VertexLayout,
|
||||
fixed_funcs: FixedFuncs,
|
||||
};
|
||||
|
||||
pub fn init(self: *Self, desc: *const Description) !void {
|
||||
_ = self;
|
||||
_ = desc;
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Self) void {
|
||||
_ = self;
|
||||
}
|
|
@ -1,13 +1,14 @@
|
|||
const std = @import("std");
|
||||
const vk = @import("vulkan");
|
||||
|
||||
const profiler = @import("/common/profiler.zig");
|
||||
const profiler = @import("../../common/profiler.zig");
|
||||
const Device = @import("device.zig").Device;
|
||||
const vkd = @import("device.zig").DeviceDispatch;
|
||||
|
||||
const allocator: std.mem.Allocator = undefined;
|
||||
// TODO memory
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
const allocator = gpa.allocator();
|
||||
|
||||
const s_cache = std.HashMap(Description, vk.RenderPass).init(allocator);
|
||||
var s_cache = std.AutoHashMap(Description, vk.RenderPass).init(allocator);
|
||||
|
||||
// https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#renderpass-compatibility
|
||||
// compatibility:
|
||||
|
@ -16,8 +17,8 @@ const s_cache = std.HashMap(Description, vk.RenderPass).init(allocator);
|
|||
const AttachmentState = packed struct {
|
||||
format: vk.Format, // must match
|
||||
layout: vk.ImageLayout, // can vary
|
||||
load: u2, // vk.AttachmentLoadOp, can vary
|
||||
store: u2, // vk.AttachmentStoreOp, can vary
|
||||
load: vk.AttachmentLoadOp, // can vary
|
||||
store: vk.AttachmentStoreOp, // can vary
|
||||
};
|
||||
|
||||
pub const Description = struct {
|
||||
|
@ -29,32 +30,31 @@ pub const Description = struct {
|
|||
};
|
||||
|
||||
const pm_get = profiler.ProfileMark.init("renderpass.get");
|
||||
pub fn get(desc: *const Description) !vk.RenderPass {
|
||||
pub fn get(device: *const Device, desc: Description) !vk.RenderPass {
|
||||
pm_get.begin();
|
||||
defer pm_get.end();
|
||||
|
||||
const result = try s_cache.getOrPut(desc);
|
||||
if (result.found_existing) {
|
||||
return result.value_ptr;
|
||||
return result.value_ptr.*;
|
||||
}
|
||||
|
||||
const attachments = [8]vk.AttachmentDescription{};
|
||||
const refs = [attachments.len]vk.AttachmentReference{};
|
||||
var attachment_count = 0;
|
||||
var ref_count = 0;
|
||||
var attachments = std.mem.zeroes([8]vk.AttachmentDescription);
|
||||
var refs = std.mem.zeroes([attachments.len]vk.AttachmentReference);
|
||||
var attachment_count: u32 = 0;
|
||||
var ref_count: usize = 0;
|
||||
const format0 = desc.attachments[0].format;
|
||||
const zero_is_depth = format0 >= .d16_unorm and format0 <= .d32_sfloat_s8_uint;
|
||||
const zero_is_depth = @enumToInt(format0) >= @enumToInt(vk.Format.d16_unorm) and @enumToInt(format0) <= @enumToInt(vk.Format.d32_sfloat_s8_uint);
|
||||
|
||||
for (desc.attachments) |dst_attachment, i| {
|
||||
for (desc.attachments) |*src, i| {
|
||||
attachments[i].load_op = .dont_care;
|
||||
attachments[i].store_op = .dont_care;
|
||||
const src = &desc.attachments[i];
|
||||
if (src.format != .@"undefined") {
|
||||
std.debug.assert(attachment_count < attachments.len);
|
||||
const dst = &dst_attachment;
|
||||
var dst = &attachments[attachment_count];
|
||||
dst.format = src.format;
|
||||
dst.initial_layout = src.layout;
|
||||
dst.samples = .@"1_bit";
|
||||
dst.samples = .{ .@"1_bit" = true };
|
||||
dst.stencil_load_op = .dont_care;
|
||||
dst.stencil_store_op = .dont_care;
|
||||
dst.load_op = src.load;
|
||||
|
@ -75,35 +75,42 @@ pub fn get(desc: *const Description) !vk.RenderPass {
|
|||
std.debug.assert(attachment_count <= attachments.len);
|
||||
std.debug.assert(attachment_count <= refs.len);
|
||||
const color_ref_count = if (zero_is_depth) attachment_count - 1 else attachment_count;
|
||||
const depth_ref_count = if (zero_is_depth) 1 else 0;
|
||||
const depth_ref_count = if (zero_is_depth) @as(u32, 1) else 0;
|
||||
|
||||
const handle = try new(attachment_count, attachments, 1, &.{
|
||||
const subpasses = [_]vk.SubpassDescription{.{
|
||||
.flags = .{},
|
||||
.input_attachment_count = 0,
|
||||
.p_input_attachments = undefined,
|
||||
.p_resolve_attachments = null,
|
||||
.preserve_attachment_count = 0,
|
||||
.p_preserve_attachments = undefined,
|
||||
.pipeline_bind_point = .graphics,
|
||||
.color_attachment_count = color_ref_count,
|
||||
.p_color_attachments = if (color_ref_count) &refs[depth_ref_count] else null,
|
||||
.p_depth_stencil_attachment = if (depth_ref_count) &refs[0] else null,
|
||||
}, 1, &.{
|
||||
.src_subpass = .external,
|
||||
.p_color_attachments = if (color_ref_count > 0) @ptrCast([*]const vk.AttachmentReference, &refs[depth_ref_count]) else undefined,
|
||||
.p_depth_stencil_attachment = if (depth_ref_count > 0) @as(?*const vk.AttachmentReference, &refs[0]) else null,
|
||||
}};
|
||||
|
||||
const dependencies = [_]vk.SubpassDependency{.{
|
||||
.dependency_flags = .{},
|
||||
.src_subpass = vk.SUBPASS_EXTERNAL,
|
||||
.dst_subpass = 0,
|
||||
.src_stage_mask = desc.src_stage_mask,
|
||||
.dst_stage_mask = desc.dest_stage_mask,
|
||||
.dst_stage_mask = desc.dst_stage_mask,
|
||||
.src_access_mask = desc.src_access_mask,
|
||||
.dst_access_mask = desc.dst_access_mask,
|
||||
});
|
||||
}};
|
||||
|
||||
const info = vk.RenderPassCreateInfo{
|
||||
.flags = .{},
|
||||
.attachment_count = attachment_count,
|
||||
.p_attachments = &attachments,
|
||||
.subpass_count = subpasses.len,
|
||||
.p_subpasses = &subpasses,
|
||||
.dependency_count = dependencies.len,
|
||||
.p_dependencies = &dependencies,
|
||||
};
|
||||
const handle = try device.dispatch.createRenderPass(device.handle, &info, null);
|
||||
|
||||
result.value_ptr.* = handle;
|
||||
}
|
||||
|
||||
fn new(device: *Device, attachment_count: i32, p_attachments: *const vk.AttachmentDescription, subpass_count: i32, p_subpasses: *const vk.SubpassDescription, dependency_count: i32, p_dependencies: *const vk.SubpassDependency) !vk.RenderPass {
|
||||
const handle: vk.RenderPass = undefined;
|
||||
try vkd.createRenderPass(device.dev, &.{
|
||||
.attachment_count = attachment_count,
|
||||
.p_attachments = p_attachments,
|
||||
.subpass_count = subpass_count,
|
||||
.p_subpasses = p_subpasses,
|
||||
.dependency_count = dependency_count,
|
||||
.p_dependencies = p_dependencies,
|
||||
}, null, &handle);
|
||||
|
||||
return handle;
|
||||
return result.value_ptr.*;
|
||||
}
|
||||
|
|
|
@ -16,14 +16,12 @@ instance: Instance,
|
|||
window: Window,
|
||||
device: Device,
|
||||
swapchain: Swapchain,
|
||||
context: Context,
|
||||
// sampler: Sampler, TODO
|
||||
// tex_table: TexTable, TODO
|
||||
// bindings: Bindings, TODO
|
||||
// targets: Targets, TODO
|
||||
// mesh_sys: MeshSys, TODO
|
||||
// im_sys: ImSys, TODO
|
||||
main_pass: MainPass,
|
||||
|
||||
const Self = @This();
|
||||
|
||||
|
@ -49,26 +47,24 @@ pub fn init() !Self {
|
|||
try framebuffer.init();
|
||||
errdefer framebuffer.deinit(&device);
|
||||
|
||||
const swapchain = try Swapchain.init(&instance, &window, &device, null);
|
||||
errdefer swapchain.deinit();
|
||||
var swapchain = try Swapchain.init(&instance, &window, &device, null);
|
||||
errdefer swapchain.deinit(&device);
|
||||
|
||||
const context = Context.init();
|
||||
errdefer context.deinit();
|
||||
Context.init();
|
||||
errdefer Context.deinit();
|
||||
// try self.sampler.init();
|
||||
// try self.texTable.init();
|
||||
// try self.bindings.init();
|
||||
// try self.targets.init();
|
||||
// try self.meshSys.init();
|
||||
// try self.imSys.init();
|
||||
const main_pass = try MainPass.init();
|
||||
try MainPass.init(&device, &swapchain);
|
||||
|
||||
return Self{
|
||||
.instance = instance,
|
||||
.window = window,
|
||||
.device = device,
|
||||
.swapchain = swapchain,
|
||||
.context = context,
|
||||
.main_pass = main_pass,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -89,14 +85,14 @@ pub fn update(self: *Self) !void {
|
|||
|
||||
// setup phase
|
||||
{
|
||||
self.main_pass.setup();
|
||||
MainPass.setup();
|
||||
// TODO textable update
|
||||
try Command.flush(&self.device);
|
||||
// TODO bindings update
|
||||
}
|
||||
|
||||
// execute phase
|
||||
self.main_pass.execute();
|
||||
try MainPass.execute(&self.device, &self.swapchain);
|
||||
|
||||
// present phase
|
||||
// currently only graphics queue
|
||||
|
@ -114,7 +110,7 @@ pub fn deinit(self: Self) void {
|
|||
|
||||
// TODO: delete lightmap pack
|
||||
|
||||
self.main_pass.deinit();
|
||||
MainPass.deinit();
|
||||
|
||||
// self.imSys.deinit();
|
||||
// self.meshSys.deinit();
|
||||
|
@ -162,7 +158,7 @@ fn windowUpdate(self: Self) !void {
|
|||
self.device.waitIdle();
|
||||
|
||||
// TODO: UI pass del
|
||||
self.swapchain.deinit();
|
||||
self.swapchain.deinit(&self.device);
|
||||
self.window.deinit();
|
||||
|
||||
self.window.init();
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
const vk = @import("vulkan");
|
||||
const Thingie = enum {
|
||||
vertex,
|
||||
fragment,
|
||||
};
|
||||
|
||||
pub fn init(info: *const vk.PipelineShaderStageCreateInfo, file_path: []const u8, section: []const u8, thingie: Thingie) !void {
|
||||
_ = info;
|
||||
_ = file_path;
|
||||
_ = section;
|
||||
_ = thingie;
|
||||
}
|
|
@ -0,0 +1,140 @@
|
|||
const assert = @import("std").debug.assert;
|
||||
const vk = @import("vulkan");
|
||||
|
||||
const Device = @import("device.zig").Device;
|
||||
const Swapchain = @import("swapchain.zig").Swapchain;
|
||||
const settings = @import("settings.zig");
|
||||
const queues = @import("queues.zig");
|
||||
const Image = @import("image.zig").Image;
|
||||
|
||||
const Self = @This();
|
||||
|
||||
width: i32,
|
||||
height: i32,
|
||||
depth: [settings.resource_sets]Image,
|
||||
scene: [settings.resource_sets]Image,
|
||||
|
||||
// TODO: scaled render resolution
|
||||
pub fn getDesiredWidth(swapchain: *const Swapchain) i32 {
|
||||
getDisplayWidth(swapchain);
|
||||
}
|
||||
|
||||
pub fn getDesiredHeight(swapchain: *const Swapchain) i32 {
|
||||
getDisplayHeight(swapchain);
|
||||
}
|
||||
|
||||
var s_targets: Self = undefined;
|
||||
|
||||
pub fn init(device: *const Device, swapchain: *const Swapchain) !void {
|
||||
errdefer deinit(device);
|
||||
|
||||
const width = getDesiredWidth(swapchain);
|
||||
const height = getDesiredHeight(swapchain);
|
||||
|
||||
s_targets.width = width;
|
||||
s_targets.height = height;
|
||||
|
||||
for (s_targets.scene) |*s| {
|
||||
const usage: vk.ImageUsageFlags = .{
|
||||
.color_attachment_bit = true,
|
||||
.sampled_bit = true,
|
||||
.storage_bit = true,
|
||||
.transfer_src_bit = true,
|
||||
.transfer_dst_bit = true,
|
||||
};
|
||||
const queue_family_indices = []u32{
|
||||
queues.get(.graphics).family,
|
||||
queues.get(.compute).family,
|
||||
};
|
||||
|
||||
try Image.init(s, &.{
|
||||
.image_type = .@"2d",
|
||||
.format = .r16g16b16a16_sfloat,
|
||||
.extent = .{
|
||||
.width = width,
|
||||
.height = height,
|
||||
.depth = 1,
|
||||
},
|
||||
.mip_levels = 1,
|
||||
.array_layers = 1,
|
||||
.samples = .@"1_bit",
|
||||
.tiling = .optimal,
|
||||
.usage = usage,
|
||||
.sharing_mode = .exclusive,
|
||||
.queue_family_index_count = queue_family_indices.len,
|
||||
.p_queue_family_indices = queue_family_indices.ptr,
|
||||
.initial_layout = .@"undefined",
|
||||
}, .gpu_only);
|
||||
}
|
||||
|
||||
for (s_targets.depth) |*d| {
|
||||
const usage: vk.ImageUsageFlags = .{
|
||||
.depth_stencil_attachment_bit = true,
|
||||
.sampled_bit = true,
|
||||
};
|
||||
const queue_family_indices = []u32{
|
||||
queues.get(.graphics).family,
|
||||
};
|
||||
try Image.init(d, &.{
|
||||
.image_type = .@"2d",
|
||||
.format = .x8_d24_unorm_pack32,
|
||||
.extent = .{
|
||||
.width = width,
|
||||
.height = height,
|
||||
.depth = 1,
|
||||
},
|
||||
.mip_levels = 1,
|
||||
.array_layers = 1,
|
||||
.samples = .@"1_bit",
|
||||
.tiling = .optimal,
|
||||
.usage = usage,
|
||||
.sharing_mode = .exclusive,
|
||||
.queue_family_index_count = queue_family_indices.len,
|
||||
.p_queue_family_indices = queue_family_indices.ptr,
|
||||
.initial_layout = .@"undefined",
|
||||
}, .gpu_only);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn deinit(device: *const Device) void {
|
||||
for (s_targets.scene) |*s| {
|
||||
s.deinit(device);
|
||||
}
|
||||
|
||||
for (s_targets.depth) |*d| {
|
||||
d.deinit(device);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn recreate(device: *const Device) void {
|
||||
if (getRenderWidth() != getDesiredWidth() or
|
||||
getRenderHeight() != getDesiredHeight())
|
||||
{
|
||||
deinit(device);
|
||||
init();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getDisplayWidth(swapchain: *const Swapchain) i32 {
|
||||
swapchain.getBackBuffer().width;
|
||||
}
|
||||
|
||||
pub fn getDisplayHeight(swapchain: *const Swapchain) i32 {
|
||||
swapchain.getBackBuffer().height;
|
||||
}
|
||||
|
||||
pub fn getRenderWidth() i32 {
|
||||
return s_targets.width;
|
||||
}
|
||||
|
||||
pub fn getRenderHeight() i32 {
|
||||
return s_targets.height;
|
||||
}
|
||||
|
||||
pub fn getRenderAspect() f32 {
|
||||
return @intToFloat(f32, s_targets.width) / @intToFloat(f32, s_targets.height);
|
||||
}
|
||||
|
||||
pub fn getRenderScale() f32 {
|
||||
return 1.0; // TODO convar
|
||||
}
|
|
@ -66,12 +66,14 @@ pub const DeviceDispatch = vk.DeviceWrapper(.{
|
|||
.cmdBeginRenderPass = true,
|
||||
.cmdEndRenderPass = true,
|
||||
.cmdBindPipeline = true,
|
||||
.cmdBindDescriptorSets = true,
|
||||
.cmdDraw = true,
|
||||
.cmdSetViewport = true,
|
||||
.cmdSetScissor = true,
|
||||
.cmdBindVertexBuffers = true,
|
||||
.cmdCopyBuffer = true,
|
||||
.cmdPipelineBarrier = true,
|
||||
.cmdPushConstants = true,
|
||||
.getFenceStatus = true,
|
||||
});
|
||||
|
||||
|
|
|
@ -11,8 +11,8 @@ const allocator = gpa.allocator();
|
|||
const num_attachments = 8;
|
||||
|
||||
const Key = struct {
|
||||
attachments: [num_attachments]vk.ImageView,
|
||||
formats: [num_attachments]vk.Format,
|
||||
attachments: [num_attachments]vk.ImageView = std.mem.zeroes([num_attachments]vk.ImageView),
|
||||
formats: [num_attachments]vk.Format = std.mem.zeroes([num_attachments]vk.Format),
|
||||
width: u16,
|
||||
height: u16,
|
||||
};
|
||||
|
@ -39,18 +39,18 @@ pub fn deinit(device: *const Device) void {
|
|||
s_fbufs.deinit();
|
||||
}
|
||||
|
||||
pub fn getOrAdd(attachments: []*const Image, width: i32, height: i32) !*Framebuffer {
|
||||
pub fn getOrAdd(device: *const Device, attachments: []*const Image, width: u32, height: u32) !vk.Framebuffer {
|
||||
std.debug.assert(attachments.len >= 1);
|
||||
std.debug.assert(attachments.len <= num_attachments);
|
||||
|
||||
const key = Key{
|
||||
.width = width,
|
||||
.height = height,
|
||||
var key = Key{
|
||||
.width = @intCast(u16, width),
|
||||
.height = @intCast(u16, height),
|
||||
};
|
||||
|
||||
for (attachments) |attachment, i| {
|
||||
if (attachment.view) |view| {
|
||||
key.attachments[i] = view;
|
||||
if (attachment.view != .null_handle) {
|
||||
key.attachments[i] = attachment.view;
|
||||
key.formats[i] = attachment.format;
|
||||
}
|
||||
}
|
||||
|
@ -58,12 +58,12 @@ pub fn getOrAdd(attachments: []*const Image, width: i32, height: i32) !*Framebuf
|
|||
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),
|
||||
.handle = try Framebuffer.init(device, key.attachments[0..attachments.len], key.formats[0..attachments.len], key.width, key.height),
|
||||
};
|
||||
result.value_ptr.* = value;
|
||||
}
|
||||
|
||||
return result.value_ptr;
|
||||
return result.value_ptr.handle;
|
||||
}
|
||||
|
||||
pub fn remove(device: *const Device, view: vk.ImageView) void {
|
||||
|
@ -87,8 +87,8 @@ fn containsView(key: *const Key, view: vk.ImageView) bool {
|
|||
}
|
||||
|
||||
pub const Framebuffer = struct {
|
||||
pub fn init(device: *Device, attachments: []const vk.ImageView, formats: []const vk.Format, width: i32, height: i32) !vk.Framebuffer {
|
||||
const pass_desc: RenderPass.Description = .{
|
||||
pub fn init(device: *const Device, attachments: []const vk.ImageView, formats: []const vk.Format, width: u32, height: u32) !vk.Framebuffer {
|
||||
var pass_desc: RenderPass.Description = .{
|
||||
.src_access_mask = .{ .shader_read_bit = true },
|
||||
.dst_access_mask = .{ .color_attachment_write_bit = true },
|
||||
.src_stage_mask = .{ .fragment_shader_bit = true },
|
||||
|
@ -97,17 +97,18 @@ pub const Framebuffer = struct {
|
|||
|
||||
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
|
||||
const layout = if (i == 0 and @enumToInt(format) >= @enumToInt(vk.Format.d16_unorm) and @enumToInt(format) <= @enumToInt(vk.Format.d32_sfloat_s8_uint))
|
||||
vk.ImageLayout.depth_stencil_attachment_optimal
|
||||
else
|
||||
.color_attachment_optimal;
|
||||
vk.ImageLayout.color_attachment_optimal;
|
||||
pass_desc.attachments[i].layout = layout;
|
||||
}
|
||||
|
||||
const pass = try RenderPass.get(&pass_desc);
|
||||
return try device.dispatch.createFramebuffer(device.handle, .{
|
||||
const pass = try RenderPass.get(device, pass_desc);
|
||||
return try device.dispatch.createFramebuffer(device.handle, &.{
|
||||
.flags = .{},
|
||||
.render_pass = pass,
|
||||
.attachment_count = attachments.len,
|
||||
.attachment_count = @intCast(u32, attachments.len),
|
||||
.p_attachments = attachments.ptr,
|
||||
.width = width,
|
||||
.height = height,
|
||||
|
|
|
@ -22,7 +22,7 @@ pub const Image = struct {
|
|||
state: State = .{},
|
||||
handle: vk.Image = .null_handle,
|
||||
allocation: vma.Allocation,
|
||||
view: vk.ImageView,
|
||||
view: vk.ImageView = .null_handle,
|
||||
format: vk.Format,
|
||||
width: u16,
|
||||
height: u16,
|
||||
|
|
|
@ -213,32 +213,32 @@ const Pool = struct {
|
|||
}
|
||||
};
|
||||
|
||||
const ReleasableType = enum {
|
||||
buffer,
|
||||
image,
|
||||
image_view,
|
||||
attachment, // view used as an attachment
|
||||
};
|
||||
|
||||
const ReleasableUnion = union(ReleasableType) {
|
||||
buffer: struct {
|
||||
handle: vk.Buffer,
|
||||
allocation: vma.Allocation,
|
||||
},
|
||||
image: struct {
|
||||
handle: vk.Image,
|
||||
allocation: vma.Allocation,
|
||||
view: vk.ImageView,
|
||||
},
|
||||
image_view: vk.ImageView,
|
||||
attachment: vk.ImageView,
|
||||
};
|
||||
|
||||
pub const Releasable = struct {
|
||||
const Self = @This();
|
||||
|
||||
const Type = enum {
|
||||
buffer,
|
||||
image,
|
||||
image_view,
|
||||
attachment, // view used as an attachment
|
||||
};
|
||||
|
||||
const Union = union(Type) {
|
||||
buffer: struct {
|
||||
handle: vk.Buffer,
|
||||
allocation: vma.Allocation,
|
||||
},
|
||||
image: struct {
|
||||
handle: vk.Image,
|
||||
allocation: vma.Allocation,
|
||||
view: vk.ImageView,
|
||||
},
|
||||
image_view: vk.ImageView,
|
||||
attachment: vk.ImageView,
|
||||
};
|
||||
|
||||
submit_id: SubmitId,
|
||||
object: ReleasableUnion,
|
||||
object: Union,
|
||||
|
||||
pub fn init(self: *const Self) void {
|
||||
// TODO
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
const vk = @import("vulkan");
|
||||
|
||||
// Compile-time settings for Vulkan.
|
||||
|
||||
pub const app_name = "efemra";
|
||||
|
@ -20,3 +22,66 @@ pub const cmds_per_queue = 64;
|
|||
pub fn OnlyIf(comptime setting: bool, t: anytype) type {
|
||||
return if (setting) t else void;
|
||||
}
|
||||
|
||||
pub const Bid = struct {
|
||||
id: u32,
|
||||
desc_type: vk.DescriptorType,
|
||||
count: u32 = 1,
|
||||
stages: vk.ShaderStageFlags,
|
||||
|
||||
pub const TextureTable = struct {
|
||||
const T1D = Bid{
|
||||
.id = 0,
|
||||
.desc_type = .combined_image_sampler,
|
||||
.count = 64,
|
||||
.stages = .{ .fragment_bit = true, .compute_bit = true },
|
||||
};
|
||||
const T2D = Bid{
|
||||
.id = T1D.id + 1,
|
||||
.desc_type = .combined_image_sampler,
|
||||
.count = 512,
|
||||
.stages = .{ .fragment_bit = true, .compute_bit = true },
|
||||
};
|
||||
const T3D = Bid{
|
||||
.id = T2D.id + 1,
|
||||
.desc_type = .combined_image_sampler,
|
||||
.count = 64,
|
||||
.stages = .{ .fragment_bit = true, .compute_bit = true },
|
||||
};
|
||||
const TCube = Bid{
|
||||
.id = T3D.id + 1,
|
||||
.desc_type = .combined_image_sampler,
|
||||
.count = 64,
|
||||
.stages = .{ .fragment_bit = true, .compute_bit = true },
|
||||
};
|
||||
const T2DArray = Bid{
|
||||
.id = TCube.id + 1,
|
||||
.desc_type = .combined_image_sampler,
|
||||
.count = 64,
|
||||
.stages = .{ .fragment_bit = true, .compute_bit = true },
|
||||
};
|
||||
};
|
||||
|
||||
const Globals = Bid{
|
||||
.id = TextureTable.T2DArray.id + 1,
|
||||
.desc_type = .uniform_buffer,
|
||||
.stages = .{}.complement(), // all
|
||||
};
|
||||
const SceneLuminance = Bid{
|
||||
.id = Globals.id + 1,
|
||||
.desc_type = .combined_image_sampler,
|
||||
.stages = .{ .fragment_bit = true, .compute_bit = true },
|
||||
};
|
||||
const HistogramBuffer = Bid{
|
||||
.id = SceneLuminance.id + 1,
|
||||
.desc_type = .storage_image,
|
||||
.stages = .{ .compute_bit = true },
|
||||
};
|
||||
const ExposureBuffer = Bid{
|
||||
.id = HistogramBuffer.id + 1,
|
||||
.desc_type = .storage_buffer,
|
||||
.stages = .{ .fragment_bit = true, .compute_bit = true },
|
||||
};
|
||||
|
||||
const Count = ExposureBuffer.id + 1;
|
||||
};
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
const vk = @import("vulkan");
|
||||
const math = @import("std").math;
|
||||
const Command = @import("Command.zig");
|
||||
|
@ -278,7 +279,7 @@ pub const Swapchain = struct {
|
|||
|
||||
const timeout = std.math.maxInt(u64);
|
||||
const result = try device.dispatch.acquireNextImageKHR(device.handle, self.handle, timeout, self.available_semas[self.sync_index].handle, .null_handle);
|
||||
std.debug.assert(result.image_index < self.length);
|
||||
assert(result.image_index < self.length);
|
||||
const sub = self.image_submits[result.image_index];
|
||||
if (sub.valid) {
|
||||
try sub.wait(device);
|
||||
|
@ -296,7 +297,7 @@ pub const Swapchain = struct {
|
|||
const image_index = self.image_index;
|
||||
const sync_index = self.sync_index;
|
||||
{
|
||||
const backbuf = self.getBackBuffer();
|
||||
var backbuf = self.getBackBuffer();
|
||||
const prev_use = backbuf.state.stage;
|
||||
_ = try Image.State.presentSrc(device, command, backbuf);
|
||||
|
||||
|
@ -322,7 +323,49 @@ pub const Swapchain = struct {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn getViewport(self: *const Self) vk.Viewport {
|
||||
assert(self.handle != .null_handle);
|
||||
return vk.Viewport{
|
||||
.x = 0.0,
|
||||
.y = 0.0,
|
||||
.width = @intToFloat(f32, self.width),
|
||||
.height = @intToFloat(f32, self.height),
|
||||
.min_depth = 0.0,
|
||||
.max_depth = 1.0,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn getRect(self: *const Self) vk.Rect2D {
|
||||
assert(self.handle != .null_handle);
|
||||
return vk.Rect2D{
|
||||
.extent = .{
|
||||
.width = self.width,
|
||||
.height = self.height,
|
||||
},
|
||||
.offset = std.mem.zeroes(vk.Offset2D),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn getAspect(self: *const Self) f32 {
|
||||
assert(self.handle != .null_handle);
|
||||
return @intToFloat(f32, self.width) / @intToFloat(f32, self.height);
|
||||
}
|
||||
|
||||
pub fn getBackBuffer(self: *Self) *Image {
|
||||
return &self.images[self.image_index];
|
||||
var img = &self.images[self.image_index];
|
||||
assert(img.handle != .null_handle);
|
||||
return img;
|
||||
}
|
||||
|
||||
pub fn getDepthBuffer(self: *Self) *Image {
|
||||
var img = &self.images[self.sync_index];
|
||||
assert(img.handle != .null_handle);
|
||||
return img;
|
||||
}
|
||||
|
||||
pub fn getSceneBuffer(self: *Self) *Image {
|
||||
var img = &self.images[self.sync_index];
|
||||
assert(img.handle != .null_handle);
|
||||
return img;
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue