@@ -157,6 +157,8 @@ class HelloTriangleApplication {
157157 vk::raii::DeviceMemory tlasScratchMemory = nullptr ;
158158 vk::raii::AccelerationStructureKHR tlas = nullptr ;
159159
160+ UniformBufferObject ubo{};
161+
160162 std::vector<vk::raii::Buffer> uniformBuffers;
161163 std::vector<vk::raii::DeviceMemory> uniformBuffersMemory;
162164 std::vector<void *> uniformBuffersMapped;
@@ -1171,6 +1173,101 @@ class HelloTriangleApplication {
11711173 endSingleTimeCommands (*cmd);
11721174 }
11731175
1176+ void updateTopLevelAS (const glm::mat4 & model) {
1177+ // Assign the model transform to each instance
1178+ vk::TransformMatrixKHR tm{};
1179+ auto &M = model;
1180+ tm.matrix = std::array<std::array<float ,4 >,3 >{{
1181+ std::array<float ,4 >{M[0 ][0 ], M[1 ][0 ], M[2 ][0 ], M[3 ][0 ]},
1182+ std::array<float ,4 >{M[0 ][1 ], M[1 ][1 ], M[2 ][1 ], M[3 ][1 ]},
1183+ std::array<float ,4 >{M[0 ][2 ], M[1 ][2 ], M[2 ][2 ], M[3 ][2 ]}
1184+ }};
1185+
1186+ for (auto & instance : instances) {
1187+ instance.setTransform (tm);
1188+ }
1189+
1190+ vk::DeviceSize instBufferSize = sizeof (instances[0 ]) * instances.size ();
1191+
1192+ vk::raii::Buffer stagingBuffer ({});
1193+ vk::raii::DeviceMemory stagingBufferMemory ({});
1194+ createBuffer (instBufferSize, vk::BufferUsageFlagBits::eTransferSrc, vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent, stagingBuffer, stagingBufferMemory);
1195+
1196+ void * dataStaging = stagingBufferMemory.mapMemory (0 , instBufferSize);
1197+ memcpy (dataStaging, instances.data (), instBufferSize);
1198+ stagingBufferMemory.unmapMemory ();
1199+
1200+ copyBuffer (stagingBuffer, instanceBuffer, instBufferSize);
1201+
1202+ auto cmd = beginSingleTimeCommands ();
1203+
1204+ // Pre-build barrier
1205+ vk::MemoryBarrier preBarrier {
1206+ .srcAccessMask = vk::AccessFlagBits::eAccelerationStructureWriteKHR | vk::AccessFlagBits::eTransferWrite | vk::AccessFlagBits::eShaderRead,
1207+ .dstAccessMask = vk::AccessFlagBits::eAccelerationStructureReadKHR | vk::AccessFlagBits::eAccelerationStructureWriteKHR
1208+ };
1209+ cmd->pipelineBarrier (
1210+ vk::PipelineStageFlagBits::eAccelerationStructureBuildKHR | vk::PipelineStageFlagBits::eTransfer | vk::PipelineStageFlagBits::eFragmentShader, // srcStageMask
1211+ vk::PipelineStageFlagBits::eAccelerationStructureBuildKHR, // dstStageMask
1212+ {}, // dependencyFlags
1213+ preBarrier, // memoryBarriers
1214+ {}, // bufferMemoryBarriers
1215+ {} // imageMemoryBarriers
1216+ );
1217+
1218+ // Re-build TLAS in place
1219+ vk::BufferDeviceAddressInfo instanceAddrInfo{ .buffer = instanceBuffer };
1220+ vk::DeviceAddress instanceAddr = device.getBufferAddressKHR (instanceAddrInfo);
1221+ vk::AccelerationStructureGeometryKHR tlasGeometry{
1222+ .geometryType = vk::GeometryTypeKHR::eInstances,
1223+ .geometry = vk::AccelerationStructureGeometryDataKHR{
1224+ vk::AccelerationStructureGeometryInstancesDataKHR{
1225+ .arrayOfPointers = vk::False,
1226+ .data = instanceAddr
1227+ }
1228+ }
1229+ };
1230+
1231+ vk::AccelerationStructureBuildGeometryInfoKHR tlasBuildInfo{
1232+ .type = vk::AccelerationStructureTypeKHR::eTopLevel,
1233+ .flags = vk::BuildAccelerationStructureFlagBitsKHR::eAllowUpdate,
1234+ .mode = vk::BuildAccelerationStructureModeKHR::eUpdate,
1235+ .geometryCount = 1 ,
1236+ .pGeometries = &tlasGeometry
1237+ };
1238+
1239+ vk::AccelerationStructureBuildRangeInfoKHR tlasRangeInfo{
1240+ .primitiveCount = static_cast <uint32_t >(instances.size ()),
1241+ .primitiveOffset = 0 ,
1242+ .firstVertex = 0 ,
1243+ .transformOffset = 0
1244+ };
1245+
1246+ tlasBuildInfo.dstAccelerationStructure = tlas;
1247+ tlasBuildInfo.srcAccelerationStructure = tlas;
1248+ vk::BufferDeviceAddressInfo scratchAddrInfo2 { .buffer = *tlasScratchBuffer };
1249+ vk::DeviceAddress tlasScratchAddr = device.getBufferAddressKHR (scratchAddrInfo2);
1250+ tlasBuildInfo.scratchData .deviceAddress = tlasScratchAddr;
1251+ cmd->buildAccelerationStructuresKHR ({ tlasBuildInfo }, { &tlasRangeInfo });
1252+
1253+ // Post-build barrier
1254+ vk::MemoryBarrier postBarrier {
1255+ .srcAccessMask = vk::AccessFlagBits::eAccelerationStructureWriteKHR,
1256+ .dstAccessMask = vk::AccessFlagBits::eAccelerationStructureReadKHR | vk::AccessFlagBits::eShaderRead
1257+ };
1258+
1259+ cmd->pipelineBarrier (
1260+ vk::PipelineStageFlagBits::eAccelerationStructureBuildKHR, // srcStageMask
1261+ vk::PipelineStageFlagBits::eAccelerationStructureBuildKHR | vk::PipelineStageFlagBits::eFragmentShader, // dstStageMask
1262+ {}, // dependencyFlags
1263+ postBarrier, // memoryBarriers
1264+ {}, // bufferMemoryBarriers
1265+ {} // imageMemoryBarriers
1266+ );
1267+
1268+ endSingleTimeCommands (*cmd);
1269+ }
1270+
11741271 void createDescriptorPool () {
11751272 std::array poolSize {
11761273 vk::DescriptorPoolSize ( vk::DescriptorType::eUniformBuffer, MAX_FRAMES_IN_FLIGHT),
@@ -1513,15 +1610,16 @@ class HelloTriangleApplication {
15131610 }
15141611 }
15151612
1516- void updateUniformBuffer (uint32_t currentImage) const {
1613+ void updateUniformBuffer (uint32_t currentImage) {
15171614 static auto startTime = std::chrono::high_resolution_clock::now ();
15181615
15191616 auto currentTime = std::chrono::high_resolution_clock::now ();
15201617 float time = std::chrono::duration<float >(currentTime - startTime).count ();
15211618
1522- UniformBufferObject ubo{};
1523- ubo.model = rotate (glm::mat4 (1 .0f ), time * glm::radians (90 .0f ), glm::vec3 (0 .0f , 0 .0f , 1 .0f ));
1524- ubo.view = lookAt (glm::vec3 (2 .0f , 2 .0f , 2 .0f ), glm::vec3 (0 .0f , 0 .0f , 0 .0f ), glm::vec3 (0 .0f , 0 .0f , 1 .0f ));
1619+ auto eye = glm::vec3 (2 .0f , 2 .0f , 2 .0f );
1620+
1621+ ubo.model = rotate (glm::mat4 (1 .0f ), time * 0 .1f * glm::radians (90 .0f ), glm::vec3 (0 .0f , 0 .0f , 1 .0f ));
1622+ ubo.view = lookAt (eye, glm::vec3 (0 .0f , 0 .0f , 0 .0f ), glm::vec3 (0 .0f , 0 .0f , 1 .0f ));
15251623 ubo.proj = glm::perspective (glm::radians (45 .0f ), static_cast <float >(swapChainExtent.width ) / static_cast <float >(swapChainExtent.height ), 0 .1f , 10 .0f );
15261624 ubo.proj [1 ][1 ] *= -1 ;
15271625
@@ -1541,6 +1639,7 @@ class HelloTriangleApplication {
15411639 throw std::runtime_error (" failed to acquire swap chain image!" );
15421640 }
15431641 updateUniformBuffer (currentFrame);
1642+ updateTopLevelAS (ubo.model );
15441643
15451644 device.resetFences ( *inFlightFences[currentFrame] );
15461645 commandBuffers[currentFrame].reset ();
0 commit comments