Pass uniform buffer via push constants, yay
This commit is contained in:
parent
3cab3f7946
commit
4b6b859f40
@ -28,7 +28,8 @@ layout(location = 0) out vec3 VertexColor;
|
||||
|
||||
void main() {
|
||||
VertexColor = colors[gl_VertexIndex];
|
||||
gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);
|
||||
|
||||
gl_Position = PushConstants.camera_matrices.view_projection * vec4(positions[gl_VertexIndex], 0.0, 1.0);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -324,11 +324,12 @@ fn loadShaderProgramErr(self: *AssetManager, id: AssetId) !LoadedShaderProgram {
|
||||
try program.serialize(&serializer);
|
||||
|
||||
const pipeline_layout = try self.gc.device.createPipelineLayout(&.{
|
||||
.push_constant_range_count = 1,
|
||||
.p_push_constant_ranges = &.{
|
||||
vk.PushConstantRange{
|
||||
.stage_flags = .{ .vertex_bit = true },
|
||||
.offset = 0,
|
||||
.size = 1,
|
||||
.size = 8,
|
||||
},
|
||||
},
|
||||
}, null);
|
||||
@ -473,6 +474,7 @@ const NullShader = LoadedShader{
|
||||
|
||||
const NullShaderProgram = LoadedShaderProgram{
|
||||
.pipeline = .null_handle,
|
||||
.layout = .null_handle,
|
||||
};
|
||||
|
||||
const NullMesh = LoadedMesh{
|
||||
@ -762,6 +764,7 @@ const LoadedShader = struct {
|
||||
|
||||
const LoadedShaderProgram = struct {
|
||||
pipeline: vk.Pipeline,
|
||||
layout: vk.PipelineLayout,
|
||||
};
|
||||
|
||||
pub const LoadedMesh = struct {
|
||||
|
@ -272,9 +272,9 @@ pub const Buffer = struct {
|
||||
allocation: vma.Allocation,
|
||||
allocation_info: vma.c.VmaAllocationInfo,
|
||||
|
||||
sync_state: SyncState,
|
||||
sync_state: SyncState = .{},
|
||||
|
||||
pub fn sync(self: *const Buffer, cmds: CommandBuffer, masks: SyncBarrierMasks) !void {
|
||||
pub fn sync(self: *Buffer, cmds: CommandBuffer, masks: SyncBarrierMasks) !void {
|
||||
if (self.sync_state.sync(masks, false)) |req| {
|
||||
cmds.pipelineBarrier2(&vk.DependencyInfo{
|
||||
.buffer_memory_barrier_count = 1,
|
||||
@ -299,9 +299,9 @@ pub const Buffer = struct {
|
||||
try vma.flushAllocation(self.gc.vma_allocator, self.allocation, offset, size);
|
||||
}
|
||||
|
||||
pub fn getAllocationMemoryProperties(self: *Buffer) !vk.MemoryPropertyFlags {
|
||||
pub fn getAllocationMemoryProperties(self: *Buffer) vk.MemoryPropertyFlags {
|
||||
var mem_prop_flags = vk.MemoryPropertyFlags{};
|
||||
try vma.getAllocationMemoryProperties(self.gc.vma_allocator, self.allocation, &mem_prop_flags);
|
||||
vma.getAllocationMemoryProperties(self.gc.vma_allocator, self.allocation, &mem_prop_flags);
|
||||
return mem_prop_flags;
|
||||
}
|
||||
|
||||
@ -362,12 +362,14 @@ pub fn init(self: *GraphicsContext, allocator: std.mem.Allocator, window: *c.SDL
|
||||
self.device_info = try selectPhysicalDevice(self.instance, self.surface, physical_devices);
|
||||
const queue_config = try selectQueues(self.instance, self.device_info.physical_device);
|
||||
|
||||
const device_create_config = vk.DeviceCreateInfo{
|
||||
.p_next = &vk.PhysicalDeviceVulkan13Features{
|
||||
// p_next is not const in PhysicalDeviceVulkan12Features, so pass it like this
|
||||
var vulkan13_device_features = vk.PhysicalDeviceVulkan13Features{
|
||||
.dynamic_rendering = vk.TRUE,
|
||||
.synchronization_2 = vk.TRUE,
|
||||
.maintenance_4 = vk.TRUE,
|
||||
},
|
||||
};
|
||||
|
||||
const device_create_config = vk.DeviceCreateInfo{
|
||||
.p_queue_create_infos = &queue_config.queue_create_info,
|
||||
.queue_create_info_count = queue_config.queue_count,
|
||||
.p_enabled_features = &self.device_info.features,
|
||||
@ -375,6 +377,10 @@ pub fn init(self: *GraphicsContext, allocator: std.mem.Allocator, window: *c.SDL
|
||||
.enabled_layer_count = @intCast(vk_layers.len),
|
||||
.pp_enabled_extension_names = @ptrCast((&device_extensions).ptr),
|
||||
.enabled_extension_count = @intCast(device_extensions.len),
|
||||
.p_next = &vk.PhysicalDeviceVulkan12Features{
|
||||
.buffer_device_address = vk.TRUE,
|
||||
.p_next = &vulkan13_device_features,
|
||||
},
|
||||
};
|
||||
|
||||
const device_handle = try self.instance.createDevice(self.device_info.physical_device, &device_create_config, null);
|
||||
@ -384,6 +390,9 @@ pub fn init(self: *GraphicsContext, allocator: std.mem.Allocator, window: *c.SDL
|
||||
self.device = Device.init(device_handle, &self.vkd);
|
||||
|
||||
self.vma_allocator = vma.createAllocator(&.{
|
||||
.flags = .{
|
||||
.buffer_device_address_bit = true,
|
||||
},
|
||||
.instance = instance_handle,
|
||||
.physical_device = self.device_info.physical_device,
|
||||
.device = device_handle,
|
||||
@ -432,7 +441,9 @@ pub fn init(self: *GraphicsContext, allocator: std.mem.Allocator, window: *c.SDL
|
||||
|
||||
pub fn createBuffer(self: *GraphicsContext, create_info: *const vk.BufferCreateInfo, allocation_create_info: *const vma.AllocationCreateInfo) !Buffer {
|
||||
var result: Buffer = undefined;
|
||||
result.handle = try vma.createBuffer(self.vma_allocator, create_info, allocation_create_info, result.allocation, result.allocation_info);
|
||||
result.gc = self;
|
||||
result.handle = try vma.createBuffer(self.vma_allocator, create_info, allocation_create_info, &result.allocation, &result.allocation_info);
|
||||
result.sync_state = .{};
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@ const GraphicsContext = @import("GraphicsContext.zig");
|
||||
const vk = @import("vk");
|
||||
const a = @import("asset_manifest");
|
||||
const za = @import("zalgebra");
|
||||
const Vec3 = za.Vec3;
|
||||
const Mat4 = za.Mat4;
|
||||
|
||||
const Render2 = @This();
|
||||
@ -24,6 +25,7 @@ pub fn init(assetman: *AssetManager, gc: *GraphicsContext) !Render2 {
|
||||
.assetman = assetman,
|
||||
.gc = gc,
|
||||
.command_pool = try gc.queues.graphics.createCommandPool(.{ .reset_command_buffer_bit = true }),
|
||||
.camera_matrices_buffer = undefined,
|
||||
};
|
||||
errdefer self.command_pool.deinit();
|
||||
|
||||
@ -44,11 +46,10 @@ pub fn init(assetman: *AssetManager, gc: *GraphicsContext) !Render2 {
|
||||
.mapped_bit = true,
|
||||
},
|
||||
});
|
||||
errdefer self.camera_matrices_buffer.deinit(self.gc);
|
||||
const mem_props = try self.camera_matrices_buffer.getAllocationMemoryProperties();
|
||||
// const mem_props = self.camera_matrices_buffer.getAllocationMemoryProperties();
|
||||
|
||||
// TODO: Assuming unified memory or resizable bar right now, should not assume that
|
||||
std.debug.assert(mem_props.contains(.{ .host_visible_bit = true }));
|
||||
// // TODO: Assuming unified memory or resizable bar right now, should not assume that
|
||||
// std.debug.assert(mem_props.contains(.{ .host_visible_bit = true }));
|
||||
|
||||
return self;
|
||||
}
|
||||
@ -73,10 +74,12 @@ pub fn draw(self: *Render2) !void {
|
||||
{
|
||||
try self.camera_matrices_buffer.sync(cmds, .{ .stage_mask = .{ .host_bit = true }, .access_mask = .{ .host_write_bit = true } });
|
||||
const c_matrices: [*c]CameraMatrices = @alignCast(@ptrCast(self.camera_matrices_buffer.allocation_info.pMappedData.?));
|
||||
const matrices: *CameraMatrices = c_matrices[0..MAX_FRAME_LAG][self.frame];
|
||||
const matrices: *CameraMatrices = &c_matrices[0..MAX_FRAME_LAG][self.frame];
|
||||
|
||||
const view = Mat4.identity();
|
||||
const projection = Mat4.perspective(60, 1.0 / 16.0, 0.1, 1000);
|
||||
const view = Mat4.lookAt(Vec3.new(0, 0, 1), Vec3.new(0, 0, 0), Vec3.new(0, 1, 0));
|
||||
const fwidth: f32 = @floatFromInt(self.gc.swapchain_extent.width);
|
||||
const fheight: f32 = @floatFromInt(self.gc.swapchain_extent.height);
|
||||
const projection = Mat4.perspective(60, fwidth / fheight, 0.1, 1000);
|
||||
const view_projection = projection.mul(view);
|
||||
matrices.* = .{
|
||||
.view = view,
|
||||
@ -109,7 +112,12 @@ pub fn draw(self: *Render2) !void {
|
||||
});
|
||||
defer cmds.endRendering();
|
||||
|
||||
cmds.bindPipeline(.graphics, self.assetman.resolveShaderProgram(a.ShaderPrograms.shaders.triangle).pipeline);
|
||||
const triangle = self.assetman.resolveShaderProgram(a.ShaderPrograms.shaders.triangle);
|
||||
|
||||
cmds.bindPipeline(.graphics, triangle.pipeline);
|
||||
|
||||
const device_address = self.gc.device.getBufferDeviceAddress(&.{ .buffer = self.camera_matrices_buffer.handle });
|
||||
cmds.pushConstants(triangle.layout, .{ .vertex_bit = true }, 0, 8, &device_address);
|
||||
|
||||
cmds.setViewportWithCount(1, &.{vk.Viewport{
|
||||
.x = 0,
|
||||
@ -124,7 +132,6 @@ pub fn draw(self: *Render2) !void {
|
||||
.extent = self.gc.swapchain_extent,
|
||||
}});
|
||||
|
||||
try self.camera_matrices_buffer.sync(cmds, .{ .stage_mask = .{ .vertex_shader_bit = true }, .access_mask = .{ .shader_read_bit = true } });
|
||||
cmds.draw(3, 1, 0, 0);
|
||||
}
|
||||
|
||||
|
28
src/RenderGraph.zig
Normal file
28
src/RenderGraph.zig
Normal file
@ -0,0 +1,28 @@
|
||||
const std = @import("std");
|
||||
const vk = @import("vk");
|
||||
const GraphicsContext = @import("GraphicsContext.zig");
|
||||
pub const RenderGraph = @This();
|
||||
|
||||
pub const PassSetupContext = struct {};
|
||||
pub const Texture2DHandle = struct { id: u64 };
|
||||
|
||||
pub fn declareTexture2D(comptime name: []const u8) Texture2DHandle {
|
||||
return Texture2DHandle{ .id = std.hash.Wyhash.hash(0, name) };
|
||||
}
|
||||
|
||||
test "RenderGraph" {
|
||||
var GraphBuilder: *RenderGraph = undefined;
|
||||
|
||||
const GBuffer = RenderGraph.declareTexture2D("GBuffer");
|
||||
|
||||
GraphBuilder.addPass(
|
||||
struct {
|
||||
fn setup(ctx: *PassSetupContext) void {
|
||||
ctx.createTexture2D(GBuffer, 1024, 1024, vk.Format.r8g8b8a8_unorm);
|
||||
}
|
||||
fn render(ctx: *GraphicsContext.CommandBuffer) void {
|
||||
ctx.getTexture2D(GBuffer);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
@ -16,7 +16,7 @@ pub const AllocatorCreateFlags = packed struct {
|
||||
khr_bind_memory2_bit: bool = false,
|
||||
ext_memory_budget_bit: bool = false,
|
||||
amd_device_coherent_memory_bit: bool = false,
|
||||
jbuffer_device_address_bit: bool = false,
|
||||
buffer_device_address_bit: bool = false,
|
||||
ext_memory_priority_bit: bool = false,
|
||||
khr_maintenance4_bit: bool = false,
|
||||
khr_maintenance5_bit: bool = false,
|
||||
@ -206,7 +206,7 @@ pub fn destroyImage(allocator: Allocator, image: vk.Image, allocation: Allocatio
|
||||
c.vmaDestroyImage(allocator, @as(*const c.VkImage, @ptrCast(&image)).*, allocation);
|
||||
}
|
||||
|
||||
pub fn flushAllocation(allocator: Allocator, allocation: Allocation, offset: vk.DeviceSize, size: vk.DeviceSize) void {
|
||||
pub fn flushAllocation(allocator: Allocator, allocation: Allocation, offset: vk.DeviceSize, size: vk.DeviceSize) Error!void {
|
||||
try checkError(c.vmaFlushAllocation(allocator, allocation, offset, size));
|
||||
}
|
||||
|
||||
@ -216,5 +216,7 @@ pub fn flushAllocations(allocator: Allocator, allocations: []const Allocation, o
|
||||
}
|
||||
|
||||
pub fn getAllocationMemoryProperties(allocator: Allocator, allocation: Allocation, mem_prop_flags: *vk.MemoryPropertyFlags) void {
|
||||
try checkError(c.vmaGetAllocationMemoryProperties(allocator, allocation, mem_prop_flags));
|
||||
var result: c.VkMemoryPropertyFlags = 0;
|
||||
c.vmaGetAllocationMemoryProperties(allocator, allocation, &result);
|
||||
mem_prop_flags.* = @bitCast(result);
|
||||
}
|
||||
|
@ -21,8 +21,6 @@ const c = @cImport({
|
||||
@cInclude("stb_image.h");
|
||||
|
||||
@cInclude("ispc_texcomp.h");
|
||||
|
||||
@cInclude("spirv-cross/spirv_cross_c.h");
|
||||
});
|
||||
|
||||
const ASSET_MAX_BYTES = 1024 * 1024 * 1024;
|
||||
@ -55,83 +53,6 @@ const Args = struct {
|
||||
output_dir: []const u8 = "",
|
||||
};
|
||||
|
||||
// Single producer, multiple consumers
|
||||
fn JobQueue(comptime JobPayload: type) type {
|
||||
return struct {
|
||||
const Self = @This();
|
||||
|
||||
pub const JobFn = fn (payload: *JobPayload) void;
|
||||
pub const Job = struct {
|
||||
payload: JobPayload,
|
||||
func: JobFn,
|
||||
};
|
||||
|
||||
running: std.atomic.Value(bool) = std.atomic.Value(bool).init(true),
|
||||
|
||||
read: std.atomic.Value(u32) = std.atomic.Value(u32).init(0),
|
||||
write: std.atomic.Value(u32) = std.atomic.Value(u32).init(0),
|
||||
buffer: []Job,
|
||||
|
||||
pub fn init(buffer: []Job) JobQueue {
|
||||
return JobQueue{
|
||||
.buffer = buffer,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn pushJobs(self: *Self, jobs: []const Job) void {
|
||||
var left_to_write: usize = jobs.len;
|
||||
while (left_to_write > 0) {
|
||||
const write = self.write.load(.unordered);
|
||||
if (write >= (self.read.load(.unordered) + self.buffer.len)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const read = self.read.load(.acquire);
|
||||
|
||||
const to_write = @min(self.buffer.len - (write - read), left_to_write);
|
||||
for (0..to_write) |i| {
|
||||
self.buffer[(write + i) % self.buffer.len] = jobs[i];
|
||||
}
|
||||
|
||||
_ = self.write.fetchAdd(to_write, .release);
|
||||
|
||||
left_to_write -= to_write;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn takeJob(self: *Self) Job {
|
||||
while (true) {
|
||||
const read = self.read.load(.acquire);
|
||||
if (self.write.load(.acquire) - read > 0) {
|
||||
if (self.read.cmpxchgStrong(read, read + 1, .release, .acquire)) {
|
||||
return self.buffer[read % self.buffer.len];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn workerEntry(userdata: *anyopaque) void {
|
||||
const self: Self = @ptrCast(userdata);
|
||||
|
||||
while (self.running.load(.acquire)) {
|
||||
const job = self.takeJob();
|
||||
|
||||
job.func(job.payload);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const ProcessAssetJobPayload = struct {
|
||||
allocator: std.mem.Allocator,
|
||||
asset_type: AssetType,
|
||||
rel_input: []const u8,
|
||||
output_dir: std.fs.Dir,
|
||||
dep_file: ?[]const u8,
|
||||
};
|
||||
|
||||
const ProcessAssetJobQueue = JobQueue(ProcessAssetJobPayload);
|
||||
|
||||
fn parseArgs(allocator: std.mem.Allocator) !Args {
|
||||
var args = try std.process.argsWithAllocator(allocator);
|
||||
defer args.deinit();
|
||||
@ -209,27 +130,14 @@ pub fn main() !void {
|
||||
var buf_asset_list_writer = std.io.bufferedWriter(std.io.getStdOut().writer());
|
||||
const asset_list_writer = buf_asset_list_writer.writer();
|
||||
|
||||
var queue = ProcessAssetJobQueue.init(try allocator.alloc(ProcessAssetJobQueue.Job, 1024));
|
||||
|
||||
const num_workers = std.Thread.getCpuCount() - 1;
|
||||
const worker_threads = allocator.alloc(std.Thread, num_workers);
|
||||
|
||||
for (0..num_workers) |i| {
|
||||
worker_threads[i] = try std.Thread.spawn(.{}, ProcessAssetJobQueue.workerEntry, .{&queue});
|
||||
}
|
||||
|
||||
std.log.debug("type: {s}, rel_input: {s}, output_dir: {s}", .{ @tagName(asset_type), rel_input, rel_output });
|
||||
queue.pushJobs(&[]ProcessAssetJobQueue.Job{.{
|
||||
.payload = .{
|
||||
.allocator = allocator,
|
||||
.asset_type = asset_type,
|
||||
.rel_input = rel_input,
|
||||
.output_dir = output_dir,
|
||||
.dep_file = args.dep_file,
|
||||
},
|
||||
.func = processAsset,
|
||||
}});
|
||||
|
||||
switch (asset_type) {
|
||||
.Scene => try processScene(allocator, rel_input, output_dir, asset_list_writer),
|
||||
.ShaderProgram => try processShaderProgram(allocator, rel_input, output_dir, args.dep_file, asset_list_writer),
|
||||
.Texture => try processTextureFromFile(allocator, rel_input, output_dir, asset_list_writer),
|
||||
else => unreachable,
|
||||
}
|
||||
try buf_asset_list_writer.flush();
|
||||
|
||||
if (args.dep_file) |dep_file_path| {
|
||||
@ -238,15 +146,6 @@ pub fn main() !void {
|
||||
}
|
||||
}
|
||||
|
||||
fn processAsset(payload: ProcessAssetJobPayload) void {
|
||||
switch (payload.asset_type) {
|
||||
.Scene => try processScene(payload.allocator, payload.rel_input, payload.output_dir, payload.asset_list_writer),
|
||||
.ShaderProgram => try processShaderProgram(payload.allocator, payload.rel_input, payload.output_dir, payload.dep_file, payload.asset_list_writer),
|
||||
.Texture => try processTextureFromFile(payload.allocator, payload.rel_input, payload.output_dir, payload.asset_list_writer),
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
|
||||
fn copyFile(_type: AssetType, input: []const u8, output_dir: std.fs.Dir, asset_list_writer: anytype) !void {
|
||||
const asset_path = AssetPath{ .simple = input };
|
||||
|
||||
@ -723,21 +622,6 @@ fn processShader(allocator: std.mem.Allocator, flags: []const []const u8, input:
|
||||
try file.writeAll(old_depfile_contents);
|
||||
}
|
||||
|
||||
// {
|
||||
// var spvc_context: c.spvc_context = null;
|
||||
// _ = c.spvc_context_create(&spvc_context);
|
||||
// defer c.spvc_context_destroy(spvc_context);
|
||||
|
||||
// var ir: c.spvc_parsed_ir = null;
|
||||
// // c.spvc_context_parse_spirv(spvc_context, spirv: [*c]const c.SpvId, word_count: usize, &ir);
|
||||
|
||||
// var compiler_glsl: c.spvc_compiler = null;
|
||||
// c.spvc_context_create_compiler(spvc_context, c.SPVC_BACKEND_GLSL, ir, c.SPVC_CAPTURE_MODE_TAKE_OWNERSHIP, &compiler_glsl);
|
||||
|
||||
// var resources: c.spvc_resources = null;
|
||||
// c.spvc_compiler_create_shader_resources(compiler_glsl, &resources);
|
||||
// }
|
||||
|
||||
return result.stdout;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user