Skip to content

Commit

Permalink
Fix scratch offset not being properly aligned.
Browse files Browse the repository at this point in the history
  • Loading branch information
GPSnoopy committed Jan 30, 2021
1 parent da0e0a3 commit 97dfaca
Show file tree
Hide file tree
Showing 9 changed files with 49 additions and 26 deletions.
23 changes: 21 additions & 2 deletions src/Vulkan/RayTracing/AccelerationStructure.cpp
Original file line number Diff line number Diff line change
@@ -1,16 +1,27 @@
#include "AccelerationStructure.hpp"
#include "DeviceProcedures.hpp"
#include "RayTracingProperties.hpp"
#include "Utilities/Exception.hpp"
#include "Vulkan/Buffer.hpp"
#include "Vulkan/Device.hpp"
#undef MemoryBarrier

namespace Vulkan::RayTracing {

AccelerationStructure::AccelerationStructure(const class DeviceProcedures& deviceProcedures) :
namespace
{
uint64_t RoundUp(uint64_t size, uint64_t granularity)
{
const auto divUp = (size + granularity - 1) / granularity;
return divUp * granularity;
}
}

AccelerationStructure::AccelerationStructure(const class DeviceProcedures& deviceProcedures, const RayTracingProperties& rayTracingProperties) :
deviceProcedures_(deviceProcedures),
flags_(VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR),
device_(deviceProcedures.Device())
device_(deviceProcedures.Device()),
rayTracingProperties_(rayTracingProperties)
{
}

Expand All @@ -20,6 +31,7 @@ AccelerationStructure::AccelerationStructure(AccelerationStructure&& other) noex
buildGeometryInfo_(other.buildGeometryInfo_),
buildSizesInfo_(other.buildSizesInfo_),
device_(other.device_),
rayTracingProperties_(other.rayTracingProperties_),
accelerationStructure_(other.accelerationStructure_)
{
other.accelerationStructure_ = nullptr;
Expand Down Expand Up @@ -47,6 +59,13 @@ VkAccelerationStructureBuildSizesInfoKHR AccelerationStructure::GetBuildSizes(co
pMaxPrimitiveCounts,
&sizeInfo);

// AccelerationStructure offset needs to be 256 bytes aligned (official Vulkan specs, don't ask me why).
const uint64_t AccelerationStructureAlignment = 256;
const uint64_t ScratchAlignment = rayTracingProperties_.MinAccelerationStructureScratchOffsetAlignment();

sizeInfo.accelerationStructureSize = RoundUp(sizeInfo.accelerationStructureSize, AccelerationStructureAlignment);
sizeInfo.buildScratchSize = RoundUp(sizeInfo.buildScratchSize, ScratchAlignment);

return sizeInfo;
}

Expand Down
5 changes: 3 additions & 2 deletions src/Vulkan/RayTracing/AccelerationStructure.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ namespace Vulkan::RayTracing

protected:

explicit AccelerationStructure(const class DeviceProcedures& deviceProcedures);
explicit AccelerationStructure(const class DeviceProcedures& deviceProcedures, const class RayTracingProperties& rayTracingProperties);

VkAccelerationStructureBuildSizesInfoKHR GetBuildSizes(const uint32_t* pMaxPrimitiveCounts) const;
void CreateAccelerationStructure(Buffer& resultBuffer, VkDeviceSize resultOffset);
Expand All @@ -46,7 +46,8 @@ namespace Vulkan::RayTracing
private:

const class Device& device_;

const class RayTracingProperties& rayTracingProperties_;

VULKAN_HANDLE(VkAccelerationStructureKHR, accelerationStructure_)
};

