Merge branch 'blender-v4.4-release'

This commit is contained in:
Jeroen Bakker
2025-02-17 08:58:44 +01:00
5 changed files with 72 additions and 7 deletions

View File

@@ -109,9 +109,32 @@ void VKBuffer::clear(VKContext &context, uint32_t clear_value)
context.render_graph().add_node(fill_buffer);
}
void VKBuffer::read(VKContext &context, void *data) const
void VKBuffer::async_flush_to_host(VKContext &context)
{
BLI_assert(async_timeline_ == 0);
context.rendering_end();
context.descriptor_set_get().upload_descriptor_sets();
async_timeline_ = context.flush_render_graph(RenderGraphFlushFlags::SUBMIT |
RenderGraphFlushFlags::RENEW_RENDER_GRAPH);
}
void VKBuffer::read_async(VKContext &context, void *data)
{
BLI_assert_msg(is_mapped(), "Cannot read a non-mapped buffer.");
if (async_timeline_ == 0) {
async_flush_to_host(context);
}
VKDevice &device = VKBackend::get().device;
device.wait_for_timeline(async_timeline_);
async_timeline_ = 0;
memcpy(data, mapped_memory_, size_in_bytes_);
}
void VKBuffer::read(VKContext &context, void *data) const
{
BLI_assert_msg(is_mapped(), "Cannot read a non-mapped buffer.");
BLI_assert(async_timeline_ == 0);
context.rendering_end();
context.descriptor_set_get().upload_descriptor_sets();
context.flush_render_graph(RenderGraphFlushFlags::SUBMIT |

View File

@@ -25,6 +25,7 @@ class VKBuffer : public NonCopyable {
VkBuffer vk_buffer_ = VK_NULL_HANDLE;
VmaAllocation allocation_ = VK_NULL_HANDLE;
VkMemoryPropertyFlags vk_memory_property_flags_;
TimelineValue async_timeline_ = 0;
/* Pointer to the virtually mapped memory. */
void *mapped_memory_ = nullptr;
@@ -53,8 +54,25 @@ class VKBuffer : public NonCopyable {
*/
void update_render_graph(VKContext &context, void *data) const;
void flush() const;
/**
* Read the buffer (synchronously).
*/
void read(VKContext &context, void *data) const;
/**
* Start a async read-back.
*/
void async_flush_to_host(VKContext &context);
/**
* Wait until the async read back is finished and fill the given data with the content of the
* buffer.
*
* Will start a new async read-back when there is no read back in progress.
*/
void read_async(VKContext &context, void *data);
/**
* Free the buffer.
*

View File

@@ -61,7 +61,7 @@ class VKStagingBuffer {
/**
* Get the reference to the host buffer to update/load the data.
*/
const VKBuffer &host_buffer_get() const
VKBuffer &host_buffer_get()
{
return host_buffer_;
}

View File

@@ -20,6 +20,13 @@ VKStorageBuffer::VKStorageBuffer(size_t size, GPUUsageType usage, const char *na
{
UNUSED_VARS(usage_);
}
VKStorageBuffer::~VKStorageBuffer()
{
if (async_read_buffer_) {
MEM_delete(async_read_buffer_);
async_read_buffer_ = nullptr;
}
}
void VKStorageBuffer::update(const void *data)
{
@@ -94,16 +101,28 @@ void VKStorageBuffer::copy_sub(VertBuf *src, uint dst_offset, uint src_offset, u
void VKStorageBuffer::async_flush_to_host()
{
GPU_memory_barrier(GPU_BARRIER_BUFFER_UPDATE);
if (async_read_buffer_ != nullptr) {
return;
}
ensure_allocated();
VKContext &context = *VKContext::get();
async_read_buffer_ = MEM_new<VKStagingBuffer>(
__func__, buffer_, VKStagingBuffer::Direction::DeviceToHost);
async_read_buffer_->copy_from_device(context);
async_read_buffer_->host_buffer_get().async_flush_to_host(context);
}
void VKStorageBuffer::read(void *data)
{
ensure_allocated();
if (async_read_buffer_ == nullptr) {
async_flush_to_host();
}
VKContext &context = *VKContext::get();
VKStagingBuffer staging_buffer(buffer_, VKStagingBuffer::Direction::DeviceToHost);
staging_buffer.copy_from_device(context);
staging_buffer.host_buffer_get().read(context, data);
async_read_buffer_->host_buffer_get().read_async(context, data);
MEM_delete(async_read_buffer_);
async_read_buffer_ = nullptr;
}
} // namespace blender::gpu

View File

@@ -14,6 +14,7 @@
#include "gpu_storage_buffer_private.hh"
#include "vk_buffer.hh"
#include "vk_staging_buffer.hh"
namespace blender::gpu {
class VertBuf;
@@ -22,8 +23,12 @@ class VKStorageBuffer : public StorageBuf {
GPUUsageType usage_;
VKBuffer buffer_;
/** Staging buffer that is used when doing an async read-back. */
VKStagingBuffer *async_read_buffer_ = nullptr;
public:
VKStorageBuffer(size_t size, GPUUsageType usage, const char *name);
~VKStorageBuffer();
void update(const void *data) override;
void bind(int slot) override;