Added Map struct and methods to create/destroy/use it

main
noah metz 2024-01-09 20:41:31 -07:00
parent 91d8ed6e3b
commit ee57d5bc81
1 changed files with 167 additions and 30 deletions

@ -64,6 +64,153 @@ typedef struct TextureStruct {
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 ObjectStruct {
Map attributes;
} Object;
// Defines how a mesh is read from a buffer into a graphics pipeline
typedef struct MeshTypeStruct {
uint32_t bindings_count;
@ -157,7 +304,7 @@ typedef struct VulkanContextStruct {
VkDescriptorPool scene_ubo_pool;
VkDescriptorSetLayout scene_ubo_layout;
VkDescriptorSet* scene_ubo_descriptors;
VkDescriptorSet* scene_descriptors;
AllocatedBuffer* scene_ubos;
void** scene_ubo_ptrs;
@ -1056,24 +1203,6 @@ VkRenderPass create_render_pass(VkDevice device, VkSurfaceFormatKHR format, VkFo
return render_pass;
}
VkPipelineLayout create_pipeline_layout(VkDevice device, uint32_t set_count, VkDescriptorSetLayout* sets, uint32_t pcr_count, VkPushConstantRange* pcrs) {
VkPipelineLayout layout;
VkPipelineLayoutCreateInfo layout_info = {};
layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
layout_info.setLayoutCount = set_count;
layout_info.pSetLayouts = sets;
layout_info.pushConstantRangeCount = pcr_count;
layout_info.pPushConstantRanges = pcrs;
VkResult result;
result = vkCreatePipelineLayout(device, &layout_info, 0, &layout);
if(result != VK_SUCCESS) {
return VK_NULL_HANDLE;
}
return layout;
}
uint32_t find_memory_type(VkPhysicalDevice physical_device, uint32_t type_filter, VkMemoryPropertyFlags properties) {
VkPhysicalDeviceMemoryProperties memory_properties;
vkGetPhysicalDeviceMemoryProperties(physical_device, &memory_properties);
@ -1700,15 +1829,15 @@ void record_command_buffer_mesh(Mesh mesh, VkCommandBuffer command_buffer) {
vkCmdDrawIndexed(command_buffer, mesh.index_count, 1, 0, 0, 0);
}
void record_command_buffer_material(Material material, uint32_t mesh_count, Mesh* meshes, VkDescriptorSet scene_ubo_descriptor, VkCommandBuffer command_buffer) {
void record_command_buffer_material(Material material, uint32_t mesh_count, Mesh* meshes, VkDescriptorSet scene_descriptor, VkCommandBuffer command_buffer) {
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, material.pipeline);
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, material.layout, 0, 1, &scene_ubo_descriptor, 0, 0);
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, material.layout, 0, 1, &scene_descriptor, 0, 0);
for(uint32_t i = 0; i < mesh_count; i++) {
record_command_buffer_mesh(meshes[i], command_buffer);
}
}
VkResult record_command_buffer_scene(uint32_t materials_count, Material* materials, uint32_t* mesh_counts, Mesh** meshes, VkDescriptorSet scene_ubo_descriptor, VkCommandBuffer command_buffer, VkRenderPass render_pass, VkFramebuffer framebuffer, VkExtent2D extent) {
VkResult record_command_buffer_scene(uint32_t materials_count, Material* materials, uint32_t* mesh_counts, Mesh** meshes, VkDescriptorSet scene_descriptor, VkCommandBuffer command_buffer, VkRenderPass render_pass, VkFramebuffer framebuffer, VkExtent2D extent) {
VkCommandBufferBeginInfo begin_info = {};
begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
begin_info.flags = 0;
@ -1757,7 +1886,7 @@ VkResult record_command_buffer_scene(uint32_t materials_count, Material* materia
vkCmdSetScissor(command_buffer, 0, 1, &scissor);
for(uint i = 0; i < materials_count; i++) {
record_command_buffer_material(materials[i], mesh_counts[i], meshes[i], scene_ubo_descriptor, command_buffer);
record_command_buffer_material(materials[i], mesh_counts[i], meshes[i], scene_descriptor, command_buffer);
}
vkCmdEndRenderPass(command_buffer);
@ -1936,9 +2065,17 @@ Material create_material(
num_layouts += 1;
}
VkPipelineLayout layout;
VkPipelineLayout layout = create_pipeline_layout(device, num_layouts, all_layouts, 0, 0);
if(layout == VK_NULL_HANDLE) {
VkPipelineLayoutCreateInfo layout_info = {};
layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
layout_info.setLayoutCount = num_layouts;
layout_info.pSetLayouts = all_layouts;
layout_info.pushConstantRangeCount = 0; // TODO
layout_info.pPushConstantRanges = 0; // TODO
VkResult result = vkCreatePipelineLayout(device, &layout_info, 0, &layout);
if(result != VK_SUCCESS) {
return zero_material;
}
@ -2327,12 +2464,12 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) {
context->scene_ubo_layout = scene_ubo_layout;
}
VkDescriptorSet* scene_ubo_descriptors = create_descriptor_sets(context->device, context->scene_ubo_layout, context->scene_ubo_pool, max_frames_in_flight);
if(scene_ubo_descriptors == 0) {
VkDescriptorSet* scene_descriptors = create_descriptor_sets(context->device, context->scene_ubo_layout, context->scene_ubo_pool, max_frames_in_flight);
if(scene_descriptors == 0) {
fprintf(stderr, "failed to create vulkan scene descriptore\n");
return 0;
} else {
context->scene_ubo_descriptors = scene_ubo_descriptors;
context->scene_descriptors = scene_descriptors;
}
AllocatedBuffer* scene_ubos = allocate_buffers(context->physical_device, context->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);
@ -2370,7 +2507,7 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) {
VkWriteDescriptorSet descriptor_write = {};
descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptor_write.dstSet = context->scene_ubo_descriptors[i];
descriptor_write.dstSet = context->scene_descriptors[i];
descriptor_write.dstBinding = 0;
descriptor_write.dstArrayElement = 0;
descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
@ -2665,7 +2802,7 @@ VkResult draw_frame(VulkanContext* context) {
uint32_t mesh_counts[] = {1};
Mesh* meshes[] = {&context->triangle_mesh_textured};
result = record_command_buffer_scene(1, &context->texture_mesh_material, (uint32_t*)&mesh_counts, (Mesh**)meshes, context->scene_ubo_descriptors[context->current_frame], context->swapchain_command_buffers[context->current_frame], context->render_pass, context->swapchain_framebuffers[image_index], context->swapchain_extent);
result = record_command_buffer_scene(1, &context->texture_mesh_material, (uint32_t*)&mesh_counts, (Mesh**)meshes, context->scene_descriptors[context->current_frame], context->swapchain_command_buffers[context->current_frame], context->render_pass, context->swapchain_framebuffers[image_index], context->swapchain_extent);
if(result != VK_SUCCESS) {
return result;
}