1 #include <kiba/renderer/vulkan/image.h>
3 #include <kiba/renderer/vulkan/buffer.h>
4 #include <kiba/renderer/vulkan/command_buffer.h>
11 VkImageUsageFlags usage,
12 VkMemoryPropertyFlags properties,
14 VkExtent3D image_extent = {
19 VkImageCreateInfo image_info = {
20 .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
21 .imageType = VK_IMAGE_TYPE_2D,
22 .extent = image_extent,
27 .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
29 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
30 .samples = VK_SAMPLE_COUNT_1_BIT,
33 VK_CALL_B8(vkCreateImage(context->device.logical, &image_info, &context->alloc.vulkan_callbacks, &image->image));
35 VkMemoryRequirements memory_requirements;
36 vkGetImageMemoryRequirements(context->device.logical, image->image, &memory_requirements);
38 u32 memory_type = vulkan_get_memory_type(context, memory_requirements.memoryTypeBits, properties);
40 "memory type must be available for the vulkan_image memory");
41 VkMemoryAllocateInfo alloc_info = {
42 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
43 .allocationSize = memory_requirements.size,
44 .memoryTypeIndex = memory_type,
47 vkAllocateMemory(context->device.logical, &alloc_info, &context->alloc.vulkan_callbacks, &image->memory));
48 VK_CALL_B8(vkBindImageMemory(context->device.logical, image->image, image->memory, 0));
56 VkFormatFeatureFlags features) {
57 KB_ASSERT(n > 0,
"must provide at least one candidate");
58 for (usize i = 0; i < n; ++i) {
59 VkFormat format = candidates[i];
60 VkFormatProperties properties;
61 vkGetPhysicalDeviceFormatProperties(context->device.physical, format, &properties);
62 if (tiling == VK_IMAGE_TILING_OPTIMAL &&
KB_FLAGS_ALL_SET(properties.optimalTilingFeatures, features)) {
65 if (tiling == VK_IMAGE_TILING_LINEAR &&
KB_FLAGS_ALL_SET(properties.linearTilingFeatures, features)) {
70 return VK_FORMAT_MAX_ENUM;
78 VkCommandBuffer command_buffer;
79 if (!vulkan_command_buffer_start_single_time_command(context, &command_buffer)) {
83 VkImageSubresourceRange subresource_range = {
84 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
90 VkImageMemoryBarrier barrier = {
91 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
94 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
95 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
96 .image = image->image,
97 .subresourceRange = subresource_range,
100 VkPipelineStageFlags src_stage;
101 VkPipelineStageFlags dst_stage;
103 if (src == VK_IMAGE_LAYOUT_UNDEFINED && dst == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
104 barrier.srcAccessMask = 0;
105 barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
106 src_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
107 dst_stage = VK_PIPELINE_STAGE_TRANSFER_BIT;
108 }
else if (src == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && dst == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
109 barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
110 barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
111 src_stage = VK_PIPELINE_STAGE_TRANSFER_BIT;
112 dst_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
113 }
else if (src == VK_IMAGE_LAYOUT_UNDEFINED && dst == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) {
114 barrier.srcAccessMask = 0;
115 barrier.dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
116 src_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
117 dst_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
118 }
else if (src == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR && dst == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) {
119 barrier.srcAccessMask = 0;
120 barrier.dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
121 src_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
122 dst_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
123 }
else if (src == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL && dst == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) {
124 barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
125 barrier.dstAccessMask = 0;
126 src_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
127 dst_stage = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
129 KB_ASSERT(
false,
"unsupported combination of src({u32}) and dst({u32}) layout", src, dst);
132 vkCmdPipelineBarrier(command_buffer, src_stage, dst_stage, 0, 0,
KB_NULL, 0,
KB_NULL, 1, &barrier);
135 return vulkan_command_buffer_end_single_time_command(context, &command_buffer);
143 VkCommandBuffer command_buffer;
144 if (!vulkan_command_buffer_start_single_time_command(context, &command_buffer)) {
148 VkImageSubresourceLayers subresource = {
149 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
154 VkOffset3D image_offset = {0, 0, 0};
155 VkExtent3D image_extent = {
160 VkBufferImageCopy region = {
162 .bufferRowLength = 0,
163 .bufferImageHeight = 0,
164 .imageSubresource = subresource,
165 .imageOffset = image_offset,
166 .imageExtent = image_extent,
168 vkCmdCopyBufferToImage(command_buffer,
171 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
175 return vulkan_command_buffer_end_single_time_command(context, &command_buffer);
179 vkDestroyImage(context->device.logical, image->image, &context->alloc.vulkan_callbacks);
180 vkFreeMemory(context->device.logical, image->memory, &context->alloc.vulkan_callbacks);
186 VkImageAspectFlags aspect_flags,
188 VkImageSubresourceRange subresource_range = {
189 .aspectMask = aspect_flags,
195 VkImageViewCreateInfo view_info = {
196 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
198 .viewType = VK_IMAGE_VIEW_TYPE_2D,
200 .subresourceRange = subresource_range,
202 VK_CALL_B8(vkCreateImageView(context->device.logical, &view_info, &context->alloc.vulkan_callbacks, view));
206 void vulkan_image_view_destroy(
vulkan_context *context, VkImageView *view) {
207 vkDestroyImageView(context->device.logical, *view, &context->alloc.vulkan_callbacks);
#define UNUSED(x)
Mark parameter as unused.
#define KB_FLAGS_ALL_SET(value, flags)
Check if all flags are set inside value.
#define KB_NULL
Value of an invalid ptr (nullptr).
#define KB_ASSERT(expr,...)
Perform runtime assertion and log failures.