-
Notifications
You must be signed in to change notification settings - Fork 64
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
Ray Tracing Pipeline #820
Changes from all commits
995f170
1f3b397
3ce37d1
e44b8d5
aa31421
3592cb5
7757888
d207add
26f4c3f
8595c88
b027bde
53f27f0
ee5bcf9
64792a8
19dfc84
c9bd800
98c29b5
98025d3
e9ed9e2
64a8760
889ebe3
32b6af7
5effecd
b5b9a7b
fc9917d
98e1ef4
4bed175
bc968dc
6fe78d1
a60dbc6
c9b2fc6
d480405
6c6b709
5114b09
3f0962c
a03701f
44b450e
9286a71
cc34962
41ffc50
cff672c
1db0c8f
b502404
85114be
20ab6d6
8294f83
1a4d0e6
b2188dc
93405e9
ee1af5d
1912cd2
240cfa1
f22c4c0
1ed9fd7
7750418
3a18b05
82e0727
42b43a5
52a636d
14f5d35
9ed0945
94cb188
266d0eb
bbcff69
67b5181
2904e3e
d79fe20
c09154b
c35d01a
3fd2e14
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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 |
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 | ||
{ | ||
|
||
devshgraphicsprogramming marked this conversation as resolved.
Show resolved
Hide resolved
|
||
struct Lcg | ||
{ | ||
static Lcg construct(NBL_CONST_REF_ARG(uint32_t) state) | ||
devshgraphicsprogramming marked this conversation as resolved.
Show resolved
Hide resolved
|
||
{ | ||
return Lcg(state); | ||
devshgraphicsprogramming marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
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
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why are you returning v Also did you mean to clear your state's highest byte? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @kevyuu I changed it to return |
||
return state; | ||
} | ||
|
||
uint32_t state; | ||
}; | ||
|
||
} | ||
} | ||
#endif |
Uh oh!
There was an error while loading. Please reload this page.