1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "render_node_default_acceleration_structure_staging.h"
17
18 #include <cinttypes>
19
20 #include <render/datastore/intf_render_data_store_manager.h>
21 #include <render/device/intf_gpu_resource_manager.h>
22 #include <render/namespace.h>
23 #include <render/nodecontext/intf_node_context_pso_manager.h>
24 #include <render/nodecontext/intf_render_command_list.h>
25 #include <render/nodecontext/intf_render_node_context_manager.h>
26
27 #include "datastore/render_data_store_default_acceleration_structure_staging.h"
28
29 #if RENDER_HAS_VULKAN_BACKEND
30 #include <vulkan/vulkan_core.h>
31
32 #include "device/gpu_resource_manager.h"
33 #include "vulkan/gpu_buffer_vk.h"
34 #endif
35
36 #include "util/log.h"
37
38 using namespace BASE_NS;
39
40 RENDER_BEGIN_NAMESPACE()
41 namespace {} // namespace
42
InitNode(IRenderNodeContextManager & renderNodeContextMgr)43 void RenderNodeDefaultAccelerationStructureStaging::InitNode(IRenderNodeContextManager& renderNodeContextMgr)
44 {
45 renderNodeContextMgr_ = &renderNodeContextMgr;
46
47 const auto& renderNodeGraphData = renderNodeContextMgr_->GetRenderNodeGraphData();
48 dsName_ = renderNodeGraphData.renderNodeGraphName + "RenderDataStoreDefaultAccelerationStructureStaging";
49 }
50
PreExecuteFrame()51 void RenderNodeDefaultAccelerationStructureStaging::PreExecuteFrame()
52 {
53 // re-create needed gpu resources
54 }
55
ExecuteFrame(IRenderCommandList & cmdList)56 void RenderNodeDefaultAccelerationStructureStaging::ExecuteFrame(IRenderCommandList& cmdList)
57 {
58 if (renderNodeContextMgr_->GetRenderNodeGraphData().renderingConfiguration.renderBackend !=
59 DeviceBackendType::VULKAN) {
60 return;
61 }
62 #if (RENDER_VULKAN_RT_ENABLED == 1)
63 const IRenderNodeRenderDataStoreManager& rdsMgr = renderNodeContextMgr_->GetRenderDataStoreManager();
64 if (RenderDataStoreDefaultAccelerationStructureStaging* ds =
65 static_cast<RenderDataStoreDefaultAccelerationStructureStaging*>(rdsMgr.GetRenderDataStore(dsName_));
66 ds) {
67 if (ds->HasStagingData()) {
68 // order does not matter ATM (the former is deferred to device the latter is coherently copied)
69 AccelerationStructureBuildConsumeStruct stagingBuildData = ds->ConsumeStagingBuildData();
70 const auto& triangles = stagingBuildData.triangles;
71 const auto& aabbs = stagingBuildData.aabbs;
72 const auto& instances = stagingBuildData.instances;
73 for (const auto geomRef : stagingBuildData.geometry) {
74 const uint32_t startIndex = geomRef.startIndex;
75 const uint32_t count = geomRef.count;
76 PLUGIN_ASSERT(count <= 1);
77 AccelerationStructureBuildGeometryData geometry { { geomRef.data.info },
78 geomRef.data.srcAccelerationStructure.GetHandle(),
79 geomRef.data.dstAccelerationStructure.GetHandle(),
80 { geomRef.data.scratchBuffer.handle.GetHandle(), geomRef.data.scratchBuffer.offset } };
81 if ((geomRef.geometryType == GeometryType::CORE_GEOMETRY_TYPE_TRIANGLES) &&
82 (startIndex + count <= static_cast<uint32_t>(triangles.size()))) {
83 const auto& triRef = triangles[startIndex];
84 AccelerationStructureGeometryTrianglesData triData { triRef.info,
85 { triRef.vertexData.handle.GetHandle(), triRef.vertexData.offset },
86 { triRef.indexData.handle.GetHandle(), triRef.indexData.offset },
87 { triRef.transformData.handle.GetHandle(), triRef.transformData.offset } };
88 cmdList.BuildAccelerationStructures(move(geometry), { &triData, 1u }, {}, {});
89 } else if (geomRef.geometryType == GeometryType::CORE_GEOMETRY_TYPE_AABBS &&
90 (startIndex + count <= static_cast<uint32_t>(aabbs.size()))) {
91 const auto& aabbRef = aabbs[startIndex];
92 AccelerationStructureGeometryAabbsData aabbData { aabbRef.info,
93 { aabbRef.data.handle.GetHandle(), aabbRef.data.offset } };
94 cmdList.BuildAccelerationStructures(move(geometry), {}, { &aabbData, count }, {});
95 } else if ((geomRef.geometryType == GeometryType::CORE_GEOMETRY_TYPE_INSTANCES) &&
96 (startIndex + count <= static_cast<uint32_t>(instances.size()))) {
97 const auto& instanceRef = instances[startIndex];
98 AccelerationStructureGeometryInstancesData instanceData { instanceRef.info,
99 { instanceRef.data.handle.GetHandle(), instanceRef.data.offset } };
100 cmdList.BuildAccelerationStructures(move(geometry), {}, {}, { &instanceData, count });
101 }
102 }
103 ExecuteFrameProcessInstanceData(*ds);
104 }
105 }
106 #endif
107 }
108
ExecuteFrameProcessInstanceData(RenderDataStoreDefaultAccelerationStructureStaging & dataStore)109 void RenderNodeDefaultAccelerationStructureStaging::ExecuteFrameProcessInstanceData(
110 RenderDataStoreDefaultAccelerationStructureStaging& dataStore)
111 {
112 #if (RENDER_VULKAN_RT_ENABLED == 1)
113 #if (RENDER_HAS_VULKAN_BACKEND == 1)
114 AccelerationStructureInstanceConsumeStruct stagingInstanceData = dataStore.ConsumeStagingInstanceData();
115 auto& gpuResourceMgr = static_cast<RenderNodeGpuResourceManager&>(renderNodeContextMgr_->GetGpuResourceManager());
116 const auto& gpuResourceMgrImpl = static_cast<const GpuResourceManager&>(gpuResourceMgr.GetGpuResourceManager());
117 for (const auto dataRef : stagingInstanceData.copyInfo) {
118 if ((!dataRef.bufferOffset.handle) || (dataRef.count == 0)) {
119 continue;
120 }
121 const RenderHandle dstHandle = dataRef.bufferOffset.handle.GetHandle();
122 const GpuBufferDesc dstBufferDesc = gpuResourceMgr.GetBufferDescriptor(dstHandle);
123 if (uint8_t* dstDataBegin = static_cast<uint8_t*>(gpuResourceMgr.MapBuffer(dstHandle)); dstDataBegin) {
124 const uint8_t* dstDataEnd = dstDataBegin + dstBufferDesc.byteSize;
125 // loop and copy all instances
126 for (uint32_t idx = 0; idx < dataRef.count; ++idx) {
127 const auto& instanceRef = stagingInstanceData.instances[dataRef.startIndex + idx];
128 uint64_t accelerationStructureReference = 0;
129 if (const GpuBufferVk* accelPtr = gpuResourceMgrImpl.GetBuffer<GpuBufferVk>(
130 instanceRef.accelerationStructureReference.GetHandle());
131 accelPtr) {
132 accelerationStructureReference = accelPtr->GetPlatformDataAccelerationStructure().deviceAddress;
133 }
134 VkTransformMatrixKHR transformMatrix = { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
135 1.0f, 0.0f };
136
137 VkAccelerationStructureInstanceKHR instance {
138 transformMatrix, // transform;
139 instanceRef.instanceCustomIndex, // instanceCustomIndex : 24
140 instanceRef.mask, // mask : 8
141 0, // instanceShaderBindingTableRecordOffset : 24
142 VkGeometryInstanceFlagsKHR(instanceRef.flags), // flags : 8
143 accelerationStructureReference, // accelerationStructureReference
144 };
145 const size_t byteSize = sizeof(VkAccelerationStructureInstanceKHR);
146 uint8_t* dstData = dstDataBegin + byteSize * idx;
147 CloneData(dstData, size_t(dstDataEnd - dstData), &instance, byteSize);
148 }
149
150 gpuResourceMgr.UnmapBuffer(dstHandle);
151 } else {
152 PLUGIN_LOG_E("accel staging: dstHandle %" PRIu64, dstHandle.id);
153 }
154 }
155 #endif
156 #endif
157 }
158
159 // for plugin / factory interface
Create()160 IRenderNode* RenderNodeDefaultAccelerationStructureStaging::Create()
161 {
162 return new RenderNodeDefaultAccelerationStructureStaging();
163 }
164
Destroy(IRenderNode * instance)165 void RenderNodeDefaultAccelerationStructureStaging::Destroy(IRenderNode* instance)
166 {
167 delete static_cast<RenderNodeDefaultAccelerationStructureStaging*>(instance);
168 }
169 RENDER_END_NAMESPACE()
170