Using buffer reference instead of un-sized array
This commit is contained in:
parent
e3a57e6d63
commit
c8a0122dd6
248 changed files with 2593 additions and 2660 deletions
|
|
@ -116,14 +116,10 @@ extensions will need to be added.
|
|||
```` C
|
||||
// #VKRay: Activate the ray tracing extension
|
||||
VkPhysicalDeviceAccelerationStructureFeaturesKHR accelFeature{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR};
|
||||
contextInfo.addDeviceExtension(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME, false, &accelFeature);
|
||||
contextInfo.addDeviceExtension(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME, false, &accelFeature); // To build acceleration structures
|
||||
VkPhysicalDeviceRayTracingPipelineFeaturesKHR rtPipelineFeature{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR};
|
||||
contextInfo.addDeviceExtension(VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME, false, &rtPipelineFeature);
|
||||
contextInfo.addDeviceExtension(VK_KHR_MAINTENANCE3_EXTENSION_NAME);
|
||||
contextInfo.addDeviceExtension(VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME);
|
||||
contextInfo.addDeviceExtension(VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME);
|
||||
contextInfo.addDeviceExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
|
||||
|
||||
contextInfo.addDeviceExtension(VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME, false, &rtPipelineFeature); // To use vkCmdTraceRaysKHR
|
||||
contextInfo.addDeviceExtension(VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME); // Required by ray tracing pipeline
|
||||
````
|
||||
|
||||
Behind the scenes, the helper is selecting a physical device supporting the required `VK_KHR_*` extensions,
|
||||
|
|
@ -293,11 +289,8 @@ potential optimization. (More specifically, this disables calls to the anyhit sh
|
|||
auto HelloVulkan::objectToVkGeometryKHR(const ObjModel& model)
|
||||
{
|
||||
// BLAS builder requires raw device addresses.
|
||||
VkBufferDeviceAddressInfo info{VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO};
|
||||
info.buffer = model.vertexBuffer.buffer;
|
||||
VkDeviceAddress vertexAddress = vkGetBufferDeviceAddress(m_device, &info);
|
||||
info.buffer = model.indexBuffer.buffer;
|
||||
VkDeviceAddress indexAddress = vkGetBufferDeviceAddress(m_device, &info);
|
||||
VkDeviceAddress vertexAddress = nvvk::getBufferDeviceAddress(m_device, model.vertexBuffer.buffer);
|
||||
VkDeviceAddress indexAddress = nvvk::getBufferDeviceAddress(m_device, model.indexBuffer.buffer);
|
||||
|
||||
uint32_t maxPrimitiveCount = model.nbIndices / 3;
|
||||
|
||||
|
|
@ -974,61 +967,31 @@ descriptor set as they semantically fit the Scene descriptor set.
|
|||
|
||||
```` C
|
||||
// Camera matrices (binding = 0)
|
||||
m_descSetLayoutBind.addBinding(0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_RAYGEN_BIT_KHR);
|
||||
// Materials (binding = 1)
|
||||
m_descSetLayoutBind.addBinding(1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, nbObj,
|
||||
VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR);
|
||||
// Scene description (binding = 2)
|
||||
m_descSetLayoutBind.addBinding(2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1,
|
||||
VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR);
|
||||
// Textures (binding = 3)
|
||||
m_descSetLayoutBind.addBinding(3, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, nbTxt,
|
||||
VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR);
|
||||
// Materials (binding = 4)
|
||||
m_descSetLayoutBind.addBinding(4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, nbObj,
|
||||
VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR);
|
||||
// Storing vertices (binding = 5)
|
||||
m_descSetLayoutBind.addBinding(5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, nbObj, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR);
|
||||
// Storing indices (binding = 6)
|
||||
m_descSetLayoutBind.addBinding(6, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, nbObj, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR);
|
||||
````
|
||||
|
||||
We set the actual contents of the descriptor set by adding those buffers in `updateDescriptorSet()`:
|
||||
|
||||
```` C
|
||||
// All material buffers, 1 buffer per OBJ
|
||||
std::vector<VkDescriptorBufferInfo> dbiMat;
|
||||
std::vector<VkDescriptorBufferInfo> dbiMatIdx;
|
||||
std::vector<VkDescriptorBufferInfo> dbiVert;
|
||||
std::vector<VkDescriptorBufferInfo> dbiIdx;
|
||||
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});
|
||||
}
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 1, dbiMat.data()));
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 4, dbiMatIdx.data()));
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 5, dbiVert.data()));
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 6, dbiIdx.data()));
|
||||
m_descSetLayoutBind.addBinding(0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_RAYGEN_BIT_KHR);
|
||||
// Scene description (binding = 1)
|
||||
m_descSetLayoutBind.addBinding(1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1,
|
||||
VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR);
|
||||
// Textures (binding = 2)
|
||||
m_descSetLayoutBind.addBinding(2, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, nbTxt,
|
||||
VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR);
|
||||
````
|
||||
|
||||
Originally the buffers containing the vertices and indices were only used by the rasterization pipeline.
|
||||
The ray tracing will need to use those buffers as storage buffers, so we add `VK_BUFFER_USAGE_STORAGE_BUFFER_BIT`;
|
||||
additionally, the buffers will be read by the acceleration structure builder, which requires raw device addresses
|
||||
(in `VkAccelerationStructureGeometryTrianglesDataKHR`), so the buffer also needs
|
||||
the `VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR`
|
||||
and `VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT` bits.
|
||||
`VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR` bits.
|
||||
|
||||
We update the usage of the buffers in `loadModel`:
|
||||
|
||||
```` C
|
||||
VkBufferUsageFlags rtUsage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT
|
||||
| VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR;
|
||||
model.vertexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_vertices, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | rtUsage);
|
||||
model.indexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_indices, VK_BUFFER_USAGE_INDEX_BUFFER_BIT | rtUsage);
|
||||
|
||||
VkBufferUsageFlags flag = VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
|
||||
VkBufferUsageFlags rayTracingFlags = // used also for building acceleration structures
|
||||
flag | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
|
||||
model.vertexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_vertices, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | rayTracingFlags);
|
||||
model.indexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_indices, VK_BUFFER_USAGE_INDEX_BUFFER_BIT | rayTracingFlags);
|
||||
model.matColorBuffer = m_alloc.createBuffer(cmdBuf, loader.m_materials, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | flag);
|
||||
model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | flag);
|
||||
````
|
||||
|
||||
!!! Note: Array of Buffers
|
||||
|
|
@ -1949,6 +1912,8 @@ We first include the payload definition and the OBJ-Wavefront structures
|
|||
```` C
|
||||
#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"
|
||||
````
|
||||
|
|
@ -1958,9 +1923,12 @@ Then we describe the resources according to the descriptor set layout
|
|||
```` C
|
||||
layout(location = 0) rayPayloadInEXT hitPayload prd;
|
||||
|
||||
layout(binding = 2, set = 1, scalar) buffer ScnDesc { sceneDesc i[]; } scnDesc;
|
||||
layout(binding = 5, set = 1, scalar) buffer Vertices { Vertex v[]; } vertices[];
|
||||
layout(binding = 6, set = 1) buffer Indices { uint i[]; } indices[];
|
||||
layout(buffer_reference, scalar) buffer Vertices {Vertex v[]; }; // Positions of an object
|
||||
layout(buffer_reference, scalar) buffer Indices {ivec3 i[]; }; // Triangle indices
|
||||
layout(buffer_reference, scalar) buffer Materials {WaveFrontMaterial m[]; }; // Array of all materials on an object
|
||||
layout(buffer_reference, scalar) buffer MatIndices {int i[]; }; // Material ID for each triangle
|
||||
layout(binding = 0, set = 0) uniform accelerationStructureEXT topLevelAS;
|
||||
layout(binding = 1, set = 1, scalar) buffer SceneDesc_ { SceneDesc i[]; } sceneDesc;
|
||||
````
|
||||
|
||||
In the Hit shader we need all the members of the push constant block:
|
||||
|
|
@ -1976,22 +1944,25 @@ layout(push_constant) uniform Constants
|
|||
pushC;
|
||||
````
|
||||
|
||||
In the `main` function, the `gl_PrimitiveID` allows us to find the vertices of the triangle hit by the ray:
|
||||
In the `main` function, the `gl_InstanceCustomIndexEXT` tells which object was hit, and the `gl_PrimitiveID` allows us to find the vertices of the triangle hit by the ray:
|
||||
|
||||
```` C
|
||||
void main()
|
||||
{
|
||||
// Object of this instance
|
||||
uint objId = scnDesc.i[gl_InstanceCustomIndexEXT].objId;
|
||||
|
||||
// Indices of the triangle
|
||||
ivec3 ind = ivec3(indices[nonuniformEXT(objId)].i[3 * gl_PrimitiveID + 0], //
|
||||
indices[nonuniformEXT(objId)].i[3 * gl_PrimitiveID + 1], //
|
||||
indices[nonuniformEXT(objId)].i[3 * gl_PrimitiveID + 2]); //
|
||||
// Vertex of the triangle
|
||||
Vertex v0 = vertices[nonuniformEXT(objId)].v[ind.x];
|
||||
Vertex v1 = vertices[nonuniformEXT(objId)].v[ind.y];
|
||||
Vertex v2 = vertices[nonuniformEXT(objId)].v[ind.z];
|
||||
// Object data
|
||||
SceneDesc objResource = sceneDesc.i[gl_InstanceCustomIndexEXT];
|
||||
MatIndices matIndices = MatIndices(objResource.materialIndexAddress);
|
||||
Materials materials = Materials(objResource.materialAddress);
|
||||
Indices indices = Indices(objResource.indexAddress);
|
||||
Vertices vertices = Vertices(objResource.vertexAddress);
|
||||
|
||||
// Indices of the triangle
|
||||
ivec3 ind = indices.i[gl_PrimitiveID];
|
||||
|
||||
// Vertex of the triangle
|
||||
Vertex v0 = vertices.v[ind.x];
|
||||
Vertex v1 = vertices.v[ind.y];
|
||||
Vertex v2 = vertices.v[ind.z];
|
||||
````
|
||||
|
||||
Using the hit point's barycentric coordinates, we can interpolate the normal:
|
||||
|
|
@ -2060,12 +2031,10 @@ simplified Alias Wavefront material definitions.
|
|||
|
||||
These materials define their basic reflectance properties using simple color coefficients, and also support texturing.
|
||||
The buffer containing the materials has already been created for rasterization, and has also been added into the ray
|
||||
tracing descriptor set. Add the binding of the material buffer and the array of texture samplers:
|
||||
tracing descriptor set. Add the binding of the array of texture samplers:
|
||||
|
||||
```` C
|
||||
layout(binding = 1, set = 1, scalar) buffer MatColorBufferObject { WaveFrontMaterial m[]; } materials[];
|
||||
layout(binding = 3, set = 1) uniform sampler2D textureSamplers[];
|
||||
layout(binding = 4, set = 1) buffer MatIndexColorBuffer { int i[]; } matIndex[];
|
||||
layout(binding = 2, set = 1) uniform sampler2D textureSamplers[];
|
||||
````
|
||||
|
||||
The declaration of the material is the same as that used for the rasterizer and is defined in
|
||||
|
|
@ -2084,8 +2053,8 @@ and fetch the material definition instead:
|
|||
|
||||
```` C
|
||||
// Material of the object
|
||||
int matIdx = matIndex[nonuniformEXT(objId)].i[gl_PrimitiveID];
|
||||
WaveFrontMaterial mat = materials[nonuniformEXT(objId)].m[matIdx];
|
||||
int matIdx = matIndices.i[gl_PrimitiveID];
|
||||
WaveFrontMaterial mat = materials.m[matIdx];
|
||||
````
|
||||
|
||||
!!! Note Note
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue