|
|
@ -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; |
|
|
|
|
|
|
|
|
|