diff --git a/include/map.h b/include/map.h new file mode 100644 index 0000000..ab04dc1 --- /dev/null +++ b/include/map.h @@ -0,0 +1,39 @@ +#ifndef MAP_H +#define MAP_H + +#include +#include + +typedef struct EntryStruct { + uint32_t key; + void* value; +} Entry; + +typedef struct MaybeValueStruct { + bool has_value; + void* value; +} MaybeValue; + +typedef struct MapIteratorStruct { + uint32_t count; + uint32_t* keys; + void** vals; +} MapIterator; + +typedef struct MapStruct { + uint32_t buckets_count; + Entry** buckets; + uint32_t* bucket_sizes; + uint32_t* bucket_usage; +} Map; + +Map map_create(uint32_t buckets_count, uint32_t initial_bucket_size); +MaybeValue map_lookup(Map map, uint32_t key); +bool map_add(Map* map, uint32_t key, void* value); +MaybeValue map_del(Map* map, uint32_t key); +void map_destroy(Map map); + +MapIterator map_iterator_create(Map map); +void map_iterator_free(MapIterator iterator); + +#endif diff --git a/include/ply.h b/include/ply.h index 1dca460..4c0c9c0 100644 --- a/include/ply.h +++ b/include/ply.h @@ -2,6 +2,8 @@ #define PLY_H #include +#include +#include typedef enum { PLY_FORMAT_INVALID = -1, @@ -48,12 +50,23 @@ typedef struct PlyElementStruct { struct PlyElementStruct* next; } PlyElement; +typedef struct PlyMeshStruct { + uint32_t vertex_count; + vec3* position; + vec4* colour; + vec3* normal; + vec2* uv; + + uint32_t index_count; + uint16_t* index; +} PlyMesh; + extern const char* const ply_formats[]; extern const char* const ply_header_items[]; extern const char* const ply_type_strings[]; extern const size_t ply_type_sizes[]; -PlyElement* ply_load_mesh(char* filename); -void ply_free_mesh(PlyElement* elements_head); +PlyMesh ply_load_mesh(char* filename); +void ply_free_elements(PlyElement* elements_head); #endif diff --git a/src/main.c b/src/main.c index 06b1441..15dbd20 100644 --- a/src/main.c +++ b/src/main.c @@ -18,6 +18,17 @@ #include #include +#include + +typedef struct AllocatedBufferStruct { + VkDeviceMemory memory; + VkBuffer buffer; +} AllocatedBuffer; + +typedef struct AllocatedImageStruct { + VkDeviceMemory memory; + VkImage image; +} AllocatedImage; typedef struct QueueIndicesStruct { uint32_t graphics_family; @@ -51,217 +62,12 @@ typedef struct SwapchainImagesStruct { uint32_t count; } SwapchainImages; -typedef struct AllocatedBufferStruct { - VkBuffer buffer; - VkDeviceMemory memory; -} AllocatedBuffer; - -typedef struct AllocatedImageStruct { - VkImage image; - VkDeviceMemory memory; -} AllocatedImage; - typedef struct TextureStruct { AllocatedImage image; VkImageView view; VkSampler sampler; } Texture; -typedef struct EntryStruct { - uint32_t key; - void* value; -} Entry; - -typedef struct MapStruct { - uint32_t buckets_count; - Entry** buckets; - uint32_t* bucket_sizes; - uint32_t* bucket_usage; -} Map; - -Map map_create(uint32_t buckets_count, uint32_t initial_bucket_size) { - Map zero = {}; - - Entry** buckets = malloc(sizeof(Entry*)*buckets_count); - if(buckets == 0) { - return zero; - } - - uint32_t* bucket_sizes = malloc(sizeof(uint32_t)*buckets_count); - if(bucket_sizes == 0) { - free(buckets); - return zero; - } - - uint32_t* bucket_usage = malloc(sizeof(uint32_t)*buckets_count); - if(bucket_usage == 0) { - free(bucket_usage); - free(buckets); - return zero; - } - - for(uint32_t i = 0; i < buckets_count; i++) { - Entry* bucket = malloc(sizeof(Entry)*initial_bucket_size); - if(bucket == 0) { - for(uint32_t j = 0; j < i; j++) { - free(buckets[j]); - } - free(bucket_sizes); - free(buckets); - return zero; - } - buckets[i] = bucket; - bucket_sizes[i] = initial_bucket_size; - bucket_usage[i] = 0; - } - - Map ret = { - .buckets_count = buckets_count, - .bucket_sizes = bucket_sizes, - .bucket_usage = bucket_usage, - .buckets = buckets, - }; - - return ret; -} - -typedef struct MaybeValueStruct { - bool has_value; - void* value; -} MaybeValue; - -MaybeValue map_lookup(Map map, uint32_t key) { - MaybeValue ret = { - .has_value = false, - .value = 0, - }; - - uint32_t bucket_index = key % map.buckets_count; - for(uint32_t i = 0; i < map.bucket_usage[bucket_index]; i++) { - if(map.buckets[bucket_index][i].key == key) { - ret.has_value = true; - ret.value = map.buckets[bucket_index][i].value; - } - } - - return ret; -} - -bool map_add(Map* map, uint32_t key, void* value) { - uint32_t bucket_index = key % map->buckets_count; - - for(uint32_t i = 0; i < map->bucket_usage[bucket_index]; i++) { - if(map->buckets[bucket_index][i].key == key) { - map->buckets[bucket_index][i].value = value; - return true; - } - } - - if(map->bucket_usage[bucket_index] < map->bucket_sizes[bucket_index]) { - map->buckets[bucket_index][map->bucket_usage[bucket_index]].key = key; - map->buckets[bucket_index][map->bucket_usage[bucket_index]].value = value; - map->bucket_usage[bucket_index] += 1; - return true; - } - - Entry* new_bucket = realloc(map->buckets[bucket_index], 2*map->bucket_sizes[bucket_index]); - if(new_bucket == 0) { - return false; - } - - map->bucket_usage[bucket_index] += 1; - map->bucket_sizes[bucket_index] *= 2; - map->buckets[bucket_index] = new_bucket; - map->buckets[bucket_index][map->bucket_usage[bucket_index]].key = key; - map->buckets[bucket_index][map->bucket_usage[bucket_index]].value = value; - - return true; -} - -MaybeValue map_del(Map* map, uint32_t key) { - MaybeValue ret = { - .has_value = false, - .value = 0, - }; - - uint32_t bucket_index = key % map->buckets_count; - for(uint32_t i = 0; i < map->bucket_usage[bucket_index]; i++) { - if(map->buckets[bucket_index][i].key == key) { - ret.value = map->buckets[bucket_index][i].value; - ret.has_value = true; - - if(map->bucket_usage[bucket_index] > 1) { - map->buckets[bucket_index][i] = map->buckets[bucket_index][map->bucket_usage[bucket_index]-1]; - } - map->bucket_usage[bucket_index] -= 1; - break; - } - } - - return ret; -} - -void map_destroy(Map map) { - for(uint32_t i = 0; i < map.buckets_count; i++) { - free(map.buckets[i]); - } - free(map.buckets); - free(map.bucket_sizes); - free(map.bucket_usage); -} - -typedef struct MapIteratorStruct { - uint32_t count; - uint32_t* keys; - void** vals; -} MapIterator; - -MapIterator map_iterator_create(Map map) { - MapIterator iterator = { - .keys = 0, - .vals = 0, - .count = 0, - }; - - uint32_t count = 0; - for(uint32_t i = 0; i < map.buckets_count; i++) { - count += map.bucket_usage[i]; - } - - uint32_t* keys = malloc(sizeof(uint32_t)*count); - if(keys == 0) { - return iterator; - } - - void** vals = malloc(sizeof(void*)*count); - if(vals == 0) { - free(keys); - return iterator; - } - - uint32_t idx = 0; - for(uint32_t i = 0; i < map.buckets_count; i++) { - for(uint32_t j = 0; j < map.bucket_usage[i]; j++) { - keys[idx] = map.buckets[i][j].key; - vals[idx] = map.buckets[i][j].value; - idx += 1; - } - } - - iterator.keys = keys; - iterator.vals = vals; - iterator.count = count; - - return iterator; -} - -void map_iterator_free(MapIterator iterator) { - if(iterator.count > 0) { - free(iterator.keys); - free(iterator.vals); - } -} - typedef struct PositionStruct { vec3 position; vec3 scale; @@ -338,6 +144,12 @@ typedef struct MaterialStruct { Map object_descriptor_mappings; } Material; +typedef struct MemoryIndicesStruct { + uint32_t host_visible; + uint32_t device_local; + uint32_t device_lazy; +} MemoryIndices; + typedef struct VulkanContextStruct { VkInstance instance; VkDebugUtilsMessengerEXT debug_messenger; @@ -362,7 +174,8 @@ typedef struct VulkanContextStruct { VkImageView* swapchain_image_views; VkFramebuffer* swapchain_framebuffers; - AllocatedImage depth_image; + VkDeviceMemory depth_image_memory; + VkImage depth_image; VkFormat depth_format; VkImageView depth_image_view; @@ -374,13 +187,14 @@ typedef struct VulkanContextStruct { VkSemaphore* render_finished_semaphores; VkFence* in_flight_fences; - VkPhysicalDeviceMemoryProperties memories; VkRenderPass render_pass; VkCommandPool graphics_command_pool; VkCommandPool transfer_command_pool; uint32_t current_frame; + + MemoryIndices memory_indices; } VulkanContext; typedef struct SceneContextStruct { @@ -440,13 +254,14 @@ uint32_t validation_layer_count = sizeof(validation_layers) / sizeof(const char const char * instance_extensions[] = { VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME, VK_EXT_DEBUG_UTILS_EXTENSION_NAME, - VK_MVK_MACOS_SURFACE_EXTENSION_NAME, + "VK_EXT_metal_surface", VK_KHR_SURFACE_EXTENSION_NAME, }; uint32_t instance_extension_count = sizeof(instance_extensions) / sizeof(const char *); const char * device_extensions[] = { VK_KHR_SWAPCHAIN_EXTENSION_NAME, + "VK_KHR_portability_subset", }; uint32_t device_extension_count = sizeof(device_extensions) / sizeof(const char *); @@ -739,7 +554,7 @@ VkInstance create_instance() { app_info.applicationVersion = VK_MAKE_VERSION(0, 0, 1); app_info.pEngineName = "spacegame"; app_info.engineVersion = VK_MAKE_VERSION(0, 0, 1); - app_info.apiVersion = VK_API_VERSION_1_3; + app_info.apiVersion = VK_API_VERSION_1_2; VkInstanceCreateInfo instance_info = {}; instance_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; @@ -1164,7 +979,7 @@ uint32_t pick_memory_type(VkPhysicalDeviceMemoryProperties memories, uint32_t fi return 0xFFFFFFFF; } -AllocatedImage allocate_image(VkPhysicalDeviceMemoryProperties memories, VkDevice device, VkImageType type, VkFormat format, VkExtent3D size, VkImageUsageFlags usage, VkMemoryPropertyFlags properties) { +AllocatedImage allocate_image(uint32_t memory_index, VkDevice device, VkImageType type, VkFormat format, VkExtent3D size, VkImageUsageFlags usage) { VkImageCreateInfo image_info = { .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, .imageType = type, @@ -1195,7 +1010,7 @@ AllocatedImage allocate_image(VkPhysicalDeviceMemoryProperties memories, VkDevic VkMemoryAllocateInfo memory_info = { .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, .allocationSize = memory_requirements.size, - .memoryTypeIndex = pick_memory_type(memories, memory_requirements.memoryTypeBits, properties), + .memoryTypeIndex = memory_index, }; result = vkAllocateMemory(device, &memory_info, 0, &allocated.memory); @@ -1218,7 +1033,7 @@ AllocatedImage allocate_image(VkPhysicalDeviceMemoryProperties memories, VkDevic return allocated; } -AllocatedBuffer allocate_buffer(VkPhysicalDeviceMemoryProperties memories, VkDevice device, VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties) { +AllocatedBuffer allocate_buffer(uint32_t memory_index, VkDevice device, VkDeviceSize size, VkBufferUsageFlags usage) { AllocatedBuffer ret = {}; ret.memory = VK_NULL_HANDLE; ret.buffer = VK_NULL_HANDLE; @@ -1243,7 +1058,7 @@ AllocatedBuffer allocate_buffer(VkPhysicalDeviceMemoryProperties memories, VkDev VkMemoryAllocateInfo alloc_info = {}; alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; alloc_info.allocationSize = memory_requirements.size; - alloc_info.memoryTypeIndex = pick_memory_type(memories, memory_requirements.memoryTypeBits, properties); + alloc_info.memoryTypeIndex = memory_index; result = vkAllocateMemory(device, &alloc_info, 0, &ret.memory); if(result != VK_SUCCESS) { @@ -1274,14 +1089,14 @@ void deallocate_image(VkDevice device, AllocatedImage image) { vkFreeMemory(device, image.memory, 0); }; -AllocatedBuffer* allocate_buffers(VkPhysicalDeviceMemoryProperties memories, VkDevice device, VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, uint32_t count) { +AllocatedBuffer* allocate_buffers(uint32_t memory_index, VkDevice device, VkDeviceSize size, VkBufferUsageFlags usage, uint32_t count) { AllocatedBuffer* buffers = malloc(sizeof(AllocatedBuffer)*count); if(buffers == 0) { return 0; } for(uint32_t i = 0; i < count; i++) { - buffers[i] = allocate_buffer(memories, device, size, usage, properties); + buffers[i] = allocate_buffer(memory_index, device, size, usage); if(buffers[i].memory == VK_NULL_HANDLE) { for(uint32_t j = 0; j < i; j++) { deallocate_buffer(device, buffers[i]); @@ -1407,10 +1222,10 @@ VkResult command_copy_buffer_to_image(VkDevice device, VkCommandPool transfer_po return command_end_single(device, command_buffer, transfer_pool, transfer_queue); } -AllocatedBuffer create_populated_buffer(VkPhysicalDeviceMemoryProperties memories, VkDevice device, void* data, VkDeviceSize size, VkCommandPool transfer_pool, VkQueue transfer_queue, VkBufferUsageFlags usage) { +AllocatedBuffer create_populated_buffer(MemoryIndices memories, VkDevice device, void* data, VkDeviceSize size, VkCommandPool transfer_pool, VkQueue transfer_queue, VkBufferUsageFlags usage) { AllocatedBuffer staging_buffer = {}; AllocatedBuffer vertex_buffer = {}; - staging_buffer = allocate_buffer(memories, device, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); + staging_buffer = allocate_buffer(memories.host_visible, device, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT); if(staging_buffer.memory == VK_NULL_HANDLE) { return vertex_buffer; } @@ -1427,7 +1242,7 @@ AllocatedBuffer create_populated_buffer(VkPhysicalDeviceMemoryProperties memorie vkUnmapMemory(device, staging_buffer.memory); - vertex_buffer = allocate_buffer(memories, device, size, VK_BUFFER_USAGE_TRANSFER_DST_BIT | usage, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + vertex_buffer = allocate_buffer(memories.device_local, device, size, VK_BUFFER_USAGE_TRANSFER_DST_BIT | usage); if(vertex_buffer.memory == VK_NULL_HANDLE) { deallocate_buffer(device, staging_buffer); return vertex_buffer; @@ -1445,7 +1260,7 @@ AllocatedBuffer create_populated_buffer(VkPhysicalDeviceMemoryProperties memorie return vertex_buffer; } -Texture load_texture(VkPhysicalDeviceMemoryProperties memories, VkDevice device, VkCommandPool transfer_pool, VkQueue transfer_queue, VkExtent2D size, uint32_t stride, VkFormat format, void* image_data){ +Texture load_texture(MemoryIndices memories, VkDevice device, VkCommandPool transfer_pool, VkQueue transfer_queue, VkExtent2D size, uint32_t stride, VkFormat format, void* image_data){ Texture ret = { .image.image = VK_NULL_HANDLE, .image.memory = VK_NULL_HANDLE, @@ -1453,7 +1268,7 @@ Texture load_texture(VkPhysicalDeviceMemoryProperties memories, VkDevice device, }; uint32_t image_size = size.width * size.height * stride; - AllocatedBuffer staging = allocate_buffer(memories, device, image_size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); + AllocatedBuffer staging = allocate_buffer(memories.host_visible, device, image_size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT); if(staging.memory == VK_NULL_HANDLE) { return ret; } @@ -1474,7 +1289,7 @@ Texture load_texture(VkPhysicalDeviceMemoryProperties memories, VkDevice device, .height = size.height, .depth = 1, }; - AllocatedImage image = allocate_image(memories, device, VK_IMAGE_TYPE_2D, format, full_extent, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + AllocatedImage image = allocate_image(memories.device_local, device, VK_IMAGE_TYPE_2D, format, full_extent, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); if(image.memory == VK_NULL_HANDLE) { deallocate_buffer(device, staging); deallocate_image(device, image); @@ -1707,49 +1522,64 @@ VkCommandPool create_command_pool(VkDevice device, uint32_t queue_family) { return command_pool; } -VkResult recreate_swap_chain(VulkanContext* context) { - for(uint32_t i = 0; i < context->swapchain_image_count; i++) { - vkDestroyFramebuffer(context->device, context->swapchain_framebuffers[i], 0); - vkDestroyImageView(context->device, context->swapchain_image_views[i], 0); - } - - vkDestroySwapchainKHR(context->device, context->swapchain, 0); - free(context->swapchain_images); - free(context->swapchain_image_views); - free(context->swapchain_framebuffers); - free(context->swapchain_details.formats); - free(context->swapchain_details.present_modes); +int create_depth_image(VulkanContext* context) { + VkExtent3D depth_extent = { + .width = context->swapchain_extent.width, + .height = context->swapchain_extent.height, + .depth = 1, + }; - vkDestroyImageView(context->device, context->depth_image_view, 0); - deallocate_image(context->device, context->depth_image); + VkImageCreateInfo depth_image_info = { + .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, + .imageType = VK_IMAGE_TYPE_2D, + .extent = depth_extent, + .mipLevels = 1, + .arrayLayers = 1, + .format = context->depth_format, + .tiling = VK_IMAGE_TILING_OPTIMAL, + .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, + .sharingMode = VK_SHARING_MODE_EXCLUSIVE, + .samples = VK_SAMPLE_COUNT_1_BIT, + .flags = 0, + }; - SwapchainDetails swapchain_details = get_swapchain_details(context->physical_device, context->surface); - if(swapchain_details.formats == 0) { - return VK_ERROR_INITIALIZATION_FAILED; + VkImage depth_image; + VkResult result = vkCreateImage(context->device, &depth_image_info, 0, &depth_image); + if(result != VK_SUCCESS) { + fprintf(stderr, "failed to create depth image\n"); + return 1; } else { - context->swapchain_details = swapchain_details; + context->depth_image = depth_image; } - context->swapchain_format = choose_swapchain_format(context->swapchain_details); - context->swapchain_present_mode = choose_present_mode(context->swapchain_details); - context->swapchain_extent = choose_swapchain_extent(context->swapchain_details); + VkMemoryRequirements depth_image_requirements; + vkGetImageMemoryRequirements(context->device, context->depth_image, &depth_image_requirements); - VkExtent3D depth_extent = { - .width = context->swapchain_extent.width, - .height = context->swapchain_extent.height, - .depth = 1, + VkMemoryAllocateInfo depth_memory_info = { + .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, + .allocationSize = depth_image_requirements.size, + .memoryTypeIndex = context->memory_indices.device_lazy, }; - AllocatedImage depth_image = allocate_image(context->memories, context->device, VK_IMAGE_TYPE_2D, context->depth_format, depth_extent, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - if(depth_image.memory == VK_NULL_HANDLE) { - return VK_ERROR_INITIALIZATION_FAILED; + VkDeviceMemory depth_image_memory; + result = vkAllocateMemory(context->device, &depth_memory_info, 0, &depth_image_memory); + if(result != VK_SUCCESS) { + fprintf(stderr, "failed to allocate memory for depth image\n"); + return 2; } else { - context->depth_image = depth_image; + context->depth_image_memory = depth_image_memory; + } + + result = vkBindImageMemory(context->device, context->depth_image, context->depth_image_memory, 0); + if(result != VK_SUCCESS) { + fprintf(stderr, "failed to bind memory for depth image\n"); + return 3; } VkImageViewCreateInfo depth_view_info = { .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, - .image = depth_image.image, + .image = context->depth_image, .viewType = VK_IMAGE_VIEW_TYPE_2D, .format = context->depth_format, .components = { @@ -1768,13 +1598,47 @@ VkResult recreate_swap_chain(VulkanContext* context) { }; VkImageView depth_image_view; - VkResult result = vkCreateImageView(context->device, &depth_view_info, 0, &depth_image_view); + result = vkCreateImageView(context->device, &depth_view_info, 0, &depth_image_view); if(result != VK_SUCCESS) { - return VK_ERROR_INITIALIZATION_FAILED; + fprintf(stderr, "failed to create vulkan depth image view\n"); + return 4; } else { context->depth_image_view = depth_image_view; } + return 0; +} + +VkResult recreate_swap_chain(VulkanContext* context) { + for(uint32_t i = 0; i < context->swapchain_image_count; i++) { + vkDestroyFramebuffer(context->device, context->swapchain_framebuffers[i], 0); + vkDestroyImageView(context->device, context->swapchain_image_views[i], 0); + } + + vkDestroySwapchainKHR(context->device, context->swapchain, 0); + free(context->swapchain_images); + free(context->swapchain_image_views); + free(context->swapchain_framebuffers); + free(context->swapchain_details.formats); + free(context->swapchain_details.present_modes); + + vkDestroyImageView(context->device, context->depth_image_view, 0); + vkDestroyImage(context->device, context->depth_image, 0); + vkFreeMemory(context->device, context->depth_image_memory, 0); + + SwapchainDetails swapchain_details = get_swapchain_details(context->physical_device, context->surface); + if(swapchain_details.formats == 0) { + return VK_ERROR_INITIALIZATION_FAILED; + } else { + context->swapchain_details = swapchain_details; + } + + context->swapchain_format = choose_swapchain_format(context->swapchain_details); + context->swapchain_present_mode = choose_present_mode(context->swapchain_details); + context->swapchain_extent = choose_swapchain_extent(context->swapchain_details); + + create_depth_image(context); + VkSwapchainKHR swapchain = create_swapchain(context->device, context->swapchain_format, context->swapchain_present_mode, context->swapchain_extent, context->surface, context->swapchain_details.capabilities, context->queue_indices, context->swapchain); if(swapchain == VK_NULL_HANDLE) { context->swapchain = VK_NULL_HANDLE; @@ -1967,7 +1831,7 @@ VkFence* create_fences(VkDevice device, VkFenceCreateFlags flags, uint32_t count return fences; } -Mesh* load_texture_mesh(VkPhysicalDeviceMemoryProperties memories, VkDevice device, struct TextureVertex* vertices, uint32_t vertex_count, uint16_t* indices, uint32_t index_count, VkCommandPool transfer_pool, VkQueue transfer_queue) { +Mesh* load_texture_mesh(MemoryIndices memories, VkDevice device, struct TextureVertex* vertices, uint32_t vertex_count, uint16_t* indices, uint32_t index_count, VkCommandPool transfer_pool, VkQueue transfer_queue) { AllocatedBuffer vertex_buffer = create_populated_buffer(memories, device, (void*)vertices, sizeof(struct TextureVertex) * vertex_count, transfer_pool, transfer_queue, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); if(vertex_buffer.memory == VK_NULL_HANDLE) { return 0; @@ -2074,7 +1938,7 @@ Object create_renderable(Mesh* mesh, Material* material, uint32_t descriptor_set return object; } -Mesh* load_simple_mesh(VkPhysicalDeviceMemoryProperties memories, VkDevice device, struct Vertex* vertices, uint32_t vertex_count, uint16_t* indices, uint32_t index_count, VkCommandPool transfer_pool, VkQueue transfer_queue) { +Mesh* load_simple_mesh(MemoryIndices memories, VkDevice device, struct Vertex* vertices, uint32_t vertex_count, uint16_t* indices, uint32_t index_count, VkCommandPool transfer_pool, VkQueue transfer_queue) { AllocatedBuffer vertex_buffer = create_populated_buffer(memories, device, (void*)vertices, sizeof(struct Vertex) * vertex_count, transfer_pool, transfer_queue, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); if(vertex_buffer.memory == VK_NULL_HANDLE) { return 0; @@ -2461,7 +2325,35 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) { context->physical_device = physical_device; } - vkGetPhysicalDeviceMemoryProperties(context->physical_device, &context->memories); + VkPhysicalDeviceMemoryProperties memories; + vkGetPhysicalDeviceMemoryProperties(context->physical_device, &memories); + MemoryIndices memory_indices = { + .device_local = 0xFFFFFFFF, + .host_visible = 0xFFFFFFFF, + }; + for(uint32_t i = 0; i < memories.memoryTypeCount; i++) { + VkMemoryPropertyFlags flags = memories.memoryTypes[i].propertyFlags; + + if((flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) + && !(flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) + && (flags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT)) { + memory_indices.device_lazy = i; + } else if((flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) + && !(flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)) { + memory_indices.device_local = i; + } else if((flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) + && !(flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) { + memory_indices.host_visible = i; + } + } + + if(memory_indices.host_visible == 0xFFFFFFFF || memory_indices.device_local == 0xFFFFFFFF || memory_indices.device_lazy == 0xFFFFFFFF) { + fprintf(stderr, "failed to select suitable memory types\n"); + fprintf(stderr, "%d, %d, %d\n", memory_indices.device_local, memory_indices.device_lazy, memory_indices.host_visible); + return 0; + } else { + context->memory_indices = memory_indices; + } VkSurfaceKHR surface; VkResult result = glfwCreateWindowSurface(instance, window, 0, &surface); @@ -2541,6 +2433,11 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) { context->depth_format = depth_format; } + if(create_depth_image(context) != 0) { + fprintf(stderr, "failed to create depth image\n"); + return 0; + } + VkRenderPass render_pass = create_render_pass(context->device, context->swapchain_format, context->depth_format); if(render_pass == VK_NULL_HANDLE) { fprintf(stderr, "failed to create vulkan render pass\n"); @@ -2549,48 +2446,6 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) { context->render_pass = render_pass; } - VkExtent3D depth_extent = { - .width = context->swapchain_extent.width, - .height = context->swapchain_extent.height, - .depth = 1, - }; - AllocatedImage depth_image = allocate_image(context->memories, context->device, VK_IMAGE_TYPE_2D, depth_format, depth_extent, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - if(depth_image.memory == VK_NULL_HANDLE) { - fprintf(stderr, "failed to create vulkan depth image\n"); - return 0; - } else { - context->depth_image = depth_image; - } - - VkImageViewCreateInfo depth_view_info = { - .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, - .image = depth_image.image, - .viewType = VK_IMAGE_VIEW_TYPE_2D, - .format = depth_format, - .components = { - .r = VK_COMPONENT_SWIZZLE_IDENTITY, - .g = VK_COMPONENT_SWIZZLE_IDENTITY, - .b = VK_COMPONENT_SWIZZLE_IDENTITY, - .a = VK_COMPONENT_SWIZZLE_IDENTITY, - }, - .subresourceRange = { - .aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT, - .baseMipLevel = 0, - .levelCount = 1, - .baseArrayLayer = 0, - .layerCount = 1, - }, - }; - - VkImageView depth_image_view; - result = vkCreateImageView(context->device, &depth_view_info, 0, &depth_image_view); - if(result != VK_SUCCESS) { - fprintf(stderr, "failed to create vulkan depth image view\n"); - return 0; - } else { - context->depth_image_view = depth_image_view; - } - VkFramebuffer* framebuffers = create_swapchain_framebuffers(context->device, context->swapchain_image_count, context->swapchain_image_views, context->depth_image_view, context->render_pass, context->swapchain_extent); if(framebuffers == 0) { fprintf(stderr, "failed to create vulkan framebuffers\n"); @@ -2652,7 +2507,7 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) { return context; } -SceneContext create_scene_context(VkDevice device, VkPhysicalDeviceMemoryProperties memories, uint32_t max_frames_in_flight) { +SceneContext create_scene_context(VkDevice device, MemoryIndices memories, uint32_t max_frames_in_flight) { SceneContext ret = { .pool = VK_NULL_HANDLE, .descriptor_layout = VK_NULL_HANDLE, @@ -2736,7 +2591,7 @@ SceneContext create_scene_context(VkDevice device, VkPhysicalDeviceMemoryPropert return ret; } - AllocatedBuffer* ubos = allocate_buffers(memories, device, sizeof(struct SceneUBO), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, max_frames_in_flight); + AllocatedBuffer* ubos = allocate_buffers(memories.host_visible, device, sizeof(struct SceneUBO), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, max_frames_in_flight); if(ubos == 0) { free(layouts); free(sets); @@ -3085,7 +2940,7 @@ VkResult draw_frame(VulkanContext* context, SceneContext* scene, uint32_t materi return vkQueuePresentKHR(context->queues.present, &present_info); } -Object create_simple_mesh_object(Material* simple_mesh_material, VkPhysicalDeviceMemoryProperties memories, VkDevice device, VkCommandPool transfer_pool, VkQueue transfer_queue, uint32_t max_frames_in_flight, VkDescriptorPool pool) { +Object create_simple_mesh_object(Material* simple_mesh_material, MemoryIndices memories, VkDevice device, VkCommandPool transfer_pool, VkQueue transfer_queue, uint32_t max_frames_in_flight, VkDescriptorPool pool) { Object zero = {}; Mesh* mesh = load_simple_mesh(memories, device, (struct Vertex*)vertices, 4, (uint16*)indices, 6, transfer_pool, transfer_queue); @@ -3140,7 +2995,7 @@ Object create_simple_mesh_object(Material* simple_mesh_material, VkPhysicalDevic return zero; } - AllocatedBuffer* position_buffers = allocate_buffers(memories, device, sizeof(struct ModelUBO), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, max_frames_in_flight); + AllocatedBuffer* position_buffers = allocate_buffers(memories.host_visible, device, sizeof(struct ModelUBO), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, max_frames_in_flight); if(position_buffers == 0) { return zero; } @@ -3179,7 +3034,7 @@ Object create_simple_mesh_object(Material* simple_mesh_material, VkPhysicalDevic return object; } -Object create_texture_mesh_object(Material* texture_mesh_material, VkPhysicalDeviceMemoryProperties memories, VkDevice device, VkCommandPool transfer_pool, VkQueue transfer_queue, uint32_t max_frames_in_flight, VkDescriptorPool pool) { +Object create_texture_mesh_object(Material* texture_mesh_material, MemoryIndices memories, VkDevice device, VkCommandPool transfer_pool, VkQueue transfer_queue, uint32_t max_frames_in_flight, VkDescriptorPool pool) { Object zero = {}; Mesh* mesh = load_texture_mesh(memories, device, (struct TextureVertex*)texture_vertices, 4, (uint16_t*)indices, 6, transfer_pool, transfer_queue); @@ -3234,7 +3089,7 @@ Object create_texture_mesh_object(Material* texture_mesh_material, VkPhysicalDev return zero; } - AllocatedBuffer* ubos = allocate_buffers(memories, device, sizeof(struct ModelUBO), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, max_frames_in_flight); + AllocatedBuffer* ubos = allocate_buffers(memories.host_visible, device, sizeof(struct ModelUBO), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, max_frames_in_flight); if(ubos == 0) { return zero; } @@ -3328,7 +3183,7 @@ Object create_texture_mesh_object(Material* texture_mesh_material, VkPhysicalDev } void main_loop(GLFWwindow* window, VulkanContext* context) { - SceneContext scene = create_scene_context(context->device, context->memories, context->max_frames_in_flight); + SceneContext scene = create_scene_context(context->device, context->memory_indices, context->max_frames_in_flight); if(scene.pool == VK_NULL_HANDLE) { return; } @@ -3360,7 +3215,7 @@ void main_loop(GLFWwindow* window, VulkanContext* context) { return; } - Object triangle_object = create_simple_mesh_object(&simple_mesh_material, context->memories, context->device, context->transfer_command_pool, context->queues.transfer, context->max_frames_in_flight, simple_pool); + Object triangle_object = create_simple_mesh_object(&simple_mesh_material, context->memory_indices, context->device, context->transfer_command_pool, context->queues.transfer, context->max_frames_in_flight, simple_pool); if(triangle_object.attributes.buckets == 0) { fprintf(stderr, "failed to create simple mesh object\n"); return; @@ -3397,7 +3252,7 @@ void main_loop(GLFWwindow* window, VulkanContext* context) { return; } - Object triangle_object_textured = create_texture_mesh_object(&texture_mesh_material, context->memories, context->device, context->transfer_command_pool, context->queues.transfer, context->max_frames_in_flight, texture_pool); + Object triangle_object_textured = create_texture_mesh_object(&texture_mesh_material, context->memory_indices, context->device, context->transfer_command_pool, context->queues.transfer, context->max_frames_in_flight, texture_pool); if(triangle_object_textured.attributes.buckets == 0) { fprintf(stderr, "failed to create texture mesh object\n"); return; @@ -3460,10 +3315,9 @@ void cleanup(GLFWwindow* window, VulkanContext* context) { } int main() { - PlyElement* monkey = ply_load_mesh("monkey.ply"); - if(monkey == 0) { + PlyMesh monkey = ply_load_mesh("monkey.ply"); + if(monkey.position == 0) { fprintf(stderr, "failed to load %s\n", "monkey.ply"); - return -1; } GLFWwindow* window = init_window(800, 600); diff --git a/src/map.c b/src/map.c new file mode 100644 index 0000000..0c77487 --- /dev/null +++ b/src/map.c @@ -0,0 +1,174 @@ +#include +#include + +Map map_create(uint32_t buckets_count, uint32_t initial_bucket_size) { + Map zero = {}; + + Entry** buckets = malloc(sizeof(Entry*)*buckets_count); + if(buckets == 0) { + return zero; + } + + uint32_t* bucket_sizes = malloc(sizeof(uint32_t)*buckets_count); + if(bucket_sizes == 0) { + free(buckets); + return zero; + } + + uint32_t* bucket_usage = malloc(sizeof(uint32_t)*buckets_count); + if(bucket_usage == 0) { + free(bucket_usage); + free(buckets); + return zero; + } + + for(uint32_t i = 0; i < buckets_count; i++) { + Entry* bucket = malloc(sizeof(Entry)*initial_bucket_size); + if(bucket == 0) { + for(uint32_t j = 0; j < i; j++) { + free(buckets[j]); + } + free(bucket_sizes); + free(buckets); + return zero; + } + buckets[i] = bucket; + bucket_sizes[i] = initial_bucket_size; + bucket_usage[i] = 0; + } + + Map ret = { + .buckets_count = buckets_count, + .bucket_sizes = bucket_sizes, + .bucket_usage = bucket_usage, + .buckets = buckets, + }; + + return ret; +} + +MaybeValue map_lookup(Map map, uint32_t key) { + MaybeValue ret = { + .has_value = false, + .value = 0, + }; + + uint32_t bucket_index = key % map.buckets_count; + for(uint32_t i = 0; i < map.bucket_usage[bucket_index]; i++) { + if(map.buckets[bucket_index][i].key == key) { + ret.has_value = true; + ret.value = map.buckets[bucket_index][i].value; + } + } + + return ret; +} + +bool map_add(Map* map, uint32_t key, void* value) { + uint32_t bucket_index = key % map->buckets_count; + + for(uint32_t i = 0; i < map->bucket_usage[bucket_index]; i++) { + if(map->buckets[bucket_index][i].key == key) { + map->buckets[bucket_index][i].value = value; + return true; + } + } + + if(map->bucket_usage[bucket_index] < map->bucket_sizes[bucket_index]) { + map->buckets[bucket_index][map->bucket_usage[bucket_index]].key = key; + map->buckets[bucket_index][map->bucket_usage[bucket_index]].value = value; + map->bucket_usage[bucket_index] += 1; + return true; + } + + Entry* new_bucket = realloc(map->buckets[bucket_index], 2*map->bucket_sizes[bucket_index]); + if(new_bucket == 0) { + return false; + } + + map->bucket_usage[bucket_index] += 1; + map->bucket_sizes[bucket_index] *= 2; + map->buckets[bucket_index] = new_bucket; + map->buckets[bucket_index][map->bucket_usage[bucket_index]].key = key; + map->buckets[bucket_index][map->bucket_usage[bucket_index]].value = value; + + return true; +} + +MaybeValue map_del(Map* map, uint32_t key) { + MaybeValue ret = { + .has_value = false, + .value = 0, + }; + + uint32_t bucket_index = key % map->buckets_count; + for(uint32_t i = 0; i < map->bucket_usage[bucket_index]; i++) { + if(map->buckets[bucket_index][i].key == key) { + ret.value = map->buckets[bucket_index][i].value; + ret.has_value = true; + + if(map->bucket_usage[bucket_index] > 1) { + map->buckets[bucket_index][i] = map->buckets[bucket_index][map->bucket_usage[bucket_index]-1]; + } + map->bucket_usage[bucket_index] -= 1; + break; + } + } + + return ret; +} + +void map_destroy(Map map) { + for(uint32_t i = 0; i < map.buckets_count; i++) { + free(map.buckets[i]); + } + free(map.buckets); + free(map.bucket_sizes); + free(map.bucket_usage); +} + +MapIterator map_iterator_create(Map map) { + MapIterator iterator = { + .keys = 0, + .vals = 0, + .count = 0, + }; + + uint32_t count = 0; + for(uint32_t i = 0; i < map.buckets_count; i++) { + count += map.bucket_usage[i]; + } + + uint32_t* keys = malloc(sizeof(uint32_t)*count); + if(keys == 0) { + return iterator; + } + + void** vals = malloc(sizeof(void*)*count); + if(vals == 0) { + free(keys); + return iterator; + } + + uint32_t idx = 0; + for(uint32_t i = 0; i < map.buckets_count; i++) { + for(uint32_t j = 0; j < map.bucket_usage[i]; j++) { + keys[idx] = map.buckets[i][j].key; + vals[idx] = map.buckets[i][j].value; + idx += 1; + } + } + + iterator.keys = keys; + iterator.vals = vals; + iterator.count = count; + + return iterator; +} + +void map_iterator_free(MapIterator iterator) { + if(iterator.count > 0) { + free(iterator.keys); + free(iterator.vals); + } +} diff --git a/src/ply.c b/src/ply.c index bd01f67..fab3e85 100644 --- a/src/ply.c +++ b/src/ply.c @@ -47,7 +47,7 @@ PlyPropertyType ply_parse_type(const char* type_string) { return PLY_TYPE_INVALID; } -void ply_free_mesh(PlyElement* elements_head) { +void ply_free_elements(PlyElement* elements_head) { PlyElement* elem = elements_head; while(elem != NULL) { PlyProperty* prop = elem->properties; @@ -90,11 +90,22 @@ void ply_free_mesh(PlyElement* elements_head) { } } -PlyElement* ply_load_mesh(char* filename) { +PlyMesh ply_load_mesh(char* filename) { + PlyMesh mesh = { + .vertex_count = 0, + .position = NULL, + .colour = NULL, + .uv = NULL, + .normal = NULL, + + .index_count = 0, + .index = NULL, + }; + FILE* ply = fopen(filename, "r"); if(ply == NULL) { fprintf(stderr, "file not found %s\n", filename); - return NULL; + return mesh; } uint8_t buffer[1024] = {0}; @@ -149,7 +160,7 @@ PlyElement* ply_load_mesh(char* filename) { if(header_id == PLY_FORMAT_INVALID) { fprintf(stderr, "unknown header line: %s\n", line); - goto close; + goto clean; } else if (header_id == PLY_HEADER_COMMENT) { continue; } else if (header_id == PLY_HEADER_END) { @@ -228,7 +239,7 @@ PlyElement* ply_load_mesh(char* filename) { } if(line == NULL) { - goto close; + goto clean; } } @@ -278,12 +289,9 @@ PlyElement* ply_load_mesh(char* filename) { elem = elem->next; } - fclose(ply); - return elements_head; - clean: - ply_free_mesh(elements_head); + ply_free_elements(elements_head); close: fclose(ply); - return NULL; + return mesh; }