Skip to content

Commit 490ce72

Browse files
committed
Reduce Vulkan animated RT buffer churn
1 parent 469a732 commit 490ce72

8 files changed

Lines changed: 510 additions & 181 deletions

File tree

frame/vulkan/buffer.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,27 @@ void Buffer::Copy(const std::vector<std::uint8_t>& vector) const
116116
IncrementGeneration(generation_);
117117
}
118118

119+
bool Buffer::CopyRange(
120+
std::size_t offset,
121+
const std::vector<std::uint8_t>& vector) const
122+
{
123+
if (vector.empty())
124+
{
125+
return false;
126+
}
127+
if (offset > data_.size() || vector.size() > data_.size() - offset)
128+
{
129+
throw std::out_of_range("Buffer::CopyRange exceeds destination size.");
130+
}
131+
if (std::memcmp(data_.data() + offset, vector.data(), vector.size()) == 0)
132+
{
133+
return false;
134+
}
135+
std::memcpy(data_.data() + offset, vector.data(), vector.size());
136+
IncrementGeneration(generation_);
137+
return true;
138+
}
139+
119140
void Buffer::Clear() const
120141
{
121142
const bool already_zero = std::all_of(

frame/vulkan/buffer.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ class Buffer : public frame::BufferInterface
2020
void Copy(const std::vector<float>& vector) const override;
2121
void Copy(const std::vector<std::uint32_t>& vector) const override;
2222
void Copy(const std::vector<std::uint8_t>& vector) const override;
23+
bool CopyRange(
24+
std::size_t offset,
25+
const std::vector<std::uint8_t>& vector) const;
2326
void Clear() const override;
2427
std::size_t GetSize() const override;
2528
void BindBase(int /*binding*/) const override

frame/vulkan/buffer_resources.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,58 @@ bool BufferResourceManager::UpdateStorageBuffer(
216216
return true;
217217
}
218218

219+
bool BufferResourceManager::UpdateStorageBufferRange(
220+
const std::string& name,
221+
const std::vector<std::uint8_t>& bytes,
222+
std::size_t offset_bytes)
223+
{
224+
if (bytes.empty())
225+
{
226+
return false;
227+
}
228+
auto it = storage_buffer_indices_.find(name);
229+
if (it == storage_buffer_indices_.end())
230+
{
231+
return false;
232+
}
233+
auto& resource = storage_buffers_[it->second];
234+
if (!resource.buffer || resource.size == 0)
235+
{
236+
return false;
237+
}
238+
if (offset_bytes > static_cast<std::size_t>(resource.size) ||
239+
bytes.size() >
240+
static_cast<std::size_t>(resource.size) - offset_bytes)
241+
{
242+
(*logger_)->warn(
243+
"Storage buffer '{}' range update [{}..{}) exceeds resource size {}.",
244+
name,
245+
offset_bytes,
246+
offset_bytes + bytes.size(),
247+
static_cast<std::size_t>(resource.size));
248+
return false;
249+
}
250+
251+
vk::UniqueDeviceMemory staging_memory;
252+
auto staging_buffer = memory_manager_->CreateBuffer(
253+
bytes.size(),
254+
vk::BufferUsageFlagBits::eTransferSrc,
255+
vk::MemoryPropertyFlagBits::eHostVisible |
256+
vk::MemoryPropertyFlagBits::eHostCoherent,
257+
staging_memory);
258+
void* mapped = device_.mapMemory(
259+
*staging_memory, 0, bytes.size());
260+
std::memcpy(mapped, bytes.data(), bytes.size());
261+
device_.unmapMemory(*staging_memory);
262+
command_queue_->CopyBuffer(
263+
*staging_buffer,
264+
*resource.buffer,
265+
static_cast<vk::DeviceSize>(bytes.size()),
266+
0,
267+
static_cast<vk::DeviceSize>(offset_bytes));
268+
return true;
269+
}
270+
219271
void BufferResourceManager::BuildUniformBuffers(
220272
std::size_t count,
221273
vk::DeviceSize size_bytes)

frame/vulkan/buffer_resources.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ class BufferResourceManager
3939
bool UpdateStorageBuffer(
4040
const std::string& name,
4141
const std::vector<std::uint8_t>& bytes);
42+
bool UpdateStorageBufferRange(
43+
const std::string& name,
44+
const std::vector<std::uint8_t>& bytes,
45+
std::size_t offset_bytes);
4246
void BuildUniformBuffers(
4347
std::size_t count,
4448
vk::DeviceSize size_bytes);

frame/vulkan/command_queue.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,14 @@ void CommandQueue::EndOneTime(vk::CommandBuffer command_buffer) const
4848
}
4949

5050
void CommandQueue::CopyBuffer(
51-
vk::Buffer src, vk::Buffer dst, vk::DeviceSize size) const
51+
vk::Buffer src,
52+
vk::Buffer dst,
53+
vk::DeviceSize size,
54+
vk::DeviceSize src_offset,
55+
vk::DeviceSize dst_offset) const
5256
{
5357
auto command_buffer = BeginOneTime();
54-
vk::BufferCopy copy_region(0, 0, size);
58+
vk::BufferCopy copy_region(src_offset, dst_offset, size);
5559
command_buffer.copyBuffer(src, dst, copy_region);
5660
EndOneTime(command_buffer);
5761
}

frame/vulkan/command_queue.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,12 @@ class CommandQueue
3434
}
3535
}
3636

37-
void CopyBuffer(vk::Buffer src, vk::Buffer dst, vk::DeviceSize size) const;
37+
void CopyBuffer(
38+
vk::Buffer src,
39+
vk::Buffer dst,
40+
vk::DeviceSize size,
41+
vk::DeviceSize src_offset = 0,
42+
vk::DeviceSize dst_offset = 0) const;
3843
void CopyBufferToImage(
3944
vk::Buffer buffer,
4045
vk::Image image,

0 commit comments

Comments
 (0)