Added buffer to image copy functions

main
noah metz 2024-01-08 21:36:45 -07:00
parent e5842f3ef5
commit fc68698ac7
1 changed files with 257 additions and 18 deletions

@ -52,6 +52,17 @@ typedef struct AllocatedBufferStruct {
VkDeviceMemory memory;
} AllocatedBuffer;
typedef struct AllocatedImageStruct {
VkImage image;
VkDeviceMemory memory;
} AllocatedImage;
typedef struct TextureStruct {
AllocatedImage image;
VkImageView view;
VkSampler sampler;
} Texture;
typedef struct MeshStruct {
uint32_t vertex_count;
AllocatedBuffer vertex_buffer;
@ -546,7 +557,9 @@ VkDevice create_logical_device(VkPhysicalDevice physical_device, QueueIndices qu
queue_create_info[i].pQueuePriorities = &default_queue_priority;
}
VkPhysicalDeviceFeatures device_features = {};
VkPhysicalDeviceFeatures device_features = {
.samplerAnisotropy = VK_TRUE,
};
VkDeviceCreateInfo device_create_info = {};
device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
@ -883,6 +896,60 @@ uint32_t find_memory_type(VkPhysicalDevice physical_device, uint32_t type_filter
return 0xFFFFFFFF;
}
AllocatedImage allocate_image(VkPhysicalDevice physical_device, VkDevice device, VkImageType type, VkFormat format, VkExtent3D size, VkImageUsageFlags usage, VkMemoryPropertyFlags properties, VkSampleCountFlagBits samples) {
VkImageCreateInfo image_info = {
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
.imageType = type,
.extent = size,
.mipLevels = 1,
.arrayLayers = 1,
.format = format,
.tiling = VK_IMAGE_TILING_OPTIMAL,
.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
.usage = usage,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
.samples = samples,
.flags = 0,
};
AllocatedImage allocated = {
.memory = VK_NULL_HANDLE,
.image = VK_NULL_HANDLE,
};
VkResult result = vkCreateImage(device, &image_info, 0, &allocated.image);
if(result != VK_SUCCESS) {
return allocated;
}
VkMemoryRequirements memory_requirements;
vkGetImageMemoryRequirements(device, allocated.image, &memory_requirements);
VkMemoryAllocateInfo memory_info = {
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
.allocationSize = memory_requirements.size,
.memoryTypeIndex = find_memory_type(physical_device, memory_requirements.memoryTypeBits, properties),
};
result = vkAllocateMemory(device, &memory_info, 0, &allocated.memory);
if(result != VK_SUCCESS) {
vkDestroyImage(device, allocated.image, 0);
allocated.image = VK_NULL_HANDLE;
return allocated;
}
result = vkBindImageMemory(device, allocated.image, allocated.memory, 0);
if(result != VK_SUCCESS) {
vkFreeMemory(device, allocated.memory, 0);
vkDestroyImage(device, allocated.image, 0);
allocated.memory = VK_NULL_HANDLE;
allocated.image = VK_NULL_HANDLE;
return allocated;
}
return allocated;
}
AllocatedBuffer allocate_buffer(VkPhysicalDevice physical_device, VkDevice device, VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties) {
AllocatedBuffer ret = {};
ret.memory = VK_NULL_HANDLE;
@ -934,6 +1001,11 @@ void deallocate_buffer(VkDevice device, AllocatedBuffer buffer) {
vkFreeMemory(device, buffer.memory, 0);
};
void deallocate_image(VkDevice device, AllocatedImage image) {
vkDestroyImage(device, image.image, 0);
vkFreeMemory(device, image.memory, 0);
};
AllocatedBuffer* allocate_buffers(VkPhysicalDevice physical_device, VkDevice device, VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, uint32_t count) {
AllocatedBuffer* buffers = malloc(sizeof(AllocatedBuffer)*count);
if(buffers == 0) {
@ -955,7 +1027,7 @@ AllocatedBuffer* allocate_buffers(VkPhysicalDevice physical_device, VkDevice dev
return buffers;
}
VkResult command_copy_buffers(VkDevice device, VkCommandPool transfer_pool, VkQueue transfer_queue, VkBuffer source, VkBuffer dest, VkDeviceSize size) {
VkCommandBuffer command_begin_single(VkDevice device, VkCommandPool transfer_pool) {
VkCommandBufferAllocateInfo command_info = {};
command_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
command_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
@ -965,7 +1037,7 @@ VkResult command_copy_buffers(VkDevice device, VkCommandPool transfer_pool, VkQu
VkCommandBuffer command_buffer;
VkResult result = vkAllocateCommandBuffers(device, &command_info, &command_buffer);
if(result != VK_SUCCESS) {
return result;
return VK_NULL_HANDLE;
}
VkCommandBufferBeginInfo begin_info = {};
@ -975,41 +1047,96 @@ VkResult command_copy_buffers(VkDevice device, VkCommandPool transfer_pool, VkQu
result = vkBeginCommandBuffer(command_buffer, &begin_info);
if(result != VK_SUCCESS) {
vkFreeCommandBuffers(device, transfer_pool, 1, &command_buffer);
return result;
return VK_NULL_HANDLE;
}
VkBufferCopy copy_region = {};
copy_region.srcOffset = 0;
copy_region.dstOffset = 0;
copy_region.size = size;
vkCmdCopyBuffer(command_buffer, source, dest, 1, &copy_region);
result = vkEndCommandBuffer(command_buffer);
if(result != VK_SUCCESS) {
vkFreeCommandBuffers(device, transfer_pool, 1, &command_buffer);
return result;
return command_buffer;
}
VkResult command_end_single(VkDevice device, VkCommandBuffer command_buffer, VkCommandPool transfer_pool, VkQueue transfer_queue) {
VkSubmitInfo submit_info = {};
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submit_info.commandBufferCount = 1;
submit_info.pCommandBuffers = &command_buffer;
result = vkQueueSubmit(transfer_queue, 1, &submit_info, 0);
VkResult result = vkQueueSubmit(transfer_queue, 1, &submit_info, 0);
if(result != VK_SUCCESS) {
vkFreeCommandBuffers(device, transfer_pool, 1, &command_buffer);
return result;
}
result = vkQueueWaitIdle(transfer_queue);
if(result != VK_SUCCESS) {
vkFreeCommandBuffers(device, transfer_pool, 1, &command_buffer);
return result;
}
VkResult command_copy_buffers(VkDevice device, VkCommandPool transfer_pool, VkQueue transfer_queue, VkBuffer source, VkBuffer dest, VkDeviceSize size) {
VkCommandBuffer command_buffer = command_begin_single(device, transfer_pool);
VkBufferCopy copy_region = {};
copy_region.srcOffset = 0;
copy_region.dstOffset = 0;
copy_region.size = size;
vkCmdCopyBuffer(command_buffer, source, dest, 1, &copy_region);
VkResult result = vkEndCommandBuffer(command_buffer);
if(result != VK_SUCCESS) {
vkFreeCommandBuffers(device, transfer_pool, 1, &command_buffer);
return result;
}
return VK_SUCCESS;
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) {
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,
.image = image,
.subresourceRange = {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.levelCount = 1,
.layerCount = 1,
.baseMipLevel = 0,
.baseArrayLayer = 0,
},
.srcAccessMask = 0,
.dstAccessMask = 0,
};
vkCmdPipelineBarrier(command_buffer, 0, 0, 0, 0, 0, 0, 0, 1, &barrier);
return command_end_single(device, command_buffer, transfer_pool, transfer_queue);
}
VkResult command_copy_buffer_to_image(VkDevice device, VkCommandPool transfer_pool, VkQueue transfer_queue, VkExtent3D image_size, VkBuffer source, VkImage dest) {
VkCommandBuffer command_buffer = command_begin_single(device, transfer_pool);
VkBufferImageCopy region = {
.bufferOffset = 0,
.bufferRowLength = 0,
.bufferImageHeight = 0,
.imageSubresource = {
.baseArrayLayer = 0,
.layerCount = 1,
.mipLevel = 0,
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
},
.imageOffset = {
.x = 0,
.y = 0,
.z = 0,
},
.imageExtent = image_size,
};
vkCmdCopyBufferToImage(command_buffer, source, dest, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
return command_end_single(device, command_buffer, transfer_pool, transfer_queue);
}
AllocatedBuffer create_populated_buffer(VkPhysicalDevice physical_device, VkDevice device, void* data, VkDeviceSize size, VkCommandPool transfer_pool, VkQueue transfer_queue, VkBufferUsageFlags usage) {
@ -1050,6 +1177,118 @@ AllocatedBuffer create_populated_buffer(VkPhysicalDevice physical_device, VkDevi
return vertex_buffer;
}
Texture load_texture(VkPhysicalDevice physical_device, VkDevice device, VkCommandPool transfer_pool, VkQueue transfer_queue, VkExtent2D size, uint32_t stride, VkFormat format, void* image_data){
Texture ret = {
.image.image = VK_NULL_HANDLE,
.image.memory = VK_NULL_HANDLE,
.view = VK_NULL_HANDLE,
};
uint32_t image_size = size.width * size.height * stride;
AllocatedBuffer staging = allocate_buffer(physical_device, 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;
}
void* staging_ptr;
VkResult result = vkMapMemory(device, staging.memory, 0, image_size, 0, &staging_ptr);
if(result != VK_SUCCESS) {
deallocate_buffer(device, staging);
return ret;
}
memcpy(staging_ptr, image_data, image_size);
vkUnmapMemory(device, staging.memory);
VkExtent3D full_extent = {
.width = size.width,
.height = size.height,
.depth = 1,
};
AllocatedImage image = allocate_image(physical_device, 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, VK_SAMPLE_COUNT_1_BIT);
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);
if(result != VK_SUCCESS) {
deallocate_buffer(device, staging);
deallocate_image(device, image);
return ret;
}
result = command_copy_buffer_to_image(device, transfer_pool, transfer_queue, full_extent, staging.buffer, image.image);
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,
.image = image.image,
.viewType = VK_IMAGE_VIEW_TYPE_2D,
.components = {
.a = VK_COMPONENT_SWIZZLE_IDENTITY,
.b = VK_COMPONENT_SWIZZLE_IDENTITY,
.g = VK_COMPONENT_SWIZZLE_IDENTITY,
.r = VK_COMPONENT_SWIZZLE_IDENTITY,
},
.format = format,
.subresourceRange = {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.layerCount = 1,
.levelCount = 1,
.baseArrayLayer = 0,
.baseMipLevel = 0,
},
};
result = vkCreateImageView(device, &view_info, 0, &view);
if(result != VK_SUCCESS) {
deallocate_buffer(device, staging);
deallocate_image(device, image);
return ret;
}
VkSampler sampler;
VkSamplerCreateInfo sampler_info = {
.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
.magFilter = VK_FILTER_NEAREST,
.minFilter = VK_FILTER_NEAREST,
.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT,
.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT,
.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT,
.anisotropyEnable = VK_TRUE,
.maxAnisotropy = 2,
.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK,
.unnormalizedCoordinates = VK_FALSE,
.compareEnable = VK_FALSE,
.compareOp = VK_COMPARE_OP_ALWAYS,
.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR,
.mipLodBias = 0.0f,
.minLod = 0.0f,
.maxLod = 0.0f,
};
result = vkCreateSampler(device, &sampler_info, 0, &sampler);
if(result != VK_SUCCESS) {
deallocate_buffer(device, staging);
deallocate_image(device, image);
return ret;
}
ret.image = image;
ret.view = view;
ret.sampler = sampler;
return ret;
}
VkPipeline create_graphics_pipeline(
VkDevice device,
VkExtent2D extent,