Skip to content

Ray Tracing Pipeline #820

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
995f170
HLSL RayTracing Compilation
Jan 21, 2025
1f3b397
Ray Tracing Pipeline creation
Jan 21, 2025
3ce37d1
Implement binding Ray Tracing Pipeline command
Jan 21, 2025
e44b8d5
Implement trace rays command
Jan 21, 2025
aa31421
Fix specializatio for ray tracing shaders
Jan 21, 2025
3592cb5
Add Validation to ray tracing pipeline creation
Jan 21, 2025
7757888
Implement Intersection Shader
Jan 21, 2025
d207add
Change order of shader groups in params to be consistent with TraceRays
Jan 24, 2025
26f4c3f
Fix buffer creation log
Jan 24, 2025
8595c88
Add more validation to ray tracing pipeline creation
Jan 25, 2025
b027bde
Remove unnecessarry command
Feb 5, 2025
53f27f0
Refactor casting pipeline bind point
Feb 5, 2025
ee5bcf9
Use static constexpr for shaderGroupHandleSize
Feb 5, 2025
64792a8
Fix indentation.
Feb 5, 2025
19dfc84
Remove unnecessary colon
Feb 5, 2025
c9bd800
Refactor SShaderGroupParams to use span and remove it from SCachedParams
Feb 5, 2025
98c29b5
Remove SStridedBufferRegion. Use SBufferRange + stride instead.
Feb 6, 2025
98025d3
Add more validation to TraceRays
Feb 6, 2025
e9ed9e2
Implement set ray tracing pipeline stack size
Feb 11, 2025
64a8760
Implement TraceRaysIndirect
Feb 11, 2025
889ebe3
Fix TraceRays command parameter
Feb 11, 2025
32b6af7
Remove unnecessary include
Feb 12, 2025
5effecd
Fix indentation
Feb 25, 2025
b5b9a7b
Fix bound pipeline don't disturb each other.
Feb 25, 2025
fc9917d
Remove pipeline binding point from Pipeline class
Feb 25, 2025
98e1ef4
Move SShaderGroupParams to IRayTracingPipelineBase
Feb 25, 2025
4bed175
Rename parameter named binding to indirectBinding
Feb 25, 2025
bc968dc
Use ShaderGroupHandle instead of span of uint_t
Feb 25, 2025
6fe78d1
Merge branch 'master' into raytracing_pipeline
Feb 25, 2025
a60dbc6
Remove unnecessary include
Feb 25, 2025
c9b2fc6
Remove replay flag from ray tracing pipeline
Feb 25, 2025
d480405
Move SShaderGroupHandle to IGPURayTracingPipeline
Feb 27, 2025
6c6b709
Remove shader handles query in CVulkanRayTracingPipeline
Mar 3, 2025
5114b09
Add space between group params and cached creation params for better …
Mar 3, 2025
3f0962c
Improve ShaderGroupParams naming
Mar 3, 2025
a03701f
Improve checking for shader stage
Mar 3, 2025
44b450e
Improve get group count method
Mar 3, 2025
9286a71
Fix maxShaderGroup calculation
Mar 3, 2025
cc34962
Check that shaders is not empty
Mar 3, 2025
41ffc50
Check for maxShaderGroupStride compliance
Mar 3, 2025
cff672c
Add more validation for trace ray dimensions.
Mar 10, 2025
1db0c8f
Fix shader group buffer alignment validation.
Mar 10, 2025
b502404
Remove unecessary raygenGroupStride parameter.
Mar 10, 2025
85114be
Fix set stack size dynamic state handling.
Mar 10, 2025
20ab6d6
Add setRayTracingStackSize validation
Mar 10, 2025
8294f83
Convert traceRaysIndirect to use vkCmdTraceRaysIndirect2KHR.
Mar 10, 2025
1a4d0e6
Add Skip triangles bit and skip aabbs bit as common flag.
Mar 12, 2025
b2188dc
Fix setRayTracingStackSize validation.
Mar 12, 2025
93405e9
Merge branch 'master' into raytracing_pipeline
Mar 12, 2025
ee1af5d
Improve some flags naming
Mar 12, 2025
1912cd2
Fix merging bug
Mar 12, 2025
240cfa1
Fix indirect Trace ray validation.
Mar 12, 2025
f22c4c0
Make the indirect buffer size check clearer.
Mar 12, 2025
1ed9fd7
Add Motion Blur validation.
Mar 12, 2025
7750418
Add comment on some validations
Mar 12, 2025
3a18b05
Move creation flags to IRayTracingPipeline
Mar 14, 2025
82e0727
Comment out some flags and add some documentation on pipeline flags.
Mar 14, 2025
42b43a5
Add rayTracingValidation feature
Mar 14, 2025
52a636d
Add validation that rayTraversalPrimitiveCulling feaature is enabled …
Mar 14, 2025
14f5d35
Add more validation.
Mar 14, 2025
9ed0945
Remove dead code
Mar 17, 2025
94cb188
Improve naming of hit group
Mar 17, 2025
266d0eb
Fix validation on raygen shaderGroup
Mar 17, 2025
bbcff69
Implement get ray tracing stack size api
Mar 17, 2025
67b5181
Change get shader group handle api to return span
Mar 17, 2025
2904e3e
Fix ray tracing capture replay feature enable logic
Mar 17, 2025
d79fe20
Remove unused code
Mar 17, 2025
c09154b
Fix ray tracing pipeline creation, by not skipping null shader instea…
Mar 17, 2025
c35d01a
Fix stack size calculation when the shader group is empty
Mar 18, 2025
3fd2e14
Add tea, lcg and pcg into nb::hlsl::random
Mar 18, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docker/compiler-explorer
2 changes: 1 addition & 1 deletion include/nbl/asset/ECommonEnums.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ enum E_PIPELINE_BIND_POINT : uint8_t
{
EPBP_GRAPHICS = 0,
EPBP_COMPUTE,

EPBP_RAY_TRACING,
EPBP_COUNT
};

