Skip to content

Commit aa553f2

Browse files
Update TLAS every frame
1 parent bcef62e commit aa553f2

File tree

1 file changed

+103
-4
lines changed

1 file changed

+103
-4
lines changed

attachments/38_ray_tracing.cpp

Lines changed: 103 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)