From 29cd7fa5e5c9e48030cc2996dd93471a0e1a6914 Mon Sep 17 00:00:00 2001 From: David Allemang Date: Fri, 5 Jul 2024 23:26:57 -0400 Subject: [PATCH] start migrating to uber-pipeline with descriptors --- src/Uber.zig | 178 ++++++++++++++++++++++++++++++++++++++++++++++++ src/main.zig | 187 +++++++++++---------------------------------------- 2 files changed, 218 insertions(+), 147 deletions(-) create mode 100644 src/Uber.zig diff --git a/src/Uber.zig b/src/Uber.zig new file mode 100644 index 0000000..1a64888 --- /dev/null +++ b/src/Uber.zig @@ -0,0 +1,178 @@ +const std = @import("std"); +const au = @import("au.zig"); +const vk = @import("vk"); +const shaders = @import("shaders"); + +const Self = @This(); + +set_layout: vk.DescriptorSetLayout, +layout: vk.PipelineLayout, +pipeline: vk.Pipeline, + +pub const Index = u16; + +pub const Vertex = extern struct { + pos: [4]f32, + color: [3]f32, + + const InputStateInfo = vk.PipelineVertexInputStateCreateInfo{ + .vertex_binding_description_count = 1, + .p_vertex_binding_descriptions = &.{ + vk.VertexInputBindingDescription{ + .binding = 0, + .stride = @sizeOf(Vertex), + .input_rate = .vertex, + }, + }, + + .vertex_attribute_description_count = 2, + .p_vertex_attribute_descriptions = &.{ + vk.VertexInputAttributeDescription{ + .binding = 0, + .location = 0, + .format = .r32g32b32a32_sfloat, + .offset = @offsetOf(Vertex, "pos"), + }, + vk.VertexInputAttributeDescription{ + .binding = 0, + .location = 1, + .format = .r32g32b32_sfloat, + .offset = @offsetOf(Vertex, "color"), + }, + }, + }; +}; + +pub const Uniform = extern struct { + proj: [16]f32 = .{ + 0.5, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1, + }, + + const DescriptorLayoutInfo = vk.DescriptorSetLayoutCreateInfo{ + .flags = .{}, + .binding_count = 1, + .p_bindings = &.{ + vk.DescriptorSetLayoutBinding{ + .binding = 0, + .descriptor_type = .uniform_buffer, + .descriptor_count = 1, + .stage_flags = .{ .vertex_bit = true }, + }, + }, + }; +}; + +pub fn init(cache: vk.PipelineCache) !Self { + const vert = try au.D.createShaderModule(&.{ + .code_size = shaders.triangle_vert.len, + .p_code = @ptrCast(&shaders.triangle_vert), + }, null); + defer au.D.destroyShaderModule(vert, null); + + const frag = try au.D.createShaderModule(&.{ + .code_size = shaders.triangle_frag.len, + .p_code = @ptrCast(&shaders.triangle_frag), + }, null); + defer au.D.destroyShaderModule(frag, null); + + const set_layout = try au.D.createDescriptorSetLayout(&Uniform.DescriptorLayoutInfo, null); + errdefer au.D.destroyDescriptorSetLayout(set_layout, null); + + const layout = try au.D.createPipelineLayout(&vk.PipelineLayoutCreateInfo{ + .push_constant_range_count = 0, + .set_layout_count = 1, + .p_set_layouts = &.{set_layout}, + }, null); + errdefer au.D.destroyPipelineLayout(layout, null); + + var pipeline: vk.Pipeline = .null_handle; + _ = try au.D.createGraphicsPipelines(cache, 1, &[1]vk.GraphicsPipelineCreateInfo{ + vk.GraphicsPipelineCreateInfo{ + .stage_count = 2, + .p_stages = &.{ + vk.PipelineShaderStageCreateInfo{ .stage = .{ .vertex_bit = true }, .module = vert, .p_name = "main" }, + vk.PipelineShaderStageCreateInfo{ .stage = .{ .fragment_bit = true }, .module = frag, .p_name = "main" }, + }, + .layout = layout, + .render_pass = .null_handle, + .subpass = 0, + .base_pipeline_handle = .null_handle, + .base_pipeline_index = -1, + .p_vertex_input_state = &Vertex.InputStateInfo, + .p_input_assembly_state = &vk.PipelineInputAssemblyStateCreateInfo{ + .topology = .triangle_list, + .primitive_restart_enable = vk.FALSE, + }, + .p_tessellation_state = null, + .p_viewport_state = &vk.PipelineViewportStateCreateInfo{ + .viewport_count = 1, + .scissor_count = 1, + }, + .p_rasterization_state = &vk.PipelineRasterizationStateCreateInfo{ + .depth_clamp_enable = vk.FALSE, + .rasterizer_discard_enable = vk.FALSE, + .polygon_mode = .fill, + .cull_mode = .{ .back_bit = true }, + .front_face = .counter_clockwise, + .depth_bias_enable = vk.FALSE, + .depth_bias_constant_factor = 0.0, + .depth_bias_clamp = 0.0, + .depth_bias_slope_factor = 0.0, + .line_width = 1.0, + }, + .p_multisample_state = &vk.PipelineMultisampleStateCreateInfo{ + .rasterization_samples = .{ .@"1_bit" = true }, + .sample_shading_enable = vk.FALSE, + .min_sample_shading = 1, + .alpha_to_coverage_enable = vk.FALSE, + .alpha_to_one_enable = vk.FALSE, + }, + .p_depth_stencil_state = null, + .p_color_blend_state = &vk.PipelineColorBlendStateCreateInfo{ + .logic_op_enable = vk.FALSE, + .logic_op = .copy, + .blend_constants = [_]f32{ 0, 0, 0, 0 }, + .attachment_count = 1, + .p_attachments = &.{ + vk.PipelineColorBlendAttachmentState{ + .blend_enable = vk.FALSE, + .color_blend_op = .add, + .src_color_blend_factor = .one, + .dst_color_blend_factor = .zero, + .alpha_blend_op = .add, + .src_alpha_blend_factor = .one, + .dst_alpha_blend_factor = .zero, + .color_write_mask = .{ .r_bit = true, .g_bit = true, .b_bit = true, .a_bit = true }, + }, + }, + }, + .p_dynamic_state = &vk.PipelineDynamicStateCreateInfo{ + .flags = .{}, + .dynamic_state_count = 2, + .p_dynamic_states = &.{ + .viewport, + .scissor, + }, + }, + .p_next = &vk.PipelineRenderingCreateInfo{ + .color_attachment_count = 1, + .p_color_attachment_formats = &.{au.device_config.format.format}, + .depth_attachment_format = .undefined, + .stencil_attachment_format = .undefined, + .view_mask = 0, + }, + }, + }, null, @ptrCast(&pipeline)); + errdefer au.D.destroyPipeline(pipeline, null); + + return .{ .pipeline = pipeline, .layout = layout, .set_layout = set_layout }; +} + +pub fn deinit(self: Self) void { + au.D.destroyPipeline(self.pipeline, null); + au.D.destroyPipelineLayout(self.layout, null); + au.D.destroyDescriptorSetLayout(self.set_layout, null); +} diff --git a/src/main.zig b/src/main.zig index 625f2c9..203eb21 100644 --- a/src/main.zig +++ b/src/main.zig @@ -7,35 +7,9 @@ const Allocator = std.mem.Allocator; const au = @import("au.zig"); const im = @import("cimgui"); -const Vertex = extern struct { - const binding_description = vk.VertexInputBindingDescription{ - .binding = 0, - .stride = @sizeOf(Vertex), - .input_rate = .vertex, - }; +const Uber = @import("Uber.zig"); - const attribute_description = [_]vk.VertexInputAttributeDescription{ - .{ - .binding = 0, - .location = 0, - .format = .r32g32b32a32_sfloat, - .offset = @offsetOf(Vertex, "pos"), - }, - .{ - .binding = 0, - .location = 1, - .format = .r32g32b32_sfloat, - .offset = @offsetOf(Vertex, "color"), - }, - }; - - pos: [4]f32, - color: [3]f32, -}; - -const Index = u16; - -const vertices = [_]Vertex{ +const vertices = [_]Uber.Vertex{ // Vulkan depth range is 0, 1 instead of OpenGL -1, 1 .{ .pos = .{ -0.5, -0.5, -0.5, 1.0 }, .color = .{ 1, 0, 0 } }, .{ .pos = .{ -0.5, 0.5, -0.5, 1.0 }, .color = .{ 0, 1, 0 } }, @@ -47,7 +21,9 @@ const vertices = [_]Vertex{ .{ .pos = .{ 0.5, 0.5, 0.5, 1.0 }, .color = .{ 1, 1, 0 } }, }; -const indices = [_]Index{ 4, 5, 6, 6, 5, 7 }; +const indices = [_]Uber.Index{ 4, 5, 6, 6, 5, 7 }; + +const uniform = Uber.Uniform{}; const Frame = struct { pub fn init() !Frame { @@ -67,6 +43,7 @@ const Frame = struct { pipeline: vk.Pipeline, vertex_buffer: vk.Buffer, index_buffer: vk.Buffer, + uniform_buffer: vk.Buffer, ) !void { _ = self; @@ -143,7 +120,7 @@ const Frame = struct { .{}, 0, null, - 1, + 2, &.{ vk.BufferMemoryBarrier{ .buffer = vertex_buffer, @@ -154,6 +131,15 @@ const Frame = struct { .src_queue_family_index = 0, .dst_queue_family_index = 0, }, + vk.BufferMemoryBarrier{ + .buffer = uniform_buffer, + .src_access_mask = .{ .shader_read_bit = true }, + .dst_access_mask = .{ .host_write_bit = true }, + .offset = 0, + .size = vk.WHOLE_SIZE, + .src_queue_family_index = 0, + .dst_queue_family_index = 0, + }, }, 0, null, @@ -254,30 +240,11 @@ pub fn main() !void { _ = im.c.ImGui_ImplVulkan_CreateFontsTexture(); defer im.c.ImGui_ImplVulkan_Shutdown(); - const vert = try au.D.createShaderModule(&vk.ShaderModuleCreateInfo{ - .code_size = shaders.triangle_vert.len, - .p_code = @ptrCast(&shaders.triangle_vert), - }, null); - defer au.D.destroyShaderModule(vert, null); - - const frag = try au.D.createShaderModule(&vk.ShaderModuleCreateInfo{ - .code_size = shaders.triangle_frag.len, - .p_code = @ptrCast(&shaders.triangle_frag), - }, null); - defer au.D.destroyShaderModule(frag, null); - const cache = try au.D.createPipelineCache(&vk.PipelineCacheCreateInfo{}, null); defer au.D.destroyPipelineCache(cache, null); - // for descriptor sets - const layout = try au.D.createPipelineLayout(&vk.PipelineLayoutCreateInfo{ - .flags = .{}, - .set_layout_count = 0, - .p_set_layouts = null, - .push_constant_range_count = 0, - .p_push_constant_ranges = null, - }, null); - defer au.D.destroyPipelineLayout(layout, null); + const uber = try Uber.init(cache); + defer uber.deinit(); const vkalloc = au.VkAllocator.init(); @@ -293,8 +260,8 @@ pub fn main() !void { ); defer vkalloc.free(vertex_memory); try au.D.bindBufferMemory(vertex_buffer, vertex_memory, 0); - - const vertex_data: *align(1) @TypeOf(vertices) = @ptrCast(try au.D.mapMemory(vertex_memory, 0, vk.WHOLE_SIZE, .{})); + const vertex_data: *align(1) @TypeOf(vertices) = + @ptrCast(try au.D.mapMemory(vertex_memory, 0, vk.WHOLE_SIZE, .{})); defer au.D.unmapMemory(vertex_memory); vertex_data.* = vertices; @@ -310,102 +277,27 @@ pub fn main() !void { ); defer vkalloc.free(index_memory); try au.D.bindBufferMemory(index_buffer, index_memory, 0); - const index_data: *align(1) @TypeOf(indices) = @ptrCast(try au.D.mapMemory(index_memory, 0, vk.WHOLE_SIZE, .{})); + const index_data: *align(1) @TypeOf(indices) = + @ptrCast(try au.D.mapMemory(index_memory, 0, vk.WHOLE_SIZE, .{})); defer au.D.unmapMemory(index_memory); index_data.* = indices; - try au.D.deviceWaitIdle(); - - const gpci: vk.GraphicsPipelineCreateInfo = .{ - .stage_count = 2, - .p_stages = &.{ - vk.PipelineShaderStageCreateInfo{ .stage = .{ .vertex_bit = true }, .module = vert, .p_name = "main" }, - vk.PipelineShaderStageCreateInfo{ .stage = .{ .fragment_bit = true }, .module = frag, .p_name = "main" }, - }, - .p_vertex_input_state = &vk.PipelineVertexInputStateCreateInfo{ - .vertex_binding_description_count = 1, - .p_vertex_binding_descriptions = @ptrCast(&Vertex.binding_description), - .vertex_attribute_description_count = Vertex.attribute_description.len, - .p_vertex_attribute_descriptions = &Vertex.attribute_description, - }, - .p_input_assembly_state = &vk.PipelineInputAssemblyStateCreateInfo{ - .topology = .triangle_list, - .primitive_restart_enable = vk.FALSE, - }, - .p_tessellation_state = null, - .p_viewport_state = &vk.PipelineViewportStateCreateInfo{ - .viewport_count = 1, - .scissor_count = 1, - }, - .p_rasterization_state = &vk.PipelineRasterizationStateCreateInfo{ - .depth_clamp_enable = vk.FALSE, - .rasterizer_discard_enable = vk.FALSE, - .polygon_mode = .fill, - .cull_mode = .{ .back_bit = true }, - .front_face = .counter_clockwise, - .depth_bias_enable = vk.FALSE, - .depth_bias_constant_factor = 0.0, - .depth_bias_clamp = 0.0, - .depth_bias_slope_factor = 0.0, - .line_width = 1.0, - }, - .p_multisample_state = &vk.PipelineMultisampleStateCreateInfo{ - .rasterization_samples = .{ .@"1_bit" = true }, - .sample_shading_enable = vk.FALSE, - .min_sample_shading = 1, - .alpha_to_coverage_enable = vk.FALSE, - .alpha_to_one_enable = vk.FALSE, - }, - .p_depth_stencil_state = null, - .p_color_blend_state = &vk.PipelineColorBlendStateCreateInfo{ - .logic_op_enable = vk.FALSE, - .logic_op = .copy, - .blend_constants = [_]f32{ 0, 0, 0, 0 }, - .attachment_count = 1, - .p_attachments = &.{ - vk.PipelineColorBlendAttachmentState{ - .blend_enable = vk.FALSE, - .color_blend_op = .add, - .src_color_blend_factor = .one, - .dst_color_blend_factor = .zero, - .alpha_blend_op = .add, - .src_alpha_blend_factor = .one, - .dst_alpha_blend_factor = .zero, - .color_write_mask = .{ .r_bit = true, .g_bit = true, .b_bit = true, .a_bit = true }, - }, - }, - }, - .p_dynamic_state = &vk.PipelineDynamicStateCreateInfo{ - .flags = .{}, - .dynamic_state_count = 2, - .p_dynamic_states = &.{ - .viewport, - .scissor, - }, - }, - .layout = layout, - .render_pass = .null_handle, // set via dynamic rendering - .subpass = 0, - .base_pipeline_handle = .null_handle, - .base_pipeline_index = -1, - .p_next = &vk.PipelineRenderingCreateInfo{ - .color_attachment_count = 1, - .p_color_attachment_formats = &.{au.device_config.format.format}, - .depth_attachment_format = .undefined, - .stencil_attachment_format = .undefined, - .view_mask = 0, - }, - }; - - var pipeline: vk.Pipeline = undefined; - _ = try au.D.createGraphicsPipelines( - cache, - 1, - @ptrCast(&gpci), - null, - @ptrCast(&pipeline), + const uniform_buffer = try au.D.createBuffer(&vk.BufferCreateInfo{ + .size = @sizeOf(@TypeOf(uniform)), + .usage = .{ .uniform_buffer_bit = true }, + .sharing_mode = .exclusive, + }, null); + defer au.D.destroyBuffer(uniform_buffer, null); + const uniform_memory = try vkalloc.alloc( + au.D.getBufferMemoryRequirements(uniform_buffer), + .{ .host_visible_bit = true, .host_coherent_bit = true }, ); - defer au.D.destroyPipeline(pipeline, null); + defer vkalloc.free(uniform_memory); + try au.D.bindBufferMemory(uniform_buffer, uniform_memory, 0); + const uniform_data: *align(1) @TypeOf(uniform) = + @ptrCast(try au.D.mapMemory(uniform_memory, 0, vk.WHOLE_SIZE, .{})); + defer au.D.unmapMemory(uniform_memory); + uniform_data.* = uniform; var prng = std.Random.Sfc64.init(std.crypto.random.int(u64)); const rand = prng.random(); @@ -457,14 +349,15 @@ pub fn main() !void { image, view, vk.Rect2D{ .offset = .{ .x = 0, .y = 0 }, .extent = sc.cinfo.image_extent }, - pipeline, + uber.pipeline, vertex_buffer, index_buffer, + uniform_buffer, ); for (vertex_data) |*v| { for (v.pos[0..2]) |*f| { - f.* += (rand.float(f32) - 0.5) * 0.01; + f.* += (rand.float(f32) - 0.5) * 0.001; } }