Fixed vulkan validation warnings\n

main
noah metz 2024-01-11 17:32:10 -07:00
parent 7043b478fe
commit 81c1c83b18
1 changed files with 111 additions and 118 deletions

@ -144,12 +144,6 @@ typedef struct MaterialStruct {
Map object_descriptor_mappings; Map object_descriptor_mappings;
} Material; } Material;
typedef struct MemoryIndicesStruct {
uint32_t host_visible;
uint32_t device_local;
uint32_t device_lazy;
} MemoryIndices;
typedef struct VulkanContextStruct { typedef struct VulkanContextStruct {
VkInstance instance; VkInstance instance;
VkDebugUtilsMessengerEXT debug_messenger; VkDebugUtilsMessengerEXT debug_messenger;
@ -194,7 +188,8 @@ typedef struct VulkanContextStruct {
uint32_t current_frame; uint32_t current_frame;
MemoryIndices memory_indices; VkPhysicalDeviceMemoryProperties memories;
VkCommandPool extra_graphics_pool;
} VulkanContext; } VulkanContext;
typedef struct SceneContextStruct { typedef struct SceneContextStruct {
@ -269,6 +264,17 @@ void glfw_error(int error, const char* description) {
fprintf(stderr, "GLFW_ERR: 0x%02x - %s\n", error, description); fprintf(stderr, "GLFW_ERR: 0x%02x - %s\n", error, description);
} }
uint32_t pick_memory(VkPhysicalDeviceMemoryProperties properties, uint32_t filter, VkMemoryPropertyFlags include, VkMemoryPropertyFlags exclude) {
for(uint32_t i = 0; i < properties.memoryTypeCount; i++){
if((filter & (1 << i))
&& ((include & properties.memoryTypes[i].propertyFlags) == include)
&& ((exclude & properties.memoryTypes[i].propertyFlags) == 0)) {
return i;
}
}
return 0xFFFFFFFF;
}
GLFWwindow* init_window(int width, int height) { GLFWwindow* init_window(int width, int height) {
glfwInit(); glfwInit();
glfwSetErrorCallback(glfw_error); glfwSetErrorCallback(glfw_error);
@ -864,7 +870,7 @@ VkFramebuffer* create_swapchain_framebuffers(VkDevice device, uint32_t image_cou
VkShaderModule create_shader_module(VkDevice device, const char * code, uint32_t code_size) { VkShaderModule create_shader_module(VkDevice device, const char * code, uint32_t code_size) {
VkShaderModuleCreateInfo shader_info = {}; VkShaderModuleCreateInfo shader_info = {};
shader_info.sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT; shader_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
shader_info.codeSize = code_size; shader_info.codeSize = code_size;
shader_info.pCode = (uint32_t*)code; shader_info.pCode = (uint32_t*)code;
@ -968,18 +974,7 @@ VkRenderPass create_render_pass(VkDevice device, VkSurfaceFormatKHR format, VkFo
return render_pass; return render_pass;
} }
uint32_t pick_memory_type(VkPhysicalDeviceMemoryProperties memories, uint32_t filter, VkMemoryPropertyFlags flags) { AllocatedImage allocate_image(VkPhysicalDeviceMemoryProperties memories, VkDevice device, VkImageType type, VkFormat format, VkExtent3D size, VkImageUsageFlags usage, VkMemoryPropertyFlags include, VkMemoryPropertyFlags exclude) {
for(uint32_t i = 0; i < memories.memoryTypeCount; i++) {
if((filter & (1 << i))
&& ((memories.memoryTypes[i].propertyFlags & flags) == flags)) {
return i;
}
}
return 0xFFFFFFFF;
}
AllocatedImage allocate_image(uint32_t memory_index, VkDevice device, VkImageType type, VkFormat format, VkExtent3D size, VkImageUsageFlags usage) {
VkImageCreateInfo image_info = { VkImageCreateInfo image_info = {
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
.imageType = type, .imageType = type,
@ -1010,7 +1005,7 @@ AllocatedImage allocate_image(uint32_t memory_index, VkDevice device, VkImageTyp
VkMemoryAllocateInfo memory_info = { VkMemoryAllocateInfo memory_info = {
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
.allocationSize = memory_requirements.size, .allocationSize = memory_requirements.size,
.memoryTypeIndex = memory_index, .memoryTypeIndex = pick_memory(memories, memory_requirements.memoryTypeBits, include, exclude),
}; };
result = vkAllocateMemory(device, &memory_info, 0, &allocated.memory); result = vkAllocateMemory(device, &memory_info, 0, &allocated.memory);
@ -1033,7 +1028,7 @@ AllocatedImage allocate_image(uint32_t memory_index, VkDevice device, VkImageTyp
return allocated; return allocated;
} }
AllocatedBuffer allocate_buffer(uint32_t memory_index, VkDevice device, VkDeviceSize size, VkBufferUsageFlags usage) { AllocatedBuffer allocate_buffer(VkPhysicalDeviceMemoryProperties memories, VkDevice device, VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags include, VkMemoryPropertyFlags exclude) {
AllocatedBuffer ret = {}; AllocatedBuffer ret = {};
ret.memory = VK_NULL_HANDLE; ret.memory = VK_NULL_HANDLE;
ret.buffer = VK_NULL_HANDLE; ret.buffer = VK_NULL_HANDLE;
@ -1058,7 +1053,7 @@ AllocatedBuffer allocate_buffer(uint32_t memory_index, VkDevice device, VkDevice
VkMemoryAllocateInfo alloc_info = {}; VkMemoryAllocateInfo alloc_info = {};
alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
alloc_info.allocationSize = memory_requirements.size; alloc_info.allocationSize = memory_requirements.size;
alloc_info.memoryTypeIndex = memory_index; alloc_info.memoryTypeIndex = pick_memory(memories, memory_requirements.memoryTypeBits, include, exclude);
result = vkAllocateMemory(device, &alloc_info, 0, &ret.memory); result = vkAllocateMemory(device, &alloc_info, 0, &ret.memory);
if(result != VK_SUCCESS) { if(result != VK_SUCCESS) {
@ -1089,14 +1084,14 @@ void deallocate_image(VkDevice device, AllocatedImage image) {
vkFreeMemory(device, image.memory, 0); vkFreeMemory(device, image.memory, 0);
}; };
AllocatedBuffer* allocate_buffers(uint32_t memory_index, VkDevice device, VkDeviceSize size, VkBufferUsageFlags usage, uint32_t count) { AllocatedBuffer* allocate_buffers(VkPhysicalDeviceMemoryProperties memories, VkDevice device, VkDeviceSize size, VkBufferUsageFlags usage, uint32_t count, VkMemoryPropertyFlags include, VkMemoryPropertyFlags exclude) {
AllocatedBuffer* buffers = malloc(sizeof(AllocatedBuffer)*count); AllocatedBuffer* buffers = malloc(sizeof(AllocatedBuffer)*count);
if(buffers == 0) { if(buffers == 0) {
return 0; return 0;
} }
for(uint32_t i = 0; i < count; i++) { for(uint32_t i = 0; i < count; i++) {
buffers[i] = allocate_buffer(memory_index, device, size, usage); buffers[i] = allocate_buffer(memories, device, size, usage, include, exclude);
if(buffers[i].memory == VK_NULL_HANDLE) { if(buffers[i].memory == VK_NULL_HANDLE) {
for(uint32_t j = 0; j < i; j++) { for(uint32_t j = 0; j < i; j++) {
deallocate_buffer(device, buffers[i]); deallocate_buffer(device, buffers[i]);
@ -1137,12 +1132,18 @@ VkCommandBuffer command_begin_single(VkDevice device, VkCommandPool transfer_poo
} }
VkResult command_end_single(VkDevice device, VkCommandBuffer command_buffer, VkCommandPool transfer_pool, VkQueue transfer_queue) { VkResult command_end_single(VkDevice device, VkCommandBuffer command_buffer, VkCommandPool transfer_pool, VkQueue transfer_queue) {
VkResult result = vkEndCommandBuffer(command_buffer);
if(result != VK_SUCCESS) {
vkFreeCommandBuffers(device, transfer_pool, 1, &command_buffer);
return result;
}
VkSubmitInfo submit_info = {}; VkSubmitInfo submit_info = {};
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submit_info.commandBufferCount = 1; submit_info.commandBufferCount = 1;
submit_info.pCommandBuffers = &command_buffer; submit_info.pCommandBuffers = &command_buffer;
VkResult result = vkQueueSubmit(transfer_queue, 1, &submit_info, 0); result = vkQueueSubmit(transfer_queue, 1, &submit_info, 0);
if(result != VK_SUCCESS) { if(result != VK_SUCCESS) {
vkFreeCommandBuffers(device, transfer_pool, 1, &command_buffer); vkFreeCommandBuffers(device, transfer_pool, 1, &command_buffer);
return result; return result;
@ -1162,24 +1163,19 @@ VkResult command_copy_buffers(VkDevice device, VkCommandPool transfer_pool, VkQu
copy_region.size = size; copy_region.size = size;
vkCmdCopyBuffer(command_buffer, source, dest, 1, &copy_region); vkCmdCopyBuffer(command_buffer, source, dest, 1, &copy_region);
VkResult result = vkEndCommandBuffer(command_buffer);
if(result != VK_SUCCESS) {
vkFreeCommandBuffers(device, transfer_pool, 1, &command_buffer);
return result;
}
return command_end_single(device, command_buffer, transfer_pool, transfer_queue); return command_end_single(device, command_buffer, transfer_pool, transfer_queue);
} }
VkResult command_transition_image_layout(VkDevice device, VkCommandPool transfer_pool, VkQueue transfer_queue, VkImageLayout old_layout, VkImageLayout new_layout, VkImage image) { VkResult command_transition_image_layout(VkDevice device, VkCommandPool transfer_pool, VkQueue transfer_queue, VkImageLayout old_layout, VkImageLayout new_layout, VkImage image, VkAccessFlags src_mask, VkAccessFlags dst_mask, VkPipelineStageFlags source, VkPipelineStageFlags dest, uint32_t source_family, uint32_t dest_family) {
VkCommandBuffer command_buffer = command_begin_single(device, transfer_pool); VkCommandBuffer command_buffer = command_begin_single(device, transfer_pool);
VkImageMemoryBarrier barrier = { VkImageMemoryBarrier barrier = {
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
.oldLayout = old_layout, .oldLayout = old_layout,
.newLayout = new_layout, .newLayout = new_layout,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .srcQueueFamilyIndex = source_family,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = dest_family,
.image = image, .image = image,
.subresourceRange = { .subresourceRange = {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
@ -1188,10 +1184,10 @@ VkResult command_transition_image_layout(VkDevice device, VkCommandPool transfer
.baseMipLevel = 0, .baseMipLevel = 0,
.baseArrayLayer = 0, .baseArrayLayer = 0,
}, },
.srcAccessMask = 0, .srcAccessMask = src_mask,
.dstAccessMask = 0, .dstAccessMask = dst_mask,
}; };
vkCmdPipelineBarrier(command_buffer, 0, 0, 0, 0, 0, 0, 0, 1, &barrier); vkCmdPipelineBarrier(command_buffer, source, dest, 0, 0, 0, 0, 0, 1, &barrier);
return command_end_single(device, command_buffer, transfer_pool, transfer_queue); return command_end_single(device, command_buffer, transfer_pool, transfer_queue);
} }
@ -1222,10 +1218,10 @@ VkResult command_copy_buffer_to_image(VkDevice device, VkCommandPool transfer_po
return command_end_single(device, command_buffer, transfer_pool, transfer_queue); return command_end_single(device, command_buffer, transfer_pool, transfer_queue);
} }
AllocatedBuffer create_populated_buffer(MemoryIndices memories, VkDevice device, void* data, VkDeviceSize size, VkCommandPool transfer_pool, VkQueue transfer_queue, VkBufferUsageFlags usage) { AllocatedBuffer create_populated_buffer(VkPhysicalDeviceMemoryProperties memories, VkDevice device, void* data, VkDeviceSize size, VkCommandPool transfer_pool, VkQueue transfer_queue, VkBufferUsageFlags usage) {
AllocatedBuffer staging_buffer = {}; AllocatedBuffer staging_buffer = {};
AllocatedBuffer vertex_buffer = {}; AllocatedBuffer vertex_buffer = {};
staging_buffer = allocate_buffer(memories.host_visible, device, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT); 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);
if(staging_buffer.memory == VK_NULL_HANDLE) { if(staging_buffer.memory == VK_NULL_HANDLE) {
return vertex_buffer; return vertex_buffer;
} }
@ -1242,7 +1238,7 @@ AllocatedBuffer create_populated_buffer(MemoryIndices memories, VkDevice device,
vkUnmapMemory(device, staging_buffer.memory); vkUnmapMemory(device, staging_buffer.memory);
vertex_buffer = allocate_buffer(memories.device_local, device, size, VK_BUFFER_USAGE_TRANSFER_DST_BIT | usage); vertex_buffer = allocate_buffer(memories, device, size, VK_BUFFER_USAGE_TRANSFER_DST_BIT | usage, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT);
if(vertex_buffer.memory == VK_NULL_HANDLE) { if(vertex_buffer.memory == VK_NULL_HANDLE) {
deallocate_buffer(device, staging_buffer); deallocate_buffer(device, staging_buffer);
return vertex_buffer; return vertex_buffer;
@ -1260,7 +1256,7 @@ AllocatedBuffer create_populated_buffer(MemoryIndices memories, VkDevice device,
return vertex_buffer; return vertex_buffer;
} }
Texture load_texture(MemoryIndices memories, VkDevice device, VkCommandPool transfer_pool, VkQueue transfer_queue, VkExtent2D size, uint32_t stride, VkFormat format, void* image_data){ Texture load_texture(VkPhysicalDeviceMemoryProperties memories, VkDevice device, VkCommandPool transfer_pool, VkQueue transfer_queue, VkCommandPool graphics_pool, VkQueue graphics_queue, VkExtent2D size, uint32_t stride, VkFormat format, void* image_data, uint32_t transfer_family, uint32_t graphics_family){
Texture ret = { Texture ret = {
.image.image = VK_NULL_HANDLE, .image.image = VK_NULL_HANDLE,
.image.memory = VK_NULL_HANDLE, .image.memory = VK_NULL_HANDLE,
@ -1268,7 +1264,7 @@ Texture load_texture(MemoryIndices memories, VkDevice device, VkCommandPool tran
}; };
uint32_t image_size = size.width * size.height * stride; uint32_t image_size = size.width * size.height * stride;
AllocatedBuffer staging = allocate_buffer(memories.host_visible, device, image_size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT); 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);
if(staging.memory == VK_NULL_HANDLE) { if(staging.memory == VK_NULL_HANDLE) {
return ret; return ret;
} }
@ -1289,14 +1285,14 @@ Texture load_texture(MemoryIndices memories, VkDevice device, VkCommandPool tran
.height = size.height, .height = size.height,
.depth = 1, .depth = 1,
}; };
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); 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, 0);
if(image.memory == VK_NULL_HANDLE) { if(image.memory == VK_NULL_HANDLE) {
deallocate_buffer(device, staging); deallocate_buffer(device, staging);
deallocate_image(device, image); deallocate_image(device, image);
return ret; return ret;
} }
result = command_transition_image_layout(device, transfer_pool, transfer_queue, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, image.image); result = command_transition_image_layout(device, transfer_pool, transfer_queue, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, image.image, 0, VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, transfer_family, transfer_family);
if(result != VK_SUCCESS) { if(result != VK_SUCCESS) {
deallocate_buffer(device, staging); deallocate_buffer(device, staging);
deallocate_image(device, image); deallocate_image(device, image);
@ -1310,6 +1306,20 @@ Texture load_texture(MemoryIndices memories, VkDevice device, VkCommandPool tran
return ret; return ret;
} }
result = command_transition_image_layout(device, transfer_pool, transfer_queue, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, image.image, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, transfer_family, graphics_family);
if(result != VK_SUCCESS) {
deallocate_buffer(device, staging);
deallocate_image(device, image);
return ret;
}
result = command_transition_image_layout(device, graphics_pool, graphics_queue, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, image.image, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, transfer_family, graphics_family);
if(result != VK_SUCCESS) {
deallocate_buffer(device, staging);
deallocate_image(device, image);
return ret;
}
VkImageView view; VkImageView view;
VkImageViewCreateInfo view_info = { VkImageViewCreateInfo view_info = {
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
@ -1491,6 +1501,7 @@ VkPipeline create_graphics_pipeline(
pipeline_info.pColorBlendState = &color_blend_info; pipeline_info.pColorBlendState = &color_blend_info;
pipeline_info.pDynamicState = &dynamic_info; pipeline_info.pDynamicState = &dynamic_info;
pipeline_info.pDepthStencilState = &depth_info; pipeline_info.pDepthStencilState = &depth_info;
pipeline_info.pMultisampleState = &multisample_info;
pipeline_info.layout = layout; pipeline_info.layout = layout;
pipeline_info.renderPass = render_pass; pipeline_info.renderPass = render_pass;
pipeline_info.subpass = 0; pipeline_info.subpass = 0;
@ -1507,21 +1518,6 @@ VkPipeline create_graphics_pipeline(
return pipeline; return pipeline;
} }
VkCommandPool create_command_pool(VkDevice device, uint32_t queue_family) {
VkCommandPoolCreateInfo pool_info = {};
pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
pool_info.queueFamilyIndex = queue_family;
VkCommandPool command_pool;
VkResult result = vkCreateCommandPool(device, &pool_info, 0, &command_pool);
if(result != VK_SUCCESS) {
return VK_NULL_HANDLE;
}
return command_pool;
}
int create_depth_image(VulkanContext* context) { int create_depth_image(VulkanContext* context) {
VkExtent3D depth_extent = { VkExtent3D depth_extent = {
.width = context->swapchain_extent.width, .width = context->swapchain_extent.width,
@ -1538,7 +1534,7 @@ int create_depth_image(VulkanContext* context) {
.format = context->depth_format, .format = context->depth_format,
.tiling = VK_IMAGE_TILING_OPTIMAL, .tiling = VK_IMAGE_TILING_OPTIMAL,
.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, .usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE, .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
.samples = VK_SAMPLE_COUNT_1_BIT, .samples = VK_SAMPLE_COUNT_1_BIT,
.flags = 0, .flags = 0,
@ -1559,7 +1555,7 @@ int create_depth_image(VulkanContext* context) {
VkMemoryAllocateInfo depth_memory_info = { VkMemoryAllocateInfo depth_memory_info = {
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
.allocationSize = depth_image_requirements.size, .allocationSize = depth_image_requirements.size,
.memoryTypeIndex = context->memory_indices.device_lazy, .memoryTypeIndex = pick_memory(context->memories, depth_image_requirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT, 0),
}; };
VkDeviceMemory depth_image_memory; VkDeviceMemory depth_image_memory;
@ -1831,7 +1827,7 @@ VkFence* create_fences(VkDevice device, VkFenceCreateFlags flags, uint32_t count
return fences; return fences;
} }
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) { 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) {
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); 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) { if(vertex_buffer.memory == VK_NULL_HANDLE) {
return 0; return 0;
@ -1938,7 +1934,7 @@ Object create_renderable(Mesh* mesh, Material* material, uint32_t descriptor_set
return object; return object;
} }
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) { 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) {
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); 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) { if(vertex_buffer.memory == VK_NULL_HANDLE) {
return 0; return 0;
@ -2105,16 +2101,21 @@ Material create_material(
Material create_simple_mesh_material(VkDevice device, VkExtent2D extent, VkRenderPass render_pass, VkDescriptorSetLayout scene_ubo_layout, uint32_t max_frames_in_flight) { Material create_simple_mesh_material(VkDevice device, VkExtent2D extent, VkRenderPass render_pass, VkDescriptorSetLayout scene_ubo_layout, uint32_t max_frames_in_flight) {
VkShaderModule vert_shader = load_shader_file(2048, "shader_src/basic.vert.spv", device); VkShaderModule vert_shader = load_shader_file(2048, "shader_src/basic.vert.spv", device);
VkShaderModule frag_shader = load_shader_file(2048, "shader_src/basic.frag.spv", device); VkShaderModule frag_shader = load_shader_file(2048, "shader_src/basic.frag.spv", device);
VkPipelineShaderStageCreateInfo shader_stages[2] = {}; VkPipelineShaderStageCreateInfo shader_stages[2] = {
shader_stages[0].sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT; {
shader_stages[0].stage = VK_SHADER_STAGE_VERTEX_BIT; .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
shader_stages[0].module = vert_shader; .stage = VK_SHADER_STAGE_VERTEX_BIT,
shader_stages[0].pName = "main"; .module = vert_shader,
.pName = "main",
},
{
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
.stage = VK_SHADER_STAGE_FRAGMENT_BIT,
.module = frag_shader,
.pName = "main",
},
};
shader_stages[1].sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT;
shader_stages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
shader_stages[1].module = frag_shader;
shader_stages[1].pName = "main";
VkVertexInputBindingDescription bindings[1] = { VkVertexInputBindingDescription bindings[1] = {
{ {
@ -2200,13 +2201,13 @@ Material create_texture_mesh_material(VkDevice device, VkExtent2D extent, VkRend
} }
VkPipelineShaderStageCreateInfo shader_stages[2] = { VkPipelineShaderStageCreateInfo shader_stages[2] = {
{ {
.sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT, .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
.stage = VK_SHADER_STAGE_VERTEX_BIT, .stage = VK_SHADER_STAGE_VERTEX_BIT,
.module = vert_shader, .module = vert_shader,
.pName = "main", .pName = "main",
}, },
{ {
.sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT, .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
.stage = VK_SHADER_STAGE_FRAGMENT_BIT, .stage = VK_SHADER_STAGE_FRAGMENT_BIT,
.module = frag_shader, .module = frag_shader,
.pName = "main", .pName = "main",
@ -2325,35 +2326,7 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) {
context->physical_device = physical_device; context->physical_device = physical_device;
} }
VkPhysicalDeviceMemoryProperties memories; vkGetPhysicalDeviceMemoryProperties(context->physical_device, &context->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; VkSurfaceKHR surface;
VkResult result = glfwCreateWindowSurface(instance, window, 0, &surface); VkResult result = glfwCreateWindowSurface(instance, window, 0, &surface);
@ -2454,16 +2427,28 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) {
context->swapchain_framebuffers = framebuffers; context->swapchain_framebuffers = framebuffers;
} }
VkCommandPool graphics_command_pool = create_command_pool(context->device, context->queue_indices.graphics_family); VkCommandPoolCreateInfo graphics_pool_info = {
if(graphics_command_pool == VK_NULL_HANDLE) { .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
.queueFamilyIndex = context->queue_indices.graphics_family,
};
VkCommandPool graphics_command_pool;
result = vkCreateCommandPool(context->device, &graphics_pool_info, 0, &graphics_command_pool);
if(result != VK_SUCCESS) {
fprintf(stderr, "failed to create vulkan graphics command pool"); fprintf(stderr, "failed to create vulkan graphics command pool");
return 0; return 0;
} else { } else {
context->graphics_command_pool = graphics_command_pool; context->graphics_command_pool = graphics_command_pool;
} }
VkCommandPool transfer_command_pool = create_command_pool(context->device, context->queue_indices.transfer_family); VkCommandPoolCreateInfo transfer_pool_info = {
if(transfer_command_pool == VK_NULL_HANDLE) { .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,
.queueFamilyIndex = context->queue_indices.transfer_family,
};
VkCommandPool transfer_command_pool;
result = vkCreateCommandPool(context->device, &transfer_pool_info, 0, &transfer_command_pool);
if(result != VK_SUCCESS) {
fprintf(stderr, "failed to create vulkan transfer command pool"); fprintf(stderr, "failed to create vulkan transfer command pool");
return 0; return 0;
} else { } else {
@ -2480,6 +2465,14 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) {
context->swapchain_command_buffers = swapchain_command_buffers; context->swapchain_command_buffers = swapchain_command_buffers;
} }
VkCommandPoolCreateInfo extra_pool_info = {
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
.queueFamilyIndex = context->queue_indices.graphics_family,
.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,
};
result = vkCreateCommandPool(context->device, &extra_pool_info, 0, &context->extra_graphics_pool);
VkSemaphore* ia_semaphores = create_semaphores(context->device, 0, max_frames_in_flight); VkSemaphore* ia_semaphores = create_semaphores(context->device, 0, max_frames_in_flight);
if(ia_semaphores == 0) { if(ia_semaphores == 0) {
fprintf(stderr, "failed to create vulkan image available semaphores\n"); fprintf(stderr, "failed to create vulkan image available semaphores\n");
@ -2507,7 +2500,7 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) {
return context; return context;
} }
SceneContext create_scene_context(VkDevice device, MemoryIndices memories, uint32_t max_frames_in_flight) { SceneContext create_scene_context(VkDevice device, VkPhysicalDeviceMemoryProperties memories, uint32_t max_frames_in_flight) {
SceneContext ret = { SceneContext ret = {
.pool = VK_NULL_HANDLE, .pool = VK_NULL_HANDLE,
.descriptor_layout = VK_NULL_HANDLE, .descriptor_layout = VK_NULL_HANDLE,
@ -2577,7 +2570,7 @@ SceneContext create_scene_context(VkDevice device, MemoryIndices memories, uint3
} }
VkDescriptorSetAllocateInfo set_alloc_info = { VkDescriptorSetAllocateInfo set_alloc_info = {
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
.descriptorPool = pool, .descriptorPool = pool,
.descriptorSetCount = max_frames_in_flight, .descriptorSetCount = max_frames_in_flight,
.pSetLayouts = layouts, .pSetLayouts = layouts,
@ -2591,7 +2584,7 @@ SceneContext create_scene_context(VkDevice device, MemoryIndices memories, uint3
return ret; return ret;
} }
AllocatedBuffer* ubos = allocate_buffers(memories.host_visible, device, sizeof(struct SceneUBO), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, max_frames_in_flight); AllocatedBuffer* ubos = allocate_buffers(memories, device, sizeof(struct SceneUBO), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, max_frames_in_flight, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
if(ubos == 0) { if(ubos == 0) {
free(layouts); free(layouts);
free(sets); free(sets);
@ -2940,7 +2933,7 @@ VkResult draw_frame(VulkanContext* context, SceneContext* scene, uint32_t materi
return vkQueuePresentKHR(context->queues.present, &present_info); return vkQueuePresentKHR(context->queues.present, &present_info);
} }
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 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 zero = {}; Object zero = {};
Mesh* mesh = load_simple_mesh(memories, device, (struct Vertex*)vertices, 4, (uint16*)indices, 6, transfer_pool, transfer_queue); Mesh* mesh = load_simple_mesh(memories, device, (struct Vertex*)vertices, 4, (uint16*)indices, 6, transfer_pool, transfer_queue);
@ -2995,7 +2988,7 @@ Object create_simple_mesh_object(Material* simple_mesh_material, MemoryIndices m
return zero; return zero;
} }
AllocatedBuffer* position_buffers = allocate_buffers(memories.host_visible, device, sizeof(struct ModelUBO), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, max_frames_in_flight); AllocatedBuffer* position_buffers = allocate_buffers(memories, device, sizeof(struct ModelUBO), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, max_frames_in_flight, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
if(position_buffers == 0) { if(position_buffers == 0) {
return zero; return zero;
} }
@ -3034,7 +3027,7 @@ Object create_simple_mesh_object(Material* simple_mesh_material, MemoryIndices m
return object; return object;
} }
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 create_texture_mesh_object(Material* texture_mesh_material, VkPhysicalDeviceMemoryProperties memories, VkDevice device, VkCommandPool transfer_pool, VkQueue transfer_queue, VkCommandPool graphics_pool, VkQueue graphics_queue, uint32_t max_frames_in_flight, VkDescriptorPool pool, uint32_t transfer_family, uint32_t graphics_family) {
Object zero = {}; Object zero = {};
Mesh* mesh = load_texture_mesh(memories, device, (struct TextureVertex*)texture_vertices, 4, (uint16_t*)indices, 6, transfer_pool, transfer_queue); Mesh* mesh = load_texture_mesh(memories, device, (struct TextureVertex*)texture_vertices, 4, (uint16_t*)indices, 6, transfer_pool, transfer_queue);
@ -3089,7 +3082,7 @@ Object create_texture_mesh_object(Material* texture_mesh_material, MemoryIndices
return zero; return zero;
} }
AllocatedBuffer* ubos = allocate_buffers(memories.host_visible, device, sizeof(struct ModelUBO), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, max_frames_in_flight); AllocatedBuffer* ubos = allocate_buffers(memories, device, sizeof(struct ModelUBO), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, max_frames_in_flight, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
if(ubos == 0) { if(ubos == 0) {
return zero; return zero;
} }
@ -3156,7 +3149,7 @@ Object create_texture_mesh_object(Material* texture_mesh_material, MemoryIndices
RED, WHT, GRN, WHT, BLU, WHT, RED, WHT, GRN, BLK, RED, WHT, GRN, WHT, BLU, WHT, RED, WHT, GRN, BLK,
}; };
Texture test_texture = load_texture(memories, device, transfer_pool, transfer_queue, texture_size, 4, VK_FORMAT_R8G8B8A8_SRGB, texture_data); Texture test_texture = load_texture(memories, device, transfer_pool, transfer_queue, graphics_pool, graphics_queue, texture_size, 4, VK_FORMAT_R8G8B8A8_SRGB, texture_data, transfer_family, graphics_family);
for(uint32_t i = 0; i < max_frames_in_flight; i++) { for(uint32_t i = 0; i < max_frames_in_flight; i++) {
VkDescriptorImageInfo image_info = { VkDescriptorImageInfo image_info = {
@ -3183,7 +3176,7 @@ Object create_texture_mesh_object(Material* texture_mesh_material, MemoryIndices
} }
void main_loop(GLFWwindow* window, VulkanContext* context) { void main_loop(GLFWwindow* window, VulkanContext* context) {
SceneContext scene = create_scene_context(context->device, context->memory_indices, context->max_frames_in_flight); SceneContext scene = create_scene_context(context->device, context->memories, context->max_frames_in_flight);
if(scene.pool == VK_NULL_HANDLE) { if(scene.pool == VK_NULL_HANDLE) {
return; return;
} }
@ -3215,7 +3208,7 @@ void main_loop(GLFWwindow* window, VulkanContext* context) {
return; return;
} }
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); 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);
if(triangle_object.attributes.buckets == 0) { if(triangle_object.attributes.buckets == 0) {
fprintf(stderr, "failed to create simple mesh object\n"); fprintf(stderr, "failed to create simple mesh object\n");
return; return;
@ -3252,7 +3245,7 @@ void main_loop(GLFWwindow* window, VulkanContext* context) {
return; return;
} }
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); Object triangle_object_textured = create_texture_mesh_object(&texture_mesh_material, context->memories, context->device, context->transfer_command_pool, context->queues.transfer, context->extra_graphics_pool, context->queues.graphics, context->max_frames_in_flight, texture_pool, context->queue_indices.transfer_family, context->queue_indices.graphics_family);
if(triangle_object_textured.attributes.buckets == 0) { if(triangle_object_textured.attributes.buckets == 0) {
fprintf(stderr, "failed to create texture mesh object\n"); fprintf(stderr, "failed to create texture mesh object\n");
return; return;