Skip to content

Commit

Permalink
Update uniform sub-buffers to the latest data before using
Browse files Browse the repository at this point in the history
  • Loading branch information
adrian-cojocaru committed Dec 16, 2024
1 parent c6f08c6 commit fd10156
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 19 deletions.
14 changes: 9 additions & 5 deletions include/mbgl/vulkan/buffer_resource.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,18 @@ class BufferResource {
void update(const void* data, std::size_t size, std::size_t offset) noexcept;

std::size_t getSizeInBytes() const noexcept { return size; }
const void* contents() const noexcept { return (raw.empty() ? nullptr : raw.data()); }
const void* contents() const noexcept;
const void* contents(uint8_t resourceIndex) const noexcept;

Context& getContext() const noexcept { return context; }
const vk::Buffer& getVulkanBuffer() const noexcept { return bufferAllocation->buffer; }
std::size_t getVulkanBufferOffset() const noexcept;
std::size_t getVulkanBufferSize() const noexcept;
std::size_t getVulkanBufferOffset(uint8_t resourceIndex) const noexcept;
// update the current sub-buffer with the latest data
void updateVulkanBuffer();
void updateVulkanBuffer(const int8_t destination, const uint8_t source);

bool isValid() const noexcept { return !raw.empty(); }
bool isValid() const noexcept { return !!bufferAllocation; }
operator bool() const noexcept { return isValid(); }
bool operator!() const noexcept { return !isValid(); }

Expand All @@ -69,14 +73,14 @@ class BufferResource {

protected:
Context& context;
std::vector<std::uint8_t> raw;
std::size_t size;
std::uint32_t usage;
std::uint16_t version = 0;
VersionType version = 0;
bool persistent;

SharedBufferAllocation bufferAllocation;
size_t bufferWindowSize = 0;
std::vector<VersionType> bufferWindowVersions;
};

} // namespace vulkan
Expand Down
72 changes: 58 additions & 14 deletions src/mbgl/vulkan/buffer_resource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,10 @@ BufferResource::BufferResource(

assert(bufferWindowSize != 0);

totalSize = bufferWindowSize * backend.getMaxFrames();
const auto frameCount = backend.getMaxFrames();
totalSize = bufferWindowSize * frameCount;

bufferWindowVersions = std::vector<std::uint16_t>(frameCount, 0);
}

const auto bufferInfo = vk::BufferCreateInfo()
Expand All @@ -87,9 +90,7 @@ BufferResource::BufferResource(
vmaMapMemory(allocator, bufferAllocation->allocation, &bufferAllocation->mappedBuffer);

if (data) {
raw.resize(size);
std::memcpy(raw.data(), data, size);
std::memcpy(static_cast<uint8_t*>(bufferAllocation->mappedBuffer) + getVulkanBufferOffset(), data, size);
update(data, size, 0);
}

if (isValid()) {
Expand All @@ -104,12 +105,13 @@ BufferResource::BufferResource(

BufferResource::BufferResource(BufferResource&& other) noexcept
: context(other.context),
raw(std::move(other.raw)),
size(other.size),
usage(other.usage),
persistent(other.persistent),
bufferAllocation(std::move(other.bufferAllocation)),
bufferWindowSize(other.bufferWindowSize) {
bufferWindowSize(other.bufferWindowSize),
version(other.version),
bufferWindowVersions(std::move(other.bufferWindowVersions)) {
other.bufferAllocation = nullptr;
}

Expand All @@ -134,7 +136,7 @@ BufferResource& BufferResource::operator=(BufferResource&& other) noexcept {
context.renderingStats().numBuffers--;
context.renderingStats().memBuffers -= size;
};
raw = std::move(other.raw);

size = other.size;
usage = other.usage;
persistent = other.persistent;
Expand All @@ -152,21 +154,63 @@ void BufferResource::update(const void* newData, std::size_t updateSize, std::si
return;
}

auto& stats = context.renderingStats();
uint8_t* data = static_cast<uint8_t*>(bufferAllocation->mappedBuffer) + getVulkanBufferOffset() + offset;
std::memcpy(data, newData, updateSize);

std::memcpy(raw.data() + offset, newData, updateSize);
std::memcpy(
static_cast<uint8_t*>(bufferAllocation->mappedBuffer) + getVulkanBufferOffset() + offset, newData, updateSize);
auto& stats = context.renderingStats();
stats.bufferUpdateBytes += updateSize;

stats.bufferUpdates++;
version++;

if (bufferWindowSize) {
const auto frameIndex = context.getCurrentFrameResourceIndex();
bufferWindowVersions[frameIndex] = version;
}
}

const void* BufferResource::contents() const noexcept {
return contents(context.getCurrentFrameResourceIndex());
}

const void* BufferResource::contents(uint8_t resourceIndex) const noexcept {
if (!isValid()) {
return nullptr;
}

return static_cast<uint8_t*>(bufferAllocation->mappedBuffer) + getVulkanBufferOffset(resourceIndex);
}

std::size_t BufferResource::getVulkanBufferOffset() const noexcept {
if (bufferWindowSize > 0) return 0;
return getVulkanBufferOffset(context.getCurrentFrameResourceIndex());
}

std::size_t BufferResource::getVulkanBufferOffset(std::uint8_t resourceIndex) const noexcept {
assert(context.getBackend().getMaxFrames() >= resourceIndex);
return bufferWindowSize ? resourceIndex * bufferWindowSize : 0;
}

void BufferResource::updateVulkanBuffer() {
const auto frameCount = context.getBackend().getMaxFrames();

const int8_t currentIndex = context.getCurrentFrameResourceIndex();
const int8_t prevIndex = currentIndex == 0 ? frameCount - 1 : currentIndex - 1;

updateVulkanBuffer(currentIndex, prevIndex);
}

void BufferResource::updateVulkanBuffer(const int8_t destination, const uint8_t source) {
if (!bufferWindowSize) {
return;
}

if (bufferWindowVersions[destination] < bufferWindowVersions[source]) {
uint8_t* dstData = static_cast<uint8_t*>(bufferAllocation->mappedBuffer) + bufferWindowSize * destination;
uint8_t* srcData = static_cast<uint8_t*>(bufferAllocation->mappedBuffer) + bufferWindowSize * source;

std::memcpy(dstData, srcData, size);

return context.getCurrentFrameResourceIndex() * bufferWindowSize;
bufferWindowVersions[destination] = bufferWindowVersions[source];
}
}

} // namespace vulkan
Expand Down
16 changes: 16 additions & 0 deletions src/mbgl/vulkan/uniform_buffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,22 @@ void UniformBufferArray::bindDescriptorSets(CommandEncoder& encoder) {
}

descriptorSet->update(*this, descriptorStartIndex, descriptorBindingCount);

const auto frameCount = encoder.getContext().getBackend().getMaxFrames();
const int32_t currentIndex = encoder.getContext().getCurrentFrameResourceIndex();
const int32_t prevIndex = currentIndex == 0 ? frameCount - 1 : currentIndex - 1;

for (uint32_t i = 0; i < descriptorBindingCount; ++i) {
const uint32_t index = descriptorStartIndex + i;

if (!uniformBufferVector[index]) {
continue;
}

auto& buff = static_cast<UniformBuffer*>(uniformBufferVector[index].get())->mutableBufferResource();
buff.updateVulkanBuffer(currentIndex, prevIndex);
}

descriptorSet->bind(encoder);
}

Expand Down

0 comments on commit fd10156

Please sign in to comment.