@@ -59,6 +59,8 @@ void VulkanAcceleration::createGroundPlane(VkPhysicalDevice physicalDevice, VkDe
5959 GeometryObject obj;
6060 obj.vertexCount = static_cast <uint32_t >(vertices.size ());
6161 obj.indexCount = static_cast <uint32_t >(indices.size ());
62+ obj.cpuVertices = vertices;
63+ obj.cpuIndices = indices;
6264
6365 VkDeviceSize vertexBufferSize = sizeof (Vertex) * vertices.size ();
6466 VkDeviceSize indexBufferSize = sizeof (uint32_t ) * indices.size ();
@@ -205,6 +207,8 @@ void VulkanAcceleration::createCube(VkPhysicalDevice physicalDevice, VkDevice de
205207 GeometryObject obj;
206208 obj.vertexCount = static_cast <uint32_t >(vertices.size ());
207209 obj.indexCount = static_cast <uint32_t >(indices.size ());
210+ obj.cpuVertices = vertices;
211+ obj.cpuIndices = indices;
208212
209213 VkDeviceSize vertexBufferSize = sizeof (Vertex) * vertices.size ();
210214 VkDeviceSize indexBufferSize = sizeof (uint32_t ) * indices.size ();
@@ -316,7 +320,8 @@ void VulkanAcceleration::createBottomLevelAS(VkPhysicalDevice physicalDevice, Vk
316320 // EXCLUSIVE OPTIMIZATION: PREFER_FAST_TRACE
317321 // We sacrifice build time to ensure maximum traversal speed on RT Cores.
318322 // This fits the "Exclusive Processing" requirement.
319- buildInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR;
323+ buildInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR |
324+ VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR;
320325 buildInfo.geometryCount = 1 ;
321326 buildInfo.pGeometries = &asGeometry;
322327
@@ -771,6 +776,144 @@ void VulkanAcceleration::recordTLASUpdate(VkCommandBuffer commandBuffer) {
771776 0 , 1 , &memBarrierAfter, 0 , nullptr , 0 , nullptr );
772777}
773778
779+ void VulkanAcceleration::updateGeometry (VkPhysicalDevice physicalDevice, VkDevice device,
780+ VkQueue graphicsQueue, VkCommandPool commandPool,
781+ uint32_t objectIndex) {
782+ if (objectIndex >= objects.size ()) return ;
783+
784+ GeometryObject& obj = objects[objectIndex];
785+ VkDeviceSize vertexBufferSize = sizeof (Vertex) * obj.cpuVertices .size ();
786+
787+ // Create staging buffer
788+ VkBuffer stagingBuffer;
789+ VkDeviceMemory stagingBufferMemory;
790+ createBuffer (physicalDevice, device, vertexBufferSize,
791+ VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
792+ VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
793+ stagingBuffer, stagingBufferMemory);
794+
795+ void * data;
796+ vkMapMemory (device, stagingBufferMemory, 0 , vertexBufferSize, 0 , &data);
797+ memcpy (data, obj.cpuVertices .data (), vertexBufferSize);
798+ vkUnmapMemory (device, stagingBufferMemory);
799+
800+ // Copy to vertex buffer
801+ VkCommandBufferAllocateInfo allocInfo{};
802+ allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
803+ allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
804+ allocInfo.commandPool = commandPool;
805+ allocInfo.commandBufferCount = 1 ;
806+
807+ VkCommandBuffer commandBuffer;
808+ vkAllocateCommandBuffers (device, &allocInfo, &commandBuffer);
809+
810+ VkCommandBufferBeginInfo beginInfo{};
811+ beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
812+ beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
813+
814+ vkBeginCommandBuffer (commandBuffer, &beginInfo);
815+ VkBufferCopy copyRegion{};
816+ copyRegion.size = vertexBufferSize;
817+ vkCmdCopyBuffer (commandBuffer, stagingBuffer, obj.vertexBuffer , 1 , ©Region);
818+ vkEndCommandBuffer (commandBuffer);
819+
820+ VkSubmitInfo submitInfo{};
821+ submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
822+ submitInfo.commandBufferCount = 1 ;
823+ submitInfo.pCommandBuffers = &commandBuffer;
824+
825+ vkQueueSubmit (graphicsQueue, 1 , &submitInfo, VK_NULL_HANDLE);
826+ vkQueueWaitIdle (graphicsQueue);
827+
828+ vkFreeCommandBuffers (device, commandPool, 1 , &commandBuffer);
829+ vkDestroyBuffer (device, stagingBuffer, nullptr );
830+ vkFreeMemory (device, stagingBufferMemory, nullptr );
831+
832+ // Update BLAS
833+ updateBottomLevelAS (physicalDevice, device, graphicsQueue, commandPool, obj);
834+ }
835+
836+ void VulkanAcceleration::updateBottomLevelAS (VkPhysicalDevice physicalDevice, VkDevice device,
837+ VkQueue graphicsQueue, VkCommandPool commandPool,
838+ GeometryObject& object) {
839+ VkAccelerationStructureGeometryKHR asGeometry{};
840+ asGeometry.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR;
841+ asGeometry.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR;
842+ asGeometry.flags = VK_GEOMETRY_OPAQUE_BIT_KHR;
843+ asGeometry.geometry .triangles .sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR;
844+ asGeometry.geometry .triangles .vertexFormat = VK_FORMAT_R32G32B32_SFLOAT;
845+ asGeometry.geometry .triangles .vertexData .deviceAddress = getBufferDeviceAddress (device, object.vertexBuffer );
846+ asGeometry.geometry .triangles .vertexStride = sizeof (Vertex);
847+ asGeometry.geometry .triangles .maxVertex = object.vertexCount ;
848+ asGeometry.geometry .triangles .indexType = VK_INDEX_TYPE_UINT32;
849+ asGeometry.geometry .triangles .indexData .deviceAddress = getBufferDeviceAddress (device, object.indexBuffer );
850+
851+ VkAccelerationStructureBuildGeometryInfoKHR buildInfo{};
852+ buildInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR;
853+ buildInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;
854+ buildInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR |
855+ VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR;
856+ buildInfo.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_UPDATE_KHR;
857+ buildInfo.srcAccelerationStructure = object.blas .handle ;
858+ buildInfo.dstAccelerationStructure = object.blas .handle ;
859+ buildInfo.geometryCount = 1 ;
860+ buildInfo.pGeometries = &asGeometry;
861+
862+ uint32_t primitiveCount = object.indexCount / 3 ;
863+
864+ VkAccelerationStructureBuildSizesInfoKHR sizeInfo{};
865+ sizeInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR;
866+ vkGetAccelerationStructureBuildSizesKHR (device, VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR,
867+ &buildInfo, &primitiveCount, &sizeInfo);
868+
869+ // Create scratch buffer for update
870+ VkBuffer scratchBuffer;
871+ VkDeviceMemory scratchMemory;
872+ createBuffer (physicalDevice, device, sizeInfo.updateScratchSize ,
873+ VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
874+ VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
875+ scratchBuffer, scratchMemory);
876+
877+ buildInfo.scratchData .deviceAddress = getBufferDeviceAddress (device, scratchBuffer);
878+
879+ VkAccelerationStructureBuildRangeInfoKHR rangeInfo{};
880+ rangeInfo.primitiveCount = primitiveCount;
881+ rangeInfo.primitiveOffset = 0 ;
882+ rangeInfo.firstVertex = 0 ;
883+ rangeInfo.transformOffset = 0 ;
884+
885+ const VkAccelerationStructureBuildRangeInfoKHR* pRangeInfo = &rangeInfo;
886+
887+ VkCommandBufferAllocateInfo allocInfo{};
888+ allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
889+ allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
890+ allocInfo.commandPool = commandPool;
891+ allocInfo.commandBufferCount = 1 ;
892+
893+ VkCommandBuffer commandBuffer;
894+ vkAllocateCommandBuffers (device, &allocInfo, &commandBuffer);
895+
896+ VkCommandBufferBeginInfo beginInfo{};
897+ beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
898+ beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
899+
900+ vkBeginCommandBuffer (commandBuffer, &beginInfo);
901+ vkCmdBuildAccelerationStructuresKHR (commandBuffer, 1 , &buildInfo, &pRangeInfo);
902+ vkEndCommandBuffer (commandBuffer);
903+
904+ VkSubmitInfo submitInfo{};
905+ submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
906+ submitInfo.commandBufferCount = 1 ;
907+ submitInfo.pCommandBuffers = &commandBuffer;
908+
909+ vkQueueSubmit (graphicsQueue, 1 , &submitInfo, VK_NULL_HANDLE);
910+ vkQueueWaitIdle (graphicsQueue);
911+
912+ vkFreeCommandBuffers (device, commandPool, 1 , &commandBuffer);
913+ vkDestroyBuffer (device, scratchBuffer, nullptr );
914+ vkFreeMemory (device, scratchMemory, nullptr );
915+ }
916+
774917void VulkanAcceleration::cleanup (VkDevice device) {
775918 // Cleanup all objects
776919 for (auto & obj : objects) {
0 commit comments