Expand Down
49 changes: 31 additions & 18 deletions include/nbl/asset/IPipeline.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,45 +54,57 @@ class IPipeline
// Compute Pipelines only
//DISPATCH_BASE = 1<<4,

// Weird extension
// This is for NV-raytracing extension. Now this is done via IDeferredOperation
//DEFER_COMPILE_NV = 1<<5,

CAPTURE_STATISTICS = 1<<6,
CAPTURE_INTERNAL_REPRESENTATIONS = 1<<7,
// We use Renderdoc to take care of this for us,
// we won't be parsing the statistics and internal representation ourselves.
//CAPTURE_STATISTICS = 1<<6,
//CAPTURE_INTERNAL_REPRESENTATIONS = 1<<7,

// We require Pipeline Cache Control feature so those are satisfied:
// https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkComputePipelineCreateInfo.html#VUID-VkComputePipelineCreateInfo-pipelineCreationCacheControl-02875
// Will soon be deprecated due to
// https://github.com/Devsh-Graphics-Programming/Nabla/issues/854
FAIL_ON_PIPELINE_COMPILE_REQUIRED = 1<<8,
EARLY_RETURN_ON_FAILURE = 1<<9,

LINK_TIME_OPTIMIZATION = 1<<10,
// Will be exposed later with the IPipelineLibrary asset implementation
// https://github.com/Devsh-Graphics-Programming/Nabla/issues/853
//LINK_TIME_OPTIMIZATION = 1<<10,

//Not Supported Yet
// Won't be exposed because we'll introduce Libraries as a separate object/asset-type
// https://github.com/Devsh-Graphics-Programming/Nabla/issues/853
//CREATE_LIBRARY = 1<<11,

// Ray Tracing Pipelines only
//RAY_TRACING_SKIP_TRIANGLES_BIT_KHR = 1<<12,
//RAY_TRACING_SKIP_AABBS_BIT_KHR = 1<<13,
//RAY_TRACING_NO_NULL_ANY_HIT_SHADERS_BIT_KHR = 1<<14,
//RAY_TRACING_NO_NULL_CLOSEST_HIT_SHADERS_BIT_KHR = 1<<15,
//RAY_TRACING_NO_NULL_MISS_SHADERS_BIT_KHR = 1<<16,
//RAY_TRACING_NO_NULL_INTERSECTION_SHADERS_BIT_KHR = 1<<17,

