Rename docs to .html to prep for updated Markdeep version.

This commit is contained in:
Neil Bickford 2021-01-06 17:47:35 -08:00
parent 7f903f8a22
commit a085dc1866
12 changed files with 2 additions and 2 deletions

View file

@ -1,251 +0,0 @@
<meta charset="utf-8" lang="en">
**Converting VK_NV_ray_tracing to VK_KHR_ray_tracing**
This document is a quick guide on what need to be changed to convert an existing application
using NV ray tracing extension to KHR.
# The Obvious
For most structures and enum, the ending with NV can be replaced with KHR.
This is true for example for:
Some examples:
NVIDIA | KHRONOS
-------------------------------|-----------------------------
VK_SHADER_STAGE_RAYGEN_BIT_NV | VK_SHADER_STAGE_RAYGEN_BIT_KHR
VK_SHADER_STAGE_CLOSEST_HIT_BIT_NV | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR
VK_GEOMETRY_INSTANCE_TRIANGLE_CULL_DISABLE_BIT_NV | VK_GEOMETRY_INSTANCE_TRIANGLE_CULL_DISABLE_BIT_KHR
VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_NV | VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR
[Types and Flags]
NVIDIA | KHRONOS
-------------------------------|-----------------------------
VkWriteDescriptorSetAccelerationStructureNV | VkWriteDescriptorSetAccelerationStructureKHR
VkRayTracingShaderGroupCreateInfoNV | VkRayTracingShaderGroupCreateInfoKHR
VkRayTracingPipelineCreateInfoNV | VkRayTracingPipelineCreateInfoKHR
[Structures]
# Handles version Device Addresses -> memory allocations
With KHR, we no longer pass the buffer or an handle, but the `vk::DeviceAddress`.
First, when allocating a buffer, it has to have the `VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT` flag.
Similarly, the memory associated with this buffer, needs also the `VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT` flag.
For the memory allocation, this could be done like this:
~~~~ C++
vk::MemoryAllocateFlagsInfo memFlagInfo;
memFlagInfo.setFlags(vk::MemoryAllocateFlagBits::eDeviceAddress);
vk::MemoryAllocateInfo memAlloc;
memAlloc.setPNext(&memFlagInfo);
// Allocate memory
~~~~
The buffer address could then be retrieved like this:
~~~~ C++
vk::DeviceAddress vertexAddress = m_device.getBufferAddress({model.vertexBuffer.buffer});
~~~~
# Where is GeometryNV?
The structure to create BLAS was replaced by different structures.
* `vk::AccelerationStructureCreateGeometryTypeInfoKHR` : describe how the acceleration structure is created. It is an indication how large it could be.
* `vk::AccelerationStructureGeometryKHR` : the geometry to build, addresses of vertices and indices
* `vk::AccelerationStructureBuildOffsetInfoKHR` : the number of elements to build and offsets
Those three structures can be an array of each, meaning that a BLAS can be a combination fo multiple geometries.
As an example on how those are filed. It returns `nvvkpp::RaytracingBuilderKHR::Blas` which has vectors
of the above structures.
~~~~ C++
//--------------------------------------------------------------------------------------------------
// Converting a OBJ primitive to the ray tracing geometry used for the BLAS
//
nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model)
{
// Setting up the creation info of acceleration structure
vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate;
asCreate.setGeometryType(vk::GeometryTypeKHR::eTriangles);
asCreate.setIndexType(vk::IndexType::eUint32);
asCreate.setVertexFormat(vk::Format::eR32G32B32Sfloat);
asCreate.setMaxPrimitiveCount(model.nbIndices / 3); // Nb triangles
asCreate.setMaxVertexCount(model.nbVertices);
asCreate.setAllowsTransforms(VK_FALSE); // No adding transformation matrices
// Building part
vk::DeviceAddress vertexAddress = m_device.getBufferAddress({model.vertexBuffer.buffer});
vk::DeviceAddress indexAddress = m_device.getBufferAddress({model.indexBuffer.buffer});
vk::AccelerationStructureGeometryTrianglesDataKHR triangles;
triangles.setVertexFormat(asCreate.vertexFormat);
triangles.setVertexData(vertexAddress);
triangles.setVertexStride(sizeof(VertexObj));
triangles.setIndexType(asCreate.indexType);
triangles.setIndexData(indexAddress);
triangles.setTransformData({});
// Setting up the build info of the acceleration
vk::AccelerationStructureGeometryKHR asGeom;
asGeom.setGeometryType(asCreate.geometryType);
asGeom.setFlags(vk::GeometryFlagBitsKHR::eOpaque);
asGeom.geometry.setTriangles(triangles);
// The primitive itself
vk::AccelerationStructureBuildOffsetInfoKHR offset;
offset.setFirstVertex(0);
offset.setPrimitiveCount(asCreate.maxPrimitiveCount);
offset.setPrimitiveOffset(0);
offset.setTransformOffset(0);
// Our blas is only one geometry, but could be made of many geometries
nvvkpp::RaytracingBuilderKHR::Blas blas;
blas.asGeometry.emplace_back(asGeom);
blas.asCreateGeometryInfo.emplace_back(asCreate);
blas.asBuildOffsetInfo.emplace_back(offset);
return blas;
}
~~~~
# Creating and building BLAS/TLAS
With the structures filled in, there are some similarities with the NVIDIA extension.
## BLAS
The construction of a BLAS AS will look like this:
~~~~ C++
vk::AccelerationStructureCreateInfoKHR asCreateInfo{{}, vk::AccelerationStructureTypeKHR::eBottomLevel};
asCreateInfo.setFlags(vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace);
asCreateInfo.setMaxGeometryCount((uint32_t)blas.asCreateGeometryInfo.size());
asCreateInfo.setPGeometryInfos(blas.asCreateGeometryInfo.data());
// Create an acceleration structure identifier and allocate memory to
// store the resulting structure data
blas.as = m_alloc.createAcceleration(asCreateInfo);
~~~~
To retrieve the memory requirements, there is a new flag, to be build on the host or the device.
~~~~ C++
vk::AccelerationStructureMemoryRequirementsInfoKHR memoryRequirementsInfo{
vk::AccelerationStructureMemoryRequirementsTypeKHR::eBuildScratch,
vk::AccelerationStructureBuildTypeKHR::eDevice, blas.as.accel};
~~~~
Building the acceleration structure requires to pass a pointer to the array of vk::AccelerationStructureGeometryKHR.
~~~~ C++
const vk::AccelerationStructureGeometryKHR* pGeometry = blas.asGeometry.data();
vk::AccelerationStructureBuildGeometryInfoKHR bottomASInfo{vk::AccelerationStructureTypeKHR::eBottomLevel};
bottomASInfo.setFlags(flags);
bottomASInfo.setUpdate(VK_FALSE);
bottomASInfo.setSrcAccelerationStructure({});
bottomASInfo.setDstAccelerationStructure(blas.as.accel);
bottomASInfo.setGeometryArrayOfPointers(VK_FALSE);
bottomASInfo.setGeometryCount((uint32_t)blas.asGeometry.size());
bottomASInfo.setPpGeometries(&pGeometry);
bottomASInfo.setScratchData(scratchAddress);
~~~~
It will be also necessary to create an array of pointers to the vk::AccelerationStructureBuildOffsetInfoKHR of each BLAS.
~~~~ C++
// Pointers of offset
std::vector<const vk::AccelerationStructureBuildOffsetInfoKHR*> pBuildOffset(blas.asBuildOffsetInfo.size());
for(size_t i = 0; i < blas.asBuildOffsetInfo.size(); i++)
pBuildOffset[i] = &blas.asBuildOffsetInfo[i];
~~~~
## TLAS
The same structures are now used to build the top-level, using instances as the type of geometry.
FOr example, here how can be created the AS for an array of instances
~~~~ C++
vk::AccelerationStructureCreateGeometryTypeInfoKHR geometryCreate{vk::GeometryTypeKHR::eInstances};
geometryCreate.setMaxPrimitiveCount(static_cast<uint32_t>(instances.size()));
geometryCreate.setAllowsTransforms(VK_TRUE);
vk::AccelerationStructureCreateInfoKHR asCreateInfo{{}, vk::AccelerationStructureTypeKHR::eTopLevel};
asCreateInfo.setFlags(flags);
asCreateInfo.setMaxGeometryCount(1);
asCreateInfo.setPGeometryInfos(&geometryCreate);
// Create the acceleration structure object and allocate the memory
// required to hold the TLAS data
m_tlas.as = m_alloc.createAcceleration(asCreateInfo);
~~~~
Also, there are now a structure to hold the instances `vk::AccelerationStructureInstanceKHR`
You will need to fill an array with all the information, create a buffer and use
the address to set the geometry
~~~~ C++
// Allocate the instance buffer and copy its contents from host to device
// memory
m_instBuffer = m_alloc.createBuffer(cmdBuf, geometryInstances,
vk::BufferUsageFlagBits::eRayTracingKHR | vk::BufferUsageFlagBits::eShaderDeviceAddress);
m_debug.setObjectName(m_instBuffer.buffer, "TLASInstances");
vk::DeviceAddress instanceAddress = m_device.getBufferAddress(m_instBuffer.buffer);
vk::AccelerationStructureGeometryKHR topASGeometry{vk::GeometryTypeKHR::eInstances};
topASGeometry.geometry.instances.setArrayOfPointers(VK_FALSE);
topASGeometry.geometry.instances.setData(instanceAddress);
~~~~
# Calling TraceRaysKHR
This is very close to the NVIDIA version, the difference is instead of passing buffer addresses, offsets, strides,
for each stages, we have to fill vk::StridedBufferRegionKHR structure of each stages, which have
the same parameters: buffer, offset, stride and SBT size
Example:
~~~~ C++
vk::DeviceSize sbtSize = progSize * (vk::DeviceSize)m_rtShaderGroups.size();
const vk::StridedBufferRegionKHR raygenShaderBindingTable = {m_rtSBTBuffer.buffer, rayGenOffset,
progSize, sbtSize};
const vk::StridedBufferRegionKHR missShaderBindingTable = {m_rtSBTBuffer.buffer, missOffset,
progSize, sbtSize};
const vk::StridedBufferRegionKHR hitShaderBindingTable = {m_rtSBTBuffer.buffer, hitGroupOffset,
progSize, sbtSize};
const vk::StridedBufferRegionKHR callableShaderBindingTable;
cmdBuf.traceRaysKHR(&raygenShaderBindingTable, &missShaderBindingTable, &hitShaderBindingTable,
&callableShaderBindingTable, //
m_size.width, m_size.height, 1); //
~~~~
<!-- Markdeep: -->
<link rel="stylesheet" href="vkrt_tutorial.css?">
<script> window.markdeepOptions = { tocStyle: "medium" };</script>
<script src="markdeep.min.js" charset="utf-8"></script>
<script src="https://developer.nvidia.com/sites/default/files/akamai/gameworks/whitepapers/markdeep.min.js" charset="utf-8"></script>
<script>
window.alreadyProcessedMarkdeep || (document.body.style.visibility = "visible")
</script>