summaryrefslogtreecommitdiffstats
path: root/src/vksetup.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/vksetup.h')
-rw-r--r--src/vksetup.h238
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,
+ &region
+ );
+
+ 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, &copy_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,