Implement staging buffer.
This commit is contained in:
@@ -121,6 +121,7 @@ void Context::initialize(const ContextSettings& settings) {
|
|||||||
create_surface(settings);
|
create_surface(settings);
|
||||||
choose_physical_device(settings);
|
choose_physical_device(settings);
|
||||||
create_device(settings);
|
create_device(settings);
|
||||||
|
create_internal_objects();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Context::shutdown() {
|
void Context::shutdown() {
|
||||||
@@ -132,6 +133,9 @@ void Context::shutdown() {
|
|||||||
for(auto& callback: m_context_destruction_callbacks)
|
for(auto& callback: m_context_destruction_callbacks)
|
||||||
callback();
|
callback();
|
||||||
|
|
||||||
|
destroy_fence(m_transfer_fence);
|
||||||
|
destroy_command_pool(m_transfer_command_pool);
|
||||||
|
|
||||||
destroy_device(m_device);
|
destroy_device(m_device);
|
||||||
destroy_surface(m_surface);
|
destroy_surface(m_surface);
|
||||||
destroy_debug_messenger(m_debug_messenger);
|
destroy_debug_messenger(m_debug_messenger);
|
||||||
@@ -334,6 +338,68 @@ std::tuple<VkBuffer, VkDeviceMemory> Context::create_buffer(VkDeviceSize size, V
|
|||||||
return { buffer, memory };
|
return { buffer, memory };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Context::copy_buffer(VkBuffer dst, VkBuffer src, uint32_t dst_queue_family, VkDeviceSize size) {
|
||||||
|
VkCommandBufferAllocateInfo alloc_info {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
|
||||||
|
.commandPool = m_transfer_command_pool,
|
||||||
|
.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
|
||||||
|
.commandBufferCount = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
VkCommandBuffer command_buffer;
|
||||||
|
vkAllocateCommandBuffers(m_device, &alloc_info, &command_buffer);
|
||||||
|
auto const command_buffer_guard = make_guard([this, command_buffer]() {
|
||||||
|
vkFreeCommandBuffers(m_device, m_transfer_command_pool, 1, &command_buffer);
|
||||||
|
});
|
||||||
|
|
||||||
|
VkCommandBufferBeginInfo begin_info {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
|
||||||
|
.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
|
||||||
|
};
|
||||||
|
vkBeginCommandBuffer(command_buffer, &begin_info);
|
||||||
|
|
||||||
|
VkBufferCopy region {
|
||||||
|
.srcOffset = 0,
|
||||||
|
.dstOffset = 0,
|
||||||
|
.size = size,
|
||||||
|
};
|
||||||
|
vkCmdCopyBuffer(command_buffer, src, dst, 1, ®ion);
|
||||||
|
|
||||||
|
VkBufferMemoryBarrier buffer_barrier {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
|
||||||
|
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||||
|
.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT,
|
||||||
|
.srcQueueFamilyIndex = queue_family(VK_QUEUE_TRANSFER_BIT),
|
||||||
|
.dstQueueFamilyIndex = dst_queue_family,
|
||||||
|
.buffer = dst,
|
||||||
|
.offset = 0,
|
||||||
|
.size = size,
|
||||||
|
};
|
||||||
|
vkCmdPipelineBarrier(
|
||||||
|
command_buffer,
|
||||||
|
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
|
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
||||||
|
0,
|
||||||
|
0, nullptr,
|
||||||
|
1, &buffer_barrier,
|
||||||
|
0, nullptr
|
||||||
|
);
|
||||||
|
|
||||||
|
vkEndCommandBuffer(command_buffer);
|
||||||
|
|
||||||
|
VkSubmitInfo submit_info {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
||||||
|
.commandBufferCount = 1,
|
||||||
|
.pCommandBuffers = &command_buffer,
|
||||||
|
};
|
||||||
|
vkQueueSubmit(
|
||||||
|
queue(m_transfer_queue_index),
|
||||||
|
1, &submit_info,
|
||||||
|
m_transfer_fence
|
||||||
|
);
|
||||||
|
vkWaitForFences(m_device, 1, &m_transfer_fence, VK_TRUE, UINT64_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Context::destroy_instance(VkInstance& instance) {
|
void Context::destroy_instance(VkInstance& instance) {
|
||||||
if(instance == nullptr)
|
if(instance == nullptr)
|
||||||
@@ -599,7 +665,8 @@ std::optional<VkPhysicalDeviceProperties> Context::select_physical_device(
|
|||||||
VkPhysicalDeviceProperties device_properties;
|
VkPhysicalDeviceProperties device_properties;
|
||||||
vkGetPhysicalDeviceProperties(physical_device, &device_properties);
|
vkGetPhysicalDeviceProperties(physical_device, &device_properties);
|
||||||
|
|
||||||
m_queue_families.assign(settings.queues().size(), INVALID_QUEUE_FAMILY);
|
m_transfer_queue_index = settings.queues().size();
|
||||||
|
m_queue_families.assign(settings.queues().size() + 1, INVALID_QUEUE_FAMILY);
|
||||||
m_presentation_queue_family = INVALID_QUEUE_FAMILY;
|
m_presentation_queue_family = INVALID_QUEUE_FAMILY;
|
||||||
|
|
||||||
auto const queue_families = this->queue_families(physical_device);
|
auto const queue_families = this->queue_families(physical_device);
|
||||||
@@ -628,6 +695,10 @@ std::optional<VkPhysicalDeviceProperties> Context::select_physical_device(
|
|||||||
m_queue_families[index] = queue_family_index;
|
m_queue_families[index] = queue_family_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(m_queue_families[m_transfer_queue_index] == INVALID_QUEUE_FAMILY
|
||||||
|
&& queue_family.queueFlags == VK_QUEUE_TRANSFER_BIT)
|
||||||
|
m_queue_families[m_transfer_queue_index] = queue_family_index;
|
||||||
|
|
||||||
queue_family_index += 1;
|
queue_family_index += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -734,6 +805,28 @@ void Context::create_device(const ContextSettings& settings) {
|
|||||||
vkGetDeviceQueue(m_device, m_presentation_queue_family, 0, &m_presentation_queue);
|
vkGetDeviceQueue(m_device, m_presentation_queue_family, 0, &m_presentation_queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Context::create_internal_objects() {
|
||||||
|
VkCommandPoolCreateInfo pool_info {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
|
||||||
|
.flags = 0,
|
||||||
|
.queueFamilyIndex = queue_family(m_transfer_queue_index),
|
||||||
|
};
|
||||||
|
if(vkCreateCommandPool(
|
||||||
|
m_device,
|
||||||
|
&pool_info,
|
||||||
|
nullptr,
|
||||||
|
&m_transfer_command_pool
|
||||||
|
) != VK_SUCCESS) {
|
||||||
|
throw std::runtime_error("failed to create command pool");
|
||||||
|
}
|
||||||
|
|
||||||
|
VkFenceCreateInfo fence_info {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
|
||||||
|
};
|
||||||
|
if(vkCreateFence(m_device, &fence_info, nullptr, &m_transfer_fence) != VK_SUCCESS)
|
||||||
|
throw std::runtime_error("failed to create fence");
|
||||||
|
}
|
||||||
|
|
||||||
void Context::initialize_extension_functions() {
|
void Context::initialize_extension_functions() {
|
||||||
uint32_t errors_count = 0;
|
uint32_t errors_count = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -104,6 +104,7 @@ public:
|
|||||||
VkDeviceMemory allocate_memory(VkDeviceSize size, uint32_t type_filter, VkMemoryPropertyFlags properties);
|
VkDeviceMemory allocate_memory(VkDeviceSize size, uint32_t type_filter, VkMemoryPropertyFlags properties);
|
||||||
|
|
||||||
std::tuple<VkBuffer, VkDeviceMemory> create_buffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags memory_properties);
|
std::tuple<VkBuffer, VkDeviceMemory> create_buffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags memory_properties);
|
||||||
|
void copy_buffer(VkBuffer dst, VkBuffer src, uint32_t dst_queue_family, VkDeviceSize size);
|
||||||
|
|
||||||
|
|
||||||
void destroy_instance(VkInstance& instance);
|
void destroy_instance(VkInstance& instance);
|
||||||
@@ -142,6 +143,7 @@ private:
|
|||||||
const ContextSettings& settings
|
const ContextSettings& settings
|
||||||
);
|
);
|
||||||
void create_device(const ContextSettings& settings);
|
void create_device(const ContextSettings& settings);
|
||||||
|
void create_internal_objects();
|
||||||
|
|
||||||
void initialize_extension_functions();
|
void initialize_extension_functions();
|
||||||
|
|
||||||
@@ -172,6 +174,10 @@ private:
|
|||||||
VkSurfaceFormatKHR m_surface_format;
|
VkSurfaceFormatKHR m_surface_format;
|
||||||
VkPresentModeKHR m_present_mode;
|
VkPresentModeKHR m_present_mode;
|
||||||
|
|
||||||
|
uint32_t m_transfer_queue_index = UINT32_MAX;
|
||||||
|
VkCommandPool m_transfer_command_pool = VK_NULL_HANDLE;
|
||||||
|
VkFence m_transfer_fence = VK_NULL_HANDLE;
|
||||||
|
|
||||||
std::vector<ContextDestructionCallback> m_context_destruction_callbacks;
|
std::vector<ContextDestructionCallback> m_context_destruction_callbacks;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -438,17 +438,30 @@ void VulkanTutorial::create_vertex_buffer() {
|
|||||||
|
|
||||||
VkDeviceSize buffer_size = sizeof(vertices[0]) * vertices.size();
|
VkDeviceSize buffer_size = sizeof(vertices[0]) * vertices.size();
|
||||||
|
|
||||||
std::tie(m_vertex_buffer, m_vertex_buffer_memory) = m_context.create_buffer(
|
VkBuffer tmp_buffer = VK_NULL_HANDLE;
|
||||||
|
VkDeviceMemory tmp_buffer_memory = VK_NULL_HANDLE;
|
||||||
|
std::tie(tmp_buffer, tmp_buffer_memory) = m_context.create_buffer(
|
||||||
buffer_size,
|
buffer_size,
|
||||||
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
|
VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
|
||||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
|
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
|
||||||
| VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
|
| VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
|
||||||
);
|
);
|
||||||
|
auto const tmp_buffer_guard = make_guard([&] {
|
||||||
|
m_context.free_memory(tmp_buffer_memory);
|
||||||
|
m_context.destroy_buffer(tmp_buffer);
|
||||||
|
});
|
||||||
|
|
||||||
|
std::tie(m_vertex_buffer, m_vertex_buffer_memory) = m_context.create_buffer(
|
||||||
|
buffer_size,
|
||||||
|
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT
|
||||||
|
| VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
||||||
|
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
|
||||||
|
);
|
||||||
|
|
||||||
void* buffer = nullptr;
|
void* buffer = nullptr;
|
||||||
vkMapMemory(
|
vkMapMemory(
|
||||||
m_context.device(),
|
m_context.device(),
|
||||||
m_vertex_buffer_memory,
|
tmp_buffer_memory,
|
||||||
0,
|
0,
|
||||||
buffer_size,
|
buffer_size,
|
||||||
0,
|
0,
|
||||||
@@ -459,7 +472,14 @@ void VulkanTutorial::create_vertex_buffer() {
|
|||||||
|
|
||||||
vkUnmapMemory(
|
vkUnmapMemory(
|
||||||
m_context.device(),
|
m_context.device(),
|
||||||
m_vertex_buffer_memory
|
tmp_buffer_memory
|
||||||
|
);
|
||||||
|
|
||||||
|
m_context.copy_buffer(
|
||||||
|
m_vertex_buffer,
|
||||||
|
tmp_buffer,
|
||||||
|
m_context.queue_family(GRAPHIC_QUEUE),
|
||||||
|
buffer_size
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user