Skip to content

Add multi-data staging to vk::buffer::transfer support #90

Description

@mrparmesan01

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

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions