Skip to content

Commit a3d89cc

Browse files
committed
Fix Vulkan RT pipelining frame state
1 parent fa51715 commit a3d89cc

3 files changed

Lines changed: 121 additions & 57 deletions

File tree

frame/vulkan/buffer_resources.cpp

Lines changed: 40 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ void BufferResourceManager::Clear()
2323
{
2424
storage_buffers_.clear();
2525
storage_buffer_indices_.clear();
26-
uniform_buffer_ = {};
26+
uniform_buffers_.clear();
2727
}
2828

2929
BufferResource BufferResourceManager::MakeGpuBuffer(
@@ -216,57 +216,74 @@ bool BufferResourceManager::UpdateStorageBuffer(
216216
return true;
217217
}
218218

219-
void BufferResourceManager::BuildUniformBuffer(vk::DeviceSize size_bytes)
219+
void BufferResourceManager::BuildUniformBuffers(
220+
std::size_t count,
221+
vk::DeviceSize size_bytes)
220222
{
221-
if (size_bytes == 0)
223+
if (count == 0 || size_bytes == 0)
222224
{
223-
throw std::runtime_error("Uniform buffer size must be non-zero.");
225+
throw std::runtime_error(
226+
"Uniform buffer count and size must be non-zero.");
224227
}
225228

226-
vk::UniqueDeviceMemory uniform_memory;
227-
auto uniform_buf = memory_manager_->CreateBuffer(
228-
size_bytes,
229-
vk::BufferUsageFlagBits::eUniformBuffer,
230-
vk::MemoryPropertyFlagBits::eHostVisible |
231-
vk::MemoryPropertyFlagBits::eHostCoherent,
232-
uniform_memory);
229+
uniform_buffers_.clear();
230+
uniform_buffers_.reserve(count);
231+
for (std::size_t i = 0; i < count; ++i)
232+
{
233+
vk::UniqueDeviceMemory uniform_memory;
234+
auto uniform_buf = memory_manager_->CreateBuffer(
235+
size_bytes,
236+
vk::BufferUsageFlagBits::eUniformBuffer,
237+
vk::MemoryPropertyFlagBits::eHostVisible |
238+
vk::MemoryPropertyFlagBits::eHostCoherent,
239+
uniform_memory);
233240

234-
uniform_buffer_.name = "uniforms";
235-
uniform_buffer_.size = size_bytes;
236-
uniform_buffer_.buffer = std::move(uniform_buf);
237-
uniform_buffer_.memory = std::move(uniform_memory);
241+
BufferResource uniform_buffer = {};
242+
uniform_buffer.name = "uniforms_" + std::to_string(i);
243+
uniform_buffer.size = size_bytes;
244+
uniform_buffer.buffer = std::move(uniform_buf);
245+
uniform_buffer.memory = std::move(uniform_memory);
246+
uniform_buffers_.push_back(std::move(uniform_buffer));
247+
}
238248
}
239249

240250
void BufferResourceManager::UpdateUniform(
251+
std::size_t index,
241252
const void* data,
242253
std::size_t byte_count) const
243254
{
244-
if (!uniform_buffer_.buffer ||
245-
!uniform_buffer_.memory ||
246-
uniform_buffer_.size == 0)
255+
if (index >= uniform_buffers_.size())
256+
{
257+
(*logger_)->warn("Uniform buffer index {} is out of range.", index);
258+
return;
259+
}
260+
const auto& uniform_buffer = uniform_buffers_[index];
261+
if (!uniform_buffer.buffer ||
262+
!uniform_buffer.memory ||
263+
uniform_buffer.size == 0)
247264
{
248265
(*logger_)->warn("Uniform buffer not initialized before update.");
249266
return;
250267
}
251-
if (byte_count > static_cast<std::size_t>(uniform_buffer_.size))
268+
if (byte_count > static_cast<std::size_t>(uniform_buffer.size))
252269
{
253270
(*logger_)->warn(
254271
"Uniform update size {} exceeds buffer capacity {}.",
255272
byte_count,
256-
static_cast<std::size_t>(uniform_buffer_.size));
273+
static_cast<std::size_t>(uniform_buffer.size));
257274
return;
258275
}
259276
void* mapped = device_.mapMemory(
260-
*uniform_buffer_.memory, 0, uniform_buffer_.size);
277+
*uniform_buffer.memory, 0, uniform_buffer.size);
261278
if (data && byte_count > 0)
262279
{
263280
std::memcpy(mapped, data, byte_count);
264281
}
265282
else
266283
{
267-
std::memset(mapped, 0, uniform_buffer_.size);
284+
std::memset(mapped, 0, uniform_buffer.size);
268285
}
269-
device_.unmapMemory(*uniform_buffer_.memory);
286+
device_.unmapMemory(*uniform_buffer.memory);
270287
}
271288

272289
void BufferResourceManager::LogCpuBufferSamples(

frame/vulkan/buffer_resources.h

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,17 +39,39 @@ class BufferResourceManager
3939
bool UpdateStorageBuffer(
4040
const std::string& name,
4141
const std::vector<std::uint8_t>& bytes);
42-
void BuildUniformBuffer(vk::DeviceSize size_bytes);
43-
void UpdateUniform(const void* data, std::size_t byte_count) const;
42+
void BuildUniformBuffers(
43+
std::size_t count,
44+
vk::DeviceSize size_bytes);
45+
void BuildUniformBuffer(vk::DeviceSize size_bytes)
46+
{
47+
BuildUniformBuffers(1, size_bytes);
48+
}
49+
void UpdateUniform(
50+
std::size_t index,
51+
const void* data,
52+
std::size_t byte_count) const;
53+
void UpdateUniform(const void* data, std::size_t byte_count) const
54+
{
55+
UpdateUniform(0, data, byte_count);
56+
}
4457

4558
const std::vector<BufferResource>& GetStorageBuffers() const
4659
{
4760
return storage_buffers_;
4861
}
4962

63+
const BufferResource* GetUniformBuffer(std::size_t index) const
64+
{
65+
if (index >= uniform_buffers_.size())
66+
{
67+
return nullptr;
68+
}
69+
return uniform_buffers_[index].buffer ? &uniform_buffers_[index]
70+
: nullptr;
71+
}
5072
const BufferResource* GetUniformBuffer() const
5173
{
52-
return uniform_buffer_.buffer ? &uniform_buffer_ : nullptr;
74+
return GetUniformBuffer(0);
5375
}
5476

5577
void LogCpuBufferSamples(
@@ -69,7 +91,7 @@ class BufferResourceManager
6991
const Logger* logger_;
7092
std::vector<BufferResource> storage_buffers_;
7193
std::unordered_map<std::string, std::size_t> storage_buffer_indices_;
72-
BufferResource uniform_buffer_;
94+
std::vector<BufferResource> uniform_buffers_;
7395
};
7496

7597
} // namespace frame::vulkan

frame/vulkan/device.cpp

Lines changed: 55 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3213,14 +3213,15 @@ void Device::RecordCommandBuffer(
32133213
{
32143214
return;
32153215
}
3216-
if (!buffer_resources_->GetUniformBuffer())
3217-
{
3218-
return;
3219-
}
3220-
auto block = MakeUniformBlock(
3221-
state, elapsed_time_seconds_);
3222-
buffer_resources_->UpdateUniform(
3223-
&block, sizeof(UniformBlock));
3216+
if (!buffer_resources_->GetUniformBuffer(current_frame_))
3217+
{
3218+
return;
3219+
}
3220+
auto block = MakeUniformBlock(
3221+
state, elapsed_time_seconds_);
3222+
buffer_resources_->UpdateUniform(
3223+
current_frame_,
3224+
&block, sizeof(UniformBlock));
32243225
};
32253226
update_uniform_buffer(scene_state);
32263227

