Skip to content

Commit b279952

Browse files
authored
Fix Scratch Buffer and SBT alignment violations in RT samples (#1417)
* Add the ability to specify a custom alignment when creating a buffer. - Use the correct alignment for scratch buffers and SBT's. * Update ray_queries, ray_tracing_reflection and mobile_nerf_rayquery samples to use the correct alignment. * Fix missing sType * Formatting fixes * Fix formatting in acceleration_structure.h * Change alignment member in buffer.h to be private.
1 parent 8e966eb commit b279952

File tree

14 files changed

+162
-53
lines changed

14 files changed

+162
-53
lines changed

framework/core/acceleration_structure.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -208,9 +208,10 @@ void AccelerationStructure::build(VkQueue queue, VkBuildAccelerationStructureFla
208208
// Create a scratch buffer as a temporary storage for the acceleration structure build
209209
scratch_buffer = std::make_unique<vkb::core::BufferC>(
210210
device,
211-
build_sizes_info.buildScratchSize,
212-
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
213-
VMA_MEMORY_USAGE_GPU_ONLY);
211+
BufferBuilderC(build_sizes_info.buildScratchSize)
212+
.with_usage(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT)
213+
.with_vma_usage(VMA_MEMORY_USAGE_GPU_ONLY)
214+
.with_alignment(scratch_buffer_alignment));
214215

215216
build_geometry_info.scratchData.deviceAddress = scratch_buffer->get_device_address();
216217
build_geometry_info.dstAccelerationStructure = handle;

framework/core/acceleration_structure.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,11 @@ class AccelerationStructure
133133
geometries.clear();
134134
}
135135

136+
void set_scrach_buffer_alignment(VkDeviceSize alignment)
137+
{
138+
scratch_buffer_alignment = alignment;
139+
}
140+
136141
private:
137142
vkb::core::DeviceC &device;
138143

@@ -144,6 +149,8 @@ class AccelerationStructure
144149

145150
VkAccelerationStructureBuildSizesInfoKHR build_sizes_info{};
146151

152+
VkDeviceSize scratch_buffer_alignment{0};
153+
147154
struct Geometry
148155
{
149156
VkAccelerationStructureGeometryKHR geometry{};
@@ -159,4 +166,4 @@ class AccelerationStructure
159166
std::unique_ptr<vkb::core::BufferC> buffer{nullptr};
160167
};
161168
} // namespace core
162-
} // namespace vkb
169+
} // namespace vkb

