diff options
Diffstat (limited to 'src/vksetup.h')
-rw-r--r-- | src/vksetup.h | 238 |
1 files changed, 235 insertions, 3 deletions
diff --git a/src/vksetup.h b/src/vksetup.h index 4f05347..e78b887 100644 --- a/src/vksetup.h +++ b/src/vksetup.h @@ -196,11 +196,40 @@ typedef struct vks_frame_data { VkDescriptorSet vk_descriptor_set; } vks_frame_data; +/* Info structs */ +typedef struct vks_command_info +{ + vks_context vk; + VkCommandPool pool; + VkQueue queue; +} vks_command_info; + +typedef struct vks_transition_image_layout_info +{ + /* command */ + vks_command_info cmd_info; + /* image */ + VkImage image; + VkFormat format; + VkAccessFlags srcAccessMask; + VkAccessFlags dstAccessMask; + VkPipelineStageFlags srcStageMask; + VkPipelineStageFlags dstStageMask; + VkImageLayout oldLayout; + VkImageLayout newLayout; + uint32_t mipLevels; +} vks_transition_image_layout_info; + /* Exported API */ -VKSDEF VkInstance vks_create_instance(bool validation_layers_toggle, const char * const validation_layers[], uint32_t validation_layer_count, SDL_Window *window); -VKSDEF void vks_create_buffer(const vks_context vk, const VkDeviceSize size, const VkBufferUsageFlags usage, const VkMemoryPropertyFlags properties, vks_buffer *buffer); -VKSDEF void vks_create_image(const vks_context vk, const uint32_t width, const uint32_t height, const uint32_t mipLevels, const VkFormat format, const VkImageTiling tiling, const VkImageUsageFlags usage, const VkMemoryPropertyFlags properties, const VkSampleCountFlagBits numSamples, vks_image *image); +VKSDEF VkInstance vks_create_instance (bool validation_layers_toggle, const char * const validation_layers[], uint32_t validation_layer_count, SDL_Window *window); +VKSDEF void vks_create_buffer (const vks_context vk, const VkDeviceSize size, const VkBufferUsageFlags usage, const VkMemoryPropertyFlags properties, vks_buffer *buffer); +VKSDEF void vks_create_image (const vks_context vk, const uint32_t width, const uint32_t height, const uint32_t mipLevels, const VkFormat format, const VkImageTiling tiling, const VkImageUsageFlags usage, const VkMemoryPropertyFlags properties, const VkSampleCountFlagBits numSamples, vks_image *image); +VKSDEF void vks_transition_image_layout (const vks_transition_image_layout_info *info); +VKSDEF void vks_copy_buffer (const vks_command_info *cmd_info, const VkBuffer src_buffer, VkBuffer dst_buffer, const VkDeviceSize size); +VKSDEF void vks_copy_buffer_to_image (const vks_command_info* cmd_info, const VkBuffer buffer, VkImage image, const uint32_t width, const uint32_t height); +VKSDEF void vks_generate_mipmaps (const vks_command_info* cmd_info, VkImage image, const VkFormat imageFormat, const int32_t texWidth, const int32_t texHeight, const uint32_t mipLevels); + /* VKSDEF void vulkan_create_surface(); */ /* VKSDEF void vulkan_pick_physical_device(); */ /* VKSDEF void vulkan_create_logical_device(); */ @@ -279,8 +308,211 @@ find_memory_type(const vks_context vk, return 9999; } +VkCommandBuffer +begin_single_time_commands(const vks_command_info *info) +{ + VkCommandBufferAllocateInfo allocInfo = {0}; + allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + allocInfo.commandPool = info->pool; + allocInfo.commandBufferCount = 1; + + VkCommandBuffer commandBuffer; + VK_CHECK(vkAllocateCommandBuffers(info->vk.device, &allocInfo, &commandBuffer)); + + VkCommandBufferBeginInfo beginInfo = {0}; + beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; + + VK_CHECK(vkBeginCommandBuffer(commandBuffer, &beginInfo)); + + return commandBuffer; +} + +void +end_single_time_commands(const vks_command_info *info, VkCommandBuffer command_buffer) +{ + VK_CHECK(vkEndCommandBuffer(command_buffer)); + + VkSubmitInfo submitInfo = {0}; + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = &command_buffer; + + VK_CHECK(vkQueueSubmit(info->queue, 1, &submitInfo, VK_NULL_HANDLE)); + VK_CHECK(vkQueueWaitIdle(info->queue)); + + vkFreeCommandBuffers(info->vk.device, info->pool, 1, &command_buffer); +} + +int +has_stencil_component(VkFormat format) +{ + return format == VK_FORMAT_D32_SFLOAT_S8_UINT || format == VK_FORMAT_D24_UNORM_S8_UINT; +} + /* Vks API implementation */ VKSDEF void +vks_generate_mipmaps(const vks_command_info* cmd_info, + VkImage image, + const VkFormat imageFormat, + const int32_t texWidth, + const int32_t texHeight, + const uint32_t mipLevels) +{ + VkCommandBuffer command_buffer = begin_single_time_commands(cmd_info); + + VkImageMemoryBarrier barrier = {0}; + barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barrier.image = image; + barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + barrier.subresourceRange.baseArrayLayer = 0; + barrier.subresourceRange.layerCount = 1; + barrier.subresourceRange.levelCount = 1; + + int32_t mipWidth = texWidth; + int32_t mipHeight = texHeight; + + for (uint32_t i = 1; i < mipLevels; i++) { + barrier.subresourceRange.baseMipLevel = i - 1; + barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; + barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; + + vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 0, NULL, 1, + &barrier); + + VkImageBlit blit = {0}; + blit.srcOffsets[0] = (VkOffset3D){ 0, 0, 0 }; + blit.srcOffsets[1] = (VkOffset3D){ mipWidth, mipHeight, 1 }; + blit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + blit.srcSubresource.mipLevel = i - 1; + blit.srcSubresource.baseArrayLayer = 0; + blit.srcSubresource.layerCount = 1; + blit.dstOffsets[0] = (VkOffset3D){ 0, 0, 0 }; + blit.dstOffsets[1] = (VkOffset3D){ mipWidth > 1 ? mipWidth / 2 : 1, mipHeight > 1 ? mipHeight / 2 : 1, 1 }; + blit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + blit.dstSubresource.mipLevel = i; + blit.dstSubresource.baseArrayLayer = 0; + blit.dstSubresource.layerCount = 1; + + vkCmdBlitImage(command_buffer, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit, + VK_FILTER_LINEAR); + + barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; + barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT; + barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + + vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, NULL, 0, + NULL, 1, &barrier); + + if (mipWidth > 1) mipWidth /= 2; + if (mipHeight > 1) mipHeight /= 2; + } + + end_single_time_commands(cmd_info, command_buffer); +} + +VKSDEF void +vks_copy_buffer_to_image(const vks_command_info* cmd_info, + const VkBuffer buffer, + VkImage image, + const uint32_t width, + const uint32_t height) +{ + VkCommandBuffer command_buffer = begin_single_time_commands(cmd_info); + + VkBufferImageCopy region = {0}; + region.bufferOffset = 0; + region.bufferRowLength = 0; + region.bufferImageHeight = 0; + + region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + region.imageSubresource.mipLevel = 0; + region.imageSubresource.baseArrayLayer = 0; + region.imageSubresource.layerCount = 1; + + region.imageOffset = (VkOffset3D){0, 0, 0}; + region.imageExtent = (VkExtent3D){width, height, 1}; + + vkCmdCopyBufferToImage(command_buffer, + buffer, + image, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + 1, + ®ion + ); + + end_single_time_commands(cmd_info, command_buffer); +} + +VKSDEF void +vks_copy_buffer(const vks_command_info *cmd_info, const VkBuffer src_buffer, VkBuffer dst_buffer, const VkDeviceSize size) +{ + VkCommandBuffer command_buffer = begin_single_time_commands(cmd_info); + + VkBufferCopy copy_region = {0}; + copy_region.srcOffset = 0; // Optional + copy_region.dstOffset = 0; // Optional + copy_region.size = size; + vkCmdCopyBuffer(command_buffer, src_buffer, dst_buffer, 1, ©_region); + + end_single_time_commands(cmd_info, command_buffer); +} + +VKSDEF void +vks_transition_image_layout(const vks_transition_image_layout_info *info) +{ + VkCommandBuffer command_buffer = begin_single_time_commands(&info->cmd_info); + + VkImageMemoryBarrier barrier = { 0 }; + barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barrier.srcAccessMask = info->srcAccessMask; + barrier.dstAccessMask = info->dstAccessMask; + barrier.oldLayout = info->oldLayout; + barrier.newLayout = info->newLayout; + barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.image = info->image; + + // barrier.subresourceRange.aspectMask = + if (info->newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) { + barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + + if (has_stencil_component(info->format)) { + barrier.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; + } + } else { + barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + } + + barrier.subresourceRange.baseMipLevel = 0; + barrier.subresourceRange.levelCount = info->mipLevels; + barrier.subresourceRange.baseArrayLayer = 0; + barrier.subresourceRange.layerCount = 1; + + vkCmdPipelineBarrier(command_buffer, + info->srcStageMask, + info->dstStageMask, + 0, + 0, + NULL, + 0, + NULL, + 1, + &barrier); + + end_single_time_commands(&info->cmd_info, command_buffer); +} + +VKSDEF void vks_create_image(const vks_context vk, const uint32_t width, const uint32_t height, |