Task Brief
This issue is also a continuation for GitHub issue #43 .
Currently vk::buffer::transfer works well for single arbitrary of data transfers via a single std::span<T>. When needing to perform multiple transfer operations, this API does not handle those complex operations nicely.
Example of this can be noticeable with loading a 6-face skybox. Where we upload individual faces of a skybox or batching texture arrays.
We should extend our API to natively support multiple parts of transfers within a single map/unmap lifecycle.
Proposed Changes
Introducing an overloaded transfer function that accepts any std::ranges::forward_range, where elements can be viewed as a std::span.
Proposal Implementation Changes
template<typename Range> requires std::ranges::forward_range<Range>
void transfer(Range&& p_data, uint64_t p_offset = 0) {
for(const auto& data : p_data){
total_size += std::span{data}.size_bytes();
}
void* mapped=nullptr;
vk_check(vkMapMemory(m_device, m_device_memory, total_size, 0, &mapped), "vkMapMemory");
auto* mapped_bytes = static_cast<uint8_t*>(mapped);
uint64_t current_offset = 0;
for(const auto& data : p_data) {
auto s = std::span{data};
std::memcpy(mapped_bytes + current_offset, s.data(), s.size_bytes());
current_offset += s.size_bytes();
}
vk_check(vkUnmapMemory(m_device, m_device_memory), "vkUnmapMemory");
}
Advantages
- Minimize CPU-to-GPU data transfers under a single
vkMapMemory/vkUnmapMemory lifecycle.
- Eliminates manual offset arithmetic (mapped_bytes + offset) in user application logic
- Using C++20
<ranges> to keep implementation type-safe and standard-container agnostic. (minimal data copying).
Task Completion Expectation
We should be able to perform skybox operations of uploading pixels for all 6 faces under a single vkMapMemory/vkUnmapMemory operation.
It should work as if we are doing the following:
std::array<std::span<const uint8_t>, 6> faces_pixels_data = m_skybox.data();
// write and manage all buffer offsets in one vkMapMemory/vkUnmapMemory lifecycle
staging_buffer.transfer(faces_pixels_data);
Task Brief
This issue is also a continuation for GitHub issue #43 .
Currently
vk::buffer::transferworks well for single arbitrary of data transfers via a singlestd::span<T>. When needing to perform multiple transfer operations, this API does not handle those complex operations nicely.Example of this can be noticeable with loading a 6-face skybox. Where we upload individual faces of a skybox or batching texture arrays.
We should extend our API to natively support multiple parts of transfers within a single map/unmap lifecycle.
Proposed Changes
Introducing an overloaded
transferfunction that accepts anystd::ranges::forward_range, where elements can be viewed as astd::span.Proposal Implementation Changes
Advantages
vkMapMemory/vkUnmapMemorylifecycle.<ranges>to keep implementation type-safe and standard-container agnostic. (minimal data copying).Task Completion Expectation
We should be able to perform skybox operations of uploading pixels for all 6 faces under a single vkMapMemory/vkUnmapMemory operation.
It should work as if we are doing the following: