Reworking GPU buffers\n

main
noah metz 2024-01-11 22:49:53 -07:00
parent f76df2b222
commit a76f9cd135
1 changed files with 209 additions and 0 deletions

@ -2355,6 +2355,215 @@ Material create_texture_mesh_material(VkDevice device, VkExtent2D extent, VkRend
return create_material(device, extent, render_pass, 2, shader_stages, scene_ubo_layout, texture_layout, textured_mesh_type, max_frames_in_flight, object_descriptor_mappings); return create_material(device, extent, render_pass, 2, shader_stages, scene_ubo_layout, texture_layout, textured_mesh_type, max_frames_in_flight, object_descriptor_mappings);
} }
typedef struct MemoryChunkStruct {
VkDeviceMemory memory;
VkDeviceSize free;
} MemoryChunk;
VkResult allocate_memory_chunk(uint32_t memory_type, VkDevice device, VkDeviceSize size, MemoryChunk* allocated) {
if(allocated == NULL) {
return VK_ERROR_UNKNOWN;
}
VkMemoryAllocateInfo allocate_info = {
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
.memoryTypeIndex = memory_type,
.allocationSize = size,
};
VkResult result = vkAllocateMemory(device, &allocate_info, 0, &allocated->memory);
if(result != VK_SUCCESS) {
return result;
}
allocated->free = size;
return VK_SUCCESS;
}
VkResult create_image(MemoryChunk* memory, VkDevice device, VkDeviceSize offset, VkImageType type, VkFormat format, VkExtent3D extent, VkImageUsageFlags usage, VkImage* image) {
if(image == NULL) {
return VK_ERROR_UNKNOWN;
} else if (*image != VK_NULL_HANDLE) {
return VK_ERROR_UNKNOWN;
} else if (memory == NULL) {
return VK_ERROR_UNKNOWN;
}
VkImageCreateInfo image_info = {
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
.imageType = type,
.extent = extent,
.mipLevels = 1,
.arrayLayers = 1,
.format = format,
.tiling = VK_IMAGE_TILING_OPTIMAL,
.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
.usage = usage,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
.samples = VK_SAMPLE_COUNT_1_BIT,
.flags = 0,
};
VkResult result = vkCreateImage(device, &image_info, 0, image);
if(result != VK_SUCCESS) {
return result;
}
result = vkBindImageMemory(device, *image, memory->memory, offset);
if(result != VK_SUCCESS) {
vkDestroyImage(device, *image, 0);
*image = VK_NULL_HANDLE;
return result;
}
VkMemoryRequirements memory_requirements;
vkGetImageMemoryRequirements(device, *image, &memory_requirements);
memory->free -= memory_requirements.size;
return VK_SUCCESS;
}
VkResult create_buffer(MemoryChunk* memory, VkDevice device, VkDeviceSize offset, VkDeviceSize size, VkBufferUsageFlags usage, VkBuffer* buffer) {
if(buffer == NULL) {
return VK_ERROR_UNKNOWN;
} else if (*buffer != VK_NULL_HANDLE) {
return VK_ERROR_UNKNOWN;
} else if (memory == NULL) {
return VK_ERROR_UNKNOWN;
} else if (memory->free < size) {
return VK_ERROR_UNKNOWN;
}
VkBufferCreateInfo buffer_info = {
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.size = size,
.usage = usage,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
};
VkResult result = vkCreateBuffer(device, &buffer_info, 0, buffer);
if(result != VK_SUCCESS) {
return result;
}
VkMemoryRequirements memory_requirements;
vkGetBufferMemoryRequirements(device, *buffer, &memory_requirements);
result = vkBindBufferMemory(device, *buffer, memory->memory, offset);
if(result != VK_SUCCESS) {
vkDestroyBuffer(device, *buffer, 0);
*buffer = VK_NULL_HANDLE;
return result;
}
memory->free -= size;
return VK_SUCCESS;
}
VkResult create_buffers(MemoryChunk* memory, VkDevice device, VkDeviceSize offset, VkDeviceSize size, VkBufferUsageFlags usage, VkBuffer** buffers, uint32_t count) {
if(buffers == NULL) {
return VK_ERROR_UNKNOWN;
} else if(*buffers == NULL) {
return VK_ERROR_UNKNOWN;
}
*buffers = malloc(sizeof(VkBuffer)*count);
if(*buffers == NULL) {
return VK_ERROR_OUT_OF_HOST_MEMORY;
}
for(uint32_t i = 0; i < count; i++) {
VkResult result = create_buffer(memory, device, offset + (i*size), size, usage, &(*buffers)[i]);
if(result != VK_SUCCESS) {
for(uint32_t j = 0; j < i; j++) {
vkDestroyBuffer(device, *buffers[j], 0);
}
free(buffers);
return result;
}
}
return VK_SUCCESS;
}
VkResult command_copy_to_image(VkDevice device, VkBuffer staging_buffer, VkDeviceMemory staging_memory, VkImage destination, void* data, VkExtent3D size, VkDeviceSize stride, VkCommandPool pool, VkQueue queue) {
VkDeviceSize data_size = size.height * size.width * stride;
void* mapped_ptr = NULL;
VkResult result = vkMapMemory(device, staging_memory, 0, data_size, 0, &mapped_ptr);
if(result != VK_SUCCESS) {
vkDestroyBuffer(device, staging_buffer, 0);
return result;
}
memcpy(mapped_ptr, data, data_size);
vkUnmapMemory(device, staging_memory);
VkCommandBuffer command_buffer = command_begin_single(device, pool);
if(command_buffer == VK_NULL_HANDLE) {
vkDestroyBuffer(device, staging_buffer, 0);
return VK_ERROR_UNKNOWN;
}
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 = size,
};
vkCmdCopyBufferToImage(command_buffer, staging_buffer, destination, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
result = command_end_single(device, command_buffer, pool, queue);
vkDestroyBuffer(device, staging_buffer, 0);
return result;
}
VkResult command_copy_to_buffer(VkDevice device, VkBuffer staging_buffer, VkDeviceMemory staging_memory, VkBuffer destination, void* data, VkDeviceSize size, VkDeviceSize offset, VkCommandPool pool, VkQueue queue) {
void* mapped_ptr = NULL;
VkResult result = vkMapMemory(device, staging_memory, 0, size, 0, &mapped_ptr);
if(result != VK_SUCCESS) {
vkDestroyBuffer(device, staging_buffer, 0);
return result;
}
memcpy(mapped_ptr, data, size);
vkUnmapMemory(device, staging_memory);
VkCommandBuffer command_buffer = command_begin_single(device, pool);
if(command_buffer == VK_NULL_HANDLE) {
vkDestroyBuffer(device, staging_buffer, 0);
return VK_ERROR_UNKNOWN;
}
VkBufferCopy region = {
.srcOffset = 0,
.dstOffset = offset,
.size = size,
};
vkCmdCopyBuffer(command_buffer, staging_buffer, destination, 1, &region);
result = command_end_single(device, command_buffer, pool, queue);
vkDestroyBuffer(device, staging_buffer, 0);
return result;
}
VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) { VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) {
VulkanContext* context = (VulkanContext*)malloc(sizeof(VulkanContext)); VulkanContext* context = (VulkanContext*)malloc(sizeof(VulkanContext));