SpiecsEngine
 
Loading...
Searching...
No Matches
RayTracingRenderer.cpp
Go to the documentation of this file.
1/**
2* @file RayTracingRenderer.cpp.
3* @brief The RayTracingRenderer Class Implementation.
4* @author Spices.
5*/
6
7#include "Pchheader.h"
9#include "PreRenderer.h"
10#include "Render/Vulkan/VulkanRayTracing.h"
11
12namespace Spices {
13
14 std::shared_ptr<VulkanRayTracing> RayTracingRenderer::m_VulkanRayTracing = nullptr;
15
17 const std::string& rendererName ,
18 VulkanState& vulkanState ,
19 const std::shared_ptr<VulkanDescriptorPool>& descriptorPool ,
20 const std::shared_ptr<VulkanDevice>& device ,
21 const std::shared_ptr<RendererResourcePool>& rendererResourcePool
22 )
23 : Renderer(rendererName, vulkanState, descriptorPool, device, rendererResourcePool)
24 {
26
27 m_VulkanRayTracing = std::make_shared<VulkanRayTracing>(m_VulkanState);
28 }
29
31 {
33
34 m_VulkanRayTracing = nullptr;
35 }
36
38 {
40
41 RendererPassBuilder{ "RayTracing", this }
42 .AddSubPass("RayTracing")
45 }
46
48 {
50
51 DescriptorSetBuilder{ "RayTracing", this }
52 .AddPushConstant(sizeof(RayTracingR::PushConstant))
53 .AddAccelerationStructure(2, 0, VK_SHADER_STAGE_RAYGEN_BIT_KHR | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR) /* @brief Acceleration Structure. */
54 .AddStorageTexture(2, 1, VK_SHADER_STAGE_RAYGEN_BIT_KHR, { "RayImage" }, VK_FORMAT_R32G32B32A32_SFLOAT) /* @brief Ray Tracing Output Image. */
55 .AddStorageTexture(2, 2, VK_SHADER_STAGE_RAYGEN_BIT_KHR, { "RayEntityID", "RayTriangleID" }, VK_FORMAT_R32_SFLOAT) /* @brief Ray Tracing Output IDs. */
56 .AddStorageBuffer(3, 0, SpicesShader::MESH_BUFFER_MAXNUM * sizeof(uint64_t), VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR) /* @brief World Mesh Buffer. */
57 .AddStorageBuffer(3, 1, sizeof(RayTracingR::DirectionalLightBuffer), VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR) /* @brief World Directional Light Buffer. */
58 .AddStorageBuffer(3, 2, sizeof(RayTracingR::PointLightBuffer), VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR) /* @brief World PointLight Buffer. */
59 .AddTexture<Texture2D>(4, 0, VK_SHADER_STAGE_MISS_BIT_KHR, {"skybox/kloofendal_48d_partly_cloudy_puresky_4k.hdr"}) /* @brief temp. */
60 .Build(m_VulkanRayTracing->GetAccelerationStructure());
61 }
62
64 {
66
67 auto view = GetEntityWithComponent<MeshComponent>(FrameInfo::Get().m_World.get());
68
69 AsyncTask(ThreadPoolEnum::Custom, [=]() {
70
71 SPICES_PROFILE_ZONEN("RayTracingRenderer::OnMeshAddedWorld");
72
73 std::shared_ptr<VulkanRayTracing> rayTracingInstance = std::make_shared<VulkanRayTracing>(m_VulkanState);
74
75 /**
76 * @brief Create BLAS/TLAS.
77 */
78 CreateBottomLevelAS(FrameInfo::Get(), view, rayTracingInstance);
79 CreateTopLevelAS (FrameInfo::Get(), view, rayTracingInstance);
80
81 /**
82 * @brief Create Pipeline/SBT.
83 */
84 CreateDefaultMaterial();
85 CreateRTShaderBindingTable(rayTracingInstance);
86
87 /**
88 * @brief Submit new raytracing instance.
89 */
90 AsyncMainTask(ThreadPoolEnum::Main, [=]() {
91
92 vkQueueWaitIdle(m_VulkanState.m_GraphicQueue);
93 m_RenderCache->PushToCaches(m_VulkanRayTracing);
94 m_VulkanRayTracing = rayTracingInstance;
95
96 });
97 });
98 }
99
101 std::shared_ptr<Material> material ,
102 VkPipelineLayout& layout ,
103 std::shared_ptr<RendererSubPass> subPass
104 )
105 {
107
108 PipelineBuilder{ subPass, material, this }
109 .SetDefault()
110 .NullBindingDescriptions()
111 .NullAttributeDescriptions()
112 .SetPipelineLayout(layout)
113 .BuildRayTracing(*GetHitGroupsCache());
114 }
115
117 {
119
120 if (m_VulkanRayTracing->GetAccelerationStructure() == VK_NULL_HANDLE) return;
121
122 UpdateTopLevelAS(frameInfo, m_VulkanRayTracing);
123
124 if(frameInfo.m_RendererType != RendererType::PathTracing) return;
125
126 RayTracingRenderBehaveBuilder builder{ this, m_VulkanRayTracing.get(), frameInfo.m_FrameIndex, frameInfo.m_ImageIndex};
127
128 builder.BeginRenderPass();
129
130 builder.BindDescriptorSet(DescriptorSetManager::GetByName("PreRenderer"));
131
132 builder.BindDescriptorSet(DescriptorSetManager::GetByName("RayTracing"));
133
134 builder.BindPipeline("RayTracingRenderer.RayTracing.Default");
135
136 builder.UpdateAccelerationStructure(2, 0, m_VulkanRayTracing->GetAccelerationStructure());
137
138 builder.UpdateStorageBuffer(3, 0, m_VulkanRayTracing->GetMeshDesc().buffer);
139
140 builder.UpdateStorageBuffer<RayTracingR::DirectionalLightBuffer>(3, 1, [&](auto& ssbo) {
141 GetDirectionalLight(frameInfo, ssbo.lights);
142 });
143
144 builder.UpdateStorageBuffer<RayTracingR::PointLightBuffer>(3, 2, [&](auto& ssbo) {
145 GetPointLight(frameInfo, ssbo.lights);
146 });
147
148 builder.UpdatePushConstant<RayTracingR::PushConstant>([&](auto& push) {
149 IterWorldCompWithBreak<SkyBoxComponent>(frameInfo, [&](int entityId, TransformComponent& transComp, SkyBoxComponent& camComp){
150 push.entityID = entityId;
151 return true;
152 });
153 });
154
155 builder.TraceRays();
156
157 builder.EndRenderPass();
158 }
159
160 VkAccelerationStructureKHR RayTracingRenderer::GetAccelerationStructure()
161 {
163
164 if(!m_VulkanRayTracing) return nullptr;
165
166 return m_VulkanRayTracing->GetAccelerationStructure();
167 }
168
169 void RayTracingRenderer::UpdateTopLevelAS(FrameInfo& frameInfo, std::shared_ptr<VulkanRayTracing> rayTracingInstance, bool update)
170 {
172
173 if(!(frameInfo.m_World->GetMarker() & World::NeedUpdateTLAS)) return;
174 frameInfo.m_World->ClearMarkerWithBits(World::NeedUpdateTLAS);
175
176 auto view = GetEntityWithComponent<MeshComponent>(frameInfo.m_World.get());
177 CreateTopLevelAS(frameInfo, view, rayTracingInstance, update);
178 }
179
180 void RayTracingRenderer::CreateRTShaderBindingTable(std::shared_ptr<VulkanRayTracing> rayTracingInstance)
181 {
183
184 const auto rayTracingMaterial = ResourcePool<Material>::Load<Material>("RayTracingRenderer.RayTracing.Default", "RayTracingRenderer.RayTracing.Default");
185
186 const uint32_t rayGenCount = static_cast<uint32_t>(rayTracingMaterial->GetShaderPath("rgen").size());
187 const uint32_t missCount = static_cast<uint32_t>(rayTracingMaterial->GetShaderPath("rmiss").size());
188
189 rayTracingInstance->CreateRTShaderBindingTable(rayGenCount, missCount, m_Pipelines.Find("RayTracingRenderer.RayTracing.Default")->GetPipeline());
190 }
191
193 {
195
196 if (!m_HitGroupsCache)
197 {
198 m_HitGroupsCache = std::make_shared<std::unordered_map<std::string, uint32_t>>();
199 }
200
201 return m_HitGroupsCache;
202 }
203
204 void RayTracingRenderer::CreateBottomLevelAS(FrameInfo& frameInfo, std::shared_ptr<std::vector<uint32_t>> view, std::shared_ptr<VulkanRayTracing> rayTracingInstance)
205 {
207
208 /**
209 * @brief BLAS - Storing each primitive in a geometry.
210 */
211 std::vector<VulkanRayTracing::BlasInput> allBlas;
212
213 /**
214 * @brief Iter all MeshComponents.
215 */
216 frameInfo.m_World->ViewComponent<MeshComponent>(*view, [&](auto e, auto& meshComp){
217
218 meshComp.GetMesh()->GetPacks().for_each([&](const uint32_t& k, const std::shared_ptr<MeshPack>& v) {
219
220 if (v->HasBlasAccel()) return false;
221
222 auto blas = v->MeshPackToVkGeometryKHR();
223 allBlas.emplace_back(blas);
224
225 return false;
226 });
227
228 return false;
229 });
230
231 /**
232 * @brief Skip if no blas build requirment.
233 */
234 if(allBlas.empty()) return;
235
236 /**
237 * @brief Build BLAS.
238 */
239 rayTracingInstance->BuildBLAS(
240 allBlas,
241 VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR |
242 VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR
243 //VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR // Compress cost too mush time in with large count of meshes.
244 );
245 }
246
247 void RayTracingRenderer::CreateTopLevelAS(FrameInfo& frameInfo, std::shared_ptr<std::vector<uint32_t>> view, std::shared_ptr<VulkanRayTracing> rayTracingInstance, bool update)
248 {
250
251 std::vector<VkAccelerationStructureInstanceKHR> tlas;
252 std::shared_ptr<std::unordered_map<std::string, uint32_t>> hitGroups = std::make_shared<std::unordered_map<std::string, uint32_t>>();
253
254 int index = 0;
255 auto& desc = rayTracingInstance->GetMeshDesc().attributes;
256 desc->resize(SpicesShader::MESH_BUFFER_MAXNUM, 0);
257
258 frameInfo.m_World->ViewComponent<MeshComponent>(*view, [&](auto e, auto& meshComp){
259
260 auto& tranComp = frameInfo.m_World->GetComponent<TransformComponent>(static_cast<entt::entity>(e));
261
262 meshComp.GetMesh()->AddMaterialToHitGroup(*hitGroups);
263 meshComp.GetMesh()->GetPacks().for_each([&](const uint32_t& k, const std::shared_ptr<MeshPack>& v) {
264
265 VkAccelerationStructureInstanceKHR rayInst{};
266 rayInst.transform = ToVkTransformMatrixKHR(tranComp.GetModelMatrix()); // Position of the instance
267 rayInst.instanceCustomIndex = index; // gl_InstanceCustomIndexEXT
268 rayInst.accelerationStructureReference = v->GetAccel().accel->GetACDeviceAddress();
269 rayInst.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
270 rayInst.mask = 0xFF; // Only be hit if rayMask & instance.mask != 0
271 rayInst.instanceShaderBindingTableRecordOffset = v->GetHitShaderHandle(); // We will use the same hit group for all objects
272
273 tlas.push_back(rayInst);
274
275 (*desc)[index] = v->GetMeshDesc().GetBufferAddress();
276
277 index += 1;
278 return false;
279 });
280
281 return false;
282 });
283
284 rayTracingInstance->GetMeshDesc().CreateBuffer("MeshDescBuffer", VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
285
286 /**
287 * @brief Cache this frame hit groups.
288 */
289 SetHitGroupsCache(hitGroups);
290
291 rayTracingInstance->SetHitGroups(hitGroups);
292
293 /**
294 * @brief Build TLAS.
295 */
296 rayTracingInstance->BuildTLAS(
297 tlas,
298 VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR |
299 VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR |
300 VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR ,
301 update
302 );
303 }
304}
#define SPICES_PROFILE_ZONEN(...)
#define SPICES_PROFILE_ZONE
static FrameInfo & Get()
Get FrameInfo.
Definition FrameInfo.cpp:14
RendererType m_RendererType
The renderer type of current world.
Definition FrameInfo.h:99
FrameInfo Class. This class defines the FrameInfo data.
Definition FrameInfo.h:32
Material Class. This class contains a branch of parameter and shader, also descriptor.
Definition Material.h:62
MeshComponent Class. This class defines the specific behaves of MeshComponent.
virtual void CreateDescriptorSet() override
The interface is inherited from Renderer. Create specific descriptor set for sub pass.
static std::shared_ptr< VulkanRayTracing > m_VulkanRayTracing
In Used VulkanRayTracing.
void CreateTopLevelAS(FrameInfo &frameInfo, std::shared_ptr< std::vector< uint32_t > > view, std::shared_ptr< VulkanRayTracing > rayTracingInstance, bool update=false)
Create TopLevelAS.
virtual void CreatePipeline(std::shared_ptr< Material > material, VkPipelineLayout &layout, std::shared_ptr< RendererSubPass > subPass) override
The interface is inherited from Renderer. Create Material Specific Pipeline.
virtual void Render(TimeStep &ts, FrameInfo &frameInfo) override
The interface is inherited from Renderer.
RayTracingRenderer(const std::string &rendererName, VulkanState &vulkanState, const std::shared_ptr< VulkanDescriptorPool > &descriptorPool, const std::shared_ptr< VulkanDevice > &device, const std::shared_ptr< RendererResourcePool > &rendererResourcePool)
Constructor Function. Init member variables.
virtual void OnMeshAddedWorld() override
virtual ~RayTracingRenderer() override
Destructor Function.
std::shared_ptr< std::unordered_map< std::string, uint32_t > > GetHitGroupsCache()
Get HitGroupsCache.
void CreateRTShaderBindingTable(std::shared_ptr< VulkanRayTracing > rayTracingInstance)
Create Shader Binding Table.
virtual void CreateRendererPass() override
The interface is inherited from Renderer. Create specific render pass.
void CreateBottomLevelAS(FrameInfo &frameInfo, std::shared_ptr< std::vector< uint32_t > > view, std::shared_ptr< VulkanRayTracing > rayTracingInstance)
Create BottomLevelAS with all MeshComponents.
void UpdateTopLevelAS(FrameInfo &frameInfo, std::shared_ptr< VulkanRayTracing > rayTracingInstance, bool update=true)
Update TopLevelAS.
RayTracingRenderer Class. This class defines the ray tracing behaves.
RendererResourcePool Class. This class is a pool of all framebuffer's attachment.
This Class Combines some data relative to sub pass. Usually as a member variable of RendererPass.
virtual void EndRenderPass() override
End this Renderer's RenderPass.
void TraceRays() const
Call vkCmdTraceRaysKHR here.
virtual void BeginRenderPass() override
Begin this Renderer's RenderPass.
This class helps to bind pipeline and bind buffer. Specific for RayTracing Renderer....
Definition Renderer.h:1558
RendererPassBuilder & EndSubPass()
End recording a sub pass.
void Build() const
Build the RendererPass.
RendererPassBuilder & AddSubPass(const std::string &subPassName, Querier::StatisticsFlags flags=Querier::ALL)
Add a new SubPass to Renderer Pass.
virtual void OnMeshAddedWorld()
Definition Renderer.cpp:86
Renderer(const std::string &rendererName, VulkanState &vulkanState, const std::shared_ptr< VulkanDescriptorPool > &DescriptorPool, const std::shared_ptr< VulkanDevice > &device, const std::shared_ptr< RendererResourcePool > &rendererResourcePool, bool isLoadDefaultMaterial=true)
Constructor Function. Init member variables.
Definition Renderer.cpp:16
void GetDirectionalLight(FrameInfo &frameInfo, std::array< SpicesShader::DirectionalLight, SpicesShader::DIRECTIONALLIGHT_BUFFER_MAXNUM > &dLightBuffer)
Get DirectionalLightComponent's render data in World.
Definition Renderer.cpp:371
void GetPointLight(FrameInfo &frameInfo, std::array< SpicesShader::PointLight, SpicesShader::POINTLIGHT_BUFFER_MAXNUM > &pLightBuffer)
Get PointLightComponent's render data in World.
Definition Renderer.cpp:445
Renderer Class. This class defines the basic behaves of renderer. When we add an new Renderer,...
Definition Renderer.h:57
SkyBoxComponent Class. This class defines the specific behaves of SkyBoxComponent.
This Class handles our engine time step during frames. Global Unique.
Definition TimeStep.h:22
TransformComponent Class. This class defines the specific behaves of TransformComponent.
VulkanDescriptorPool Class. This class is the wrapper of VkDescriptorPool.
VulkanInstance Class. This class defines the VulkanDevice behave. This class is just a wrapper of vkd...
Wrapper of Scene RayTracing (KHR/VK) Features and Data.
@ NeedUpdateTLAS
Definition World.h:49
World Class. This class defines the basic behaves of World. When we create an new world,...
Definition World.h:41
RendererType
Definition FrameInfo.h:22
This struct contains all Vulkan object in used global.
Definition VulkanUtils.h:74