// Not Supported Yet
//SKIP_BUILT_IN_PRIMITIVES = 1<<12,
//SKIP_AABBS = 1<<13,
//NO_NULL_ANY_HIT_SHADERS = 1<<14,
//NO_NULL_CLOSEST_HIT_SHADERS = 1<<15,
//NO_NULL_MISS_SHADERS = 1<<16,
//NO_NULL_INTERSECTION_SHADERS = 1<<17,

// There is a new Device Generated Commands extension with its own flag that will deprecate this
//INDIRECT_BINDABLE_NV = 1<<18,

// Ray Tracing Pipelines only
// For debug tools
//RAY_TRACING_SHADER_GROUP_HANDLE_CAPTURE_REPLAY_BIT_KHR = 1<<19,
//RAY_TRACING_ALLOW_MOTION_BIT_NV = 1<<20,

// Ray Tracing Pipelines only
//ALLOW_MOTION = 1<<20,

// Graphics Pipelineonly (we don't support subpass shading)
//RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 1<<21,
//RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT = 1<<22,

RETAIN_LINK_TIME_OPTIMIZATION_INFO = 1<<23,
// Will be exposed later with the IPipelineLibrary asset implementation
// https://github.com/Devsh-Graphics-Programming/Nabla/issues/853
//RETAIN_LINK_TIME_OPTIMIZATION_INFO = 1<<23,

// Ray Tracing Pipelines only
//RAY_TRACING_OPACITY_MICROMAP_BIT_EXT = 1<<24,

// Not supported yet, and we will move to dynamic rendering, so this might never be supported
//COLOR_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT = 1<<25,
//DEPTH_STENCIL_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT = 1<<26,

Expand All @@ -107,7 +119,8 @@ class IPipeline
inline const PipelineLayout* getLayout() const {return m_layout.get();}

protected:
inline IPipeline(core::smart_refctd_ptr<const PipelineLayout>&& _layout) : m_layout(std::move(_layout)) {}
inline IPipeline(core::smart_refctd_ptr<const PipelineLayout>&& _layout)
: m_layout(std::move(_layout)) {}

core::smart_refctd_ptr<const PipelineLayout> m_layout;
};
Expand Down
207 changes: 207 additions & 0 deletions include/nbl/asset/IRayTracingPipeline.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
#ifndef _NBL_ASSET_I_RAY_TRACING_PIPELINE_H_INCLUDED_
#define _NBL_ASSET_I_RAY_TRACING_PIPELINE_H_INCLUDED_

#include "nbl/asset/IShader.h"
#include "nbl/asset/IPipeline.h"

#include <span>
#include <bit>
#include <type_traits>