@@ -3310,13 +3311,27 @@ void Device::RecordCommandBuffer(
33103311
compute_output_in_shader_read_ = false;
33113312
}
33123313

3313-
if (use_raytracing_pipeline_ &&
3314-
raytracing_pipeline_ &&
3315-
raytracing_pipeline_layout_)
3316-
{
3317-
command_buffer.bindPipeline(
3318-
vk::PipelineBindPoint::eRayTracingKHR,
3319-
*raytracing_pipeline_);
3314+
if (use_raytracing_pipeline_ &&
3315+
raytracing_pipeline_ &&
3316+
raytracing_pipeline_layout_)
3317+
{
3318+
if (use_hardware_raytracing_)
3319+
{
3320+
vk::MemoryBarrier acceleration_structure_barrier(
3321+
vk::AccessFlagBits::eAccelerationStructureWriteKHR,
3322+
vk::AccessFlagBits::eAccelerationStructureReadKHR |
3323+
vk::AccessFlagBits::eShaderRead);
3324+
command_buffer.pipelineBarrier(
3325+
vk::PipelineStageFlagBits::eAccelerationStructureBuildKHR,
3326+
vk::PipelineStageFlagBits::eRayTracingShaderKHR,
3327+
{},
3328+
acceleration_structure_barrier,
3329+
nullptr,
3330+
nullptr);
3331+
}
3332+
command_buffer.bindPipeline(
3333+
vk::PipelineBindPoint::eRayTracingKHR,
3334+
*raytracing_pipeline_);
33203335
command_buffer.bindDescriptorSets(
33213336
vk::PipelineBindPoint::eRayTracingKHR,
33223337
*raytracing_pipeline_layout_,
@@ -4987,18 +5002,28 @@ void Device::CreateDescriptorResources()
49875002
}
49885003

49895004

4990-
const BufferResource* uniform = nullptr;
4991-
if (!uniform_bindings.empty())
4992-
{
4993-
buffer_resources_->BuildUniformBuffer(
4994-
static_cast<vk::DeviceSize>(sizeof(UniformBlock)));
4995-
uniform = buffer_resources_->GetUniformBuffer();
4996-
if (!uniform)
4997-
{
4998-
logger_->error("Failed to allocate Vulkan uniform buffer.");
4999-
return;
5000-
}
5001-
}
5005+
std::array<const BufferResource*, kMaxFramesInFlight> uniforms = {};
5006+
if (!uniform_bindings.empty())
5007+
{
5008+
buffer_resources_->BuildUniformBuffers(
5009+
kMaxFramesInFlight,
5010+
static_cast<vk::DeviceSize>(sizeof(UniformBlock)));
5011+
bool have_uniforms = true;
5012+
for (std::size_t frame = 0; frame < uniforms.size(); ++frame)
5013+
{
5014+
uniforms[frame] = buffer_resources_->GetUniformBuffer(frame);
5015+
if (!uniforms[frame])
5016+
{
5017+
have_uniforms = false;
5018+
break;
5019+
}
5020+
}
5021+
if (!have_uniforms)
5022+
{
5023+
logger_->error("Failed to allocate Vulkan uniform buffers.");
5024+
return;
5025+
}
5026+
}
50025027

50035028
std::vector<vk::DescriptorImageInfo> texture_infos;
50045029
if (!texture_ids.empty())
@@ -5211,12 +5236,12 @@ void Device::CreateDescriptorResources()
52115236
&storage_infos.back());
52125237
}
52135238

5214-
if (uniform && !uniform_bindings.empty())
5239+
if (uniforms[frame] && !uniform_bindings.empty())
52155240
{
52165241
uniform_infos.emplace_back(
5217-
*uniform->buffer,
5242+
*uniforms[frame]->buffer,
52185243
0,
5219-
uniform->size);
5244+
uniforms[frame]->size);
52205245
descriptor_writes.emplace_back(
52215246
descriptor_set,
52225247
uniform_bindings.front(),

0 commit comments

Comments
 (0)