main
noah metz 2024-01-11 16:16:10 -07:00
parent 80aff7e188
commit 7043b478fe
5 changed files with 410 additions and 322 deletions

@ -0,0 +1,39 @@
#ifndef MAP_H
#define MAP_H
#include <stdint.h>
#include <stdbool.h>
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

@ -2,6 +2,8 @@
#define PLY_H
#include <stddef.h>
#include <cglm/types.h>
#include <stdint.h>
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

@ -18,6 +18,17 @@
#include <string.h>
#include <ply.h>
#include <map.h>
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);

@ -0,0 +1,174 @@
#include <map.h>
#include <stdlib.h>
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);
}
}

@ -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;
}