From e3195c9b1230bd07f49af22b52fc05c1aebf8909 Mon Sep 17 00:00:00 2001 From: Abdelrahman Date: Mon, 1 Jun 2026 00:08:39 +0100 Subject: [PATCH] Load meshes and setup shader data buffers --- build | 2 +- main.cpp | 183 +++++++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 160 insertions(+), 25 deletions(-) diff --git a/build b/build index 55dcc43..14372e0 100755 --- a/build +++ b/build @@ -2,5 +2,5 @@ bear -- clang++ -g -c -Wno-nullability-completeness -DVK_NO_PROTOTYPES -I$VULKAN_SDK/include vulkan_profiles/vulkan_profiles.cpp main.cpp bear -a -- clang -g -c -DVK_NO_PROTOTYPES -Ivulkan_profiles -I$VULKAN_SDK/include $VULKAN_SDK/include/volk/volk.c wapp/wapp.c -bear -a -- clang++ -g -DVK_NO_PROTOTYPES -lSDL3 -lglm -o main *.o +bear -a -- clang++ -g -DVK_NO_PROTOTYPES -lSDL3 -lglm -ltinyobjloader -o main *.o rm *.o diff --git a/main.cpp b/main.cpp index 15ba0f2..a285391 100644 --- a/main.cpp +++ b/main.cpp @@ -2,19 +2,23 @@ #include "wapp/wapp.h" #include "vulkan_profiles/vulkan_profiles.h" -#include +#include +#include +#include #include #include #include #include #include #include +#include #define VMA_IMPLEMENTATION #include #include #include #include #include +#include enum ExitCode { EXIT_CODE_SUCCESS, @@ -32,6 +36,28 @@ enum ExitCode { EXIT_CODE_NO_QUEUE_FAMILIES, EXIT_CODE_NO_SUITABLE_QUEUE_FAMILY, EXIT_CODE_NO_SUITABLE_DEPTH_FORMAT, + EXIT_CODE_MESH_LOAD_FAILED, +}; + +struct Vertex { + glm::vec3 pos; + glm::vec3 normal; + glm::vec2 uv; +}; + +struct ShaderData { + glm::mat4 projection; + glm::mat4 view; + glm::mat4 model[3]; + glm::vec4 light_pos{ 0.0f, -10.0f, 10.0f, 0.0f }; + u32 selected{ 1 }; +}; + +struct ShaderDataBuffer { + VmaAllocation allocation; + VmaAllocationInfo allocation_info; + VkBuffer buffer; + VkDeviceAddress device_address; }; typedef VkPhysicalDevice *VkPhysicalDeviceArray; @@ -39,37 +65,44 @@ typedef VkQueueFamilyProperties2 *VkQueueFamilyProperties2Array; typedef VkImage *VkImageArray; typedef VkImageView *VkImageViewArray; typedef VkFormat *VkFormatArray; +typedef Vertex *VertexArray; +typedef ShaderDataBuffer *ShaderDataBufferArray; wapp_intern inline void check(VkResult result); wapp_intern inline void check_swapchain(VkResult result); wapp_intern inline void check(bool result, i32 code); -wapp_intern bool running = true; -wapp_intern bool update_swapchain = false; -wapp_intern f32 display_scale = 1.0f; -wapp_intern SDL_Window *window = nullptr; -wapp_intern VkInstance instance = VK_NULL_HANDLE; -wapp_intern VkPhysicalDevice physical_device = VK_NULL_HANDLE; -wapp_intern VkSurfaceKHR surface = VK_NULL_HANDLE; -wapp_intern u32 queue_family_index = 0; -wapp_intern VkDevice device = VK_NULL_HANDLE; -wapp_intern VkQueue queue = VK_NULL_HANDLE; -wapp_intern VmaAllocator allocator = VK_NULL_HANDLE; -wapp_intern glm::ivec2 window_size = {}; +wapp_intern constexpr u32 max_frames_in_flight = 2; +wapp_intern bool running = true; +wapp_intern bool update_swapchain = false; +wapp_intern f32 display_scale = 1.0f; +wapp_intern SDL_Window *window = nullptr; +wapp_intern VkInstance instance = VK_NULL_HANDLE; +wapp_intern VkPhysicalDevice physical_device = VK_NULL_HANDLE; +wapp_intern VkSurfaceKHR surface = VK_NULL_HANDLE; +wapp_intern u32 queue_family_index = 0; +wapp_intern VkDevice device = VK_NULL_HANDLE; +wapp_intern VkQueue queue = VK_NULL_HANDLE; +wapp_intern VmaAllocator allocator = VK_NULL_HANDLE; +wapp_intern glm::ivec2 window_size = {}; // NOTE (Abdelrahman): The following three variables are better queried from the physical device // to find the different supported values. For the purposes of this tutorial, we're using defaults // that are guaranteed by the spec to be available on any valid implementation. -wapp_intern VkFormat image_format = VK_FORMAT_B8G8R8A8_SRGB; -wapp_intern VkColorSpaceKHR colorspace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR; -wapp_intern VkPresentModeKHR present_mode = VK_PRESENT_MODE_FIFO_KHR; -wapp_intern VkSwapchainKHR swapchain = VK_NULL_HANDLE; -wapp_intern u32 swapchain_image_count = 0; -wapp_intern VkImageArray swapchain_images = nullptr; -wapp_intern VkImageViewArray swapchain_views = nullptr; -wapp_intern VkFormat depth_format = VK_FORMAT_UNDEFINED; -wapp_intern VkImage depth_image = VK_NULL_HANDLE; -wapp_intern VkImageView depth_view = VK_NULL_HANDLE; -wapp_intern VmaAllocation depth_allocation = VK_NULL_HANDLE; +wapp_intern VkFormat image_format = VK_FORMAT_B8G8R8A8_SRGB; +wapp_intern VkColorSpaceKHR colorspace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR; +wapp_intern VkPresentModeKHR present_mode = VK_PRESENT_MODE_FIFO_KHR; +wapp_intern VkSwapchainKHR swapchain = VK_NULL_HANDLE; +wapp_intern u32 swapchain_image_count = 0; +wapp_intern VkImageArray swapchain_images = nullptr; +wapp_intern VkImageViewArray swapchain_views = nullptr; +wapp_intern VkFormat depth_format = VK_FORMAT_UNDEFINED; +wapp_intern VkImage depth_image = VK_NULL_HANDLE; +wapp_intern VkImageView depth_view = VK_NULL_HANDLE; +wapp_intern VmaAllocation depth_allocation = VK_NULL_HANDLE; +wapp_intern VkBuffer vert_index_buf = VK_NULL_HANDLE; +wapp_intern VmaAllocation vert_index_buf_alloc = VK_NULL_HANDLE; +wapp_intern ShaderData shader_data = {}; +wapp_intern ShaderDataBufferArray shader_data_bufs; int main() { // {{{ Initialisation @@ -407,6 +440,104 @@ int main() { // }}} // }}} + wapp_mem_arena_allocator_temp_begin(&arena); + + // {{{ Mesh Loading + // {{{ Load Mesh Data + tinyobj::attrib_t attrib; + std::vector shapes; + std::vector materials; + + check(tinyobj::LoadObj(&attrib, &shapes, &materials, nullptr, nullptr, "assets/suzanne.obj"), + EXIT_CODE_MESH_LOAD_FAILED); + const VkDeviceSize index_count = shapes[0].mesh.indices.size(); + + VertexArray vertices = wapp_array_alloc_capacity(Vertex, &arena, 128, ARRAY_INIT_NONE); + U16Array indices = wapp_array_alloc_capacity(u16, &arena, 128, ARRAY_INIT_NONE); + + for (tinyobj::index_t &index : shapes[0].mesh.indices) { + Vertex v = {}; + v.pos = { + attrib.vertices[index.vertex_index * 3], + -attrib.vertices[index.vertex_index * 3 + 1], + attrib.vertices[index.vertex_index * 3 + 2] + }; + v.normal = { + attrib.normals[index.normal_index * 3], + -attrib.normals[index.normal_index * 3 + 1], + attrib.normals[index.normal_index * 3 + 2] + }; + v.uv = { + attrib.texcoords[index.texcoord_index * 2], + 1.0 - attrib.texcoords[index.texcoord_index * 2 + 1] + }; + + u16 idx = (u16)wapp_array_count(indices); + wapp_array_append_alloc(Vertex, &arena, vertices, &v, ARRAY_INIT_NONE); + wapp_array_append_alloc(u16, &arena, indices, &idx, ARRAY_INIT_NONE); + } + // }}} + + // {{{ Upload to GPU + VkDeviceSize vertex_buf_size = sizeof(Vertex) * wapp_array_count(vertices); + VkDeviceSize index_buf_size = sizeof(u16) * wapp_array_count(vertices); + + VkBufferCreateInfo buf_create_info = {}; + buf_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + buf_create_info.size = vertex_buf_size + index_buf_size; + buf_create_info.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT; + + VmaAllocationCreateInfo buf_alloc_create_info = {}; + buf_alloc_create_info.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | + VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT | + VMA_ALLOCATION_CREATE_MAPPED_BIT; + buf_alloc_create_info.usage = VMA_MEMORY_USAGE_AUTO; + + VmaAllocationInfo buf_alloc_info = {}; + + check(vmaCreateBuffer(allocator, &buf_create_info, &buf_alloc_create_info, &vert_index_buf, + &vert_index_buf_alloc, &buf_alloc_info)); + memcpy(buf_alloc_info.pMappedData, vertices, vertex_buf_size); + memcpy((void *)((u8 *)buf_alloc_info.pMappedData + vertex_buf_size), indices, index_buf_size); + // }}} + // }}} + + wapp_mem_arena_allocator_temp_end(&arena); + + // {{{ Shader Data Buffers + shader_data_bufs = wapp_array_with_capacity(ShaderDataBuffer, 3, ARRAY_INIT_FILLED); + for (u32 i = 0; i < max_frames_in_flight; ++i) { + // {{{ Create Buffer + VkBufferUsageFlags2CreateInfo data_buf_usage_flags = {}; + data_buf_usage_flags.sType = VK_STRUCTURE_TYPE_BUFFER_USAGE_FLAGS_2_CREATE_INFO; + data_buf_usage_flags.usage = VK_BUFFER_USAGE_2_SHADER_DEVICE_ADDRESS_BIT; + VkBufferCreateInfo data_buf_create_info = {}; + data_buf_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + data_buf_create_info.size = sizeof(ShaderData); + data_buf_create_info.usage = VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; + data_buf_create_info.pNext = &data_buf_usage_flags; + + VmaAllocationCreateInfo data_buf_alloc_create_info = {}; + data_buf_alloc_create_info.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | + VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT | + VMA_ALLOCATION_CREATE_MAPPED_BIT; + data_buf_create_info.usage = VMA_MEMORY_USAGE_AUTO; + + check(vmaCreateBuffer(allocator, &data_buf_create_info, &data_buf_alloc_create_info, + &shader_data_bufs[i].buffer, &shader_data_bufs[i].allocation, + &shader_data_bufs[i].allocation_info)); + // }}} + + // {{{ Get Buffer GPU Address + VkBufferDeviceAddressInfo buf_dev_addr_info = {}; + buf_dev_addr_info.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO; + buf_dev_addr_info.buffer = shader_data_bufs[i].buffer; + + shader_data_bufs[i].device_address = vkGetBufferDeviceAddress(device, &buf_dev_addr_info); + // }}} + } + // }}} + // {{{ Render Loop SDL_Event event = {}; while (running) { @@ -426,6 +557,10 @@ int main() { // }}} // {{{ Cleanup + for (u32 i = 0; i < max_frames_in_flight; ++i) { + vmaDestroyBuffer(allocator, shader_data_bufs[i].buffer, shader_data_bufs[i].allocation); + } + vmaDestroyBuffer(allocator, vert_index_buf, vert_index_buf_alloc); vkDestroyImageView(device, depth_view, nullptr); vmaDestroyImage(allocator, depth_image, depth_allocation); for (u32 i = 0; i < swapchain_image_count; ++i) {