|
|
|
@ -49,6 +49,14 @@ typedef struct AllocatedBufferStruct {
|
|
|
|
|
VkDeviceMemory memory;
|
|
|
|
|
} AllocatedBuffer;
|
|
|
|
|
|
|
|
|
|
typedef uint32_t PipelineIdx;
|
|
|
|
|
|
|
|
|
|
typedef struct MeshStruct {
|
|
|
|
|
AllocatedBuffer vertex_buffer;
|
|
|
|
|
AllocatedBuffer index_buffer;
|
|
|
|
|
PipelineIdx pipeline;
|
|
|
|
|
} Mesh;
|
|
|
|
|
|
|
|
|
|
typedef struct VulkanContextStruct {
|
|
|
|
|
VkInstance instance;
|
|
|
|
|
VkDebugUtilsMessengerEXT debug_messenger;
|
|
|
|
@ -80,21 +88,20 @@ typedef struct VulkanContextStruct {
|
|
|
|
|
VkSemaphore* render_finished_semaphores;
|
|
|
|
|
VkFence* in_flight_fences;
|
|
|
|
|
|
|
|
|
|
AllocatedBuffer* uniform_buffers;
|
|
|
|
|
void** uniform_buffer_ptrs;
|
|
|
|
|
VkDescriptorPool descriptor_pool;
|
|
|
|
|
VkDescriptorSet* descriptor_sets;
|
|
|
|
|
|
|
|
|
|
VkRenderPass render_pass;
|
|
|
|
|
|
|
|
|
|
VkCommandPool graphics_command_pool;
|
|
|
|
|
VkCommandPool transfer_command_pool;
|
|
|
|
|
|
|
|
|
|
VkDescriptorSetLayout triangle_descriptor_set;
|
|
|
|
|
VkPipelineLayout triangle_pipeline_layout;
|
|
|
|
|
VkPipeline triangle_pipeline;
|
|
|
|
|
AllocatedBuffer triangle_vertex_buffer;
|
|
|
|
|
AllocatedBuffer triangle_index_buffer;
|
|
|
|
|
VkDescriptorSetLayout mesh_descriptor_set_layout;
|
|
|
|
|
VkPipelineLayout mesh_pipeline_layout;
|
|
|
|
|
VkPipeline default_mesh_pipeline;
|
|
|
|
|
AllocatedBuffer* mesh_uniform_buffers;
|
|
|
|
|
void** mesh_uniform_buffer_ptrs;
|
|
|
|
|
VkDescriptorPool mesh_descriptor_pool;
|
|
|
|
|
VkDescriptorSet* mesh_descriptor_sets;
|
|
|
|
|
|
|
|
|
|
Mesh triangle_mesh;
|
|
|
|
|
|
|
|
|
|
uint32_t current_frame;
|
|
|
|
|
} VulkanContext;
|
|
|
|
@ -1326,6 +1333,34 @@ VkFence* create_fences(VkDevice device, VkFenceCreateFlags flags, uint32_t count
|
|
|
|
|
return fences;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Mesh load_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, PipelineIdx pipeline_index) {
|
|
|
|
|
Mesh mesh = {};
|
|
|
|
|
mesh.vertex_buffer.buffer = VK_NULL_HANDLE;
|
|
|
|
|
mesh.vertex_buffer.memory = VK_NULL_HANDLE;
|
|
|
|
|
mesh.index_buffer.buffer = VK_NULL_HANDLE;
|
|
|
|
|
mesh.index_buffer.memory = VK_NULL_HANDLE;
|
|
|
|
|
mesh.pipeline = 0xFFFFFFFF;
|
|
|
|
|
|
|
|
|
|
AllocatedBuffer vertex_buffer = create_populated_buffer(physical_device, 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 mesh;
|
|
|
|
|
} else {
|
|
|
|
|
mesh.vertex_buffer = vertex_buffer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AllocatedBuffer index_buffer = create_populated_buffer(physical_device, device, (void*)indices, sizeof(uint16_t) * index_count, transfer_pool, transfer_queue, VK_BUFFER_USAGE_INDEX_BUFFER_BIT);
|
|
|
|
|
if(index_buffer.memory == VK_NULL_HANDLE) {
|
|
|
|
|
AllocatedBuffer tmp = { .memory = VK_NULL_HANDLE, .buffer = VK_NULL_HANDLE};
|
|
|
|
|
mesh.vertex_buffer = tmp;
|
|
|
|
|
return mesh;
|
|
|
|
|
} else {
|
|
|
|
|
mesh.index_buffer = index_buffer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mesh.pipeline = pipeline_index;
|
|
|
|
|
return mesh;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) {
|
|
|
|
|
VulkanContext* context = (VulkanContext*)malloc(sizeof(VulkanContext));
|
|
|
|
|
|
|
|
|
@ -1483,19 +1518,19 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) {
|
|
|
|
|
context->in_flight_fences = if_fences;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AllocatedBuffer* uniform_buffers = allocate_buffers(context->physical_device, context->device, sizeof(struct ShaderUBO), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, max_frames_in_flight);
|
|
|
|
|
if(uniform_buffers == 0) {
|
|
|
|
|
AllocatedBuffer* mesh_uniform_buffers = allocate_buffers(context->physical_device, context->device, sizeof(struct ShaderUBO), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, max_frames_in_flight);
|
|
|
|
|
if(mesh_uniform_buffers == 0) {
|
|
|
|
|
fprintf(stderr, "failed to create vulkan uniform buffers\n");
|
|
|
|
|
return 0;
|
|
|
|
|
} else {
|
|
|
|
|
context->uniform_buffers = uniform_buffers;
|
|
|
|
|
context->uniform_buffer_ptrs = malloc(sizeof(void*)*max_frames_in_flight);
|
|
|
|
|
if(context->uniform_buffer_ptrs == 0) {
|
|
|
|
|
context->mesh_uniform_buffers = mesh_uniform_buffers;
|
|
|
|
|
context->mesh_uniform_buffer_ptrs = malloc(sizeof(void*)*max_frames_in_flight);
|
|
|
|
|
if(context->mesh_uniform_buffer_ptrs == 0) {
|
|
|
|
|
fprintf(stderr, "failed to allocate cpu pointers for uniform buffers\n");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
for(uint32_t i = 0; i < max_frames_in_flight; i++) {
|
|
|
|
|
VkResult result = vkMapMemory(context->device, context->uniform_buffers[i].memory, 0, sizeof(struct ShaderUBO), 0, &context->uniform_buffer_ptrs[i]);
|
|
|
|
|
VkResult result = vkMapMemory(context->device, context->mesh_uniform_buffers[i].memory, 0, sizeof(struct ShaderUBO), 0, &context->mesh_uniform_buffer_ptrs[i]);
|
|
|
|
|
if(result != VK_SUCCESS) {
|
|
|
|
|
fprintf(stderr, "failed to map cpu pointer for uniform buffer\n");
|
|
|
|
|
return 0;
|
|
|
|
@ -1503,58 +1538,51 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VkDescriptorPool descriptor_pool = create_descriptor_pool(context->device, max_frames_in_flight);
|
|
|
|
|
if(descriptor_pool == VK_NULL_HANDLE) {
|
|
|
|
|
VkDescriptorPool mesh_descriptor_pool = create_descriptor_pool(context->device, max_frames_in_flight);
|
|
|
|
|
if(mesh_descriptor_pool == VK_NULL_HANDLE) {
|
|
|
|
|
fprintf(stderr, "failed to create vulkan descriptor pool\n");
|
|
|
|
|
return 0;
|
|
|
|
|
} else {
|
|
|
|
|
context->descriptor_pool = descriptor_pool;
|
|
|
|
|
context->mesh_descriptor_pool = mesh_descriptor_pool;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VkDescriptorSetLayout triangle_descriptor_set = create_descriptor_set_layout(device);
|
|
|
|
|
if(triangle_descriptor_set == VK_NULL_HANDLE) {
|
|
|
|
|
VkDescriptorSetLayout mesh_descriptor_set_layout = create_descriptor_set_layout(device);
|
|
|
|
|
if(mesh_descriptor_set_layout == VK_NULL_HANDLE) {
|
|
|
|
|
fprintf(stderr, "failed to create vulkan descriptor set layout\n");
|
|
|
|
|
return 0;
|
|
|
|
|
} else {
|
|
|
|
|
context->triangle_descriptor_set = triangle_descriptor_set;
|
|
|
|
|
context->mesh_descriptor_set_layout = mesh_descriptor_set_layout;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VkDescriptorSet* descriptor_sets = create_descriptor_sets(context->device, context->triangle_descriptor_set, context->descriptor_pool, context->uniform_buffers, max_frames_in_flight);
|
|
|
|
|
if(descriptor_sets == 0) {
|
|
|
|
|
VkDescriptorSet* mesh_descriptor_sets = create_descriptor_sets(context->device, context->mesh_descriptor_set_layout, context->mesh_descriptor_pool, context->mesh_uniform_buffers, max_frames_in_flight);
|
|
|
|
|
if(mesh_descriptor_sets == 0) {
|
|
|
|
|
fprintf(stderr, "failed to create vulkan descriptor sets\n");
|
|
|
|
|
return 0;
|
|
|
|
|
} else {
|
|
|
|
|
context->descriptor_sets = descriptor_sets;
|
|
|
|
|
context->mesh_descriptor_sets = mesh_descriptor_sets;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VkPipelineLayout triangle_pipeline_layout = create_pipeline_layout(device, 1, &context->triangle_descriptor_set, 0, 0);
|
|
|
|
|
if(triangle_pipeline_layout == VK_NULL_HANDLE) {
|
|
|
|
|
VkPipelineLayout mesh_pipeline_layout = create_pipeline_layout(device, 1, &context->mesh_descriptor_set_layout, 0, 0);
|
|
|
|
|
if(mesh_pipeline_layout == VK_NULL_HANDLE) {
|
|
|
|
|
fprintf(stderr, "failed to create vulkan pipeline layout\n");
|
|
|
|
|
return 0;
|
|
|
|
|
} else {
|
|
|
|
|
context->triangle_pipeline_layout = triangle_pipeline_layout;
|
|
|
|
|
context->mesh_pipeline_layout = mesh_pipeline_layout;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VkPipeline triangle_pipeline = create_graphics_pipeline(context->device, context->swapchain_extent, context->triangle_pipeline_layout, context->render_pass);
|
|
|
|
|
if(triangle_pipeline == VK_NULL_HANDLE) {
|
|
|
|
|
VkPipeline default_mesh_pipeline = create_graphics_pipeline(context->device, context->swapchain_extent, context->mesh_pipeline_layout, context->render_pass);
|
|
|
|
|
if(default_mesh_pipeline == VK_NULL_HANDLE) {
|
|
|
|
|
fprintf(stderr, "failed to create vulkan graphics pipeline\n");
|
|
|
|
|
return 0;
|
|
|
|
|
} else {
|
|
|
|
|
context->triangle_pipeline = triangle_pipeline;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AllocatedBuffer triangle_vertex_buffer = create_populated_buffer(context->physical_device, context->device, (void*)vertices, sizeof(vertices), context->transfer_command_pool, context->queues.transfer, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
|
|
|
|
|
if(triangle_vertex_buffer.memory == VK_NULL_HANDLE) {
|
|
|
|
|
fprintf(stderr, "failed to allocate vulkan buffer for triangle buffer\n");
|
|
|
|
|
} else {
|
|
|
|
|
context->triangle_vertex_buffer = triangle_vertex_buffer;
|
|
|
|
|
context->default_mesh_pipeline = default_mesh_pipeline;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AllocatedBuffer triangle_index_buffer = create_populated_buffer(context->physical_device, context->device, (void*)indices, sizeof(indices), context->transfer_command_pool, context->queues.transfer, VK_BUFFER_USAGE_INDEX_BUFFER_BIT);
|
|
|
|
|
if(triangle_index_buffer.memory == VK_NULL_HANDLE) {
|
|
|
|
|
fprintf(stderr, "failed to allocate vulkan buffer for triangle buffer\n");
|
|
|
|
|
Mesh triangle_mesh = load_mesh(context->physical_device, context->device, (struct Vertex*)vertices, 4, (uint16_t*)indices, 6, context->transfer_command_pool, context->queues.transfer, 0x00000000);
|
|
|
|
|
if(triangle_mesh.vertex_buffer.buffer == VK_NULL_HANDLE) {
|
|
|
|
|
fprintf(stderr, "failed to load triangle mesh\n");
|
|
|
|
|
} else {
|
|
|
|
|
context->triangle_index_buffer = triangle_index_buffer;
|
|
|
|
|
context->triangle_mesh = triangle_mesh;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return context;
|
|
|
|
@ -1572,7 +1600,7 @@ VkResult update_ubo(void** buffers, uint32_t frame_index) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VkResult draw_frame(VulkanContext* context) {
|
|
|
|
|
update_ubo(context->uniform_buffer_ptrs, context->current_frame);
|
|
|
|
|
update_ubo(context->mesh_uniform_buffer_ptrs, context->current_frame);
|
|
|
|
|
|
|
|
|
|
VkResult result;
|
|
|
|
|
result = vkWaitForFences(context->device, 1, &context->in_flight_fences[context->current_frame], VK_TRUE, UINT64_MAX);
|
|
|
|
@ -1596,7 +1624,7 @@ VkResult draw_frame(VulkanContext* context) {
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
result = record_command_buffer_triangle(context->swapchain_command_buffers[context->current_frame], image_index, context->render_pass, context->swapchain_framebuffers, context->swapchain_extent, context->triangle_pipeline, context->triangle_pipeline_layout, context->descriptor_sets[context->current_frame], context->triangle_vertex_buffer.buffer, context->triangle_index_buffer.buffer, 6);
|
|
|
|
|
result = record_command_buffer_triangle(context->swapchain_command_buffers[context->current_frame], image_index, context->render_pass, context->swapchain_framebuffers, context->swapchain_extent, context->default_mesh_pipeline, context->mesh_pipeline_layout, context->mesh_descriptor_sets[context->current_frame], context->triangle_mesh.vertex_buffer.buffer, context->triangle_mesh.index_buffer.buffer, 6);
|
|
|
|
|
if(result != VK_SUCCESS) {
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|