Merge branch 'blender-v4.4-release'
This commit is contained in:
@@ -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 |
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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_;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user