framework/core/allocated.h

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ class Allocated : public vkb::core::VulkanResource<bindingType, HandleType>
306306
* Present in this common base class in order to allow the internal state members to remain `private`
307307
* instead of `protected`, and because it (mostly) isolates interaction with the VMA to a single class
308308
*/
309-
[[nodiscard]] BufferType create_buffer(BufferCreateInfoType const &create_info);
309+
[[nodiscard]] BufferType create_buffer(BufferCreateInfoType const &create_info, DeviceSizeType alignment);
310310
/**
311311
* @brief Internal method to actually create the image, allocate the memory and bind them.
312312
* Should only be called from the `Image` derived class.
@@ -363,7 +363,7 @@ class Allocated : public vkb::core::VulkanResource<bindingType, HandleType>
363363
void clear();
364364

365365
private:
366-
vk::Buffer create_buffer_impl(vk::BufferCreateInfo const &create_info);
366+
vk::Buffer create_buffer_impl(vk::BufferCreateInfo const &create_info, DeviceSizeType alignment);
367367
vk::Image create_image_impl(vk::ImageCreateInfo const &create_info);
368368

369369
VmaAllocationCreateInfo allocation_create_info = {};
@@ -428,31 +428,46 @@ inline void Allocated<bindingType, HandleType>::clear()
428428
}
429429

430430
template <vkb::BindingType bindingType, typename HandleType>
431-
inline typename Allocated<bindingType, HandleType>::BufferType Allocated<bindingType, HandleType>::create_buffer(BufferCreateInfoType const &create_info)
431+
inline typename Allocated<bindingType, HandleType>::BufferType Allocated<bindingType, HandleType>::create_buffer(BufferCreateInfoType const &create_info, DeviceSizeType alignment)
432432
{
433433
if constexpr (bindingType == vkb::BindingType::Cpp)
434434
{
435-
return create_buffer_impl(create_info);
435+
return create_buffer_impl(create_info, alignment);
436436
}
437437
else
438438
{
439-
return static_cast<VkBuffer>(create_buffer_impl(reinterpret_cast<vk::BufferCreateInfo const &>(create_info)));
439+
return static_cast<VkBuffer>(create_buffer_impl(reinterpret_cast<vk::BufferCreateInfo const &>(create_info), alignment));
440440
}
441441
}
442442

443443
template <vkb::BindingType bindingType, typename HandleType>
444-
inline vk::Buffer Allocated<bindingType, HandleType>::create_buffer_impl(vk::BufferCreateInfo const &create_info)
444+
inline vk::Buffer Allocated<bindingType, HandleType>::create_buffer_impl(vk::BufferCreateInfo const &create_info, DeviceSizeType alignment)
445445
{
446446
vk::Buffer buffer = VK_NULL_HANDLE;
447447
VmaAllocationInfo allocation_info{};
448448

449-
auto result = vmaCreateBuffer(
450-
get_memory_allocator(),
451-
reinterpret_cast<VkBufferCreateInfo const *>(&create_info),
452-
&allocation_create_info,
453-
reinterpret_cast<VkBuffer *>(&buffer),
454-
&allocation,
455-
&allocation_info);
449+
auto result = VK_SUCCESS;
450+
if (alignment == 0)
451+
{
452+
result = vmaCreateBuffer(
453+
get_memory_allocator(),
454+
reinterpret_cast<VkBufferCreateInfo const *>(&create_info),
455+
&allocation_create_info,
456+
reinterpret_cast<VkBuffer *>(&buffer),
457+
&allocation,
458+
&allocation_info);
459+
}
460+
else
461+
{
462+
result = vmaCreateBufferWithAlignment(
463+
get_memory_allocator(),
464+
reinterpret_cast<VkBufferCreateInfo const *>(&create_info),
465+
&allocation_create_info,
466+
alignment,
467+
reinterpret_cast<VkBuffer *>(&buffer),
468+
&allocation,
469+
&allocation_info);
470+
}
456471

457472
if (result != VK_SUCCESS)
458473
{

framework/core/buffer.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,14 @@ struct BufferBuilder
5656
BufferPtr<bindingType> build_unique(vkb::core::Device<bindingType> &device) const;
5757
BufferBuilder &with_flags(BufferCreateFlagsType flags);
5858
BufferBuilder &with_usage(BufferUsageFlagsType usage);
59+
BufferBuilder &with_alignment(DeviceSizeType align);
60+
DeviceSizeType get_alignment() const
61+
{
62+
return alignment;
63+
}
64+
65+
private:
66+
DeviceSizeType alignment{0};
5967
};
6068

6169
using BufferBuilderC = BufferBuilder<vkb::BindingType::C>;
@@ -98,6 +106,13 @@ inline BufferBuilder<bindingType> &BufferBuilder<bindingType>::with_usage(Buffer
98106
return *this;
99107
}
100108

109+
template <vkb::BindingType bindingType>
110+
inline BufferBuilder<bindingType> &BufferBuilder<bindingType>::with_alignment(DeviceSizeType align)
111+
{
112+
this->alignment = align;
113+
return *this;
114+
}
115+
101116
/*=========================================================*/
102117

