Commit ffb60e55 authored by Nicholas Milef's avatar Nicholas Milef

ENH: added ray tracing scene

parent 036ad371
Pipeline #126508 passed with stage
......@@ -59,6 +59,7 @@ set(VULKAN_H_FILES
VulkanRenderer/imstkVulkanVertexBuffer.h
VulkanRenderer/imstkVulkanFramebuffer.h
VulkanRenderer/imstkVulkanUtilities.h
VulkanRenderer/imstkVulkanExtensionFunctions.h
VulkanRenderer/imstkVulkanRenderPassGenerator.h
VulkanRenderer/PostProcessing/imstkVulkanPostProcess.h
VulkanRenderer/PostProcessing/imstkVulkanPostProcessingChain.h)
......
......@@ -194,4 +194,116 @@ VulkanRenderDelegate::updateUniforms(uint32_t frameIndex)
m_fragmentUniformBuffer->updateUniforms(sizeof(VulkanLocalFragmentUniforms),
(void*)&m_localFragmentUniforms, frameIndex);
}
bool
VulkanRenderDelegate::updateRayTracingStructure(
std::shared_ptr<VulkanExtensionFunctions> extensionFunctions,
VkDevice& device,
std::shared_ptr<VulkanCommandBuffer> commandBuffer,
VulkanMemoryManager& memoryManager)
{
if (m_rayTracingStructure != nullptr)
{
return false;
}
VkGeometryTrianglesNV triangles;
triangles.sType = VK_STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NV;
triangles.pNext = nullptr;
triangles.vertexData = *m_vertexBuffer->getVulkanVertexBuffer();
triangles.vertexOffset = m_vertexBuffer->getVertexBufferOffset();
triangles.vertexCount = (uint32_t)m_numVertices;
triangles.vertexStride = sizeof(VulkanBasicVertex);
triangles.vertexFormat = VK_FORMAT_R32G32B32_SFLOAT;
triangles.indexData = *m_vertexBuffer->getVulkanIndexBuffer();
triangles.indexOffset = m_vertexBuffer->getIndexBufferOffset();
triangles.indexCount = (uint32_t)m_numTriangles * 3;
triangles.indexType = VK_INDEX_TYPE_UINT32;
triangles.transformData = nullptr;
triangles.transformOffset = 0;
VkGeometryAABBNV aabb;
aabb.sType = VK_STRUCTURE_TYPE_GEOMETRY_AABB_NV;
aabb.pNext = nullptr;
aabb.aabbData = nullptr;
aabb.numAABBs = 0;
aabb.stride = 0;
aabb.offset = 0;
VkGeometryDataNV geometryData;
geometryData.triangles = triangles;
geometryData.aabbs = aabb; // Leave blank
VkGeometryNV geometry;
geometry.sType = VK_STRUCTURE_TYPE_GEOMETRY_NV;
geometry.pNext = nullptr;
geometry.flags = 0;
geometry.geometry = geometryData;
geometry.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_NV;
VkAccelerationStructureInfoNV rayTracingStructureInfo;
rayTracingStructureInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_INFO_NV;
rayTracingStructureInfo.pNext = nullptr;
rayTracingStructureInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV;
rayTracingStructureInfo.flags = 0;
rayTracingStructureInfo.instanceCount = 0;
rayTracingStructureInfo.geometryCount = 1;
rayTracingStructureInfo.pGeometries = &geometry;
VkAccelerationStructureCreateInfoNV rayTracingStructureCreateInfo;
rayTracingStructureCreateInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_NV;
rayTracingStructureCreateInfo.pNext = nullptr;
rayTracingStructureCreateInfo.compactedSize = 0;
rayTracingStructureCreateInfo.info = rayTracingStructureInfo;
extensionFunctions->vkCreateAccelerationStructureNV(device,
&rayTracingStructureCreateInfo,
nullptr,
&m_rayTracingStructure);
VkAccelerationStructureMemoryRequirementsInfoNV memoryRequirementsInfo;
memoryRequirementsInfo.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV;
memoryRequirementsInfo.pNext = nullptr;
memoryRequirementsInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV;
memoryRequirementsInfo.accelerationStructure = m_rayTracingStructure;
VkMemoryRequirements2KHR memoryRequirements;
extensionFunctions->vkGetAccelerationStructureMemoryRequirementsNV(device,
&memoryRequirementsInfo,
&memoryRequirements);
VkBufferCreateInfo scratchBufferInfo;
scratchBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
scratchBufferInfo.pNext = nullptr;
scratchBufferInfo.flags = 0;
scratchBufferInfo.size = memoryRequirements.memoryRequirements.size;
scratchBufferInfo.usage = VK_BUFFER_USAGE_RAY_TRACING_BIT_NV;
scratchBufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
scratchBufferInfo.queueFamilyIndexCount = 0;
scratchBufferInfo.pQueueFamilyIndices = nullptr;
auto scratchBuffer = memoryManager.requestBuffer(device,
scratchBufferInfo,
VulkanMemoryType::RT_SCRATCH,
memoryRequirements.memoryRequirements.alignment);
extensionFunctions->vkCmdBuildAccelerationStructureNV(commandBuffer->getCommandBuffer(),
&rayTracingStructureInfo,
VK_NULL_HANDLE, // This is a bottom-level structure
0, // This is a bottom-level structure
VK_FALSE,
m_rayTracingStructure,
VK_NULL_HANDLE,
*scratchBuffer->getBuffer(),
scratchBuffer->getOffset());
/*extensionFunctions->vkGetAccelerationStructureHandleNV(device,
m_rayTracingStructure,
8,
&m_rayTracingStructureHandle);*/
return true;
}
}
\ No newline at end of file
......@@ -33,8 +33,7 @@
#include "imstkVulkanVertexBuffer.h"
#include "imstkVulkanUniformBuffer.h"
#include "imstkVulkanMaterialDelegate.h"
#include "vtkPolyDataMapper.h"
#include "imstkVulkanExtensionFunctions.h"
namespace imstk
{
......@@ -92,10 +91,22 @@ public:
void updateUniforms(uint32_t frameIndex);
///
/// \brief Updates ray tracing structure if necessary
///
/// \returns True if updated, else false
///
bool updateRayTracingStructure(
std::shared_ptr<VulkanExtensionFunctions> extensionFunctions,
VkDevice& device,
std::shared_ptr<VulkanCommandBuffer> commandBuffer,
VulkanMemoryManager& memoryManager);
protected:
friend class VulkanVertexBuffer;
friend class VulkanRenderer;
friend class VulkanUniformBuffer;
friend class VulkanRayTracingScene;
unsigned int m_numTriangles;
unsigned int m_numVertices;
......@@ -119,6 +130,9 @@ protected:
VulkanLocalVertexUniforms m_localVertexUniforms;
VulkanLocalFragmentUniforms m_localFragmentUniforms;
VkAccelerationStructureNV m_rayTracingStructure = nullptr; ///< for ray tracing
uint64_t m_rayTracingStructureHandle;
};
}
......
/*=========================================================================
Library: iMSTK
Copyright (c) Kitware, Inc. & Center for Modeling, Simulation,
& Imaging in Medicine, Rensselaer Polytechnic Institute.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0.txt
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
=========================================================================*/
#include "imstkVulkanCommandBuffer.h"
namespace imstk
{
VulkanCommandBuffer::VulkanCommandBuffer(VkCommandBuffer& commandBuffer)
: m_commandBuffer(commandBuffer)
{
}
void
VulkanCommandBuffer::begin()
{
VkCommandBufferBeginInfo commandBufferBeginInfo;
commandBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
commandBufferBeginInfo.pNext = nullptr;
commandBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
commandBufferBeginInfo.pInheritanceInfo = nullptr;
vkBeginCommandBuffer(m_commandBuffer, &commandBufferBeginInfo);
}
void
VulkanCommandBuffer::end()
{
vkEndCommandBuffer(m_commandBuffer);
}
VkCommandBuffer&
VulkanCommandBuffer::getCommandBuffer()
{
return m_commandBuffer;
}
} // imstk
\ No newline at end of file
/*=========================================================================
Library: iMSTK
Copyright (c) Kitware, Inc. & Center for Modeling, Simulation,
& Imaging in Medicine, Rensselaer Polytechnic Institute.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0.txt
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
=========================================================================*/
#ifndef imstkVulkanCommandBuffer_h
#define imstkVulkanCommandBuffer_h
#include "vulkan/vulkan.h"
namespace imstk
{
///
/// \class VulkanCommandBuffer
///
/// \brief A wrapper around the Vulkan command buffer
///
class VulkanCommandBuffer
{
public:
///
/// \brief Default constructor
///
VulkanCommandBuffer(VkCommandBuffer& commandBuffer);
///
/// \brief Begin command buffer
///
void begin();
///
/// \brief End command buffer
///
void end();
///
/// \brief Get Vulkan command buffer
///
VkCommandBuffer& getCommandBuffer();
protected:
VkCommandBuffer& m_commandBuffer;
};
} // imstk
#endif // imstkVulkanCommandBuffer_h
\ No newline at end of file
/*=========================================================================
Library: iMSTK
Copyright (c) Kitware, Inc. & Center for Modeling, Simulation,
& Imaging in Medicine, Rensselaer Polytechnic Institute.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0.txt
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
=========================================================================*/
#include "imstkVulkanCommandPool.h"
namespace imstk
{
VulkanCommandPool::VulkanCommandPool(VkDevice& device, uint32_t numBuffers)
{
// Allocate command pool
VkCommandPoolCreateInfo commandPoolInfo;
commandPoolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
commandPoolInfo.pNext = nullptr;
commandPoolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
commandPoolInfo.queueFamilyIndex = 0;
vkCreateCommandPool(device, &commandPoolInfo, nullptr, &m_commandPool);
// Allocate command buffers
VkCommandBufferAllocateInfo commandBufferInfo;
commandBufferInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
commandBufferInfo.pNext = nullptr;
commandBufferInfo.commandPool = m_commandPool;
commandBufferInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
commandBufferInfo.commandBufferCount = numBuffers;
m_commandBuffersBacking.resize(numBuffers);
vkAllocateCommandBuffers(device, &commandBufferInfo, &m_commandBuffersBacking[0]);
// Create command buffer objects
for (int i = 0; i < numBuffers; i++)
{
m_commandBuffers.push_back(std::make_shared<VulkanCommandBuffer>(m_commandBuffersBacking[i]));
}
}
std::shared_ptr<VulkanCommandBuffer>
VulkanCommandPool::getCommandBuffer(uint32_t index)
{
return m_commandBuffers[index];
}
VkCommandBuffer&
VulkanCommandPool::getVulkanCommandBuffer(uint32_t index)
{
return m_commandBuffersBacking[index];
}
void
VulkanCommandPool::destroy(VkDevice& device)
{
vkDestroyCommandPool(device, m_commandPool, nullptr);
}
} // imstk
\ No newline at end of file
/*=========================================================================
Library: iMSTK
Copyright (c) Kitware, Inc. & Center for Modeling, Simulation,
& Imaging in Medicine, Rensselaer Polytechnic Institute.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0.txt
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
=========================================================================*/
#ifndef imstkVulkanCommandPool_h
#define imstkVulkanCommandPool_h
#include <vector>
#include <memory>
#include "vulkan/vulkan.h"
#include "imstkVulkanCommandBuffer.h"
namespace imstk
{
///
/// \class VulkanCommandPool
///
/// \brief Wrapper around Vulkan command pool
/// If doing multithreading, it's best to use separate pools per thread (i.e.,
/// threads shouldn't share pools)
///
class VulkanCommandPool
{
public:
///
/// \brief Default constructor
/// \param device Vulkan device
/// \param numBuffers Number of command buffers to allocate
/// Often, numBuffers will be the buffering mode supported by the renderer
///
VulkanCommandPool(VkDevice& device, uint32_t numBuffers);
///
/// \brief Get command buffer
/// \param index Index of command buffer
///
std::shared_ptr<VulkanCommandBuffer> getCommandBuffer(uint32_t index);
///
/// \brief Shortcut for getting Vulkan command buffer
/// \param index Index of command buffer
///
VkCommandBuffer& getVulkanCommandBuffer(uint32_t index);
///
/// \brief Destroy command pool
///
void destroy(VkDevice& device);
protected:
std::vector<std::shared_ptr<VulkanCommandBuffer>> m_commandBuffers;
std::vector<VkCommandBuffer> m_commandBuffersBacking;
VkCommandPool m_commandPool;
};
} // imstk
#endif // imstkVulkanCommandPool_h
\ No newline at end of file
/*=========================================================================
Library: iMSTK
Copyright (c) Kitware, Inc. & Center for Modeling, Simulation,
& Imaging in Medicine, Rensselaer Polytechnic Institute.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0.txt
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
=========================================================================*/
#ifndef imstkVulkanExtensionFunctions_h
#define imstkVulkanExtensionFunctions_h
#include "vulkan/vulkan.h"
namespace imstk
{
///
/// \class Vulkan Extension Functions
///
/// \brief Loads extension functions
/// The problem is that vulkan-1.lib provided with the VulkanSDK provides
/// pointers to only the core functions. To access the extension functions,
/// we have to find the address of the functions separately.
///
class VulkanExtensionFunctions
{
public:
///
/// \brief Default constructor
///
VulkanExtensionFunctions() {}
///
/// \brief Load instance-level extension functions
///
void loadInstanceFunctions(VkInstance& instance)
{
vkCreateAccelerationStructureNV =
(PFN_vkCreateAccelerationStructureNV) vkGetInstanceProcAddr(instance, "vkCreateAccelerationStructureNV");
}
///
/// \brief Load device-level extension functions
///
void loadDeviceFunctions(VkDevice& device)
{
vkCmdBuildAccelerationStructureNV =
(PFN_vkCmdBuildAccelerationStructureNV) vkGetDeviceProcAddr(device, "vkCmdBuildAccelerationStructureNV");
vkGetAccelerationStructureMemoryRequirementsNV =
(PFN_vkGetAccelerationStructureMemoryRequirementsNV) vkGetDeviceProcAddr(device, "vkGetAccelerationStructureMemoryRequirementsNV");
vkGetAccelerationStructureHandleNV =
(PFN_vkGetAccelerationStructureHandleNV) vkGetDeviceProcAddr(device, "vkGetAccelerationStructureHandleNV");
}
PFN_vkCreateAccelerationStructureNV vkCreateAccelerationStructureNV;
PFN_vkCmdBuildAccelerationStructureNV vkCmdBuildAccelerationStructureNV;
PFN_vkGetAccelerationStructureMemoryRequirementsNV vkGetAccelerationStructureMemoryRequirementsNV;
PFN_vkGetAccelerationStructureHandleNV vkGetAccelerationStructureHandleNV;
};
}
#endif
\ No newline at end of file
......@@ -68,12 +68,14 @@ VulkanMemoryManager::requestMemoryAllocation(
case INDEX:
case UNIFORM:
case FRAMEBUFFER:
case RT_SCRATCH:
location = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
break;
case STAGING_TEXTURE:
case STAGING_VERTEX:
case STAGING_INDEX:
case STAGING_UNIFORM:
case RT_INSTANCE_DATA:
location = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
break;
default:
......
......@@ -22,12 +22,13 @@
#ifndef imstkVulkanMemoryManager_h
#define imstkVulkanMemoryManager_h
#include "vulkan/vulkan.h"
#include <vector>
#include "vulkan/vulkan.h"
#include "g3log/g3log.hpp"
#include "imstkVulkanCommandPool.h"
namespace imstk
{
enum VulkanMemoryType
......@@ -40,7 +41,9 @@ enum VulkanMemoryType
STAGING_INDEX,
UNIFORM,
STAGING_UNIFORM,
FRAMEBUFFER
FRAMEBUFFER,
RT_SCRATCH,
RT_INSTANCE_DATA
};
class VulkanInternalMemory
......@@ -223,7 +226,7 @@ public:
VkPhysicalDeviceMemoryProperties m_deviceMemoryProperties;
uint32_t m_queueFamilyIndex;
VkCommandBuffer * m_transferCommandBuffer;
std::shared_ptr<VulkanCommandPool> m_transferCommandPool;
VkQueue * m_transferQueue;
uint32_t m_buffering = 3;
......
/*=========================================================================
Library: iMSTK
Copyright (c) Kitware, Inc. & Center for Modeling, Simulation,
& Imaging in Medicine, Rensselaer Polytechnic Institute.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0.txt
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
=========================================================================*/
#include "imstkVulkanRayTracingScene.h"
namespace imstk
{
VulkanRayTracingScene::VulkanRayTracingScene()
{
}
void
VulkanRayTracingScene::initialize(VulkanMemoryManager& memoryManager, VkDevice& device)
{
VkBufferCreateInfo bufferInfo;
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
bufferInfo.pNext = nullptr;
bufferInfo.flags = 0;
bufferInfo.size = c_instanceDataBufferSize;
bufferInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
bufferInfo.queueFamilyIndexCount = 0;
bufferInfo.pQueueFamilyIndices = nullptr;
m_instanceDataBuffer = memoryManager.requestBuffer(device,
bufferInfo,
VulkanMemoryType::RT_INSTANCE_DATA,
sizeof(VulkanRayTracingInstanceData));
m_instanceData =
(VulkanRayTracingInstanceData*)m_instanceDataBuffer->getMemoryData(device);
}
void
VulkanRayTracingScene::addRayTracingObject(std::shared_ptr<VulkanRenderDelegate> renderDelegate)
{
m_renderDelegates.push_back(renderDelegate);
}
void
VulkanRayTracingScene::update(
std::shared_ptr<VulkanExtensionFunctions> extensionFunctions,
VkDevice& device,
std::shared_ptr<VulkanCommandBuffer> commandBuffer,
VulkanMemoryManager& memoryManager)
{
commandBuffer->begin();
for (size_t i = 0; i < m_renderDelegates.size(); i++)
{
auto renderDelegate = m_renderDelegates[i];
if (renderDelegate->updateRayTracingStructure(extensionFunctions,
device,
commandBuffer,
memoryManager))
{
updateInstanceData(i);
}
}
commandBuffer->end();
}
void
VulkanRayTracingScene::updateInstanceData(size_t index)
{
auto transform = m_renderDelegates[index]->m_localVertexUniforms.transform;
memcpy(&m_instanceData[index].transform[0], &transform, 12 * sizeof(float));
m_instanceData[index].index = (uint32_t)index;
m_instanceData[index].mask = 1;
m_instanceData[index].offset = (uint32_t)(index * sizeof(VulkanRayTracingInstanceData));
m_instanceData[index].flags = 0;
m_instanceData[index].structure = m_renderDelegates[index]->m_rayTracingStructureHandle;
}
} // imstk
\ No newline at end of file
/*=========================================================================
Library: iMSTK
Copyright (c) Kitware, Inc. & Center for Modeling, Simulation,
& Imaging in Medicine, Rensselaer Polytechnic Institute.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0.txt
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
=========================================================================*/
#ifndef imstkVulkanRayTracingScene_h
#define imstkVulkanRayTracingScene_h
#include "vulkan/vulkan.h"
#include "imstkVulkanRenderDelegate.h"
#include "imstkVulkanMemoryManager.h"
#include "imstkVulkanBuffer.h"
namespace imstk
{
struct VulkanRayTracingInstanceData
{
float transform[12];
uint32_t index : 24;
uint32_t mask : 8;
uint32_t offset : 24;
uint32_t flags : 8;
uint64_t struct