diff --git a/shader_src/texture.vert b/shader_src/texture.vert index df9d222..69020ec 100644 --- a/shader_src/texture.vert +++ b/shader_src/texture.vert @@ -1,9 +1,13 @@ #version 450 -layout(binding = 0) uniform UniformBufferObject { +layout(set = 0, binding = 0) uniform SceneUniformBuffer { mat4 view; mat4 proj; -} ubo; +} scene_ubo; + +layout(set = 2, binding = 1) uniform ObjectUniformBuffer { + mat4 model; +} object_ubo; layout(location = 0) in vec3 inPosition; layout(location = 1) in vec3 inColor; @@ -13,7 +17,7 @@ layout(location = 0) out vec3 fragColor; layout(location = 1) out vec2 fragTex; void main() { - gl_Position = ubo.proj * ubo.view * vec4(inPosition, 1.0); + gl_Position = scene_ubo.proj * scene_ubo.view * object_ubo.model * vec4(inPosition, 1.0); fragColor = inColor; fragTex = inTex; } diff --git a/src/main.c b/src/main.c index ff60b21..1c72271 100644 --- a/src/main.c +++ b/src/main.c @@ -260,15 +260,30 @@ void map_iterator_free(MapIterator iterator) { } typedef struct PositionStruct { - vec4 position; + vec3 position; + vec3 scale; versor rotation; } Position; -typedef struct AttributeMappingStruct { - uint32_t attribute_id; // Which attribute to map +typedef void(*MappingFunc)(void*,void*); + +void attribute_mapping_position_to_matrix(void* dest, void* source) { + Position* position = source; + glm_translate_make(dest, position->position); + glm_quat_rotate(dest, position->rotation, dest); + glm_scale(dest, position->scale); +} + +#define MAPPING_POSITION_TO_MATRIX 0 + +MappingFunc mapping_functions[] = { + attribute_mapping_position_to_matrix, +}; + +typedef struct MappingStruct { uint32_t mapping_type; // What function to use to map it - uint32_t binding; // Which index to use in the ATTRIBUTE_ID_DESCRIPTORS array -} AttributeMapping; + uint32_t index; // Which index to use in the ATTRIBUTE_ID_DESCRIPTORS array +} Mapping; #define ATTRIBUTE_ID_MESH 0x00000001 // Mesh* #define ATTRIBUTE_ID_MATERIAL 0x00000002 // Material* @@ -387,23 +402,27 @@ struct Vertex { vec3 color; }; +struct ModelUBO { + mat4 model; +}; + struct SceneUBO { mat4 view; mat4 proj; }; const struct Vertex vertices[] = { - {.pos = {-0.5f, -0.5f, 0.5f}, .color = {1.0f, 0.0f, 0.0f}}, - {.pos = { 0.5f, -0.5f, 0.5f}, .color = {0.0f, 1.0f, 0.0f}}, - {.pos = { 0.5f, 0.5f, 0.5f}, .color = {0.0f, 0.0f, 1.0f}}, - {.pos = {-0.5f, 0.5f, 0.5f}, .color = {1.0f, 1.0f, 1.0f}}, + {.pos = {-1.f, -1.f, 0.f}, .color = {1.0f, 0.0f, 0.0f}}, + {.pos = { 1.f, -1.f, 0.f}, .color = {0.0f, 1.0f, 0.0f}}, + {.pos = { 1.f, 1.f, 0.f}, .color = {0.0f, 0.0f, 1.0f}}, + {.pos = {-1.f, 1.f, 0.f}, .color = {1.0f, 1.0f, 1.0f}}, }; const struct TextureVertex texture_vertices[] = { - {.pos = {-0.5f, -0.5f, 0.5f}, .color = {1.0f, 0.0f, 0.0f}, .tex = {1.0f, 1.0f}}, - {.pos = { 0.5f, -0.5f, 0.5f}, .color = {0.0f, 1.0f, 0.0f}, .tex = {0.0f, 1.0f}}, - {.pos = { 0.5f, 0.5f, 0.5f}, .color = {0.0f, 0.0f, 1.0f}, .tex = {0.0f, 0.0f}}, - {.pos = {-0.5f, 0.5f, 0.5f}, .color = {1.0f, 1.0f, 1.0f}, .tex = {1.0f, 0.0f}}, + {.pos = {-1.f, -1.f, 0.f}, .color = {1.0f, 0.0f, 0.0f}, .tex = {1.0f, 1.0f}}, + {.pos = { 1.f, -1.f, 0.f}, .color = {0.0f, 1.0f, 0.0f}, .tex = {0.0f, 1.0f}}, + {.pos = { 1.f, 1.f, 0.f}, .color = {0.0f, 0.0f, 1.0f}, .tex = {0.0f, 0.0f}}, + {.pos = {-1.f, 1.f, 0.f}, .color = {1.0f, 1.0f, 1.0f}, .tex = {1.0f, 0.0f}}, }; const uint16_t indices[] = { @@ -447,6 +466,35 @@ GLFWwindow* init_window(int width, int height) { return window; } +void object_update_mappings(Material material, Object object, uint32_t frame_num) { + if(material.object_descriptor_mappings.buckets == 0) { + return; + } + + MaybeValue maybe_descriptors = map_lookup(object.attributes, ATTRIBUTE_ID_DESCRIPTORS); + if(maybe_descriptors.has_value == false) { + return; + } + + void** descriptors = ((void***)(maybe_descriptors.value))[frame_num]; + + MapIterator mapping_iterator = map_iterator_create(material.object_descriptor_mappings); + for(uint32_t i = 0; i < mapping_iterator.count; i++) { + MaybeValue maybe_attribute = map_lookup(object.attributes, mapping_iterator.keys[i]); + if(maybe_attribute.has_value == true) { + Mapping* mapping = mapping_iterator.vals[i]; + if(mapping->mapping_type > sizeof(mapping_functions)/sizeof(MappingFunc)) { + fprintf(stderr, "material requested mapping_function 0x%02x which does not exist\n", mapping->mapping_type); + continue; + } + mapping_functions[mapping->mapping_type](descriptors[mapping->index], maybe_attribute.value); + } else { + fprintf(stderr, "material requested attribute 0x%02x from object, but it does not have it\n", mapping_iterator.keys[i]); + } + } + map_iterator_free(mapping_iterator); +} + VkFormat find_depth_format(VkPhysicalDevice physical_device, uint32_t num_requested, VkFormat* requested, VkImageTiling tiling, VkFormatFeatureFlags features) { for(uint32_t i = 0; i < num_requested; i++) { VkFormatProperties properties; @@ -1809,6 +1857,8 @@ void command_draw_object(Material material, Object object, uint32_t frame_num, V return; } + object_update_mappings(material, object, frame_num); + Mesh* mesh = maybe_mesh.value; VkBuffer vertex_buffers[] = {mesh->vertex_buffer.buffer}; @@ -1987,7 +2037,7 @@ Mesh load_texture_mesh(VkPhysicalDevice physical_device, VkDevice device, struct return mesh; } -Object create_object() { +Object create_object(uint32_t max_frames_in_flight, uint32_t descriptor_count) { Object ret = { .attributes = { .buckets = 0, @@ -1999,50 +2049,72 @@ Object create_object() { return ret; } + if(descriptor_count > 0) { + void*** descriptor_arrays = malloc(sizeof(void**)*max_frames_in_flight); + if(descriptor_arrays == 0) { + return ret; + } + for(uint32_t i = 0; i < max_frames_in_flight; i++) { + descriptor_arrays[i] = malloc(sizeof(void*)*descriptor_count); + + if(descriptor_arrays[i] == 0) { + for(uint32_t j = 0; j < i; j++) { + free(descriptor_arrays[j]); + } + free(descriptor_arrays); + map_destroy(attributes); + } + } + + bool result = map_add(&attributes, ATTRIBUTE_ID_DESCRIPTORS, descriptor_arrays); + if(result == false) { + for(uint32_t i = 0; i < max_frames_in_flight; i++) { + free(descriptor_arrays[i]); + } + free(descriptor_arrays); + map_destroy(attributes); + } + } + ret.attributes = attributes; return ret; } -Object create_renderable(Mesh* mesh, Material* material, VkDescriptorSet* descriptor_sets) { +Object create_renderable(Mesh* mesh, Material* material, VkDescriptorSet* descriptor_sets, uint32_t max_frames_in_flight, uint32_t descriptor_count) { Object zero = { .attributes = { .buckets = 0, }, }; - if(mesh == 0 || material == 0) { + Object object = create_object(max_frames_in_flight, descriptor_count); + if(object.attributes.buckets == 0) { return zero; } - Map attributes = map_create(8, 2); - if(attributes.buckets == 0) { + if(mesh == 0 || material == 0) { return zero; } - bool result = map_add(&attributes, ATTRIBUTE_ID_MESH, mesh); + bool result = map_add(&object.attributes, ATTRIBUTE_ID_MESH, mesh); if(result == false) { - map_destroy(attributes); + map_destroy(object.attributes); return zero; } - result = map_add(&attributes, ATTRIBUTE_ID_MATERIAL, material); + result = map_add(&object.attributes, ATTRIBUTE_ID_MATERIAL, material); if(result == false) { - map_destroy(attributes); + map_destroy(object.attributes); return zero; } - result = map_add(&attributes, ATTRIBUTE_ID_DESCRIPTOR_SETS, descriptor_sets); + result = map_add(&object.attributes, ATTRIBUTE_ID_DESCRIPTOR_SETS, descriptor_sets); if(result == false) { - map_destroy(attributes); + map_destroy(object.attributes); return zero; } - - Object ret = { - .attributes = attributes, - }; - - return ret; + return object; } Mesh load_simple_mesh(VkPhysicalDevice physical_device, VkDevice device, struct Vertex* vertices, uint32_t vertex_count, uint16_t* indices, uint32_t index_count, VkCommandPool transfer_pool, VkQueue transfer_queue) { @@ -2083,7 +2155,8 @@ Material create_material( VkDescriptorSetLayout scene_ubo_layout, PipelineLayout pipeline_layout, MeshType mesh_type, - uint32_t max_frames_in_flight + uint32_t max_frames_in_flight, + Map object_descriptor_mappings ) { Material zero_material = { .pipeline = VK_NULL_HANDLE, @@ -2204,6 +2277,7 @@ Material create_material( .material_descriptors = material_descriptors, .material_descriptor_pool = material_descriptor_pool, .material_descriptors_count = max_frames_in_flight, + .object_descriptor_mappings = object_descriptor_mappings, }; return material; @@ -2257,7 +2331,12 @@ Material create_simple_mesh_material(VkDevice device, VkExtent2D extent, VkRende }; - return create_material(device, extent, render_pass, 2, shader_stages, scene_ubo_layout, simple_layout, simple_mesh_type, max_frames_in_flight); + Map empty_map = { + .buckets = 0, + .buckets_count = 0, + }; + + return create_material(device, extent, render_pass, 2, shader_stages, scene_ubo_layout, simple_layout, simple_mesh_type, max_frames_in_flight, empty_map); } Material create_texture_mesh_material(VkDevice device, VkExtent2D extent, VkRenderPass render_pass, VkDescriptorSetLayout scene_ubo_layout, uint32_t max_frames_in_flight) { @@ -2319,6 +2398,13 @@ Material create_texture_mesh_material(VkDevice device, VkExtent2D extent, VkRend .pImmutableSamplers = 0, .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, }, + { + .binding = 1, + .descriptorCount = 1, + .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, + .pImmutableSamplers = 0, + .stageFlags = VK_SHADER_STAGE_VERTEX_BIT, + }, }; MeshType textured_mesh_type = { @@ -2333,7 +2419,30 @@ Material create_texture_mesh_material(VkDevice device, VkExtent2D extent, VkRend .object_bindings = mesh_set_bindings, }; - return create_material(device, extent, render_pass, 2, shader_stages, scene_ubo_layout, texture_layout, textured_mesh_type, max_frames_in_flight); + Map object_descriptor_mappings = map_create(8, 2); + if(object_descriptor_mappings.buckets == 0) { + Material tmp = {}; + return tmp; + } + + Mapping* position_mapping = malloc(sizeof(Mapping)); + if(position_mapping == 0) { + map_destroy(object_descriptor_mappings); + Material tmp = {}; + return tmp; + } + position_mapping->mapping_type = MAPPING_POSITION_TO_MATRIX; + position_mapping->index = 0; + + bool map_result = map_add(&object_descriptor_mappings, ATTRIBUTE_ID_POSITION, position_mapping); + if(map_result != true) { + map_destroy(object_descriptor_mappings); + free(position_mapping); + Material tmp = {}; + return tmp; + } + + return create_material(device, extent, render_pass, 2, shader_stages, scene_ubo_layout, texture_layout, textured_mesh_type, max_frames_in_flight, object_descriptor_mappings); } VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) { @@ -2649,7 +2758,7 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) { context->triangle_mesh = triangle_mesh; } - Object triangle_object = create_renderable(&context->triangle_mesh, &context->simple_mesh_material, 0); + Object triangle_object = create_renderable(&context->triangle_mesh, &context->simple_mesh_material, 0, 2, 0); if(triangle_object.attributes.buckets == 0) { fprintf(stderr, "failed to create renderable triangle object\n"); return 0; @@ -2678,11 +2787,15 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) { .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, .descriptorCount = max_frames_in_flight, }, + { + .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, + .descriptorCount = max_frames_in_flight, + }, }; VkDescriptorPoolCreateInfo TODO_info = { .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, - .poolSizeCount = 1, + .poolSizeCount = sizeof(TODO_sizes)/sizeof(VkDescriptorPoolSize), .maxSets = max_frames_in_flight, .pPoolSizes = TODO_sizes, }; @@ -2723,7 +2836,7 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) { return 0; } - Object triangle_object_textured = create_renderable(&context->triangle_mesh_textured, &context->texture_mesh_material, TODO_sets); + Object triangle_object_textured = create_renderable(&context->triangle_mesh_textured, &context->texture_mesh_material, TODO_sets, max_frames_in_flight, 1); if(triangle_object_textured.attributes.buckets == 0) { fprintf(stderr, "failed to create renderable textured triangle object\n"); return 0; @@ -2731,6 +2844,57 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) { context->triangle_object_textured = triangle_object_textured; } + Position* position = malloc(sizeof(Position)); + if(position == 0) { + return 0; + } + glm_quat_identity(position->rotation); + position->scale[0] = 0.1f; + position->scale[1] = 0.1f; + position->scale[2] = 0.1f; + position->position[2] = 1.0f; + bool map_result = map_add(&triangle_object_textured.attributes, ATTRIBUTE_ID_POSITION, position); + if(map_result == 0) { + return 0; + } + + AllocatedBuffer* triangle_ubos = allocate_buffers(context->physical_device, context->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); + if(triangle_ubos == 0) { + return 0; + } + + MaybeValue maybe_descriptors = map_lookup(triangle_object_textured.attributes, ATTRIBUTE_ID_DESCRIPTORS); + if(maybe_descriptors.has_value == false) { + return 0; + } + + void*** descriptors = maybe_descriptors.value; + + for(uint32_t i = 0; i < max_frames_in_flight; i++) { + VkResult result = vkMapMemory(device, triangle_ubos[i].memory, 0, sizeof(Position), 0, &descriptors[i][0]); + if(result != VK_SUCCESS) { + return 0; + } + + VkDescriptorBufferInfo buffer_info = { + .buffer = triangle_ubos[i].buffer, + .offset = 0, + .range = sizeof(struct ModelUBO), + }; + + VkWriteDescriptorSet write_info = { + .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .dstSet = TODO_sets[i], + .dstBinding = 1, + .dstArrayElement = 0, + .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, + .descriptorCount = 1, + .pBufferInfo = &buffer_info, + }; + + vkUpdateDescriptorSets(context->device, 1, &write_info, 0, 0); + } + VkExtent2D texture_size = { .width = 10, .height = 10, @@ -2932,20 +3096,20 @@ VkResult update_scene_descriptor(void** buffers, uint32_t frame_index, vec3 worl movement_sum[2] += 1 * time_delta; } - if(key_flags.left) { + if(key_flags.right) { movement_sum[0] += 1 * time_delta; } - if(key_flags.right) { + if(key_flags.left) { movement_sum[0] -= 1 * time_delta; } if(key_flags.up) { - movement_sum[1] += 1 * time_delta; + movement_sum[1] -= 1 * time_delta; } if(key_flags.down) { - movement_sum[1] -= 1 * time_delta; + movement_sum[1] += 1 * time_delta; } @@ -2959,11 +3123,11 @@ VkResult update_scene_descriptor(void** buffers, uint32_t frame_index, vec3 worl } if(key_flags.turn_up) { - eular_rotation[1] += 1 * time_delta; + eular_rotation[1] -= 1 * time_delta; } if(key_flags.turn_down) { - eular_rotation[1] -= 1 * time_delta; + eular_rotation[1] += 1 * time_delta; } if(key_flags.roll_right) { @@ -2974,15 +3138,15 @@ VkResult update_scene_descriptor(void** buffers, uint32_t frame_index, vec3 worl eular_rotation[2] -= 1 * time_delta; } - vec3 left = {1.0f, 0.0f, 0.0f}; - vec3 up = {0.0f, -1.0f, 0.0f}; + vec3 right = {1.0f, 0.0f, 0.0f}; + vec3 up = {0.0f, 1.0f, 0.0f}; vec3 forward = {0.0f, 0.0f, 1.0f}; - glm_quat_rotatev(world_rotation, left, left); + glm_quat_rotatev(world_rotation, right, right); glm_quat_rotatev(world_rotation, up, up); glm_quat_rotatev(world_rotation, forward, forward); versor relative_rotation_y; - glm_quatv(relative_rotation_y, eular_rotation[1], left); + glm_quatv(relative_rotation_y, eular_rotation[1], right); versor relative_rotation_x; glm_quatv(relative_rotation_x, eular_rotation[0], up); @@ -3000,7 +3164,7 @@ VkResult update_scene_descriptor(void** buffers, uint32_t frame_index, vec3 worl struct SceneUBO ubo = {}; - glm_perspective(100.0f, aspect_ratio, 0.01, 100, ubo.proj); + glm_perspective(1.5708f, aspect_ratio, 0.01, 1000, ubo.proj); glm_quat_look(world_position, world_rotation, ubo.view); memcpy(buffers[frame_index], (void*)&ubo, sizeof(ubo));