diff --git a/include/ply.h b/include/ply.h index 0ec54c0..ae3605d 100644 --- a/include/ply.h +++ b/include/ply.h @@ -7,29 +7,29 @@ typedef enum { PLY_FORMAT_INVALID = -1, - PLY_FORMAT_ASCII, - PLY_FORMAT_LE, - PLY_FORMAT_BE, + PLY_FORMAT_ASCII = 0, + PLY_FORMAT_LE = 1, + PLY_FORMAT_BE = 2, } PlyFormatType; typedef enum { PLY_HEADER_INVALID = -1, - PLY_HEADER_COMMENT, - PLY_HEADER_END, - PLY_HEADER_ELEMENT, - PLY_HEADER_PROPERTY, + PLY_HEADER_COMMENT = 0, + PLY_HEADER_END = 1, + PLY_HEADER_ELEMENT = 2, + PLY_HEADER_PROPERTY = 3, } PlyHeaderType; typedef enum { PLY_TYPE_INVALID = -1, - PLY_TYPE_CHAR, - PLY_TYPE_UCHAR, - PLY_TYPE_SHORT, - PLY_TYPE_USHORT, - PLY_TYPE_INT, - PLY_TYPE_UINT, - PLY_TYPE_FLOAT, - PLY_TYPE_DOUBLE, + PLY_TYPE_CHAR = 0, + PLY_TYPE_UCHAR = 1, + PLY_TYPE_SHORT = 2, + PLY_TYPE_USHORT = 3, + PLY_TYPE_INT = 4, + PLY_TYPE_UINT = 5, + PLY_TYPE_FLOAT = 6, + PLY_TYPE_DOUBLE = 7, } PlyPropertyType; typedef struct PlyPropertyStruct { @@ -63,18 +63,10 @@ typedef struct PlyMeshStruct { typedef struct PlyMappingsStruct { char* vertex_element; - char* x; - char* y; - char* z; - char* nx; - char* ny; - char* nz; - char* r; - char* g; - char* b; - char* a; - char* u; - char* v; + char* position[3]; + char* normal[3]; + char* colour[4]; + char* texture[2]; char* face_element; char* index; diff --git a/monkey.ply b/monkey.ply new file mode 100644 index 0000000..58de342 Binary files /dev/null and b/monkey.ply differ diff --git a/src/gpu_mem.c b/src/gpu_mem.c index b7d2653..087aaf6 100644 --- a/src/gpu_mem.c +++ b/src/gpu_mem.c @@ -205,6 +205,9 @@ VkResult gpu_buffer_malloc(VkDevice device, GPUPage* page, VkDeviceSize size, Vk return VK_ERROR_VALIDATION_FAILED_EXT; } + //TODO: use real alignment size instead of hard-coded to 16 + size += size % 16; + VkBufferCreateInfo buffer_info = { .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, .size = size, diff --git a/src/main.c b/src/main.c index e11d196..e59b169 100644 --- a/src/main.c +++ b/src/main.c @@ -978,30 +978,37 @@ VkRenderPass create_render_pass(VkDevice device, VkSurfaceFormatKHR format, VkFo .layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, }; - VkSubpassDescription subpass = { - .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, - .colorAttachmentCount = sizeof(color_attachment_refs)/sizeof(VkAttachmentReference), - .pColorAttachments = color_attachment_refs, - .pDepthStencilAttachment = &depth_attachment_ref, + // Create a subpass with the color and depth attachments + VkSubpassDescription subpasses[] = { + { + .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, + .colorAttachmentCount = sizeof(color_attachment_refs)/sizeof(VkAttachmentReference), + .pColorAttachments = color_attachment_refs, + .pDepthStencilAttachment = &depth_attachment_ref, + }, }; - VkSubpassDependency dependency = { - .srcSubpass = VK_SUBPASS_EXTERNAL, - .dstSubpass = 0, - .srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, - .srcAccessMask = 0, - .dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, - .dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + // This basically says "make sure nothing else is writing to the depth_stencil or the color attachment during the pipeline + VkSubpassDependency dependencies[] = { + { + .srcSubpass = VK_SUBPASS_EXTERNAL, + .dstSubpass = 0, + .srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, + .srcAccessMask = 0, + .dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, + .dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + .dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT, + } }; VkRenderPassCreateInfo render_info = { .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, .attachmentCount = sizeof(attachments)/sizeof(VkAttachmentDescription), .pAttachments = attachments, - .subpassCount = 1, - .pSubpasses = &subpass, - .dependencyCount = 1, - .pDependencies = &dependency, + .subpassCount = sizeof(subpasses)/sizeof(VkSubpassDescription), + .pSubpasses = subpasses, + .dependencyCount = sizeof(dependencies)/sizeof(VkSubpassDependency), + .pDependencies = dependencies, }; VkRenderPass render_pass; @@ -2800,28 +2807,38 @@ 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(PlyMesh ply_mesh, Material* simple_mesh_material, VkPhysicalDeviceMemoryProperties memories, VkDevice device, VkCommandPool transfer_pool, VkQueue transfer_queue, uint32_t max_frames_in_flight, VkDescriptorPool pool) { Object zero = {}; GPUPage* mesh_memory = NULL; - VkResult result = gpu_page_allocate(device, memories, 10000, 0xFFFFFFFF, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT, &mesh_memory); + VkResult result = gpu_page_allocate(device, memories, 100000, 0xFFFFFFFF, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT, &mesh_memory); if(result != VK_SUCCESS) { return zero; } GPUPage* transfer_memory = NULL; - result = gpu_page_allocate(device, memories, 100000, 0xFFFFFFFF, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &transfer_memory); + result = gpu_page_allocate(device, memories, 200000, 0xFFFFFFFF, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &transfer_memory); if(result != VK_SUCCESS) { return zero; } GPUBuffer transfer_buffer = {0}; - result = gpu_buffer_malloc(device, transfer_memory, 10000, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, &transfer_buffer); + result = gpu_buffer_malloc(device, transfer_memory, 100000, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, &transfer_buffer); if(result != VK_SUCCESS) { return zero; } - Mesh* mesh = load_mesh_to_buffer(device, mesh_memory, transfer_buffer, 4, sizeof(struct Vertex), (void*)vertices, 6, sizeof(uint16_t), (void*)indices, transfer_pool, transfer_queue); + struct Vertex* tmp = malloc(sizeof(struct Vertex)*ply_mesh.vertex_count); + for(uint32_t i = 0; i < ply_mesh.vertex_count; i++) { + tmp[i].pos[0] = ply_mesh.position[i][0]; + tmp[i].pos[1] = ply_mesh.position[i][1]; + tmp[i].pos[2] = ply_mesh.position[i][2]; + tmp[i].color[0] = ply_mesh.colour[i][0]; + tmp[i].color[1] = ply_mesh.colour[i][1]; + tmp[i].color[2] = ply_mesh.colour[i][2]; + } + + Mesh* mesh = load_mesh_to_buffer(device, mesh_memory, transfer_buffer, ply_mesh.vertex_count, sizeof(struct Vertex), (void*)tmp, ply_mesh.index_count, sizeof(uint16_t), (void*)ply_mesh.index, transfer_pool, transfer_queue); if(mesh == 0) { return zero; } @@ -2862,9 +2879,9 @@ Object create_simple_mesh_object(Material* simple_mesh_material, VkPhysicalDevic return zero; } glm_quat_identity(position->rotation); - position->scale[0] = 10.f; - position->scale[1] = 10.f; - position->scale[2] = 10.f; + position->scale[0] = 1.f; + position->scale[1] = 1.f; + position->scale[2] = 1.f; position->position[0] = 0.0f; position->position[1] = 0.0f; position->position[2] = 1.1f; @@ -3006,7 +3023,7 @@ Object create_texture_mesh_object(Material* texture_mesh_material, VkPhysicalDev return object; } -void main_loop(GLFWwindow* window, VulkanContext* context) { +void main_loop(PlyMesh ply_mesh, GLFWwindow* window, VulkanContext* context) { SceneContext scene = create_scene_context(context->device, context->memories, context->max_frames_in_flight); if(scene.pool == VK_NULL_HANDLE) { return; @@ -3039,7 +3056,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(ply_mesh, &simple_mesh_material, context->memories, 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; @@ -3201,7 +3218,7 @@ int main() { } glfwSetKeyCallback(window, key_callback); - main_loop(window, context); + main_loop(monkey, window, context); cleanup(window, context); diff --git a/src/ply.c b/src/ply.c index 90c612e..749e9f4 100644 --- a/src/ply.c +++ b/src/ply.c @@ -92,22 +92,99 @@ void ply_free_elements(PlyElement* elements_head) { PlyMappings default_ply_mappings = { .vertex_element = "vertex", - .x = "x", - .y = "y", - .z = "z", - .nx = "nx", - .ny = "ny", - .nz = "nz", - .r = "red", - .g = "green", - .b = "blue", - .a = "alpha", - .u = "s", - .v = "t", + .position = {"x", "y", "z"}, + .normal = {"nx", "ny", "nz"}, + .colour = {"red", "green", "blue", "alpha"}, + .texture = {"s", "t"}, .face_element = "face", .index = "vetex_indices", }; +uint16_t ply_conv_index(PlyPropertyType type, void* value, int swap_order) { + if(type == PLY_TYPE_INVALID) { + return 0.0f; + } + + uint8_t* ptr = value; + uint8_t tmp[8]; + size_t type_size = ply_type_sizes[type]; + for(uint32_t i = 0; i < type_size; i++) { + if(swap_order) { + tmp[type_size-i] = ptr[i]; + } else { + tmp[i] = ptr[i]; + } + } + + switch(type) { + case PLY_TYPE_CHAR: + return (uint16_t)*(int8_t*)(tmp); + case PLY_TYPE_UCHAR: + return (uint16_t)*(uint8_t*)(tmp); + case PLY_TYPE_SHORT: + return *(int16_t*)(tmp); + case PLY_TYPE_USHORT: + return (uint16_t)*(uint16_t*)(tmp); + case PLY_TYPE_INT: + return (uint16_t)*(int32_t*)(tmp); + case PLY_TYPE_UINT: + return (uint16_t)*(uint32_t*)(tmp); + default: + return 0.0f; + } +} + +float ply_conv_value(PlyPropertyType type, void* value, int swap_order) { + if(type == PLY_TYPE_INVALID) { + return 0.0f; + } + + uint8_t* ptr = value; + uint8_t tmp[8]; + size_t type_size = ply_type_sizes[type]; + for(uint32_t i = 0; i < type_size; i++) { + if(swap_order) { + tmp[type_size-i] = ptr[i]; + } else { + tmp[i] = ptr[i]; + } + } + + switch(type) { + case PLY_TYPE_CHAR: + return (float)*(int8_t*)(tmp)/(float)INT8_MAX; + case PLY_TYPE_UCHAR: + return (float)*(uint8_t*)(tmp)/(float)UINT8_MAX; + case PLY_TYPE_SHORT: + return (float)*(int16_t*)(tmp)/(float)INT16_MAX; + case PLY_TYPE_USHORT: + return (float)*(uint16_t*)(tmp)/(float)UINT16_MAX; + case PLY_TYPE_INT: + return (float)*(int32_t*)(tmp)/(float)INT32_MAX; + case PLY_TYPE_UINT: + return (float)*(uint32_t*)(tmp)/(float)UINT32_MAX; + case PLY_TYPE_FLOAT: + return *(float*)(tmp); + case PLY_TYPE_DOUBLE: + return *(float*)(tmp); + default: + return 0.0f; + } +} + +int ply_map_values(char* name, int stride, int count, PlyPropertyType type, int mapping_count, char** mapping, void* data, float* out) { + for(int i = 0; i < mapping_count; i++) { + if(strcmp(name, mapping[i]) == 0) { + for(int j = 0; j < count; j++) { + size_t type_size = ply_type_sizes[type]; + out[(stride*j)+i] = ply_conv_value(type, data + (type_size*j), 0); + } + return 1; + } + } + return 0; +} + PlyMesh ply_load_mesh(char* filename, PlyMappings mappings) { PlyMesh mesh = { .vertex_count = 0, @@ -263,12 +340,6 @@ PlyMesh ply_load_mesh(char* filename, PlyMappings mappings) { PlyElement* elem = elements_head; while(elem != NULL) { - if(strcmp(elem->name, mappings.vertex_element) == 0) { - - } else if(strcmp(elem->name, mappings.face_element) == 0) { - - } - PlyProperty* prop = elem->properties; while(prop != NULL) { if(prop->count == PLY_TYPE_INVALID) { @@ -313,6 +384,74 @@ PlyMesh ply_load_mesh(char* filename, PlyMappings mappings) { elem = elem->next; } + elem = elements_head; + while(elem != NULL) { + int type = -1; + if(strcmp(elem->name, mappings.vertex_element) == 0) { + type = 0; + mesh.position = malloc(sizeof(vec3)*elem->count); + mesh.colour = malloc(sizeof(vec4)*elem->count); + mesh.normal = malloc(sizeof(vec3)*elem->count); + mesh.uv = malloc(sizeof(vec2)*elem->count); + mesh.vertex_count = elem->count; + } else if(strcmp(elem->name, mappings.face_element) == 0) { + type = 1; + mesh.index_count = 3*elem->count; + mesh.index = malloc(3*elem->count*sizeof(uint16_t)); + } else { + continue; + } + + PlyProperty* prop = elem->properties; + while(prop != NULL) { + if(prop->count == PLY_TYPE_INVALID && type == 0) { + if(ply_map_values(prop->name, + 3, + elem->count, + prop->element, + sizeof(mappings.position)/sizeof(char*), + mappings.position, + prop->elements, + (float*)mesh.position)) { + } else if(ply_map_values(prop->name, + 4, + elem->count, + prop->element, + sizeof(mappings.colour)/sizeof(char*), + mappings.colour, + prop->elements, + (float*)mesh.colour)) { + } else if(ply_map_values(prop->name, + 3, + elem->count, + prop->element, + sizeof(mappings.normal)/sizeof(char*), + mappings.normal, + prop->elements, + (float*)mesh.normal)) { + } else if(ply_map_values(prop->name, + 2, + elem->count, + prop->element, + sizeof(mappings.texture)/sizeof(char*), + mappings.texture, + prop->elements, + (float*)mesh.uv)) { + } + } else if (prop->count != PLY_TYPE_INVALID && type == 1) { + for(int i = 0; i < elem->count; i++) { + int type_size = ply_type_sizes[prop->element]; + void ** lists = prop->elements; + mesh.index[i*3 + 0] = ply_conv_index(prop->element, lists[i] + (0*type_size), 0); + mesh.index[i*3 + 1] = ply_conv_index(prop->element, lists[i] + (1*type_size), 0); + mesh.index[i*3 + 2] = ply_conv_index(prop->element, lists[i] + (2*type_size), 0); + } + } + prop = prop->next; + } + elem = elem->next; + } + clean: ply_free_elements(elements_head); close: