@@ -97,4 +97,125 @@ void destroyBuffer(VulkanContext* context, VulkanBuffer* buffer) {
9797 VK (vkDestroyBuffer (context->device , buffer->buffer , 0 ));
9898 // Assumes that the buffer owns its own memory block
9999 VK (vkFreeMemory (context->device , buffer->memory , 0 ));
100+ }
101+
102+ void createImage (VulkanContext* context, VulkanImage* image, uint32_t width, uint32_t height, VkFormat format, VkImageUsageFlags usage) {
103+ {
104+ VkImageCreateInfo createInfo = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO};
105+ createInfo.imageType = VK_IMAGE_TYPE_2D;
106+ createInfo.extent .width = width;
107+ createInfo.extent .height = height;
108+ createInfo.extent .depth = 1 ;
109+ createInfo.mipLevels = 1 ;
110+ createInfo.arrayLayers = 1 ;
111+ createInfo.format = format;
112+ createInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
113+ createInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
114+ createInfo.usage = usage;
115+ createInfo.samples = VK_SAMPLE_COUNT_1_BIT;
116+ createInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
117+ VKA (vkCreateImage (context->device , &createInfo, 0 , &image->image ));
118+ }
119+
120+ VkMemoryRequirements memoryRequirements;
121+ VK (vkGetImageMemoryRequirements (context->device , image->image , &memoryRequirements));
122+ VkMemoryAllocateInfo allocateInfo = {VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO};
123+ allocateInfo.allocationSize = memoryRequirements.size ;
124+ allocateInfo.memoryTypeIndex = findMemoryType (context, memoryRequirements.memoryTypeBits , VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
125+ VKA (vkAllocateMemory (context->device , &allocateInfo, 0 , &image->memory ));
126+ VKA (vkBindImageMemory (context->device , image->image , image->memory , 0 ));
127+
128+ {
129+ VkImageViewCreateInfo createInfo = {VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO};
130+ createInfo.image = image->image ;
131+ createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
132+ createInfo.format = format;
133+ createInfo.subresourceRange .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
134+ createInfo.subresourceRange .levelCount = 1 ;
135+ createInfo.subresourceRange .layerCount = 1 ;
136+ VKA (vkCreateImageView (context->device , &createInfo, 0 , &image->view ));
137+ }
138+ }
139+
140+ void uploadDataToImage (VulkanContext* context, VulkanImage* image, void * data, size_t size, uint32_t width, uint32_t height, VkImageLayout finalLayout, VkAccessFlags dstAccessMask) {
141+ // Upload with staging buffer
142+ VulkanQueue* queue = &context->graphicsQueue ;
143+ VkCommandPool commandPool;
144+ VkCommandBuffer commandBuffer;
145+ VulkanBuffer stagingBuffer;
146+ createBuffer (context, &stagingBuffer, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
147+ void * mapped;
148+ VKA (vkMapMemory (context->device , stagingBuffer.memory , 0 , size, 0 , &mapped));
149+ memcpy (mapped, data, size);
150+ VK (vkUnmapMemory (context->device , stagingBuffer.memory ));
151+ {
152+ VkCommandPoolCreateInfo createInfo = { VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO };
153+ createInfo.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT;
154+ createInfo.queueFamilyIndex = queue->familyIndex ;
155+ VKA (vkCreateCommandPool (context->device , &createInfo, 0 , &commandPool));
156+ }
157+ {
158+ VkCommandBufferAllocateInfo allocateInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO };
159+ allocateInfo.commandPool = commandPool;
160+ allocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
161+ allocateInfo.commandBufferCount = 1 ;
162+ VKA (vkAllocateCommandBuffers (context->device , &allocateInfo, &commandBuffer));
163+ }
164+
165+ VkCommandBufferBeginInfo beginInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
166+ beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
167+ VKA (vkBeginCommandBuffer (commandBuffer, &beginInfo));
168+
169+ {
170+ VkImageMemoryBarrier imageBarrier = {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER};
171+ imageBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
172+ imageBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
173+ imageBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
174+ imageBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
175+ imageBarrier.image = image->image ;
176+ imageBarrier.subresourceRange .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
177+ imageBarrier.subresourceRange .levelCount = 1 ;
178+ imageBarrier.subresourceRange .layerCount = 1 ;
179+ imageBarrier.srcAccessMask = 0 ;
180+ imageBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
181+ vkCmdPipelineBarrier (commandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0 , 0 , 0 , 0 , 0 , 1 , &imageBarrier);
182+ }
183+
184+ VkBufferImageCopy region = {};
185+ region.imageSubresource .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
186+ region.imageSubresource .layerCount = 1 ;
187+ region.imageExtent = {width, height, 1 };
188+ VK (vkCmdCopyBufferToImage (commandBuffer, stagingBuffer.buffer , image->image , VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1 , ®ion));
189+
190+ {
191+ VkImageMemoryBarrier imageBarrier = {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER};
192+ imageBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
193+ imageBarrier.newLayout = finalLayout;
194+ imageBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
195+ imageBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
196+ imageBarrier.image = image->image ;
197+ imageBarrier.subresourceRange .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
198+ imageBarrier.subresourceRange .levelCount = 1 ;
199+ imageBarrier.subresourceRange .layerCount = 1 ;
200+ imageBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
201+ imageBarrier.dstAccessMask = VK_ACCESS_NONE;
202+ vkCmdPipelineBarrier (commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0 , 0 , 0 , 0 , 0 , 1 , &imageBarrier);
203+ }
204+
205+ VKA (vkEndCommandBuffer (commandBuffer));
206+
207+ VkSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_SUBMIT_INFO };
208+ submitInfo.commandBufferCount = 1 ;
209+ submitInfo.pCommandBuffers = &commandBuffer;
210+ VKA (vkQueueSubmit (queue->queue , 1 , &submitInfo, VK_NULL_HANDLE));
211+ VKA (vkQueueWaitIdle (queue->queue ));
212+
213+ VK (vkDestroyCommandPool (context->device , commandPool, 0 ));
214+ destroyBuffer (context, &stagingBuffer);
215+ }
216+
217+ void destroyImage (VulkanContext* context, VulkanImage* image) {
218+ VK (vkDestroyImageView (context->device , image->view , 0 ));
219+ VK (vkDestroyImage (context->device , image->image , 0 ));
220+ VK (vkFreeMemory (context->device , image->memory , 0 ));
100221}
0 commit comments