Expand Down
23 changes: 7 additions & 16 deletions src/Vulkan/RayTracing/Application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,23 +24,14 @@ namespace Vulkan::RayTracing {

namespace
{
// AccelerationStructure offset needs to be 256 bytes aligned (official Vulkan specs, don't ask me why).
const uint64_t AccelerationStructureAlignment = 256;

uint64_t RoundUp(uint64_t size, uint64_t granularity)
{
const auto divUp = (size + granularity - 1) / granularity;
return divUp * granularity;
}

template <class TAccelerationStructure>
VkAccelerationStructureBuildSizesInfoKHR GetTotalRequirements(const std::vector<TAccelerationStructure>& accelerationStructures)
{
VkAccelerationStructureBuildSizesInfoKHR total{};

for (const auto& accelerationStructure : accelerationStructures)
{
total.accelerationStructureSize += RoundUp(accelerationStructure.BuildSizes().accelerationStructureSize, AccelerationStructureAlignment);
total.accelerationStructureSize += accelerationStructure.BuildSizes().accelerationStructureSize;
total.buildScratchSize += accelerationStructure.BuildSizes().buildScratchSize;
total.updateScratchSize += accelerationStructure.BuildSizes().updateScratchSize;
}
Expand All @@ -59,8 +50,8 @@ Application::~Application()
Application::DeleteSwapChain();
DeleteAccelerationStructures();

rayTracingProperties_.reset();
deviceProcedures_.reset();
properties_.reset();
}

void Application::SetPhysicalDevice(
Expand Down Expand Up @@ -105,8 +96,8 @@ void Application::OnDeviceSet()
{
Vulkan::Application::OnDeviceSet();

properties_.reset(new RayTracingProperties(Device()));
deviceProcedures_.reset(new DeviceProcedures(Device()));
rayTracingProperties_.reset(new RayTracingProperties(Device()));
}

void Application::CreateAccelerationStructures()
Expand Down Expand Up @@ -157,7 +148,7 @@ void Application::CreateSwapChain()
const std::vector<ShaderBindingTable::Entry> missPrograms = { {rayTracingPipeline_->MissShaderIndex(), {}} };
const std::vector<ShaderBindingTable::Entry> hitGroups = { {rayTracingPipeline_->TriangleHitGroupIndex(), {}}, {rayTracingPipeline_->ProceduralHitGroupIndex(), {}} };

shaderBindingTable_.reset(new ShaderBindingTable(*deviceProcedures_, *rayTracingPipeline_, *properties_, rayGenPrograms, missPrograms, hitGroups));
shaderBindingTable_.reset(new ShaderBindingTable(*deviceProcedures_, *rayTracingPipeline_, *rayTracingProperties_, rayGenPrograms, missPrograms, hitGroups));
}

void Application::DeleteSwapChain()
Expand Down Expand Up @@ -266,7 +257,7 @@ void Application::CreateBottomLevelStructures(VkCommandBuffer commandBuffer)
? geometries.AddGeometryAabb(scene, aabbOffset, 1, true)
: geometries.AddGeometryTriangles(scene, vertexOffset, vertexCount, indexOffset, indexCount, true);

bottomAs_.emplace_back(*deviceProcedures_, geometries);
bottomAs_.emplace_back(*deviceProcedures_, *rayTracingProperties_, geometries);

vertexOffset += vertexCount * sizeof(Assets::Vertex);
indexOffset += indexCount * sizeof(uint32_t);
Expand Down Expand Up @@ -294,7 +285,7 @@ void Application::CreateBottomLevelStructures(VkCommandBuffer commandBuffer)
{
bottomAs_[i].Generate(commandBuffer, *bottomScratchBuffer_, scratchOffset, *bottomBuffer_, resultOffset);

resultOffset += RoundUp(bottomAs_[i].BuildSizes().accelerationStructureSize, AccelerationStructureAlignment);
resultOffset += bottomAs_[i].BuildSizes().accelerationStructureSize;
scratchOffset += bottomAs_[i].BuildSizes().buildScratchSize;

debugUtils.SetObjectName(bottomAs_[i].Handle(), ("BLAS #" + std::to_string(i)).c_str());
Expand Down Expand Up @@ -326,7 +317,7 @@ void Application::CreateTopLevelStructures(VkCommandBuffer commandBuffer)
// Memory barrier for the bottom level acceleration structure builds.
AccelerationStructure::MemoryBarrier(commandBuffer);

topAs_.emplace_back(*deviceProcedures_, instancesBuffer_->GetDeviceAddress(), static_cast<uint32_t>(instances.size()));
topAs_.emplace_back(*deviceProcedures_, *rayTracingProperties_, instancesBuffer_->GetDeviceAddress(), static_cast<uint32_t>(instances.size()));

// Allocate the structure memory.
const auto total = GetTotalRequirements(topAs_);
Expand Down
2 changes: 1 addition & 1 deletion src/Vulkan/RayTracing/Application.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ namespace Vulkan::RayTracing
void CreateTopLevelStructures(VkCommandBuffer commandBuffer);
void CreateOutputImage();

std::unique_ptr<class RayTracingProperties> properties_;
std::unique_ptr<class DeviceProcedures> deviceProcedures_;
std::unique_ptr<class RayTracingProperties> rayTracingProperties_;

std::vector<class BottomLevelAccelerationStructure> bottomAs_;
std::unique_ptr<Buffer> bottomBuffer_;
Expand Down
7 changes: 5 additions & 2 deletions src/Vulkan/RayTracing/BottomLevelAccelerationStructure.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@

namespace Vulkan::RayTracing {

BottomLevelAccelerationStructure::BottomLevelAccelerationStructure(const class DeviceProcedures& deviceProcedures, const BottomLevelGeometry& geometries) :
AccelerationStructure(deviceProcedures),
BottomLevelAccelerationStructure::BottomLevelAccelerationStructure(
const class DeviceProcedures& deviceProcedures,
const class RayTracingProperties& rayTracingProperties,
const BottomLevelGeometry& geometries) :
AccelerationStructure(deviceProcedures, rayTracingProperties),
geometries_(geometries)
{
buildGeometryInfo_.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR;
Expand Down
5 changes: 4 additions & 1 deletion src/Vulkan/RayTracing/BottomLevelAccelerationStructure.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ namespace Vulkan::RayTracing
BottomLevelAccelerationStructure& operator = (const BottomLevelAccelerationStructure&) = delete;
BottomLevelAccelerationStructure& operator = (BottomLevelAccelerationStructure&&) = delete;

BottomLevelAccelerationStructure(const class DeviceProcedures& deviceProcedures, const BottomLevelGeometry& geometries);
BottomLevelAccelerationStructure(
const class DeviceProcedures& deviceProcedures,
const class RayTracingProperties& rayTracingProperties,
const BottomLevelGeometry& geometries);
BottomLevelAccelerationStructure(BottomLevelAccelerationStructure&& other) noexcept;
~BottomLevelAccelerationStructure();

Expand Down
1 change: 1 addition & 0 deletions src/Vulkan/RayTracing/RayTracingProperties.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ namespace Vulkan
uint64_t MaxPrimitiveCount() const { return accelProps_.maxPrimitiveCount; }
uint32_t MaxRayRecursionDepth() const { return pipelineProps_.maxRayRecursionDepth; }
uint32_t MaxShaderGroupStride() const { return pipelineProps_.maxShaderGroupStride; }
uint32_t MinAccelerationStructureScratchOffsetAlignment() const { return accelProps_.minAccelerationStructureScratchOffsetAlignment; }
uint32_t ShaderGroupBaseAlignment() const { return pipelineProps_.shaderGroupBaseAlignment; }
uint32_t ShaderGroupHandleCaptureReplaySize() const { return pipelineProps_.shaderGroupHandleCaptureReplaySize; }
uint32_t ShaderGroupHandleSize() const { return pipelineProps_.shaderGroupHandleSize; }
Expand Down
3 changes: 2 additions & 1 deletion src/Vulkan/RayTracing/TopLevelAccelerationStructure.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ namespace Vulkan::RayTracing {

TopLevelAccelerationStructure::TopLevelAccelerationStructure(
const class DeviceProcedures& deviceProcedures,
const class RayTracingProperties& rayTracingProperties,
const VkDeviceAddress instanceAddress,
const uint32_t instancesCount) :
AccelerationStructure(deviceProcedures),
AccelerationStructure(deviceProcedures, rayTracingProperties),
instancesCount_(instancesCount)
{
// Create VkAccelerationStructureGeometryInstancesDataKHR. This wraps a device pointer to the above uploaded instances.
Expand Down
6 changes: 5 additions & 1 deletion src/Vulkan/RayTracing/TopLevelAccelerationStructure.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ namespace Vulkan::RayTracing
TopLevelAccelerationStructure& operator = (const TopLevelAccelerationStructure&) = delete;
TopLevelAccelerationStructure& operator = (TopLevelAccelerationStructure&&) = delete;

TopLevelAccelerationStructure(const class DeviceProcedures& deviceProcedures, VkDeviceAddress instanceAddress, uint32_t instancesCount);
TopLevelAccelerationStructure(
const class DeviceProcedures& deviceProcedures,
const class RayTracingProperties& rayTracingProperties,
VkDeviceAddress instanceAddress,
uint32_t instancesCount);
TopLevelAccelerationStructure(TopLevelAccelerationStructure&& other) noexcept;
virtual ~TopLevelAccelerationStructure();

Expand Down

0 comments on commit 97dfaca

Please sign in to comment.