namespace nbl::asset
{

class IRayTracingPipelineBase : public virtual core::IReferenceCounted
{
public:
struct SShaderGroupsParams
{
struct SIndex
{
constexpr static inline uint32_t Unused = 0xffFFffFFu;
uint32_t index = Unused;
};

struct SHitGroup
{
uint32_t closestHit = SIndex::Unused;
uint32_t anyHit = SIndex::Unused;
uint32_t intersection = SIndex::Unused;
};

SIndex raygen;
std::span<SIndex> misses;
std::span<SHitGroup> hits;
std::span<SIndex> callables;

inline uint32_t getShaderGroupCount() const
{
return 1 + hits.size() + misses.size() + callables.size();
}

};
using SGeneralShaderGroup = SShaderGroupsParams::SIndex;
using SHitShaderGroup = SShaderGroupsParams::SHitGroup;

struct SCachedCreationParams final
{
uint32_t maxRecursionDepth : 6 = 0;
uint32_t dynamicStackSize : 1 = false;
};
};

template<typename PipelineLayoutType, typename ShaderType>
class IRayTracingPipeline : public IPipeline<PipelineLayoutType>, public IRayTracingPipelineBase
{
using base_creation_params_t = IPipeline<PipelineLayoutType>::SCreationParams;
public:

using SGeneralShaderGroupContainer = core::smart_refctd_dynamic_array<SGeneralShaderGroup>;
using SHitShaderGroupContainer = core::smart_refctd_dynamic_array<SHitShaderGroup>;

struct SCreationParams : base_creation_params_t
{
public:
#define base_flag(F) static_cast<uint64_t>(base_creation_params_t::FLAGS::F)
enum class FLAGS : uint64_t
{
NONE = base_flag(NONE),
DISABLE_OPTIMIZATIONS = base_flag(DISABLE_OPTIMIZATIONS),
ALLOW_DERIVATIVES = base_flag(ALLOW_DERIVATIVES),
FAIL_ON_PIPELINE_COMPILE_REQUIRED = base_flag(FAIL_ON_PIPELINE_COMPILE_REQUIRED),
EARLY_RETURN_ON_FAILURE = base_flag(EARLY_RETURN_ON_FAILURE),
SKIP_BUILT_IN_PRIMITIVES = 1<<12,
SKIP_AABBS = 1<<13,
NO_NULL_ANY_HIT_SHADERS = 1<<14,
NO_NULL_CLOSEST_HIT_SHADERS = 1<<15,
NO_NULL_MISS_SHADERS = 1<<16,
NO_NULL_INTERSECTION_SHADERS = 1<<17,
ALLOW_MOTION = 1<<20,
};
#undef base_flag

protected:
using SpecInfo = ShaderType::SSpecInfo;
template<typename ExtraLambda>
inline bool impl_valid(ExtraLambda&& extra) const
{
if (!IPipeline<PipelineLayoutType>::SCreationParams::layout)
return false;

for (const auto info : shaders)
{
if (info.shader)
{
if (!extra(info))
return false;
const auto stage = info.shader->getStage();
if ((stage & ~ICPUShader::E_SHADER_STAGE::ESS_ALL_RAY_TRACING) != 0)
return false;
if (!std::has_single_bit<std::underlying_type_t<ICPUShader::E_SHADER_STAGE>>(stage))
return false;
}
else
{
// every shader must not be null. use SIndex::Unused to represent unused shader.
return false;
}
}

auto getShaderStage = [this](size_t index) -> ICPUShader::E_SHADER_STAGE
{
return shaders[index].shader->getStage();
};

auto isValidShaderIndex = [this, getShaderStage](size_t index, ICPUShader::E_SHADER_STAGE expectedStage, bool is_unused_shader_forbidden) -> bool
{
if (index == SShaderGroupsParams::SIndex::Unused)
return !is_unused_shader_forbidden;
if (index >= shaders.size())
return false;
if (getShaderStage(index) != expectedStage)
return false;
return true;
};

if (!isValidShaderIndex(shaderGroups.raygen.index, ICPUShader::E_SHADER_STAGE::ESS_RAYGEN, true))
{
return false;
}

for (const auto& shaderGroup : shaderGroups.hits)
{
// https://docs.vulkan.org/spec/latest/chapters/pipelines.html#VUID-VkRayTracingPipelineCreateInfoKHR-flags-03470
if (!isValidShaderIndex(shaderGroup.anyHit,
ICPUShader::E_SHADER_STAGE::ESS_ANY_HIT,
bool(flags & FLAGS::NO_NULL_ANY_HIT_SHADERS)))
return false;

// https://docs.vulkan.org/spec/latest/chapters/pipelines.html#VUID-VkRayTracingPipelineCreateInfoKHR-flags-03471
if (!isValidShaderIndex(shaderGroup.closestHit,
ICPUShader::E_SHADER_STAGE::ESS_CLOSEST_HIT,
bool(flags & FLAGS::NO_NULL_CLOSEST_HIT_SHADERS)))
return false;

if (!isValidShaderIndex(shaderGroup.intersection,
ICPUShader::E_SHADER_STAGE::ESS_INTERSECTION,
false))
return false;
}

for (const auto& shaderGroup : shaderGroups.misses)
{
if (!isValidShaderIndex(shaderGroup.index,
ICPUShader::E_SHADER_STAGE::ESS_MISS,
false))
return false;
}

for (const auto& shaderGroup : shaderGroups.callables)
{
if (!isValidShaderIndex(shaderGroup.index, ICPUShader::E_SHADER_STAGE::ESS_CALLABLE, false))
return false;
}
return true;
}

public:
inline bool valid() const
{
return impl_valid([](const SpecInfo& info)->bool
{
if (!info.valid())
return false;
return false;
});
}

std::span<const SpecInfo> shaders = {};
SShaderGroupsParams shaderGroups;
SCachedCreationParams cached = {};
// TODO: Could guess the required flags from SPIR-V introspection of declared caps
core::bitflag<FLAGS> flags = FLAGS::NONE;
};

inline const SCachedCreationParams& getCachedCreationParams() const { return m_params; }

protected:
explicit IRayTracingPipeline(const SCreationParams& _params) :
IPipeline<PipelineLayoutType>(core::smart_refctd_ptr<const PipelineLayoutType>(_params.layout)),
m_params(_params.cached),
m_raygenShaderGroup(_params.shaderGroups.raygen),
m_missShaderGroups(core::make_refctd_dynamic_array<SGeneralShaderGroupContainer>(_params.shaderGroups.misses)),
m_hitShaderGroups(core::make_refctd_dynamic_array<SHitShaderGroupContainer>(_params.shaderGroups.hits)),
m_callableShaderGroups(core::make_refctd_dynamic_array<SGeneralShaderGroupContainer>(_params.shaderGroups.callables))
{}

SCachedCreationParams m_params;
SGeneralShaderGroup m_raygenShaderGroup;
SGeneralShaderGroupContainer m_missShaderGroups;
SHitShaderGroupContainer m_hitShaderGroups;
SGeneralShaderGroupContainer m_callableShaderGroups;

};

}

