From c87271d2f53ba0b09355c59a6ba85f6a01d0ed6d Mon Sep 17 00:00:00 2001 From: Riley King-Saunders Date: Thu, 10 Jul 2025 22:00:35 +1000 Subject: [PATCH] Expanded basic program to use a vertex buffer via the new basalt::Buffer Updated vertex function get_attribute_descriptions to conform to new standard for template-based binding Moved definition of triangle verticies inside of the application function Maps, copies into and unmaps the vertex buffer from the darray Uses a reference to refer to the current frames command buffer to not repeat the ugly indexing render area and viewport extent is updated every frame with the swapchain extent No longer directly recreate the framebuffers, now using the recreate function with the renderpass passed as a paramater --- tests/basic/src/main.cpp | 91 ++++++++++++++++++++++++---------------- 1 file changed, 56 insertions(+), 35 deletions(-) diff --git a/tests/basic/src/main.cpp b/tests/basic/src/main.cpp index c9d2cf8..f0b748e 100644 --- a/tests/basic/src/main.cpp +++ b/tests/basic/src/main.cpp @@ -3,6 +3,7 @@ #include "vulkan/basalt_command_buffer.h" #include "vulkan/basalt_swapchain.h" +#include "vulkan/basalt_buffer.h" #include struct Vertex @@ -11,19 +12,19 @@ struct Vertex glm::vec3 colour; static VkVertexInputBindingDescription get_binding_description(void); - static VkResult get_attribute_descriptions(VkVertexInputAttributeDescription** out_attributes, u32* out_num_attributes); + static VkResult get_attribute_descriptions(VkVertexInputAttributeDescription* out_attributes, u32* out_num_attributes); }; -static basalt::darray verts({ - {{0.0f, -0.5f}, {1.0f, 0.0f, 0.0f}}, - {{0.5f, 0.5f}, {0.0f, 1.0f, 0.0f}}, - {{-0.5f, 0.5f}, {0.0f, 0.0f, 1.0f}} - }, MEMORY_TAG_CLASS_ARRAY | MEMORY_TAG_ZONE_APPLICATION | MEMORY_TAG_ALIGN_32); - void framebuffer_resized(GLFWwindow* window, int width, int height); void application() { + basalt::darray verts({ + {{0.0f, -0.5f}, {1.0f, 0.0f, 0.0f}}, + {{0.5f, 0.5f}, {0.0f, 1.0f, 0.0f}}, + {{-0.5f, 0.5f}, {0.0f, 0.0f, 1.0f}} + }, MEMORY_TAG_CLASS_ARRAY | MEMORY_TAG_ZONE_APPLICATION | MEMORY_TAG_ALIGN_32); + VkResult err = VK_SUCCESS; basalt::Context ctx("Basic", @@ -87,9 +88,6 @@ void application() }) .build(); - VkVertexInputAttributeDescription* vertex_attribs = nullptr; - u32 num_vertex_attribs = 0; - VK_ASSERT(Vertex::get_attribute_descriptions(&vertex_attribs, &num_vertex_attribs), "Failed to get vertex input attribute description(s)\n\tAt %s:%d\n\tError %s\n\tVertex class %s\n", typeid(Vertex).name()); basalt::Pipeline pipeline = basalt::PipelineBuilder(dev, swapchain.swapchain_extent, VK_NULL_HANDLE) .add_dynamic_state(VK_DYNAMIC_STATE_SCISSOR) .add_dynamic_state(VK_DYNAMIC_STATE_VIEWPORT) @@ -106,12 +104,18 @@ void application() }) .add_shader("shaders/out/simple.vert.spv", VK_SHADER_STAGE_VERTEX_BIT) .add_shader("shaders/out/simple.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT) - .add_vertex_binding(Vertex::get_binding_description(), vertex_attribs, num_vertex_attribs) + .add_vertex_binding() .build(); - basalt::mem::dealloc(vertex_attribs, sizeof(VkVertexInputAttributeDescription) * num_vertex_attribs, MEMORY_TAG_CLASS_ARRAY | MEMORY_TAG_ZONE_APPLICATION | MEMORY_TAG_ALIGN_ANY); swapchain.create_framebuffers(pass.render_pass); + basalt::Buffer vertex_buffer(dev, verts.m_nelements * sizeof(Vertex), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); + { + void* dst = vertex_buffer.map(); + memcpy(dst, verts.m_pdata, vertex_buffer.size); + vertex_buffer.unmap(); + } + basalt::CommandPool cmdpool(dev, phy_dev.indicies.graphics); basalt::darray cmdbufs(swapchain.max_frames_in_flight, MEMORY_TAG_CLASS_DYNARRAY | MEMORY_TAG_ZONE_APPLICATION | MEMORY_TAG_ALIGN_32); for (u32 i = 0; i < swapchain.max_frames_in_flight; ++i) @@ -133,32 +137,41 @@ void application() .minDepth = 0.0f, .maxDepth = 1.0f }; + VkBuffer buffers[] = { vertex_buffer.buffer }; + VkDeviceSize offsets[] = { 0 }; + while (!window.should_close()) { + render_area.extent = swapchain.swapchain_extent; + viewport.width = render_area.extent.width; + viewport.height = render_area.extent.height; + glfwPollEvents(); - + basalt::CommandBuffer& cmdbuf = cmdbufs[swapchain.current_frame]; + u32 image_index = swapchain.wait_acquire_reset(); if (image_index == -1 || !swapchain.framebuffers_created) { - swapchain.create_framebuffers(pass.render_pass); + swapchain.recreate(pass.render_pass); swapchain.current_frame = (swapchain.current_frame + 1) % swapchain.max_frames_in_flight; continue; } - cmdbufs[swapchain.current_frame].reset(); - cmdbufs[swapchain.current_frame].start(pass, swapchain.framebuffers[image_index], render_area); - cmdbufs[swapchain.current_frame].bind_pipeline(pipeline, VK_PIPELINE_BIND_POINT_GRAPHICS); - cmdbufs[swapchain.current_frame].set_scissor(render_area); - cmdbufs[swapchain.current_frame].set_viewport(viewport); - vkCmdDraw(cmdbufs[swapchain.current_frame].vk, 3, 1, 0, 0); - cmdbufs[swapchain.current_frame].stop(); + cmdbuf.reset(); + cmdbuf.start(pass, swapchain.framebuffers[image_index], render_area); + cmdbuf.bind_pipeline(pipeline, VK_PIPELINE_BIND_POINT_GRAPHICS); + vkCmdBindVertexBuffers(cmdbuf.vk, 0, sizeof(buffers) / sizeof(buffers[0]), buffers, offsets); + cmdbuf.set_scissor(render_area); + cmdbuf.set_viewport(viewport); + vkCmdDraw(cmdbuf.vk, vertex_buffer.size / sizeof(Vertex), 1, 0, 0); + cmdbuf.stop(); VkSubmitInfo submit_info = {VK_STRUCTURE_TYPE_SUBMIT_INFO}; VkSemaphore wait_semaphores[] = {swapchain.semaphores_image_available[swapchain.current_frame]}; VkSemaphore signal_semaphores[] = {swapchain.semaphores_render_finished[image_index]}; VkPipelineStageFlags wait_stages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT}; submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &cmdbufs[swapchain.current_frame].vk; + submit_info.pCommandBuffers = &cmdbuf.vk; submit_info.waitSemaphoreCount = 1; submit_info.pWaitSemaphores = wait_semaphores; submit_info.pWaitDstStageMask = wait_stages; @@ -227,20 +240,28 @@ VkVertexInputBindingDescription Vertex::get_binding_description(void) return ret; } -VkResult Vertex::get_attribute_descriptions(VkVertexInputAttributeDescription** out_attributes, u32* out_num_attributes) +VkResult Vertex::get_attribute_descriptions(VkVertexInputAttributeDescription* out_attributes, u32* out_num_attributes) { - *out_attributes = basalt::mem::allocT(2, MEMORY_TAG_CLASS_ARRAY | MEMORY_TAG_ZONE_APPLICATION | MEMORY_TAG_ALIGN_ANY); + constexpr u32 num_attribs = 2; if (out_attributes == nullptr) - return VK_ERROR_OUT_OF_HOST_MEMORY; - *out_num_attributes = 2; - VkVertexInputAttributeDescription* ptr = *out_attributes; - ptr[0].binding = 0; - ptr[0].location = 0; - ptr[0].format = VK_FORMAT_R32G32_SFLOAT; - ptr[0].offset = offsetof(Vertex, pos); - ptr[1].binding = 0; - ptr[1].location = 1; - ptr[1].format = VK_FORMAT_R32G32B32_SFLOAT; - ptr[1].offset = offsetof(Vertex, colour); + { + *out_num_attributes = num_attribs; + return VK_SUCCESS; + } + BASSERT_ERROR(*out_num_attributes == num_attribs, + return VK_ERROR_OUT_OF_HOST_MEMORY;, + "Assertion %s failed at %s:%d\n\tAttempted to get attribute descriptions for object type %s but the allocated size %u was not sufficient. Expected %u\n", + typeid(Vertex).name(), out_num_attributes, num_attribs + ); + + out_attributes[0].binding = 0; + out_attributes[0].location = 0; + out_attributes[0].format = VK_FORMAT_R32G32_SFLOAT; + out_attributes[0].offset = offsetof(Vertex, pos); + out_attributes[1].binding = 0; + out_attributes[1].location = 1; + out_attributes[1].format = VK_FORMAT_R32G32B32_SFLOAT; + out_attributes[1].offset = offsetof(Vertex, colour); + return VK_SUCCESS; }