|
|
|
@ -144,12 +144,6 @@ typedef struct MaterialStruct {
|
|
|
|
|
Map object_descriptor_mappings;
|
|
|
|
|
} Material;
|
|
|
|
|
|
|
|
|
|
typedef struct MemoryIndicesStruct {
|
|
|
|
|
uint32_t host_visible;
|
|
|
|
|
uint32_t device_local;
|
|
|
|
|
uint32_t device_lazy;
|
|
|
|
|
} MemoryIndices;
|
|
|
|
|
|
|
|
|
|
typedef struct VulkanContextStruct {
|
|
|
|
|
VkInstance instance;
|
|
|
|
|
VkDebugUtilsMessengerEXT debug_messenger;
|
|
|
|
@ -194,7 +188,8 @@ typedef struct VulkanContextStruct {
|
|
|
|
|
|
|
|
|
|
uint32_t current_frame;
|
|
|
|
|
|
|
|
|
|
MemoryIndices memory_indices;
|
|
|
|
|
VkPhysicalDeviceMemoryProperties memories;
|
|
|
|
|
VkCommandPool extra_graphics_pool;
|
|
|
|
|
} VulkanContext;
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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) {
|
|
|
|
|
glfwInit();
|
|
|
|
|
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) {
|
|
|
|
|
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.pCode = (uint32_t*)code;
|
|
|
|
|
|
|
|
|
@ -968,18 +974,7 @@ VkRenderPass create_render_pass(VkDevice device, VkSurfaceFormatKHR format, VkFo
|
|
|
|
|
return render_pass;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t pick_memory_type(VkPhysicalDeviceMemoryProperties memories, uint32_t filter, VkMemoryPropertyFlags flags) {
|
|
|
|
|
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) {
|
|
|
|
|
AllocatedImage allocate_image(VkPhysicalDeviceMemoryProperties memories, VkDevice device, VkImageType type, VkFormat format, VkExtent3D size, VkImageUsageFlags usage, VkMemoryPropertyFlags include, VkMemoryPropertyFlags exclude) {
|
|
|
|
|
VkImageCreateInfo image_info = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
|
|
|
|
|
.imageType = type,
|
|
|
|
@ -1010,7 +1005,7 @@ AllocatedImage allocate_image(uint32_t memory_index, VkDevice device, VkImageTyp
|
|
|
|
|
VkMemoryAllocateInfo memory_info = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
|
|
|
|
.allocationSize = memory_requirements.size,
|
|
|
|
|
.memoryTypeIndex = memory_index,
|
|
|
|
|
.memoryTypeIndex = pick_memory(memories, memory_requirements.memoryTypeBits, include, exclude),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
result = vkAllocateMemory(device, &memory_info, 0, &allocated.memory);
|
|
|
|
@ -1033,7 +1028,7 @@ AllocatedImage allocate_image(uint32_t memory_index, VkDevice device, VkImageTyp
|
|
|
|
|
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 = {};
|
|
|
|
|
ret.memory = 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 = {};
|
|
|
|
|
alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
|
|
|
|
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);
|
|
|
|
|
if(result != VK_SUCCESS) {
|
|
|
|
@ -1089,14 +1084,14 @@ void deallocate_image(VkDevice device, AllocatedImage image) {
|
|
|
|
|
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);
|
|
|
|
|
if(buffers == 0) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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) {
|
|
|
|
|
for(uint32_t j = 0; j < i; j++) {
|
|
|
|
|
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 result = vkEndCommandBuffer(command_buffer);
|
|
|
|
|
if(result != VK_SUCCESS) {
|
|
|
|
|
vkFreeCommandBuffers(device, transfer_pool, 1, &command_buffer);
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VkSubmitInfo submit_info = {};
|
|
|
|
|
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
|
|
|
|
submit_info.commandBufferCount = 1;
|
|
|
|
|
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) {
|
|
|
|
|
vkFreeCommandBuffers(device, transfer_pool, 1, &command_buffer);
|
|
|
|
|
return result;
|
|
|
|
@ -1162,24 +1163,19 @@ VkResult command_copy_buffers(VkDevice device, VkCommandPool transfer_pool, VkQu
|
|
|
|
|
copy_region.size = size;
|
|
|
|
|
|
|
|
|
|
vkCmdCopyBuffer(command_buffer, source, dest, 1, ©_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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
VkImageMemoryBarrier barrier = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
|
|
|
|
.oldLayout = old_layout,
|
|
|
|
|
.newLayout = new_layout,
|
|
|
|
|
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
|
|
|
|
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
|
|
|
|
.srcQueueFamilyIndex = source_family,
|
|
|
|
|
.dstQueueFamilyIndex = dest_family,
|
|
|
|
|
.image = image,
|
|
|
|
|
.subresourceRange = {
|
|
|
|
|
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
|
|
|
@ -1188,10 +1184,10 @@ VkResult command_transition_image_layout(VkDevice device, VkCommandPool transfer
|
|
|
|
|
.baseMipLevel = 0,
|
|
|
|
|
.baseArrayLayer = 0,
|
|
|
|
|
},
|
|
|
|
|
.srcAccessMask = 0,
|
|
|
|
|
.dstAccessMask = 0,
|
|
|
|
|
.srcAccessMask = src_mask,
|
|
|
|
|
.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);
|
|
|
|
|
}
|
|
|
|
@ -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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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 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) {
|
|
|
|
|
return vertex_buffer;
|
|
|
|
|
}
|
|
|
|
@ -1242,7 +1238,7 @@ AllocatedBuffer create_populated_buffer(MemoryIndices memories, VkDevice device,
|
|
|
|
|
|
|
|
|
|
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) {
|
|
|
|
|
deallocate_buffer(device, staging_buffer);
|
|
|
|
|
return vertex_buffer;
|
|
|
|
@ -1260,7 +1256,7 @@ AllocatedBuffer create_populated_buffer(MemoryIndices memories, VkDevice device,
|
|
|
|
|
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 = {
|
|
|
|
|
.image.image = 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;
|
|
|
|
|
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) {
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
@ -1289,14 +1285,14 @@ Texture load_texture(MemoryIndices memories, VkDevice device, VkCommandPool tran
|
|
|
|
|
.height = size.height,
|
|
|
|
|
.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) {
|
|
|
|
|
deallocate_buffer(device, staging);
|
|
|
|
|
deallocate_image(device, image);
|
|
|
|
|
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) {
|
|
|
|
|
deallocate_buffer(device, staging);
|
|
|
|
|
deallocate_image(device, image);
|
|
|
|
@ -1310,6 +1306,20 @@ Texture load_texture(MemoryIndices memories, VkDevice device, VkCommandPool tran
|
|
|
|
|
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;
|
|
|
|
|
VkImageViewCreateInfo view_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.pDynamicState = &dynamic_info;
|
|
|
|
|
pipeline_info.pDepthStencilState = &depth_info;
|
|
|
|
|
pipeline_info.pMultisampleState = &multisample_info;
|
|
|
|
|
pipeline_info.layout = layout;
|
|
|
|
|
pipeline_info.renderPass = render_pass;
|
|
|
|
|
pipeline_info.subpass = 0;
|
|
|
|
@ -1507,21 +1518,6 @@ VkPipeline create_graphics_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) {
|
|
|
|
|
VkExtent3D depth_extent = {
|
|
|
|
|
.width = context->swapchain_extent.width,
|
|
|
|
@ -1538,7 +1534,7 @@ int create_depth_image(VulkanContext* context) {
|
|
|
|
|
.format = context->depth_format,
|
|
|
|
|
.tiling = VK_IMAGE_TILING_OPTIMAL,
|
|
|
|
|
.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,
|
|
|
|
|
.samples = VK_SAMPLE_COUNT_1_BIT,
|
|
|
|
|
.flags = 0,
|
|
|
|
@ -1559,7 +1555,7 @@ int create_depth_image(VulkanContext* context) {
|
|
|
|
|
VkMemoryAllocateInfo depth_memory_info = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
|
|
|
|
.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;
|
|
|
|
@ -1831,7 +1827,7 @@ VkFence* create_fences(VkDevice device, VkFenceCreateFlags flags, uint32_t count
|
|
|
|
|
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);
|
|
|
|
|
if(vertex_buffer.memory == VK_NULL_HANDLE) {
|
|
|
|
|
return 0;
|
|
|
|
@ -1938,7 +1934,7 @@ Object create_renderable(Mesh* mesh, Material* material, uint32_t descriptor_set
|
|
|
|
|
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);
|
|
|
|
|
if(vertex_buffer.memory == VK_NULL_HANDLE) {
|
|
|
|
|
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) {
|
|
|
|
|
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);
|
|
|
|
|
VkPipelineShaderStageCreateInfo shader_stages[2] = {};
|
|
|
|
|
shader_stages[0].sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT;
|
|
|
|
|
shader_stages[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
|
|
|
|
|
shader_stages[0].module = vert_shader;
|
|
|
|
|
shader_stages[0].pName = "main";
|
|
|
|
|
VkPipelineShaderStageCreateInfo shader_stages[2] = {
|
|
|
|
|
{
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
|
|
|
|
.stage = VK_SHADER_STAGE_VERTEX_BIT,
|
|
|
|
|
.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] = {
|
|
|
|
|
{
|
|
|
|
@ -2200,13 +2201,13 @@ Material create_texture_mesh_material(VkDevice device, VkExtent2D extent, VkRend
|
|
|
|
|
}
|
|
|
|
|
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,
|
|
|
|
|
.module = vert_shader,
|
|
|
|
|
.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,
|
|
|
|
|
.module = frag_shader,
|
|
|
|
|
.pName = "main",
|
|
|
|
@ -2325,35 +2326,7 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) {
|
|
|
|
|
context->physical_device = physical_device;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VkPhysicalDeviceMemoryProperties 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;
|
|
|
|
|
}
|
|
|
|
|
vkGetPhysicalDeviceMemoryProperties(context->physical_device, &context->memories);
|
|
|
|
|
|
|
|
|
|
VkSurfaceKHR 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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VkCommandPool graphics_command_pool = create_command_pool(context->device, context->queue_indices.graphics_family);
|
|
|
|
|
if(graphics_command_pool == VK_NULL_HANDLE) {
|
|
|
|
|
VkCommandPoolCreateInfo graphics_pool_info = {
|
|
|
|
|
.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");
|
|
|
|
|
return 0;
|
|
|
|
|
} else {
|
|
|
|
|
context->graphics_command_pool = graphics_command_pool;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VkCommandPool transfer_command_pool = create_command_pool(context->device, context->queue_indices.transfer_family);
|
|
|
|
|
if(transfer_command_pool == VK_NULL_HANDLE) {
|
|
|
|
|
VkCommandPoolCreateInfo transfer_pool_info = {
|
|
|
|
|
.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");
|
|
|
|
|
return 0;
|
|
|
|
|
} else {
|
|
|
|
@ -2480,6 +2465,14 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) {
|
|
|
|
|
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);
|
|
|
|
|
if(ia_semaphores == 0) {
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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 = {
|
|
|
|
|
.pool = 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 = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
|
|
|
|
|
.descriptorPool = pool,
|
|
|
|
|
.descriptorSetCount = max_frames_in_flight,
|
|
|
|
|
.pSetLayouts = layouts,
|
|
|
|
@ -2591,7 +2584,7 @@ SceneContext create_scene_context(VkDevice device, MemoryIndices memories, uint3
|
|
|
|
|
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) {
|
|
|
|
|
free(layouts);
|
|
|
|
|
free(sets);
|
|
|
|
@ -2940,7 +2933,7 @@ 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, 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 = {};
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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) {
|
|
|
|
|
return zero;
|
|
|
|
|
}
|
|
|
|
@ -3034,7 +3027,7 @@ Object create_simple_mesh_object(Material* simple_mesh_material, MemoryIndices m
|
|
|
|
|
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 = {};
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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) {
|
|
|
|
|
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,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
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++) {
|
|
|
|
|
VkDescriptorImageInfo image_info = {
|
|
|
|
@ -3183,7 +3176,7 @@ Object create_texture_mesh_object(Material* texture_mesh_material, MemoryIndices
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
@ -3215,7 +3208,7 @@ void main_loop(GLFWwindow* window, VulkanContext* context) {
|
|
|
|
|
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) {
|
|
|
|
|
fprintf(stderr, "failed to create simple mesh object\n");
|
|
|
|
|
return;
|
|
|
|
@ -3252,7 +3245,7 @@ void main_loop(GLFWwindow* window, VulkanContext* context) {
|
|
|
|
|
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) {
|
|
|
|
|
fprintf(stderr, "failed to create texture mesh object\n");
|
|
|
|
|
return;
|
|
|
|
|