Using buffer reference instead of un-sized array

This commit is contained in:
mklefrancois 2021-06-11 12:25:06 +02:00
parent e3a57e6d63
commit c8a0122dd6
248 changed files with 2593 additions and 2660 deletions

View file

@ -130,6 +130,13 @@ void HelloVulkan::createSpheres(uint32_t nbSpheres)
m_debug.setObjectName(m_spheresAabbBuffer.buffer, "spheresAabb");
m_debug.setObjectName(m_spheresMatColorBuffer.buffer, "spheresMat");
m_debug.setObjectName(m_spheresMatIndexBuffer.buffer, "spheresMatIdx");
// Adding an extra instance to get access to the material buffers
ObjInstance instance{};
instance.objIndex = static_cast<uint32_t>(m_objModel.size());
instance.materials = nvvk::getBufferDeviceAddress(m_device, m_spheresMatColorBuffer.buffer);
instance.materialIndices = nvvk::getBufferDeviceAddress(m_device, m_spheresMatIndexBuffer.buffer);
m_objInstance.emplace_back(instance);
}
~~~~
@ -152,9 +159,7 @@ What is changing compare to triangle primitive is the Aabb data (see Aabb struct
//
nvvk::RaytracingBuilderKHR::BlasInput HelloVulkan::sphereToVkGeometryKHR()
{
VkBufferDeviceAddressInfo info{VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO};
info.buffer = m_spheresAabbBuffer.buffer;
VkDeviceAddress dataAddress = vkGetBufferDeviceAddress(m_device, &info);
VkDeviceAddress dataAddress = nvvk::getBufferDeviceAddress(m_device, m_spheresAabbBuffer.buffer);
VkAccelerationStructureGeometryAabbsDataKHR aabbs{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_AABBS_DATA_KHR};
aabbs.data.deviceAddress = dataAddress;
@ -233,14 +238,26 @@ Similarly in `createTopLevelAS()`, the top level acceleration structure will nee
The hitGroupId will be set to 1 instead of 0. We need to add a new hit group for the implicit primitives, since we will need to compute attributes like the normal, since they are not provide like with triangle primitives.
Just before building the TLAS, we need to add the following
Because we have added an extra instance when creating the implicit objects, there is one element less to loop for. Therefore the loop will now look like this:
~~~~ C++
auto nbObj = static_cast<uint32_t>(m_objInstance.size()) - 1;
tlas.reserve(nbObj);
for(uint32_t i = 0; i < nbObj; i++)
{
...
}
~~~~
Just after the loop and before building the TLAS, we need to add the following.
~~~~ C++
// Add the blas containing all spheres
{
nvvk::RaytracingBuilder::Instance rayInst;
rayInst.transform = m_objInstance[0].transform; // Position of the instance
rayInst.instanceCustomId = static_cast<uint32_t>(tlas.size()); // gl_InstanceCustomIndexEXT
rayInst.transform = m_objInstance[0].transform; // Position of the instance
rayInst.instanceCustomId = nbObj; // gl_InstanceCustomIndexEXT
rayInst.blasId = static_cast<uint32_t>(m_objModel.size());
rayInst.hitGroupId = 1; // We will use the same hit group for all objects
rayInst.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
@ -248,50 +265,26 @@ Just before building the TLAS, we need to add the following
}
~~~~
The `instanceCustomId` will give us the last element of m_objInstance, and in the shader will will be able to access the materials
assigned to the implicit objects.
## Descriptors
To access the newly created buffers holding all the spheres and materials, some changes are required to the descriptors.
In function `createDescriptorSetLayout()`, the addition of the material and material index need to be instructed.
To access the newly created buffers holding all the spheres, some changes are required to the descriptors.
The descriptor need to add an binding to the implicit object buffer.
~~~~ C++
// Materials (binding = 1)
m_descSetLayoutBind.addBinding(1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, nbObj+1,
VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR);
// Materials Index (binding = 4)
m_descSetLayoutBind.addBinding(4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, nbObj +1,
VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR);
~~~~
And the new buffer holding the spheres
~~~~ C++
// Storing spheres (binding = 7)
m_descSetLayoutBind.addBinding(7, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1,
// Storing spheres (binding = 3)
m_descSetLayoutBind.addBinding(3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1,
VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_INTERSECTION_BIT_KHR);
~~~~
The function `updateDescriptorSet()` which is writing the values of the buffer need also to be modified.
At the end of the loop on all models, lets add the new material and material index.
~~~~ C++
for(auto& m : m_objModel)
{
dbiMat.push_back({m.matColorBuffer.buffer, 0, VK_WHOLE_SIZE});
dbiMatIdx.push_back({m.matIndexBuffer.buffer, 0, VK_WHOLE_SIZE});
dbiVert.push_back({m.vertexBuffer.buffer, 0, VK_WHOLE_SIZE});
dbiIdx.push_back({m.indexBuffer.buffer, 0, VK_WHOLE_SIZE});
}
dbiMat.push_back({m_spheresMatColorBuffer.buffer, 0, VK_WHOLE_SIZE});
dbiMatIdx.push_back({m_spheresMatIndexBuffer.buffer, 0, VK_WHOLE_SIZE});
~~~~
Then write the buffer for the spheres
Then write the buffer for the spheres after the array of textures
~~~~ C++
VkDescriptorBufferInfo dbiSpheres{m_spheresBuffer.buffer, 0, VK_WHOLE_SIZE};
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 7, &dbiSpheres));
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 3, &dbiSpheres));
~~~~
## Intersection Shader
@ -365,6 +358,8 @@ We first declare the extensions and include common files.
#extension GL_EXT_nonuniform_qualifier : enable
#extension GL_EXT_scalar_block_layout : enable
#extension GL_GOOGLE_include_directive : enable
#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require
#extension GL_EXT_buffer_reference2 : require
#include "raycommon.glsl"
#include "wavefront.glsl"
~~~~
@ -373,11 +368,10 @@ We first declare the extensions and include common files.
The following is the topology of all spheres, which we will be able to retrieve using `gl_PrimitiveID`.
~~~~ C++
layout(binding = 7, set = 1, scalar) buffer allSpheres_
layout(binding = 3, set = 1, scalar) buffer allSpheres_
{
Sphere i[];
}
allSpheres;
Sphere allSpheres[];
};
~~~~
We will implement two intersetion method against the incoming ray.