103118
template <vkb::BindingType bindingType>
@@ -221,6 +236,7 @@ inline Buffer<bindingType>::Buffer(vkb::core::Device<bindingType> &device,
221236
BufferBuilder<bindingType>(size)
222237
.with_usage(buffer_usage)
223238
.with_vma_usage(memory_usage)
239+
.with_alignment(0)
224240
.with_vma_flags(flags)
225241
.with_queue_families(queue_family_indices)
226242
.with_implicit_sharing_mode())
@@ -230,7 +246,7 @@ template <vkb::BindingType bindingType>
230246
inline Buffer<bindingType>::Buffer(vkb::core::Device<bindingType> &device, const BufferBuilder<bindingType> &builder) :
231247
ParentType(builder.get_allocation_create_info(), nullptr, &device), size(builder.get_create_info().size)
232248
{
233-
this->set_handle(this->create_buffer(builder.get_create_info()));
249+
this->set_handle(this->create_buffer(builder.get_create_info(), builder.get_alignment()));
234250
if (!builder.get_debug_name().empty())
235251
{
236252
this->set_debug_name(builder.get_debug_name());

samples/extensions/ray_queries/ray_queries.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,12 @@ bool RayQueries::prepare(const vkb::ApplicationOptions &options)
175175
device_features.pNext = &acceleration_structure_features;
176176
vkGetPhysicalDeviceFeatures2(get_device().get_gpu().get_handle(), &device_features);
177177

178+
acceleration_structure_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_PROPERTIES_KHR;
179+
VkPhysicalDeviceProperties2 device_properties{};
180+
device_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
181+
device_properties.pNext = &acceleration_structure_properties;
182+
vkGetPhysicalDeviceProperties2(get_device().get_gpu().get_handle(), &device_properties);
183+
178184
camera.type = vkb::CameraType::FirstPerson;
179185
camera.set_perspective(60.0f, static_cast<float>(width) / static_cast<float>(height), 0.1f, 512.0f);
180186
camera.set_rotation(glm::vec3(0.0f, 90.0f, 0.0f));
@@ -225,6 +231,7 @@ void RayQueries::create_top_level_acceleration_structure()
225231
// Top Level AS with single instance
226232
top_level_acceleration_structure = std::make_unique<vkb::core::AccelerationStructure>(get_device(), VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR);
227233
top_level_acceleration_structure->add_instance_geometry(instances_buffer, 1);
234+
top_level_acceleration_structure->set_scrach_buffer_alignment(acceleration_structure_properties.minAccelerationStructureScratchOffsetAlignment);
228235
top_level_acceleration_structure->build(queue);
229236
}
230237

@@ -270,6 +277,7 @@ void RayQueries::create_bottom_level_acceleration_structure()
270277
get_buffer_device_address(vertex_buffer->get_handle()),
271278
get_buffer_device_address(index_buffer->get_handle()));
272279
}
280+
bottom_level_acceleration_structure->set_scrach_buffer_alignment(acceleration_structure_properties.minAccelerationStructureScratchOffsetAlignment);
273281
bottom_level_acceleration_structure->build(queue, VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR, VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR);
274282
}
275283

samples/extensions/ray_queries/ray_queries.h

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,13 @@ class RayQueries : public ApiVulkanSample
7373
std::unique_ptr<vkb::core::BufferC> uniform_buffer{nullptr};
7474

7575
// Ray tracing structures
76-
VkPhysicalDeviceAccelerationStructureFeaturesKHR acceleration_structure_features{};
77-
std::unique_ptr<vkb::core::AccelerationStructure> top_level_acceleration_structure = nullptr;
78-
std::unique_ptr<vkb::core::AccelerationStructure> bottom_level_acceleration_structure = nullptr;
79-
uint64_t get_buffer_device_address(VkBuffer buffer);
80-
void create_top_level_acceleration_structure();
81-
void create_bottom_level_acceleration_structure();
76+
VkPhysicalDeviceAccelerationStructureFeaturesKHR acceleration_structure_features{};
77+
VkPhysicalDeviceAccelerationStructurePropertiesKHR acceleration_structure_properties{};
78+
std::unique_ptr<vkb::core::AccelerationStructure> top_level_acceleration_structure = nullptr;
79+
std::unique_ptr<vkb::core::AccelerationStructure> bottom_level_acceleration_structure = nullptr;
80+
uint64_t get_buffer_device_address(VkBuffer buffer);
81+
void create_top_level_acceleration_structure();
82+
void create_bottom_level_acceleration_structure();
8283