#endif
1 change: 1 addition & 0 deletions include/nbl/builtin/hlsl/enums.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ enum ShaderStage : uint32_t
ESS_INTERSECTION = 1 << 12,
ESS_CALLABLE = 1 << 13,
ESS_ALL_GRAPHICS = 0x0000001F,
ESS_ALL_RAY_TRACING = ESS_RAYGEN | ESS_ANY_HIT | ESS_CLOSEST_HIT | ESS_MISS | ESS_INTERSECTION | ESS_CALLABLE,
ESS_ALL_OR_LIBRARY = 0x7fffffff
};

Expand Down
18 changes: 18 additions & 0 deletions include/nbl/builtin/hlsl/indirect_commands.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,24 @@ struct DispatchIndirectCommand_t
uint32_t num_groups_z;
};

struct TraceRaysIndirectCommand_t
{
uint64_t raygenShaderRecordAddress;
uint64_t raygenShaderRecordSize;
uint64_t missShaderBindingTableAddress;
uint64_t missShaderBindingTableSize;
uint64_t missShaderBindingTableStride;
uint64_t hitShaderBindingTableAddress;
uint64_t hitShaderBindingTableSize;
uint64_t hitShaderBindingTableStride;
uint64_t callableShaderBindingTableAddress;
uint64_t callableShaderBindingTableSize;
uint64_t callableShaderBindingTableStride;
uint32_t width;
uint32_t height;
uint32_t depth;
};

}
}

Expand Down
34 changes: 34 additions & 0 deletions include/nbl/builtin/hlsl/random/lcg.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright (C) 2018-2025 - DevSH Graphics Programming Sp. z O.O.
// This file is part of the "Nabla Engine".
// For conditions of distribution and use, see copyright notice in nabla.h

#ifndef _NBL_BUILTIN_GLSL_RANDOM_LCG_HLSL_INCLUDED_
#define _NBL_BUILTIN_GLSL_RANDOM_LCG_HLSL_INCLUDED_

namespace nbl
{
namespace hlsl
{

struct Lcg
{
static Lcg construct(NBL_CONST_REF_ARG(uint32_t) state)
{
return Lcg(state);
}

uint32_t2 operator()()
{
uint32_t LCG_A = 1664525u;
uint32_t LCG_C = 1013904223u;
state = (LCG_A * state + LCG_C);
state &= 0x00FFFFFF;
Comment on lines +20 to +25

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why are you returning vector<uint32_t,2> ?

Also did you mean to clear your state's highest byte?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kevyuu I changed it to return uint32_t, I need the answer on the last question

return state;
}

uint32_t state;
};

}
}
#endif
Loading