8384
VkPipeline pipeline{VK_NULL_HANDLE};
8485
VkPipelineLayout pipeline_layout{VK_NULL_HANDLE};

samples/extensions/ray_tracing_extended/ray_tracing_extended.cpp

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,7 @@ void RaytracingExtended::create_bottom_level_acceleration_structure(bool is_upda
405405
model_buffer.vertex_offset + (model_buffer.is_static ? static_vertex_handle : dynamic_vertex_handle),
406406
model_buffer.index_offset + (model_buffer.is_static ? static_index_handle : dynamic_index_handle));
407407
}
408+
model_buffer.bottom_level_acceleration_structure->set_scrach_buffer_alignment(acceleration_structure_properties.minAccelerationStructureScratchOffsetAlignment);
408409
model_buffer.bottom_level_acceleration_structure->build(queue,
409410
model_buffer.is_static ? VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR : VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR | VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR,
410411
is_update ? VK_BUILD_ACCELERATION_STRUCTURE_MODE_UPDATE_KHR : VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR);
@@ -458,6 +459,7 @@ void RaytracingExtended::create_bottom_level_acceleration_structure(bool is_upda
458459
uint32_t primitive_count = model_buffer.num_triangles;
459460

460461
auto &acceleration_structure_build_sizes_info = model_buffer.buildSize;
462+
acceleration_structure_build_sizes_info.pNext = nullptr;
461463
acceleration_structure_build_sizes_info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR;
462464
vkGetAccelerationStructureBuildSizesKHR(
463465
get_device().get_handle(),
@@ -490,10 +492,11 @@ void RaytracingExtended::create_bottom_level_acceleration_structure(bool is_upda
490492
// The actual build process starts here
491493

492494
// Create a scratch buffer as a temporary storage for the acceleration structure build
493-
auto scratch_buffer = std::make_unique<vkb::core::BufferC>(get_device(),
494-
model_buffer.buildSize.buildScratchSize,
495-
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
496-
VMA_MEMORY_USAGE_CPU_TO_GPU);
495+
auto scratch_buffer = std::make_unique<vkb::core::BufferC>(get_device(), vkb::core::BufferBuilderC(model_buffer.buildSize.buildScratchSize)
496+
.with_usage(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT)
497+
.with_vma_usage(VMA_MEMORY_USAGE_GPU_ONLY)
498+
.with_alignment(acceleration_structure_properties.minAccelerationStructureScratchOffsetAlignment));
499+
497500
{
498501
VkAccelerationStructureBuildGeometryInfoKHR acceleration_build_geometry_info{};
499502
acceleration_build_geometry_info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR;
@@ -659,6 +662,7 @@ void RaytracingExtended::create_top_level_acceleration_structure(bool print_time
659662
{
660663
top_level_acceleration_structure->update_instance_geometry(instance_uid, instances_buffer, static_cast<uint32_t>(instances.size()));
661664
}
665+
top_level_acceleration_structure->set_scrach_buffer_alignment(acceleration_structure_properties.minAccelerationStructureScratchOffsetAlignment);
662666
top_level_acceleration_structure->build(queue);
663667
#else
664668
VkDeviceOrHostAddressConstKHR instance_data_device_address{};
@@ -723,9 +727,10 @@ void RaytracingExtended::create_top_level_acceleration_structure(bool print_time
723727

724728
// Create a scratch buffer as a temporary storage for the acceleration structure build
725729
auto scratch_buffer = std::make_unique<vkb::core::BufferC>(get_device(),
726-
acceleration_structure_build_sizes_info.buildScratchSize,
727-
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
728-
VMA_MEMORY_USAGE_CPU_TO_GPU);
730+
vkb::core::BufferBuilderC(acceleration_structure_build_sizes_info.buildScratchSize)
731+
.with_usage(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_2_SHADER_DEVICE_ADDRESS_BIT)
732+
.with_vma_usage(VMA_MEMORY_USAGE_GPU_ONLY)
733+
.with_alignment(acceleration_structure_properties.minAccelerationStructureScratchOffsetAlignment));
729734

730735
VkAccelerationStructureBuildGeometryInfoKHR acceleration_build_geometry_info{};
731736
acceleration_build_geometry_info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR;
@@ -857,9 +862,21 @@ void RaytracingExtended::create_shader_binding_tables()
857862

858863
// Raygen
859864
// Create binding table buffers for each shader type
860-
raygen_shader_binding_table = std::make_unique<vkb::core::BufferC>(get_device(), handle_size, sbt_buffer_usage_flags, sbt_memory_usage, 0);
861-
miss_shader_binding_table = std::make_unique<vkb::core::BufferC>(get_device(), handle_size, sbt_buffer_usage_flags, sbt_memory_usage, 0);
862-
hit_shader_binding_table = std::make_unique<vkb::core::BufferC>(get_device(), handle_size, sbt_buffer_usage_flags, sbt_memory_usage, 0);
865+
raygen_shader_binding_table = std::make_unique<vkb::core::BufferC>(get_device(), vkb::core::BufferBuilderC(handle_size)
866+
.with_usage(sbt_buffer_usage_flags)
867+
.with_vma_usage(sbt_memory_usage)
868+
.with_vma_flags(0)
869+
.with_alignment(ray_tracing_pipeline_properties.shaderGroupBaseAlignment));
870+
miss_shader_binding_table = std::make_unique<vkb::core::BufferC>(get_device(), vkb::core::BufferBuilderC(handle_size)
871+
.with_usage(sbt_buffer_usage_flags)
872+
.with_vma_usage(sbt_memory_usage)
873+
.with_vma_flags(0)
874+
.with_alignment(ray_tracing_pipeline_properties.shaderGroupBaseAlignment));
875+
hit_shader_binding_table = std::make_unique<vkb::core::BufferC>(get_device(), vkb::core::BufferBuilderC(handle_size)
876+
.with_usage(sbt_buffer_usage_flags)
877+
.with_vma_usage(sbt_memory_usage)
878+
.with_vma_flags(0)
879+
.with_alignment(ray_tracing_pipeline_properties.shaderGroupBaseAlignment));
863880

864881
// Copy the pipeline's shader handles into a host buffer
865882
std::vector<uint8_t> shader_handle_storage(sbt_size);
@@ -1350,8 +1367,13 @@ bool RaytracingExtended::prepare(const vkb::ApplicationOptions &options)
13501367
std::set<VkImageUsageFlagBits> image_usage_flags = {VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_USAGE_TRANSFER_DST_BIT};
13511368
get_render_context().update_swapchain(image_usage_flags);
13521369

1370+
// Get the acceleration structure properties
1371+
acceleration_structure_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_PROPERTIES_KHR;
1372+
13531373
// Get the ray tracing pipeline properties, which we'll need later on in the sample
13541374
ray_tracing_pipeline_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR;
1375+
ray_tracing_pipeline_properties.pNext = &acceleration_structure_properties;
1376+
13551377
VkPhysicalDeviceProperties2 device_properties{};
13561378
device_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
13571379
device_properties.pNext = &ray_tracing_pipeline_properties;

samples/extensions/ray_tracing_extended/ray_tracing_extended.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,9 @@
2929
class RaytracingExtended : public ApiVulkanSample
3030
{
3131
public:
32-
VkPhysicalDeviceRayTracingPipelinePropertiesKHR ray_tracing_pipeline_properties{};
33-
VkPhysicalDeviceAccelerationStructureFeaturesKHR acceleration_structure_features{};
32+
VkPhysicalDeviceRayTracingPipelinePropertiesKHR ray_tracing_pipeline_properties{};
33+
VkPhysicalDeviceAccelerationStructureFeaturesKHR acceleration_structure_features{};
34+
VkPhysicalDeviceAccelerationStructurePropertiesKHR acceleration_structure_properties{};
3435

3536
enum RenderMode : uint32_t
3637
{

0 commit comments

Comments
 (0)