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;
|
||||
|
||||
|
|
@ -975,60 +968,30 @@ 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,
|
||||
// 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);
|
||||
// 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,
|
||||
// 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);
|
||||
// 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()));
|
||||
````
|
||||
|
||||
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;
|
||||
// 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 = 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]); //
|
||||
ivec3 ind = indices.i[gl_PrimitiveID];
|
||||
|
||||
// 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];
|
||||
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
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ compile_glsl_directory(
|
|||
SRC "${CMAKE_CURRENT_SOURCE_DIR}/shaders"
|
||||
DST "${CMAKE_CURRENT_SOURCE_DIR}/spv"
|
||||
VULKAN_TARGET "vulkan1.2"
|
||||
DEPENDENCY ${VULKAN_BUILD_DEPENDENCIES}
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -52,7 +53,8 @@ target_sources(${PROJNAME} PUBLIC ${GLSL_SOURCES} ${GLSL_HEADERS})
|
|||
source_group("Common" FILES ${COMMON_SOURCE_FILES} ${PACKAGE_SOURCE_FILES})
|
||||
source_group("Sources" FILES ${SOURCE_FILES})
|
||||
source_group("Headers" FILES ${HEADER_FILES})
|
||||
source_group("Shader_Files" FILES ${GLSL_SOURCES} ${GLSL_HEADERS})
|
||||
source_group("Shader Sources" FILES ${GLSL_SOURCES})
|
||||
source_group("Shader Headers" FILES ${GLSL_HEADERS})
|
||||
|
||||
|
||||
#--------------------------------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
#include "nvvk/commands_vk.hpp"
|
||||
#include "nvvk/renderpasses_vk.hpp"
|
||||
|
||||
#include "nvvk/buffers_vk.hpp"
|
||||
|
||||
extern std::vector<std::string> defaultSearchPaths;
|
||||
|
||||
|
|
@ -119,30 +120,19 @@ void HelloVulkan::updateUniformBuffer(const VkCommandBuffer& cmdBuf)
|
|||
void HelloVulkan::createDescriptorSetLayout()
|
||||
{
|
||||
auto nbTxt = static_cast<uint32_t>(m_textures.size());
|
||||
auto nbObj = static_cast<uint32_t>(m_objModel.size());
|
||||
|
||||
// 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 + 1,
|
||||
// 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 | VK_SHADER_STAGE_ANY_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 | VK_SHADER_STAGE_ANY_HIT_BIT_KHR);
|
||||
// Textures (binding = 3)
|
||||
m_descSetLayoutBind.addBinding(3, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, nbTxt,
|
||||
// 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 | VK_SHADER_STAGE_ANY_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 | VK_SHADER_STAGE_ANY_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);
|
||||
// Storing implicit obj (binding = 7)
|
||||
m_descSetLayoutBind.addBinding(7, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1,
|
||||
|
||||
// Storing implicit obj (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
|
||||
| VK_SHADER_STAGE_ANY_HIT_BIT_KHR);
|
||||
|
||||
|
|
@ -162,26 +152,9 @@ void HelloVulkan::updateDescriptorSet()
|
|||
// Camera matrices and scene description
|
||||
VkDescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE};
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 0, &dbiUnif));
|
||||
VkDescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 2, &dbiSceneDesc));
|
||||
|
||||
// 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});
|
||||
}
|
||||
dbiMat.push_back({m_implObjects.implMatBuf.buffer, 0, VK_WHOLE_SIZE}); // Adding implicit mat
|
||||
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()));
|
||||
VkDescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 1, &dbiSceneDesc));
|
||||
|
||||
// All texture samplers
|
||||
std::vector<VkDescriptorImageInfo> diit;
|
||||
|
|
@ -189,10 +162,10 @@ void HelloVulkan::updateDescriptorSet()
|
|||
{
|
||||
diit.emplace_back(texture.descriptor);
|
||||
}
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 3, diit.data()));
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 2, diit.data()));
|
||||
|
||||
VkDescriptorBufferInfo dbiImplDesc{m_implObjects.implBuf.buffer, 0, VK_WHOLE_SIZE};
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 7, &dbiImplDesc));
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 3, &dbiImplDesc));
|
||||
|
||||
// Writing the information
|
||||
vkUpdateDescriptorSets(m_device, static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
||||
|
|
@ -250,12 +223,6 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
|
|||
m.specular = nvmath::pow(m.specular, 2.2f);
|
||||
}
|
||||
|
||||
ObjInstance instance;
|
||||
instance.objIndex = static_cast<uint32_t>(m_objModel.size());
|
||||
instance.transform = transform;
|
||||
instance.transformIT = nvmath::transpose(nvmath::invert(transform));
|
||||
instance.txtOffset = static_cast<uint32_t>(m_textures.size());
|
||||
|
||||
ObjModel model;
|
||||
model.nbIndices = static_cast<uint32_t>(loader.m_indices.size());
|
||||
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
|
||||
|
|
@ -263,23 +230,35 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
|
|||
// Create the buffers on Device and copy vertices, indices and materials
|
||||
nvvk::CommandPool cmdBufGet(m_device, m_graphicsQueueIndex);
|
||||
VkCommandBuffer cmdBuf = cmdBufGet.createCommandBuffer();
|
||||
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);
|
||||
model.matColorBuffer = m_alloc.createBuffer(cmdBuf, loader.m_materials, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
|
||||
model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
|
||||
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);
|
||||
// Creates all textures found
|
||||
uint32_t txtOffset = static_cast<uint32_t>(m_textures.size());
|
||||
createTextureImages(cmdBuf, loader.m_textures);
|
||||
cmdBufGet.submitAndWait(cmdBuf);
|
||||
m_alloc.finalizeAndReleaseStaging();
|
||||
|
||||
std::string objNb = std::to_string(instance.objIndex);
|
||||
std::string objNb = std::to_string(m_objModel.size());
|
||||
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
|
||||
m_debug.setObjectName(model.indexBuffer.buffer, (std::string("index_" + objNb).c_str()));
|
||||
m_debug.setObjectName(model.matColorBuffer.buffer, (std::string("mat_" + objNb).c_str()));
|
||||
m_debug.setObjectName(model.matIndexBuffer.buffer, (std::string("matIdx_" + objNb).c_str()));
|
||||
|
||||
ObjInstance instance;
|
||||
instance.objIndex = static_cast<uint32_t>(m_objModel.size());
|
||||
instance.transform = transform;
|
||||
instance.transformIT = nvmath::transpose(nvmath::invert(transform));
|
||||
instance.txtOffset = txtOffset;
|
||||
instance.vertices = nvvk::getBufferDeviceAddress(m_device, model.vertexBuffer.buffer);
|
||||
instance.indices = nvvk::getBufferDeviceAddress(m_device, model.indexBuffer.buffer);
|
||||
instance.materials = nvvk::getBufferDeviceAddress(m_device, model.matColorBuffer.buffer);
|
||||
instance.materialIndices = nvvk::getBufferDeviceAddress(m_device, model.matIndexBuffer.buffer);
|
||||
|
||||
m_objModel.emplace_back(model);
|
||||
m_objInstance.emplace_back(instance);
|
||||
}
|
||||
|
|
@ -573,9 +552,16 @@ void HelloVulkan::createImplictBuffers()
|
|||
m_implObjects.implBuf = m_alloc.createBuffer(cmdBuf, m_implObjects.objImpl,
|
||||
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR
|
||||
| VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
|
||||
m_implObjects.implMatBuf = m_alloc.createBuffer(cmdBuf, m_implObjects.implMat, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
|
||||
m_implObjects.implMatBuf = m_alloc.createBuffer(cmdBuf, m_implObjects.implMat,
|
||||
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
|
||||
cmdGen.submitAndWait(cmdBuf);
|
||||
m_alloc.finalizeAndReleaseStaging();
|
||||
m_debug.setObjectName(m_implObjects.implBuf.buffer, "implicitObj");
|
||||
m_debug.setObjectName(m_implObjects.implMatBuf.buffer, "implicitMat");
|
||||
|
||||
// Adding an instance to hold the buffer address of implicit materials
|
||||
ObjInstance instance{};
|
||||
instance.objIndex = static_cast<uint32_t>(m_objModel.size());
|
||||
instance.materials = nvvk::getBufferDeviceAddress(m_device, m_implObjects.implMatBuf.buffer);
|
||||
m_objInstance.emplace_back(instance);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@ public:
|
|||
Offscreen& offscreen() { return m_offscreen; }
|
||||
Raytracer& raytracer() { return m_raytrace; }
|
||||
|
||||
|
||||
ObjPushConstants m_pushConstants;
|
||||
|
||||
// Array of objects and instances in the scene
|
||||
|
|
@ -96,6 +97,7 @@ public:
|
|||
|
||||
nvvk::Buffer m_cameraMat; // Device-Host of the camera matrices
|
||||
nvvk::Buffer m_sceneDesc; // Device buffer of the OBJ instances
|
||||
|
||||
std::vector<nvvk::Texture> m_textures; // vector of all textures of the scene
|
||||
|
||||
nvvk::DebugUtil m_debug; // Utility to name objects
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@ void renderUI(HelloVulkan& helloVk)
|
|||
static int const SAMPLE_WIDTH = 1280;
|
||||
static int const SAMPLE_HEIGHT = 720;
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
// Application Entry
|
||||
//
|
||||
|
|
@ -139,34 +140,26 @@ int main(int argc, char** argv)
|
|||
std::string(PROJECT_NAME),
|
||||
};
|
||||
|
||||
// Vulkan required extensions
|
||||
assert(glfwVulkanSupported() == 1);
|
||||
uint32_t count{0};
|
||||
auto reqExtensions = glfwGetRequiredInstanceExtensions(&count);
|
||||
|
||||
// Requesting Vulkan extensions and layers
|
||||
nvvk::ContextCreateInfo contextInfo(true);
|
||||
contextInfo.setVersion(1, 2);
|
||||
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
|
||||
contextInfo.addInstanceExtension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME, true);
|
||||
contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME);
|
||||
#ifdef _WIN32
|
||||
contextInfo.addInstanceExtension(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
|
||||
#else
|
||||
contextInfo.addInstanceExtension(VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
|
||||
contextInfo.addInstanceExtension(VK_KHR_XCB_SURFACE_EXTENSION_NAME);
|
||||
#endif
|
||||
contextInfo.addInstanceExtension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
|
||||
contextInfo.addDeviceExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
|
||||
contextInfo.addDeviceExtension(VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME);
|
||||
contextInfo.addDeviceExtension(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME);
|
||||
contextInfo.addDeviceExtension(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME);
|
||||
contextInfo.addDeviceExtension(VK_EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME);
|
||||
nvvk::ContextCreateInfo contextInfo;
|
||||
contextInfo.setVersion(1, 2); // Using Vulkan 1.2
|
||||
for(uint32_t ext_id = 0; ext_id < count; ext_id++) // Adding required extensions (surface, win32, linux, ..)
|
||||
contextInfo.addInstanceExtension(reqExtensions[ext_id]);
|
||||
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true); // FPS in titlebar
|
||||
contextInfo.addInstanceExtension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME, true); // Allow debug names
|
||||
contextInfo.addDeviceExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME); // Enabling ability to present rendering
|
||||
|
||||
// #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
|
||||
|
||||
// Creating Vulkan base application
|
||||
nvvk::Context vkctx{};
|
||||
|
|
|
|||
|
|
@ -34,10 +34,14 @@ struct ObjModel
|
|||
// Instance of the OBJ
|
||||
struct ObjInstance
|
||||
{
|
||||
uint32_t objIndex{0}; // Reference to the `m_objModel`
|
||||
uint32_t txtOffset{0}; // Offset in `m_textures`
|
||||
nvmath::mat4f transform{1}; // Position of the instance
|
||||
nvmath::mat4f transformIT{1}; // Inverse transpose
|
||||
uint32_t objIndex{0}; // Reference to the `m_objModel`
|
||||
uint32_t txtOffset{0}; // Offset in `m_textures`
|
||||
VkDeviceAddress vertices;
|
||||
VkDeviceAddress indices;
|
||||
VkDeviceAddress materials;
|
||||
VkDeviceAddress materialIndices;
|
||||
};
|
||||
|
||||
// Information pushed at each draw call
|
||||
|
|
|
|||
|
|
@ -171,7 +171,7 @@ void Offscreen::updateDescriptorSet()
|
|||
//--------------------------------------------------------------------------------------------------
|
||||
// Draw a full screen quad with the attached image
|
||||
//
|
||||
void Offscreen::draw(VkCommandBuffer cmdBuf, VkExtent2D& size)
|
||||
void Offscreen::draw(VkCommandBuffer cmdBuf, const VkExtent2D& size)
|
||||
{
|
||||
m_debug.beginLabel(cmdBuf, "Post");
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ public:
|
|||
void createPipeline(VkRenderPass& renderPass);
|
||||
void createDescriptor();
|
||||
void updateDescriptorSet();
|
||||
void draw(VkCommandBuffer cmdBuf, VkExtent2D& size);
|
||||
void draw(VkCommandBuffer cmdBuf, const VkExtent2D& size);
|
||||
|
||||
const VkRenderPass& renderPass() { return m_renderPass; }
|
||||
const VkFramebuffer& frameBuffer() { return m_framebuffer; }
|
||||
|
|
|
|||
|
|
@ -157,12 +157,15 @@ void Raytracer::createBottomLevelAS(std::vector<ObjModel>& models, ImplInst& imp
|
|||
void Raytracer::createTopLevelAS(std::vector<ObjInstance>& instances, ImplInst& implicitObj)
|
||||
{
|
||||
std::vector<nvvk::RaytracingBuilderKHR::Instance> tlas;
|
||||
|
||||
|
||||
auto nbObj = static_cast<uint32_t>(instances.size()) - 1; // minus the implicit (for material)
|
||||
tlas.reserve(instances.size());
|
||||
for(int i = 0; i < static_cast<int>(instances.size()); i++)
|
||||
for(uint32_t i = 0; i < nbObj; i++)
|
||||
{
|
||||
nvvk::RaytracingBuilderKHR::Instance rayInst;
|
||||
rayInst.transform = instances[i].transform; // Position of the instance
|
||||
rayInst.instanceCustomId = i; // gl_InstanceCustomIndexEXT
|
||||
rayInst.instanceCustomId = instances[i].objIndex; // gl_InstanceCustomIndexEXT
|
||||
rayInst.blasId = instances[i].objIndex;
|
||||
rayInst.hitGroupId = 0; // We will use the same hit group for all objects
|
||||
rayInst.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
|
||||
|
|
@ -174,7 +177,7 @@ void Raytracer::createTopLevelAS(std::vector<ObjInstance>& instances, ImplInst&
|
|||
{
|
||||
nvvk::RaytracingBuilderKHR::Instance rayInst;
|
||||
rayInst.transform = implicitObj.transform; // Position of the instance
|
||||
rayInst.instanceCustomId = static_cast<uint32_t>(implicitObj.blasId); // Same for material index
|
||||
rayInst.instanceCustomId = nbObj; // Same for material index
|
||||
rayInst.blasId = static_cast<uint32_t>(implicitObj.blasId);
|
||||
rayInst.hitGroupId = 1; // We will use the same hit group for all objects (the second one)
|
||||
rayInst.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
|
||||
|
|
|
|||
|
|
@ -23,6 +23,9 @@
|
|||
#extension GL_GOOGLE_include_directive : enable
|
||||
#extension GL_EXT_scalar_block_layout : enable
|
||||
|
||||
#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require
|
||||
#extension GL_EXT_buffer_reference2 : require
|
||||
|
||||
#include "wavefront.glsl"
|
||||
|
||||
|
||||
|
|
@ -40,37 +43,38 @@ pushC;
|
|||
|
||||
// clang-format off
|
||||
// Incoming
|
||||
//layout(location = 0) flat in int matIndex;
|
||||
layout(location = 1) in vec2 fragTexCoord;
|
||||
layout(location = 2) in vec3 fragNormal;
|
||||
layout(location = 3) in vec3 viewDir;
|
||||
layout(location = 4) in vec3 worldPos;
|
||||
// Outgoing
|
||||
layout(location = 0) out vec4 outColor;
|
||||
// Buffers
|
||||
layout(binding = 1, scalar) buffer MatColorBufferObject { WaveFrontMaterial m[]; } materials[];
|
||||
layout(binding = 2, scalar) buffer ScnDesc { sceneDesc i[]; } scnDesc;
|
||||
layout(binding = 3) uniform sampler2D[] textureSamplers;
|
||||
layout(binding = 4, scalar) buffer MatIndex { int i[]; } matIdx[];
|
||||
|
||||
layout(buffer_reference, scalar) buffer Vertices {Vertex v[]; }; // Positions of an object
|
||||
layout(buffer_reference, scalar) buffer Indices {uint 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 = 1, scalar) buffer SceneDesc_ { SceneDesc i[]; } sceneDesc;
|
||||
layout(binding = 2) uniform sampler2D[] textureSamplers;
|
||||
// clang-format on
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
// Object of this instance
|
||||
int objId = scnDesc.i[pushC.instanceId].objId;
|
||||
|
||||
// Material of the object
|
||||
int matIndex = matIdx[nonuniformEXT(objId)].i[gl_PrimitiveID];
|
||||
WaveFrontMaterial mat = materials[nonuniformEXT(objId)].m[matIndex];
|
||||
SceneDesc objResource = sceneDesc.i[pushC.instanceId];
|
||||
MatIndices matIndices = MatIndices(objResource.materialIndexAddress);
|
||||
Materials materials = Materials(objResource.materialAddress);
|
||||
|
||||
int matIndex = matIndices.i[gl_PrimitiveID];
|
||||
WaveFrontMaterial mat = materials.m[matIndex];
|
||||
|
||||
vec3 N = normalize(fragNormal);
|
||||
|
||||
// Vector toward light
|
||||
vec3 LightDir;
|
||||
float lightIntensity;
|
||||
;
|
||||
|
||||
// Point light
|
||||
if(pushC.lightType == 0)
|
||||
|
|
@ -101,7 +105,7 @@ void main()
|
|||
vec3 diffuse = computeDiffuse(mat, LightDir, N);
|
||||
if(mat.textureId >= 0)
|
||||
{
|
||||
int txtOffset = scnDesc.i[pushC.instanceId].txtOffset;
|
||||
int txtOffset = sceneDesc.i[pushC.instanceId].txtOffset;
|
||||
uint txtId = txtOffset + mat.textureId;
|
||||
vec3 diffuseTxt = texture(textureSamplers[nonuniformEXT(txtId)], fragTexCoord).xyz;
|
||||
diffuse *= diffuseTxt;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@
|
|||
#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 "random.glsl"
|
||||
#include "raycommon.glsl"
|
||||
|
|
@ -30,19 +32,22 @@
|
|||
// clang-format off
|
||||
layout(location = 0) rayPayloadInEXT hitPayload prd;
|
||||
|
||||
layout(binding = 2, set = 1, scalar) buffer ScnDesc { sceneDesc i[]; } scnDesc;
|
||||
layout(binding = 4, set = 1) buffer MatIndexColorBuffer { int i[]; } matIndex[];
|
||||
layout(binding = 1, set = 1, scalar) buffer MatColorBufferObject { WaveFrontMaterial m[]; } materials[];
|
||||
layout(buffer_reference, scalar) buffer Vertices {Vertex v[]; }; // Positions of an object
|
||||
layout(buffer_reference, scalar) buffer Indices {uint 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 = 1, set = 1, scalar) buffer SceneDesc_ { SceneDesc i[]; } sceneDesc;
|
||||
// clang-format on
|
||||
|
||||
void main()
|
||||
{
|
||||
// Object of this instance
|
||||
uint objId = scnDesc.i[gl_InstanceCustomIndexEXT].objId;
|
||||
SceneDesc objResource = sceneDesc.i[gl_InstanceCustomIndexEXT];
|
||||
MatIndices matIndices = MatIndices(objResource.materialIndexAddress);
|
||||
Materials materials = Materials(objResource.materialAddress);
|
||||
|
||||
// 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];
|
||||
|
||||
if(mat.illum != 4)
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,10 @@
|
|||
#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"
|
||||
|
||||
|
|
@ -31,16 +35,13 @@ hitAttributeEXT vec2 attribs;
|
|||
layout(location = 0) rayPayloadInEXT hitPayload prd;
|
||||
layout(location = 1) rayPayloadEXT bool isShadowed;
|
||||
|
||||
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 = 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(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 = 1, set = 1, scalar) buffer SceneDesc_ { SceneDesc i[]; } sceneDesc;
|
||||
layout(binding = 2, set = 1) uniform sampler2D textureSamplers[];
|
||||
// clang-format on
|
||||
|
||||
layout(push_constant) uniform Constants
|
||||
|
|
@ -60,30 +61,33 @@ layout(location = 3) callableDataEXT rayLight cLight;
|
|||
|
||||
void main()
|
||||
{
|
||||
// Object of this instance
|
||||
uint objId = scnDesc.i[gl_InstanceCustomIndexEXT].objId;
|
||||
// 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 = 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]); //
|
||||
ivec3 ind = indices.i[gl_PrimitiveID];
|
||||
|
||||
// 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];
|
||||
Vertex v0 = vertices.v[ind.x];
|
||||
Vertex v1 = vertices.v[ind.y];
|
||||
Vertex v2 = vertices.v[ind.z];
|
||||
|
||||
const vec3 barycentrics = vec3(1.0 - attribs.x - attribs.y, attribs.x, attribs.y);
|
||||
|
||||
// Computing the normal at hit position
|
||||
vec3 normal = v0.nrm * barycentrics.x + v1.nrm * barycentrics.y + v2.nrm * barycentrics.z;
|
||||
// Transforming the normal to world space
|
||||
normal = normalize(vec3(scnDesc.i[gl_InstanceCustomIndexEXT].transfoIT * vec4(normal, 0.0)));
|
||||
normal = normalize(vec3(sceneDesc.i[gl_InstanceCustomIndexEXT].transfoIT * vec4(normal, 0.0)));
|
||||
|
||||
|
||||
// Computing the coordinates of the hit position
|
||||
vec3 worldPos = v0.pos * barycentrics.x + v1.pos * barycentrics.y + v2.pos * barycentrics.z;
|
||||
// Transforming the position to world space
|
||||
worldPos = vec3(scnDesc.i[gl_InstanceCustomIndexEXT].transfo * vec4(worldPos, 1.0));
|
||||
worldPos = vec3(sceneDesc.i[gl_InstanceCustomIndexEXT].transfo * vec4(worldPos, 1.0));
|
||||
|
||||
cLight.inHitPosition = worldPos;
|
||||
//#define DONT_USE_CALLABLE
|
||||
|
|
@ -101,8 +105,7 @@ void main()
|
|||
{
|
||||
vec3 lDir = pushC.lightPosition - cLight.inHitPosition;
|
||||
cLight.outLightDistance = length(lDir);
|
||||
cLight.outIntensity =
|
||||
pushC.lightIntensity / (cLight.outLightDistance * cLight.outLightDistance);
|
||||
cLight.outIntensity = pushC.lightIntensity / (cLight.outLightDistance * cLight.outLightDistance);
|
||||
cLight.outLightDir = normalize(lDir);
|
||||
float theta = dot(cLight.outLightDir, normalize(-pushC.lightDirection));
|
||||
float epsilon = pushC.lightSpotCutoff - pushC.lightSpotOuterCutoff;
|
||||
|
|
@ -120,17 +123,16 @@ void main()
|
|||
#endif
|
||||
|
||||
// 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];
|
||||
|
||||
|
||||
// Diffuse
|
||||
vec3 diffuse = computeDiffuse(mat, cLight.outLightDir, normal);
|
||||
if(mat.textureId >= 0)
|
||||
{
|
||||
uint txtId = mat.textureId + scnDesc.i[gl_InstanceCustomIndexEXT].txtOffset;
|
||||
vec2 texCoord =
|
||||
v0.texCoord * barycentrics.x + v1.texCoord * barycentrics.y + v2.texCoord * barycentrics.z;
|
||||
uint txtId = mat.textureId + sceneDesc.i[gl_InstanceCustomIndexEXT].txtOffset;
|
||||
vec2 texCoord = v0.texCoord * barycentrics.x + v1.texCoord * barycentrics.y + v2.texCoord * barycentrics.z;
|
||||
diffuse *= texture(textureSamplers[nonuniformEXT(txtId)], texCoord).xyz;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -55,8 +55,7 @@ const int NBSAMPLES = 5;
|
|||
void main()
|
||||
{
|
||||
// Initialize the random number
|
||||
uint seed =
|
||||
tea(gl_LaunchIDEXT.y * gl_LaunchSizeEXT.x + gl_LaunchIDEXT.x, pushC.frame * NBSAMPLES);
|
||||
uint seed = tea(gl_LaunchIDEXT.y * gl_LaunchSizeEXT.x + gl_LaunchIDEXT.x, pushC.frame * NBSAMPLES);
|
||||
prd.seed = seed;
|
||||
|
||||
vec3 hitValues = vec3(0);
|
||||
|
|
|
|||
|
|
@ -22,12 +22,15 @@
|
|||
#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"
|
||||
|
||||
hitAttributeEXT vec3 HitAttribute;
|
||||
|
||||
layout(binding = 7, set = 1, scalar) buffer allImpl_
|
||||
layout(binding = 3, set = 1, scalar) buffer allImpl_
|
||||
{
|
||||
Implicit i[];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@
|
|||
#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 "random.glsl"
|
||||
#include "raycommon.glsl"
|
||||
|
|
@ -30,15 +32,23 @@
|
|||
// clang-format off
|
||||
layout(location = 0) rayPayloadInEXT hitPayload prd;
|
||||
|
||||
layout(binding = 1, set = 1, scalar) buffer MatColorBufferObject { WaveFrontMaterial m[]; } materials[];
|
||||
layout(binding = 7, set = 1, scalar) buffer allImplicits_ {Implicit i[];} allImplicits;
|
||||
layout(buffer_reference, scalar) buffer Vertices {Vertex v[]; }; // Positions of an object
|
||||
layout(buffer_reference, scalar) buffer Indices {uint 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 = 1, set = 1, scalar) buffer SceneDesc_ { SceneDesc i[]; } sceneDesc;
|
||||
layout(binding = 3, set = 1, scalar) buffer allImplicits_ {Implicit i[];} allImplicits;
|
||||
// clang-format on
|
||||
|
||||
void main()
|
||||
{
|
||||
// Material of the object
|
||||
Implicit impl = allImplicits.i[gl_PrimitiveID];
|
||||
WaveFrontMaterial mat = materials[nonuniformEXT(gl_InstanceCustomIndexEXT)].m[impl.matId];
|
||||
|
||||
SceneDesc objResource = sceneDesc.i[gl_InstanceCustomIndexEXT];
|
||||
Materials materials = Materials(objResource.materialAddress);
|
||||
|
||||
WaveFrontMaterial mat = materials.m[impl.matId];
|
||||
|
||||
if(mat.illum != 4)
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,9 @@
|
|||
#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"
|
||||
|
||||
|
|
@ -33,14 +36,13 @@ layout(location = 1) rayPayloadEXT bool isShadowed;
|
|||
|
||||
layout(binding = 0, set = 0) uniform accelerationStructureEXT topLevelAS;
|
||||
|
||||
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(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 = 7, set = 1, scalar) buffer allImplicits_ {Implicit i[];} allImplicits;
|
||||
layout(buffer_reference, scalar) buffer Vertices {Vertex v[]; }; // Positions of an object
|
||||
layout(buffer_reference, scalar) buffer Indices {uint 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 = 1, set = 1, scalar) buffer SceneDesc_ { SceneDesc i[]; } sceneDesc;
|
||||
layout(binding = 3, set = 1, scalar) buffer allImplicits_ {Implicit i[];} allImplicits;
|
||||
|
||||
// clang-format on
|
||||
|
||||
|
|
@ -93,7 +95,9 @@ void main()
|
|||
executeCallableEXT(pushC.lightType, 3);
|
||||
|
||||
// Material of the object
|
||||
WaveFrontMaterial mat = materials[nonuniformEXT(gl_InstanceCustomIndexEXT)].m[impl.matId];
|
||||
SceneDesc objResource = sceneDesc.i[gl_InstanceCustomIndexEXT];
|
||||
Materials materials = Materials(objResource.materialAddress);
|
||||
WaveFrontMaterial mat = materials.m[impl.matId];
|
||||
|
||||
|
||||
// Diffuse
|
||||
|
|
|
|||
|
|
@ -22,10 +22,12 @@
|
|||
#extension GL_EXT_scalar_block_layout : enable
|
||||
#extension GL_GOOGLE_include_directive : enable
|
||||
|
||||
#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require
|
||||
|
||||
#include "wavefront.glsl"
|
||||
|
||||
// clang-format off
|
||||
layout(binding = 2, set = 0, scalar) buffer ScnDesc { sceneDesc i[]; } scnDesc;
|
||||
layout(binding = 1, scalar) buffer SceneDesc_ { SceneDesc i[]; } sceneDesc;
|
||||
// clang-format on
|
||||
|
||||
layout(binding = 0) uniform UniformBufferObject
|
||||
|
|
@ -68,8 +70,8 @@ out gl_PerVertex
|
|||
|
||||
void main()
|
||||
{
|
||||
mat4 objMatrix = scnDesc.i[pushC.instanceId].transfo;
|
||||
mat4 objMatrixIT = scnDesc.i[pushC.instanceId].transfoIT;
|
||||
mat4 objMatrix = sceneDesc.i[pushC.instanceId].transfo;
|
||||
mat4 objMatrixIT = sceneDesc.i[pushC.instanceId].transfoIT;
|
||||
|
||||
vec3 origin = vec3(ubo.viewI * vec4(0, 0, 0, 1));
|
||||
|
||||
|
|
|
|||
|
|
@ -39,12 +39,17 @@ struct WaveFrontMaterial
|
|||
int textureId;
|
||||
};
|
||||
|
||||
struct sceneDesc
|
||||
struct SceneDesc
|
||||
{
|
||||
int objId;
|
||||
int txtOffset;
|
||||
mat4 transfo;
|
||||
mat4 transfoIT;
|
||||
int objId;
|
||||
int txtOffset;
|
||||
|
||||
uint64_t vertexAddress;
|
||||
uint64_t indexAddress;
|
||||
uint64_t materialAddress;
|
||||
uint64_t materialIndexAddress;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ compile_glsl_directory(
|
|||
SRC "${CMAKE_CURRENT_SOURCE_DIR}/shaders"
|
||||
DST "${CMAKE_CURRENT_SOURCE_DIR}/spv"
|
||||
VULKAN_TARGET "vulkan1.2"
|
||||
DEPENDENCY ${VULKAN_BUILD_DEPENDENCIES}
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -52,7 +53,8 @@ target_sources(${PROJNAME} PUBLIC ${GLSL_SOURCES} ${GLSL_HEADERS})
|
|||
source_group("Common" FILES ${COMMON_SOURCE_FILES} ${PACKAGE_SOURCE_FILES})
|
||||
source_group("Sources" FILES ${SOURCE_FILES})
|
||||
source_group("Headers" FILES ${HEADER_FILES})
|
||||
source_group("Shader_Files" FILES ${GLSL_SOURCES} ${GLSL_HEADERS})
|
||||
source_group("Shader Sources" FILES ${GLSL_SOURCES})
|
||||
source_group("Shader Headers" FILES ${GLSL_HEADERS})
|
||||
|
||||
|
||||
#--------------------------------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
#include "nvvk/pipeline_vk.hpp"
|
||||
#include "nvvk/renderpasses_vk.hpp"
|
||||
#include "nvvk/shaders_vk.hpp"
|
||||
#include "nvvk/buffers_vk.hpp"
|
||||
|
||||
extern std::vector<std::string> defaultSearchPaths;
|
||||
|
||||
|
|
@ -108,18 +109,13 @@ void HelloVulkan::updateUniformBuffer(const VkCommandBuffer& cmdBuf)
|
|||
void HelloVulkan::createDescriptorSetLayout()
|
||||
{
|
||||
auto nbTxt = static_cast<uint32_t>(m_textures.size());
|
||||
auto nbObj = static_cast<uint32_t>(m_objModel.size());
|
||||
|
||||
// Camera matrices (binding = 0)
|
||||
m_descSetLayoutBind.addBinding(0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT);
|
||||
// Materials (binding = 1)
|
||||
m_descSetLayoutBind.addBinding(1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, nbObj, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
// Scene description (binding = 2)
|
||||
m_descSetLayoutBind.addBinding(2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
// Textures (binding = 3)
|
||||
m_descSetLayoutBind.addBinding(3, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, nbTxt, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
// Materials (binding = 4)
|
||||
m_descSetLayoutBind.addBinding(4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, nbObj, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
// Scene description (binding = 1)
|
||||
m_descSetLayoutBind.addBinding(1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
// Textures (binding = 2)
|
||||
m_descSetLayoutBind.addBinding(2, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, nbTxt, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
|
||||
|
||||
m_descSetLayout = m_descSetLayoutBind.createLayout(m_device);
|
||||
|
|
@ -137,19 +133,9 @@ void HelloVulkan::updateDescriptorSet()
|
|||
// Camera matrices and scene description
|
||||
VkDescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE};
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 0, &dbiUnif));
|
||||
VkDescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 2, &dbiSceneDesc));
|
||||
|
||||
// All material buffers, 1 buffer per OBJ
|
||||
std::vector<VkDescriptorBufferInfo> dbiMat;
|
||||
std::vector<VkDescriptorBufferInfo> dbiMatIdx;
|
||||
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});
|
||||
}
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 1, dbiMat.data()));
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 4, dbiMatIdx.data()));
|
||||
VkDescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 1, &dbiSceneDesc));
|
||||
|
||||
// All texture samplers
|
||||
std::vector<VkDescriptorImageInfo> diit;
|
||||
|
|
@ -157,7 +143,7 @@ void HelloVulkan::updateDescriptorSet()
|
|||
{
|
||||
diit.emplace_back(texture.descriptor);
|
||||
}
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 3, diit.data()));
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 2, diit.data()));
|
||||
|
||||
// Writing the information
|
||||
vkUpdateDescriptorSets(m_device, static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
||||
|
|
@ -215,12 +201,6 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
|
|||
m.specular = nvmath::pow(m.specular, 2.2f);
|
||||
}
|
||||
|
||||
ObjInstance instance;
|
||||
instance.objIndex = static_cast<uint32_t>(m_objModel.size());
|
||||
instance.transform = transform;
|
||||
instance.transformIT = nvmath::transpose(nvmath::invert(transform));
|
||||
instance.txtOffset = static_cast<uint32_t>(m_textures.size());
|
||||
|
||||
ObjModel model;
|
||||
model.nbIndices = static_cast<uint32_t>(loader.m_indices.size());
|
||||
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
|
||||
|
|
@ -228,21 +208,33 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
|
|||
// Create the buffers on Device and copy vertices, indices and materials
|
||||
nvvk::CommandPool cmdBufGet(m_device, m_graphicsQueueIndex);
|
||||
VkCommandBuffer cmdBuf = cmdBufGet.createCommandBuffer();
|
||||
model.vertexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_vertices, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
|
||||
model.indexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_indices, VK_BUFFER_USAGE_INDEX_BUFFER_BIT);
|
||||
model.matColorBuffer = m_alloc.createBuffer(cmdBuf, loader.m_materials, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
|
||||
model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
|
||||
VkBufferUsageFlags flag = VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
|
||||
model.vertexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_vertices, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | flag);
|
||||
model.indexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_indices, VK_BUFFER_USAGE_INDEX_BUFFER_BIT | flag);
|
||||
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);
|
||||
// Creates all textures found
|
||||
uint32_t txtOffset = static_cast<uint32_t>(m_textures.size());
|
||||
createTextureImages(cmdBuf, loader.m_textures);
|
||||
cmdBufGet.submitAndWait(cmdBuf);
|
||||
m_alloc.finalizeAndReleaseStaging();
|
||||
|
||||
std::string objNb = std::to_string(instance.objIndex);
|
||||
std::string objNb = std::to_string(m_objModel.size());
|
||||
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
|
||||
m_debug.setObjectName(model.indexBuffer.buffer, (std::string("index_" + objNb).c_str()));
|
||||
m_debug.setObjectName(model.matColorBuffer.buffer, (std::string("mat_" + objNb).c_str()));
|
||||
m_debug.setObjectName(model.matIndexBuffer.buffer, (std::string("matIdx_" + objNb).c_str()));
|
||||
|
||||
ObjInstance instance;
|
||||
instance.objIndex = static_cast<uint32_t>(m_objModel.size());
|
||||
instance.transform = transform;
|
||||
instance.transformIT = nvmath::transpose(nvmath::invert(transform));
|
||||
instance.txtOffset = txtOffset;
|
||||
instance.vertices = nvvk::getBufferDeviceAddress(m_device, model.vertexBuffer.buffer);
|
||||
instance.indices = nvvk::getBufferDeviceAddress(m_device, model.indexBuffer.buffer);
|
||||
instance.materials = nvvk::getBufferDeviceAddress(m_device, model.matColorBuffer.buffer);
|
||||
instance.materialIndices = nvvk::getBufferDeviceAddress(m_device, model.matIndexBuffer.buffer);
|
||||
|
||||
m_objModel.emplace_back(model);
|
||||
m_objInstance.emplace_back(instance);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,10 +62,14 @@ public:
|
|||
// Instance of the OBJ
|
||||
struct ObjInstance
|
||||
{
|
||||
uint32_t objIndex{0}; // Reference to the `m_objModel`
|
||||
uint32_t txtOffset{0}; // Offset in `m_textures`
|
||||
nvmath::mat4f transform{1}; // Position of the instance
|
||||
nvmath::mat4f transformIT{1}; // Inverse transpose
|
||||
uint32_t objIndex{0}; // Reference to the `m_objModel`
|
||||
uint32_t txtOffset{0}; // Offset in `m_textures`
|
||||
VkDeviceAddress vertices;
|
||||
VkDeviceAddress indices;
|
||||
VkDeviceAddress materials;
|
||||
VkDeviceAddress materialIndices;
|
||||
};
|
||||
|
||||
// Information pushed at each draw call
|
||||
|
|
@ -92,6 +96,7 @@ public:
|
|||
|
||||
nvvk::Buffer m_cameraMat; // Device-Host of the camera matrices
|
||||
nvvk::Buffer m_sceneDesc; // Device buffer of the OBJ instances
|
||||
|
||||
std::vector<nvvk::Texture> m_textures; // vector of all textures of the scene
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -110,24 +110,19 @@ int main(int argc, char** argv)
|
|||
std::string(PROJECT_NAME),
|
||||
};
|
||||
|
||||
// Vulkan required extensions
|
||||
assert(glfwVulkanSupported() == 1);
|
||||
uint32_t count{0};
|
||||
auto reqExtensions = glfwGetRequiredInstanceExtensions(&count);
|
||||
|
||||
// Requesting Vulkan extensions and layers
|
||||
nvvk::ContextCreateInfo contextInfo;
|
||||
contextInfo.setVersion(1, 2);
|
||||
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
|
||||
contextInfo.addInstanceExtension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME, true);
|
||||
contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME);
|
||||
#ifdef _WIN32
|
||||
contextInfo.addInstanceExtension(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
|
||||
#else
|
||||
contextInfo.addInstanceExtension(VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
|
||||
contextInfo.addInstanceExtension(VK_KHR_XCB_SURFACE_EXTENSION_NAME);
|
||||
#endif
|
||||
contextInfo.addInstanceExtension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
|
||||
contextInfo.addDeviceExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
|
||||
contextInfo.addDeviceExtension(VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME);
|
||||
contextInfo.addDeviceExtension(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME);
|
||||
contextInfo.addDeviceExtension(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME);
|
||||
contextInfo.addDeviceExtension(VK_EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME);
|
||||
contextInfo.setVersion(1, 2); // Using Vulkan 1.2
|
||||
for(uint32_t ext_id = 0; ext_id < count; ext_id++) // Adding required extensions (surface, win32, linux, ..)
|
||||
contextInfo.addInstanceExtension(reqExtensions[ext_id]);
|
||||
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true); // FPS in titlebar
|
||||
contextInfo.addInstanceExtension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME, true); // Allow debug names
|
||||
contextInfo.addDeviceExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME); // Enabling ability to present rendering
|
||||
|
||||
// Creating Vulkan base application
|
||||
nvvk::Context vkctx{};
|
||||
|
|
|
|||
|
|
@ -23,6 +23,9 @@
|
|||
#extension GL_GOOGLE_include_directive : enable
|
||||
#extension GL_EXT_scalar_block_layout : enable
|
||||
|
||||
#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require
|
||||
#extension GL_EXT_buffer_reference2 : require
|
||||
|
||||
#include "wavefront.glsl"
|
||||
|
||||
|
||||
|
|
@ -37,30 +40,35 @@ pushC;
|
|||
|
||||
// clang-format off
|
||||
// Incoming
|
||||
//layout(location = 0) flat in int matIndex;
|
||||
layout(location = 1) in vec2 fragTexCoord;
|
||||
layout(location = 2) in vec3 fragNormal;
|
||||
layout(location = 3) in vec3 viewDir;
|
||||
layout(location = 4) in vec3 worldPos;
|
||||
// Outgoing
|
||||
layout(location = 0) out vec4 outColor;
|
||||
// Buffers
|
||||
layout(binding = 1, scalar) buffer MatColorBufferObject { WaveFrontMaterial m[]; } materials[];
|
||||
layout(binding = 2, scalar) buffer ScnDesc { sceneDesc i[]; } scnDesc;
|
||||
layout(binding = 3) uniform sampler2D[] textureSamplers;
|
||||
layout(binding = 4, scalar) buffer MatIndex { int i[]; } matIdx[];
|
||||
|
||||
layout(buffer_reference, scalar) buffer Vertices {Vertex v[]; }; // Positions of an object
|
||||
layout(buffer_reference, scalar) buffer Indices {uint 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 = 1, scalar) buffer SceneDesc_ { SceneDesc i[]; } sceneDesc;
|
||||
layout(binding = 2) uniform sampler2D[] textureSamplers;
|
||||
// clang-format on
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
// Object of this instance
|
||||
int objId = scnDesc.i[pushC.instanceId].objId;
|
||||
int objId = sceneDesc.i[pushC.instanceId].objId;
|
||||
|
||||
// Material of the object
|
||||
int matIndex = matIdx[nonuniformEXT(objId)].i[gl_PrimitiveID];
|
||||
WaveFrontMaterial mat = materials[nonuniformEXT(objId)].m[matIndex];
|
||||
SceneDesc objResource = sceneDesc.i[pushC.instanceId];
|
||||
MatIndices matIndices = MatIndices(objResource.materialIndexAddress);
|
||||
Materials materials = Materials(objResource.materialAddress);
|
||||
|
||||
int matIndex = matIndices.i[gl_PrimitiveID];
|
||||
WaveFrontMaterial mat = materials.m[matIndex];
|
||||
|
||||
vec3 N = normalize(fragNormal);
|
||||
|
||||
|
|
@ -84,7 +92,7 @@ void main()
|
|||
vec3 diffuse = computeDiffuse(mat, L, N);
|
||||
if(mat.textureId >= 0)
|
||||
{
|
||||
int txtOffset = scnDesc.i[pushC.instanceId].txtOffset;
|
||||
int txtOffset = sceneDesc.i[pushC.instanceId].txtOffset;
|
||||
uint txtId = txtOffset + mat.textureId;
|
||||
vec3 diffuseTxt = texture(textureSamplers[nonuniformEXT(txtId)], fragTexCoord).xyz;
|
||||
diffuse *= diffuseTxt;
|
||||
|
|
|
|||
|
|
@ -22,10 +22,12 @@
|
|||
#extension GL_EXT_scalar_block_layout : enable
|
||||
#extension GL_GOOGLE_include_directive : enable
|
||||
|
||||
#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require
|
||||
|
||||
#include "wavefront.glsl"
|
||||
|
||||
// clang-format off
|
||||
layout(binding = 2, set = 0, scalar) buffer ScnDesc { sceneDesc i[]; } scnDesc;
|
||||
layout(binding = 1, scalar) buffer SceneDesc_ { SceneDesc i[]; } sceneDesc;
|
||||
// clang-format on
|
||||
|
||||
layout(binding = 0) uniform UniformBufferObject
|
||||
|
|
@ -65,8 +67,8 @@ out gl_PerVertex
|
|||
|
||||
void main()
|
||||
{
|
||||
mat4 objMatrix = scnDesc.i[pushC.instanceId].transfo;
|
||||
mat4 objMatrixIT = scnDesc.i[pushC.instanceId].transfoIT;
|
||||
mat4 objMatrix = sceneDesc.i[pushC.instanceId].transfo;
|
||||
mat4 objMatrixIT = sceneDesc.i[pushC.instanceId].transfoIT;
|
||||
|
||||
vec3 origin = vec3(ubo.viewI * vec4(0, 0, 0, 1));
|
||||
|
||||
|
|
|
|||
|
|
@ -39,12 +39,17 @@ struct WaveFrontMaterial
|
|||
int textureId;
|
||||
};
|
||||
|
||||
struct sceneDesc
|
||||
struct SceneDesc
|
||||
{
|
||||
int objId;
|
||||
int txtOffset;
|
||||
mat4 transfo;
|
||||
mat4 transfoIT;
|
||||
int objId;
|
||||
int txtOffset;
|
||||
|
||||
uint64_t vertexAddress;
|
||||
uint64_t indexAddress;
|
||||
uint64_t materialAddress;
|
||||
uint64_t materialIndexAddress;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ compile_glsl_directory(
|
|||
SRC "${CMAKE_CURRENT_SOURCE_DIR}/shaders"
|
||||
DST "${CMAKE_CURRENT_SOURCE_DIR}/spv"
|
||||
VULKAN_TARGET "vulkan1.2"
|
||||
DEPENDENCY ${VULKAN_BUILD_DEPENDENCIES}
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -52,7 +53,8 @@ target_sources(${PROJNAME} PUBLIC ${GLSL_SOURCES} ${GLSL_HEADERS})
|
|||
source_group("Common" FILES ${COMMON_SOURCE_FILES} ${PACKAGE_SOURCE_FILES})
|
||||
source_group("Sources" FILES ${SOURCE_FILES})
|
||||
source_group("Headers" FILES ${HEADER_FILES})
|
||||
source_group("Shader_Files" FILES ${GLSL_SOURCES} ${GLSL_HEADERS})
|
||||
source_group("Shader Sources" FILES ${GLSL_SOURCES})
|
||||
source_group("Shader Headers" FILES ${GLSL_HEADERS})
|
||||
|
||||
|
||||
#--------------------------------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
#include "nvvk/pipeline_vk.hpp"
|
||||
#include "nvvk/renderpasses_vk.hpp"
|
||||
#include "nvvk/shaders_vk.hpp"
|
||||
#include "nvvk/buffers_vk.hpp"
|
||||
|
||||
extern std::vector<std::string> defaultSearchPaths;
|
||||
|
||||
|
|
@ -113,26 +114,15 @@ void HelloVulkan::updateUniformBuffer(const VkCommandBuffer& cmdBuf)
|
|||
void HelloVulkan::createDescriptorSetLayout()
|
||||
{
|
||||
auto nbTxt = static_cast<uint32_t>(m_textures.size());
|
||||
auto nbObj = static_cast<uint32_t>(m_objModel.size());
|
||||
|
||||
// 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,
|
||||
// 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);
|
||||
// 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,
|
||||
// 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);
|
||||
// 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);
|
||||
|
||||
|
||||
m_descSetLayout = m_descSetLayoutBind.createLayout(m_device);
|
||||
|
|
@ -150,25 +140,9 @@ void HelloVulkan::updateDescriptorSet()
|
|||
// Camera matrices and scene description
|
||||
VkDescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE};
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 0, &dbiUnif));
|
||||
VkDescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 2, &dbiSceneDesc));
|
||||
|
||||
// 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()));
|
||||
VkDescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 1, &dbiSceneDesc));
|
||||
|
||||
// All texture samplers
|
||||
std::vector<VkDescriptorImageInfo> diit;
|
||||
|
|
@ -176,7 +150,7 @@ void HelloVulkan::updateDescriptorSet()
|
|||
{
|
||||
diit.emplace_back(texture.descriptor);
|
||||
}
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 3, diit.data()));
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 2, diit.data()));
|
||||
|
||||
// Writing the information
|
||||
vkUpdateDescriptorSets(m_device, static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
||||
|
|
@ -234,12 +208,6 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
|
|||
m.specular = nvmath::pow(m.specular, 2.2f);
|
||||
}
|
||||
|
||||
ObjInstance instance;
|
||||
instance.objIndex = static_cast<uint32_t>(m_objModel.size());
|
||||
instance.transform = transform;
|
||||
instance.transformIT = nvmath::transpose(nvmath::invert(transform));
|
||||
instance.txtOffset = static_cast<uint32_t>(m_textures.size());
|
||||
|
||||
ObjModel model;
|
||||
model.nbIndices = static_cast<uint32_t>(loader.m_indices.size());
|
||||
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
|
||||
|
|
@ -247,23 +215,35 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
|
|||
// Create the buffers on Device and copy vertices, indices and materials
|
||||
nvvk::CommandPool cmdBufGet(m_device, m_graphicsQueueIndex);
|
||||
VkCommandBuffer cmdBuf = cmdBufGet.createCommandBuffer();
|
||||
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);
|
||||
model.matColorBuffer = m_alloc.createBuffer(cmdBuf, loader.m_materials, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
|
||||
model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
|
||||
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);
|
||||
// Creates all textures found
|
||||
uint32_t txtOffset = static_cast<uint32_t>(m_textures.size());
|
||||
createTextureImages(cmdBuf, loader.m_textures);
|
||||
cmdBufGet.submitAndWait(cmdBuf);
|
||||
m_alloc.finalizeAndReleaseStaging();
|
||||
|
||||
std::string objNb = std::to_string(instance.objIndex);
|
||||
std::string objNb = std::to_string(m_objModel.size());
|
||||
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
|
||||
m_debug.setObjectName(model.indexBuffer.buffer, (std::string("index_" + objNb).c_str()));
|
||||
m_debug.setObjectName(model.matColorBuffer.buffer, (std::string("mat_" + objNb).c_str()));
|
||||
m_debug.setObjectName(model.matIndexBuffer.buffer, (std::string("matIdx_" + objNb).c_str()));
|
||||
|
||||
ObjInstance instance;
|
||||
instance.objIndex = static_cast<uint32_t>(m_objModel.size());
|
||||
instance.transform = transform;
|
||||
instance.transformIT = nvmath::transpose(nvmath::invert(transform));
|
||||
instance.txtOffset = txtOffset;
|
||||
instance.vertices = nvvk::getBufferDeviceAddress(m_device, model.vertexBuffer.buffer);
|
||||
instance.indices = nvvk::getBufferDeviceAddress(m_device, model.indexBuffer.buffer);
|
||||
instance.materials = nvvk::getBufferDeviceAddress(m_device, model.matColorBuffer.buffer);
|
||||
instance.materialIndices = nvvk::getBufferDeviceAddress(m_device, model.matIndexBuffer.buffer);
|
||||
|
||||
m_objModel.emplace_back(model);
|
||||
m_objInstance.emplace_back(instance);
|
||||
}
|
||||
|
|
@ -625,11 +605,8 @@ void HelloVulkan::initRayTracing()
|
|||
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;
|
||||
|
||||
|
|
@ -928,9 +905,7 @@ void HelloVulkan::raytrace(const VkCommandBuffer& cmdBuf, const nvmath::vec4f& c
|
|||
uint32_t groupSize = nvh::align_up(m_rtProperties.shaderGroupHandleSize, m_rtProperties.shaderGroupBaseAlignment);
|
||||
uint32_t groupStride = groupSize;
|
||||
|
||||
VkBufferDeviceAddressInfo info{VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO};
|
||||
info.buffer = m_rtSBTBuffer.buffer;
|
||||
VkDeviceAddress sbtAddress = vkGetBufferDeviceAddress(m_device, &info);
|
||||
VkDeviceAddress sbtAddress = nvvk::getBufferDeviceAddress(m_device, m_rtSBTBuffer.buffer);
|
||||
|
||||
using Stride = VkStridedDeviceAddressRegionKHR;
|
||||
std::array<Stride, 4> strideAddresses{Stride{sbtAddress + 0u * groupSize, groupStride, groupSize * 1}, // raygen
|
||||
|
|
|
|||
|
|
@ -65,10 +65,14 @@ public:
|
|||
// Instance of the OBJ
|
||||
struct ObjInstance
|
||||
{
|
||||
uint32_t objIndex{0}; // Reference to the `m_objModel`
|
||||
uint32_t txtOffset{0}; // Offset in `m_textures`
|
||||
nvmath::mat4f transform{1}; // Position of the instance
|
||||
nvmath::mat4f transformIT{1}; // Inverse transpose
|
||||
uint32_t objIndex{0}; // Reference to the `m_objModel`
|
||||
uint32_t txtOffset{0}; // Offset in `m_textures`
|
||||
VkDeviceAddress vertices;
|
||||
VkDeviceAddress indices;
|
||||
VkDeviceAddress materials;
|
||||
VkDeviceAddress materialIndices;
|
||||
};
|
||||
|
||||
// Information pushed at each draw call
|
||||
|
|
@ -95,6 +99,7 @@ public:
|
|||
|
||||
nvvk::Buffer m_cameraMat; // Device-Host of the camera matrices
|
||||
nvvk::Buffer m_sceneDesc; // Device buffer of the OBJ instances
|
||||
|
||||
std::vector<nvvk::Texture> m_textures; // vector of all textures of the scene
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ int main(int argc, char** argv)
|
|||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||
GLFWwindow* window = glfwCreateWindow(SAMPLE_WIDTH, SAMPLE_HEIGHT, PROJECT_NAME, nullptr, nullptr);
|
||||
|
||||
|
||||
// Setup camera
|
||||
CameraManip.setWindowSize(SAMPLE_WIDTH, SAMPLE_HEIGHT);
|
||||
CameraManip.setLookat(nvmath::vec3f(5, 4, -4), nvmath::vec3f(0, 1, 0), nvmath::vec3f(0, 1, 0));
|
||||
|
|
@ -109,34 +110,26 @@ int main(int argc, char** argv)
|
|||
std::string(PROJECT_NAME),
|
||||
};
|
||||
|
||||
// Vulkan required extensions
|
||||
assert(glfwVulkanSupported() == 1);
|
||||
uint32_t count{0};
|
||||
auto reqExtensions = glfwGetRequiredInstanceExtensions(&count);
|
||||
|
||||
// Requesting Vulkan extensions and layers
|
||||
nvvk::ContextCreateInfo contextInfo(true);
|
||||
contextInfo.setVersion(1, 2);
|
||||
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
|
||||
contextInfo.addInstanceExtension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME, true);
|
||||
contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME);
|
||||
#ifdef _WIN32
|
||||
contextInfo.addInstanceExtension(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
|
||||
#else
|
||||
contextInfo.addInstanceExtension(VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
|
||||
contextInfo.addInstanceExtension(VK_KHR_XCB_SURFACE_EXTENSION_NAME);
|
||||
#endif
|
||||
contextInfo.addInstanceExtension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
|
||||
contextInfo.addDeviceExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
|
||||
contextInfo.addDeviceExtension(VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME);
|
||||
contextInfo.addDeviceExtension(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME);
|
||||
contextInfo.addDeviceExtension(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME);
|
||||
contextInfo.addDeviceExtension(VK_EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME);
|
||||
nvvk::ContextCreateInfo contextInfo;
|
||||
contextInfo.setVersion(1, 2); // Using Vulkan 1.2
|
||||
for(uint32_t ext_id = 0; ext_id < count; ext_id++) // Adding required extensions (surface, win32, linux, ..)
|
||||
contextInfo.addInstanceExtension(reqExtensions[ext_id]);
|
||||
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true); // FPS in titlebar
|
||||
contextInfo.addInstanceExtension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME, true); // Allow debug names
|
||||
contextInfo.addDeviceExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME); // Enabling ability to present rendering
|
||||
|
||||
// #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
|
||||
|
||||
// Creating Vulkan base application
|
||||
nvvk::Context vkctx{};
|
||||
|
|
@ -167,7 +160,6 @@ int main(int argc, char** argv)
|
|||
helloVk.loadModel(nvh::findFile("media/scenes/Medieval_building.obj", defaultSearchPaths, true));
|
||||
helloVk.loadModel(nvh::findFile("media/scenes/plane.obj", defaultSearchPaths, true));
|
||||
|
||||
|
||||
helloVk.createOffscreenRender();
|
||||
helloVk.createDescriptorSetLayout();
|
||||
helloVk.createGraphicsPipeline();
|
||||
|
|
|
|||
|
|
@ -23,6 +23,9 @@
|
|||
#extension GL_GOOGLE_include_directive : enable
|
||||
#extension GL_EXT_scalar_block_layout : enable
|
||||
|
||||
#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require
|
||||
#extension GL_EXT_buffer_reference2 : require
|
||||
|
||||
#include "wavefront.glsl"
|
||||
|
||||
|
||||
|
|
@ -37,30 +40,32 @@ pushC;
|
|||
|
||||
// clang-format off
|
||||
// Incoming
|
||||
//layout(location = 0) flat in int matIndex;
|
||||
layout(location = 1) in vec2 fragTexCoord;
|
||||
layout(location = 2) in vec3 fragNormal;
|
||||
layout(location = 3) in vec3 viewDir;
|
||||
layout(location = 4) in vec3 worldPos;
|
||||
// Outgoing
|
||||
layout(location = 0) out vec4 outColor;
|
||||
// Buffers
|
||||
layout(binding = 1, scalar) buffer MatColorBufferObject { WaveFrontMaterial m[]; } materials[];
|
||||
layout(binding = 2, scalar) buffer ScnDesc { sceneDesc i[]; } scnDesc;
|
||||
layout(binding = 3) uniform sampler2D[] textureSamplers;
|
||||
layout(binding = 4, scalar) buffer MatIndex { int i[]; } matIdx[];
|
||||
|
||||
layout(buffer_reference, scalar) buffer Vertices {Vertex v[]; }; // Positions of an object
|
||||
layout(buffer_reference, scalar) buffer Indices {uint 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 = 1, scalar) buffer SceneDesc_ { SceneDesc i[]; } sceneDesc;
|
||||
layout(binding = 2) uniform sampler2D[] textureSamplers;
|
||||
// clang-format on
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
// Object of this instance
|
||||
int objId = scnDesc.i[pushC.instanceId].objId;
|
||||
|
||||
// Material of the object
|
||||
int matIndex = matIdx[nonuniformEXT(objId)].i[gl_PrimitiveID];
|
||||
WaveFrontMaterial mat = materials[nonuniformEXT(objId)].m[matIndex];
|
||||
SceneDesc objResource = sceneDesc.i[pushC.instanceId];
|
||||
MatIndices matIndices = MatIndices(objResource.materialIndexAddress);
|
||||
Materials materials = Materials(objResource.materialAddress);
|
||||
|
||||
int matIndex = matIndices.i[gl_PrimitiveID];
|
||||
WaveFrontMaterial mat = materials.m[matIndex];
|
||||
|
||||
vec3 N = normalize(fragNormal);
|
||||
|
||||
|
|
@ -84,7 +89,7 @@ void main()
|
|||
vec3 diffuse = computeDiffuse(mat, L, N);
|
||||
if(mat.textureId >= 0)
|
||||
{
|
||||
int txtOffset = scnDesc.i[pushC.instanceId].txtOffset;
|
||||
int txtOffset = sceneDesc.i[pushC.instanceId].txtOffset;
|
||||
uint txtId = txtOffset + mat.textureId;
|
||||
vec3 diffuseTxt = texture(textureSamplers[nonuniformEXT(txtId)], fragTexCoord).xyz;
|
||||
diffuse *= diffuseTxt;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,10 @@
|
|||
#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"
|
||||
|
||||
|
|
@ -31,14 +35,13 @@ hitAttributeEXT vec2 attribs;
|
|||
layout(location = 0) rayPayloadInEXT hitPayload prd;
|
||||
layout(location = 1) rayPayloadEXT bool isShadowed;
|
||||
|
||||
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 MatColorBufferObject { WaveFrontMaterial m[]; } materials[];
|
||||
layout(binding = 2, set = 1, scalar) buffer ScnDesc { sceneDesc i[]; } scnDesc;
|
||||
layout(binding = 3, set = 1) uniform sampler2D textureSamplers[];
|
||||
layout(binding = 4, set = 1) buffer MatIndexColorBuffer { int i[]; } matIndex[];
|
||||
layout(binding = 5, set = 1, scalar) buffer Vertices { Vertex v[]; } vertices[];
|
||||
layout(binding = 6, set = 1) buffer Indices { uint i[]; } indices[];
|
||||
|
||||
layout(binding = 1, set = 1, scalar) buffer SceneDesc_ { SceneDesc i[]; } sceneDesc;
|
||||
layout(binding = 2, set = 1) uniform sampler2D textureSamplers[];
|
||||
// clang-format on
|
||||
|
||||
layout(push_constant) uniform Constants
|
||||
|
|
@ -53,30 +56,33 @@ pushC;
|
|||
|
||||
void main()
|
||||
{
|
||||
// Object of this instance
|
||||
uint objId = scnDesc.i[gl_InstanceCustomIndexEXT].objId;
|
||||
// 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 = 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]); //
|
||||
ivec3 ind = indices.i[gl_PrimitiveID];
|
||||
|
||||
// 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];
|
||||
Vertex v0 = vertices.v[ind.x];
|
||||
Vertex v1 = vertices.v[ind.y];
|
||||
Vertex v2 = vertices.v[ind.z];
|
||||
|
||||
const vec3 barycentrics = vec3(1.0 - attribs.x - attribs.y, attribs.x, attribs.y);
|
||||
|
||||
// Computing the normal at hit position
|
||||
vec3 normal = v0.nrm * barycentrics.x + v1.nrm * barycentrics.y + v2.nrm * barycentrics.z;
|
||||
// Transforming the normal to world space
|
||||
normal = normalize(vec3(scnDesc.i[gl_InstanceCustomIndexEXT].transfoIT * vec4(normal, 0.0)));
|
||||
normal = normalize(vec3(sceneDesc.i[gl_InstanceCustomIndexEXT].transfoIT * vec4(normal, 0.0)));
|
||||
|
||||
|
||||
// Computing the coordinates of the hit position
|
||||
vec3 worldPos = v0.pos * barycentrics.x + v1.pos * barycentrics.y + v2.pos * barycentrics.z;
|
||||
// Transforming the position to world space
|
||||
worldPos = vec3(scnDesc.i[gl_InstanceCustomIndexEXT].transfo * vec4(worldPos, 1.0));
|
||||
worldPos = vec3(sceneDesc.i[gl_InstanceCustomIndexEXT].transfo * vec4(worldPos, 1.0));
|
||||
|
||||
// Vector toward the light
|
||||
vec3 L;
|
||||
|
|
@ -96,17 +102,16 @@ void main()
|
|||
}
|
||||
|
||||
// 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];
|
||||
|
||||
|
||||
// Diffuse
|
||||
vec3 diffuse = computeDiffuse(mat, L, normal);
|
||||
if(mat.textureId >= 0)
|
||||
{
|
||||
uint txtId = mat.textureId + scnDesc.i[gl_InstanceCustomIndexEXT].txtOffset;
|
||||
vec2 texCoord =
|
||||
v0.texCoord * barycentrics.x + v1.texCoord * barycentrics.y + v2.texCoord * barycentrics.z;
|
||||
uint txtId = mat.textureId + sceneDesc.i[gl_InstanceCustomIndexEXT].txtOffset;
|
||||
vec2 texCoord = v0.texCoord * barycentrics.x + v1.texCoord * barycentrics.y + v2.texCoord * barycentrics.z;
|
||||
diffuse *= texture(textureSamplers[nonuniformEXT(txtId)], texCoord).xyz;
|
||||
}
|
||||
|
||||
|
|
@ -120,8 +125,7 @@ void main()
|
|||
float tMax = lightDistance;
|
||||
vec3 origin = gl_WorldRayOriginEXT + gl_WorldRayDirectionEXT * gl_HitTEXT;
|
||||
vec3 rayDir = L;
|
||||
uint flags = gl_RayFlagsTerminateOnFirstHitEXT | gl_RayFlagsOpaqueEXT
|
||||
| gl_RayFlagsSkipClosestHitShaderEXT;
|
||||
uint flags = gl_RayFlagsTerminateOnFirstHitEXT | gl_RayFlagsOpaqueEXT | gl_RayFlagsSkipClosestHitShaderEXT;
|
||||
isShadowed = true;
|
||||
traceRayEXT(topLevelAS, // acceleration structure
|
||||
flags, // rayFlags
|
||||
|
|
|
|||
|
|
@ -22,10 +22,12 @@
|
|||
#extension GL_EXT_scalar_block_layout : enable
|
||||
#extension GL_GOOGLE_include_directive : enable
|
||||
|
||||
#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require
|
||||
|
||||
#include "wavefront.glsl"
|
||||
|
||||
// clang-format off
|
||||
layout(binding = 2, set = 0, scalar) buffer ScnDesc { sceneDesc i[]; } scnDesc;
|
||||
layout(binding = 1, scalar) buffer SceneDesc_ { SceneDesc i[]; } sceneDesc;
|
||||
// clang-format on
|
||||
|
||||
layout(binding = 0) uniform UniformBufferObject
|
||||
|
|
@ -65,8 +67,8 @@ out gl_PerVertex
|
|||
|
||||
void main()
|
||||
{
|
||||
mat4 objMatrix = scnDesc.i[pushC.instanceId].transfo;
|
||||
mat4 objMatrixIT = scnDesc.i[pushC.instanceId].transfoIT;
|
||||
mat4 objMatrix = sceneDesc.i[pushC.instanceId].transfo;
|
||||
mat4 objMatrixIT = sceneDesc.i[pushC.instanceId].transfoIT;
|
||||
|
||||
vec3 origin = vec3(ubo.viewI * vec4(0, 0, 0, 1));
|
||||
|
||||
|
|
|
|||
|
|
@ -39,12 +39,17 @@ struct WaveFrontMaterial
|
|||
int textureId;
|
||||
};
|
||||
|
||||
struct sceneDesc
|
||||
struct SceneDesc
|
||||
{
|
||||
int objId;
|
||||
int txtOffset;
|
||||
mat4 transfo;
|
||||
mat4 transfoIT;
|
||||
int objId;
|
||||
int txtOffset;
|
||||
|
||||
uint64_t vertexAddress;
|
||||
uint64_t indexAddress;
|
||||
uint64_t materialAddress;
|
||||
uint64_t materialIndexAddress;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ compile_glsl_directory(
|
|||
SRC "${CMAKE_CURRENT_SOURCE_DIR}/shaders"
|
||||
DST "${CMAKE_CURRENT_SOURCE_DIR}/spv"
|
||||
VULKAN_TARGET "vulkan1.2"
|
||||
DEPENDENCY ${VULKAN_BUILD_DEPENDENCIES}
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -52,7 +53,8 @@ target_sources(${PROJNAME} PUBLIC ${GLSL_SOURCES} ${GLSL_HEADERS})
|
|||
source_group("Common" FILES ${COMMON_SOURCE_FILES} ${PACKAGE_SOURCE_FILES})
|
||||
source_group("Sources" FILES ${SOURCE_FILES})
|
||||
source_group("Headers" FILES ${HEADER_FILES})
|
||||
source_group("Shader_Files" FILES ${GLSL_SOURCES} ${GLSL_HEADERS})
|
||||
source_group("Shader Sources" FILES ${GLSL_SOURCES})
|
||||
source_group("Shader Headers" FILES ${GLSL_HEADERS})
|
||||
|
||||
|
||||
#--------------------------------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -21,7 +21,12 @@ Using monolithic pipeline definitions all stages are compiled for each pipeline,
|
|||
Pipeline libraries are `VkPipeline` objects that cannot be bound directly. Instead, they can be compiled once and linked into as many pipelines as necessary. The Shader Binding Table of the resulting pipeline references the shader groups of the library as if they had been appended to the groups and stages in the main `VkRayTracingPipelineCreateInfo`
|
||||

|
||||
|
||||
We start by adding a new member in the `HelloVulkan` class:
|
||||
We start by adding the device extension in main()
|
||||
~~~~ C
|
||||
contextInfo.addDeviceExtension(VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME);
|
||||
~~~~
|
||||
|
||||
Following by adding a new member in the `HelloVulkan` class:
|
||||
~~~~ C
|
||||
// Ray tracing shader library
|
||||
VkPipeline m_rtShaderLibrary;
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@
|
|||
#include "nvvk/pipeline_vk.hpp"
|
||||
#include "nvvk/renderpasses_vk.hpp"
|
||||
#include "nvvk/shaders_vk.hpp"
|
||||
#include "nvvk/buffers_vk.hpp"
|
||||
// Support for C++ multithreading
|
||||
#include <future>
|
||||
|
||||
|
|
@ -116,26 +117,15 @@ void HelloVulkan::updateUniformBuffer(const VkCommandBuffer& cmdBuf)
|
|||
void HelloVulkan::createDescriptorSetLayout()
|
||||
{
|
||||
auto nbTxt = static_cast<uint32_t>(m_textures.size());
|
||||
auto nbObj = static_cast<uint32_t>(m_objModel.size());
|
||||
|
||||
// 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,
|
||||
// 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 = 3)
|
||||
m_descSetLayoutBind.addBinding(3, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, nbTxt,
|
||||
m_descSetLayoutBind.addBinding(2, 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);
|
||||
|
||||
|
||||
m_descSetLayout = m_descSetLayoutBind.createLayout(m_device);
|
||||
|
|
@ -153,25 +143,9 @@ void HelloVulkan::updateDescriptorSet()
|
|||
// Camera matrices and scene description
|
||||
VkDescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE};
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 0, &dbiUnif));
|
||||
VkDescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 2, &dbiSceneDesc));
|
||||
|
||||
// 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()));
|
||||
VkDescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 1, &dbiSceneDesc));
|
||||
|
||||
// All texture samplers
|
||||
std::vector<VkDescriptorImageInfo> diit;
|
||||
|
|
@ -179,7 +153,7 @@ void HelloVulkan::updateDescriptorSet()
|
|||
{
|
||||
diit.emplace_back(texture.descriptor);
|
||||
}
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 3, diit.data()));
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 2, diit.data()));
|
||||
|
||||
// Writing the information
|
||||
vkUpdateDescriptorSets(m_device, static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
||||
|
|
@ -237,12 +211,6 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
|
|||
m.specular = nvmath::pow(m.specular, 2.2f);
|
||||
}
|
||||
|
||||
ObjInstance instance;
|
||||
instance.objIndex = static_cast<uint32_t>(m_objModel.size());
|
||||
instance.transform = transform;
|
||||
instance.transformIT = nvmath::transpose(nvmath::invert(transform));
|
||||
instance.txtOffset = static_cast<uint32_t>(m_textures.size());
|
||||
|
||||
ObjModel model;
|
||||
model.nbIndices = static_cast<uint32_t>(loader.m_indices.size());
|
||||
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
|
||||
|
|
@ -250,23 +218,35 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
|
|||
// Create the buffers on Device and copy vertices, indices and materials
|
||||
nvvk::CommandPool cmdBufGet(m_device, m_graphicsQueueIndex);
|
||||
VkCommandBuffer cmdBuf = cmdBufGet.createCommandBuffer();
|
||||
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);
|
||||
model.matColorBuffer = m_alloc.createBuffer(cmdBuf, loader.m_materials, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
|
||||
model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
|
||||
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);
|
||||
// Creates all textures found
|
||||
uint32_t txtOffset = static_cast<uint32_t>(m_textures.size());
|
||||
createTextureImages(cmdBuf, loader.m_textures);
|
||||
cmdBufGet.submitAndWait(cmdBuf);
|
||||
m_alloc.finalizeAndReleaseStaging();
|
||||
|
||||
std::string objNb = std::to_string(instance.objIndex);
|
||||
std::string objNb = std::to_string(m_objModel.size());
|
||||
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
|
||||
m_debug.setObjectName(model.indexBuffer.buffer, (std::string("index_" + objNb).c_str()));
|
||||
m_debug.setObjectName(model.matColorBuffer.buffer, (std::string("mat_" + objNb).c_str()));
|
||||
m_debug.setObjectName(model.matIndexBuffer.buffer, (std::string("matIdx_" + objNb).c_str()));
|
||||
|
||||
ObjInstance instance;
|
||||
instance.objIndex = static_cast<uint32_t>(m_objModel.size());
|
||||
instance.transform = transform;
|
||||
instance.transformIT = nvmath::transpose(nvmath::invert(transform));
|
||||
instance.txtOffset = txtOffset;
|
||||
instance.vertices = nvvk::getBufferDeviceAddress(m_device, model.vertexBuffer.buffer);
|
||||
instance.indices = nvvk::getBufferDeviceAddress(m_device, model.indexBuffer.buffer);
|
||||
instance.materials = nvvk::getBufferDeviceAddress(m_device, model.matColorBuffer.buffer);
|
||||
instance.materialIndices = nvvk::getBufferDeviceAddress(m_device, model.matIndexBuffer.buffer);
|
||||
|
||||
m_objModel.emplace_back(model);
|
||||
m_objInstance.emplace_back(instance);
|
||||
}
|
||||
|
|
@ -631,11 +611,8 @@ void HelloVulkan::initRayTracing()
|
|||
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;
|
||||
|
||||
|
|
|
|||
|
|
@ -66,10 +66,14 @@ public:
|
|||
// Instance of the OBJ
|
||||
struct ObjInstance
|
||||
{
|
||||
uint32_t objIndex{0}; // Reference to the `m_objModel`
|
||||
uint32_t txtOffset{0}; // Offset in `m_textures`
|
||||
nvmath::mat4f transform{1}; // Position of the instance
|
||||
nvmath::mat4f transformIT{1}; // Inverse transpose
|
||||
uint32_t objIndex{0}; // Reference to the `m_objModel`
|
||||
uint32_t txtOffset{0}; // Offset in `m_textures`
|
||||
VkDeviceAddress vertices;
|
||||
VkDeviceAddress indices;
|
||||
VkDeviceAddress materials;
|
||||
VkDeviceAddress materialIndices;
|
||||
};
|
||||
|
||||
// Information pushed at each draw call
|
||||
|
|
@ -97,6 +101,8 @@ public:
|
|||
|
||||
nvvk::Buffer m_cameraMat; // Device-Host of the camera matrices
|
||||
nvvk::Buffer m_sceneDesc; // Device buffer of the OBJ instances
|
||||
nvvk::Buffer m_bufReference; // Buffer references of the OBJ
|
||||
|
||||
std::vector<nvvk::Texture> m_textures; // vector of all textures of the scene
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -120,34 +120,27 @@ int main(int argc, char** argv)
|
|||
std::string(PROJECT_NAME),
|
||||
};
|
||||
|
||||
// Vulkan required extensions
|
||||
assert(glfwVulkanSupported() == 1);
|
||||
uint32_t count{0};
|
||||
auto reqExtensions = glfwGetRequiredInstanceExtensions(&count);
|
||||
|
||||
// Requesting Vulkan extensions and layers
|
||||
nvvk::ContextCreateInfo contextInfo;
|
||||
contextInfo.setVersion(1, 2);
|
||||
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
|
||||
contextInfo.addInstanceExtension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME, true);
|
||||
contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME);
|
||||
#ifdef _WIN32
|
||||
contextInfo.addInstanceExtension(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
|
||||
#else
|
||||
contextInfo.addInstanceExtension(VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
|
||||
contextInfo.addInstanceExtension(VK_KHR_XCB_SURFACE_EXTENSION_NAME);
|
||||
#endif
|
||||
contextInfo.addInstanceExtension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
|
||||
contextInfo.addDeviceExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
|
||||
contextInfo.addDeviceExtension(VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME);
|
||||
contextInfo.addDeviceExtension(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME);
|
||||
contextInfo.addDeviceExtension(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME);
|
||||
contextInfo.addDeviceExtension(VK_EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME);
|
||||
contextInfo.setVersion(1, 2); // Using Vulkan 1.2
|
||||
for(uint32_t ext_id = 0; ext_id < count; ext_id++) // Adding required extensions (surface, win32, linux, ..)
|
||||
contextInfo.addInstanceExtension(reqExtensions[ext_id]);
|
||||
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true); // FPS in titlebar
|
||||
contextInfo.addInstanceExtension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME, true); // Allow debug names
|
||||
contextInfo.addDeviceExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME); // Enabling ability to present rendering
|
||||
|
||||
// #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_RAY_TRACING_PIPELINE_EXTENSION_NAME, false, &rtPipelineFeature); // To use vkCmdTraceRaysKHR
|
||||
contextInfo.addDeviceExtension(VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME); // Required by ray tracing pipeline
|
||||
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);
|
||||
|
||||
// Creating Vulkan base application
|
||||
nvvk::Context vkctx{};
|
||||
|
|
@ -178,7 +171,6 @@ int main(int argc, char** argv)
|
|||
helloVk.loadModel(nvh::findFile("media/scenes/Medieval_building.obj", defaultSearchPaths, true));
|
||||
helloVk.loadModel(nvh::findFile("media/scenes/plane.obj", defaultSearchPaths, true));
|
||||
|
||||
|
||||
helloVk.createOffscreenRender();
|
||||
helloVk.createDescriptorSetLayout();
|
||||
helloVk.createGraphicsPipeline();
|
||||
|
|
|
|||
|
|
@ -23,6 +23,9 @@
|
|||
#extension GL_GOOGLE_include_directive : enable
|
||||
#extension GL_EXT_scalar_block_layout : enable
|
||||
|
||||
#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require
|
||||
#extension GL_EXT_buffer_reference2 : require
|
||||
|
||||
#include "wavefront.glsl"
|
||||
|
||||
|
||||
|
|
@ -37,30 +40,35 @@ pushC;
|
|||
|
||||
// clang-format off
|
||||
// Incoming
|
||||
//layout(location = 0) flat in int matIndex;
|
||||
layout(location = 1) in vec2 fragTexCoord;
|
||||
layout(location = 2) in vec3 fragNormal;
|
||||
layout(location = 3) in vec3 viewDir;
|
||||
layout(location = 4) in vec3 worldPos;
|
||||
// Outgoing
|
||||
layout(location = 0) out vec4 outColor;
|
||||
// Buffers
|
||||
layout(binding = 1, scalar) buffer MatColorBufferObject { WaveFrontMaterial m[]; } materials[];
|
||||
layout(binding = 2, scalar) buffer ScnDesc { sceneDesc i[]; } scnDesc;
|
||||
layout(binding = 3) uniform sampler2D[] textureSamplers;
|
||||
layout(binding = 4, scalar) buffer MatIndex { int i[]; } matIdx[];
|
||||
|
||||
layout(buffer_reference, scalar) buffer Vertices {Vertex v[]; }; // Positions of an object
|
||||
layout(buffer_reference, scalar) buffer Indices {uint 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 = 1, scalar) buffer SceneDesc_ { SceneDesc i[]; } sceneDesc;
|
||||
layout(binding = 2) uniform sampler2D[] textureSamplers;
|
||||
// clang-format on
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
// Object of this instance
|
||||
int objId = scnDesc.i[pushC.instanceId].objId;
|
||||
int objId = sceneDesc.i[pushC.instanceId].objId;
|
||||
|
||||
// Material of the object
|
||||
int matIndex = matIdx[nonuniformEXT(objId)].i[gl_PrimitiveID];
|
||||
WaveFrontMaterial mat = materials[nonuniformEXT(objId)].m[matIndex];
|
||||
SceneDesc objResource = sceneDesc.i[pushC.instanceId];
|
||||
MatIndices matIndices = MatIndices(objResource.materialIndexAddress);
|
||||
Materials materials = Materials(objResource.materialAddress);
|
||||
|
||||
int matIndex = matIndices.i[gl_PrimitiveID];
|
||||
WaveFrontMaterial mat = materials.m[matIndex];
|
||||
|
||||
vec3 N = normalize(fragNormal);
|
||||
|
||||
|
|
@ -84,7 +92,7 @@ void main()
|
|||
vec3 diffuse = computeDiffuse(mat, L, N);
|
||||
if(mat.textureId >= 0)
|
||||
{
|
||||
int txtOffset = scnDesc.i[pushC.instanceId].txtOffset;
|
||||
int txtOffset = sceneDesc.i[pushC.instanceId].txtOffset;
|
||||
uint txtId = txtOffset + mat.textureId;
|
||||
vec3 diffuseTxt = texture(textureSamplers[nonuniformEXT(txtId)], fragTexCoord).xyz;
|
||||
diffuse *= diffuseTxt;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,10 @@
|
|||
#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"
|
||||
|
||||
|
|
@ -31,15 +35,13 @@ hitAttributeEXT vec2 attribs;
|
|||
layout(location = 0) rayPayloadInEXT hitPayload prd;
|
||||
layout(location = 1) rayPayloadEXT bool isShadowed;
|
||||
|
||||
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 MatColorBufferObject { WaveFrontMaterial m[]; } materials[];
|
||||
layout(binding = 2, set = 1, scalar) buffer ScnDesc { sceneDesc i[]; } scnDesc;
|
||||
layout(binding = 3, set = 1) uniform sampler2D textureSamplers[];
|
||||
layout(binding = 4, set = 1) buffer MatIndexColorBuffer { int i[]; } matIndex[];
|
||||
layout(binding = 5, set = 1, scalar) buffer Vertices { Vertex v[]; } vertices[];
|
||||
layout(binding = 6, set = 1) buffer Indices { uint i[]; } indices[];
|
||||
|
||||
|
||||
layout(binding = 1, set = 1, scalar) buffer SceneDesc_ { SceneDesc i[]; } sceneDesc;
|
||||
layout(binding = 2, set = 1) uniform sampler2D textureSamplers[];
|
||||
layout(constant_id = 0) const int USE_DIFFUSE = 1;
|
||||
layout(constant_id = 1) const int USE_SPECULAR = 1;
|
||||
layout(constant_id = 2) const int TRACE_SHADOW = 1;
|
||||
|
|
@ -59,30 +61,33 @@ pushC;
|
|||
|
||||
void main()
|
||||
{
|
||||
// Object of this instance
|
||||
uint objId = scnDesc.i[gl_InstanceCustomIndexEXT].objId;
|
||||
// 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 = 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]); //
|
||||
ivec3 ind = indices.i[gl_PrimitiveID];
|
||||
|
||||
// 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];
|
||||
Vertex v0 = vertices.v[ind.x];
|
||||
Vertex v1 = vertices.v[ind.y];
|
||||
Vertex v2 = vertices.v[ind.z];
|
||||
|
||||
const vec3 barycentrics = vec3(1.0 - attribs.x - attribs.y, attribs.x, attribs.y);
|
||||
|
||||
// Computing the normal at hit position
|
||||
vec3 normal = v0.nrm * barycentrics.x + v1.nrm * barycentrics.y + v2.nrm * barycentrics.z;
|
||||
// Transforming the normal to world space
|
||||
normal = normalize(vec3(scnDesc.i[gl_InstanceCustomIndexEXT].transfoIT * vec4(normal, 0.0)));
|
||||
normal = normalize(vec3(sceneDesc.i[gl_InstanceCustomIndexEXT].transfoIT * vec4(normal, 0.0)));
|
||||
|
||||
|
||||
// Computing the coordinates of the hit position
|
||||
vec3 worldPos = v0.pos * barycentrics.x + v1.pos * barycentrics.y + v2.pos * barycentrics.z;
|
||||
// Transforming the position to world space
|
||||
worldPos = vec3(scnDesc.i[gl_InstanceCustomIndexEXT].transfo * vec4(worldPos, 1.0));
|
||||
worldPos = vec3(sceneDesc.i[gl_InstanceCustomIndexEXT].transfo * vec4(worldPos, 1.0));
|
||||
|
||||
// Vector toward the light
|
||||
vec3 L;
|
||||
|
|
@ -102,8 +107,8 @@ void main()
|
|||
}
|
||||
|
||||
// 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];
|
||||
|
||||
|
||||
// Diffuse
|
||||
|
|
@ -113,9 +118,8 @@ void main()
|
|||
diffuse = computeDiffuse(mat, L, normal);
|
||||
if(mat.textureId >= 0)
|
||||
{
|
||||
uint txtId = mat.textureId + scnDesc.i[gl_InstanceCustomIndexEXT].txtOffset;
|
||||
vec2 texCoord = v0.texCoord * barycentrics.x + v1.texCoord * barycentrics.y
|
||||
+ v2.texCoord * barycentrics.z;
|
||||
uint txtId = mat.textureId + sceneDesc.i[gl_InstanceCustomIndexEXT].txtOffset;
|
||||
vec2 texCoord = v0.texCoord * barycentrics.x + v1.texCoord * barycentrics.y + v2.texCoord * barycentrics.z;
|
||||
diffuse *= texture(textureSamplers[nonuniformEXT(txtId)], texCoord).xyz;
|
||||
}
|
||||
}
|
||||
|
|
@ -132,8 +136,7 @@ void main()
|
|||
float tMax = lightDistance;
|
||||
vec3 origin = gl_WorldRayOriginEXT + gl_WorldRayDirectionEXT * gl_HitTEXT;
|
||||
vec3 rayDir = L;
|
||||
uint flags = gl_RayFlagsTerminateOnFirstHitEXT | gl_RayFlagsOpaqueEXT
|
||||
| gl_RayFlagsSkipClosestHitShaderEXT;
|
||||
uint flags = gl_RayFlagsTerminateOnFirstHitEXT | gl_RayFlagsOpaqueEXT | gl_RayFlagsSkipClosestHitShaderEXT;
|
||||
isShadowed = true;
|
||||
traceRayEXT(topLevelAS, // acceleration structure
|
||||
flags, // rayFlags
|
||||
|
|
|
|||
|
|
@ -22,10 +22,12 @@
|
|||
#extension GL_EXT_scalar_block_layout : enable
|
||||
#extension GL_GOOGLE_include_directive : enable
|
||||
|
||||
#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require
|
||||
|
||||
#include "wavefront.glsl"
|
||||
|
||||
// clang-format off
|
||||
layout(binding = 2, set = 0, scalar) buffer ScnDesc { sceneDesc i[]; } scnDesc;
|
||||
layout(binding = 1, scalar) buffer SceneDesc_ { SceneDesc i[]; } sceneDesc;
|
||||
// clang-format on
|
||||
|
||||
layout(binding = 0) uniform UniformBufferObject
|
||||
|
|
@ -65,8 +67,8 @@ out gl_PerVertex
|
|||
|
||||
void main()
|
||||
{
|
||||
mat4 objMatrix = scnDesc.i[pushC.instanceId].transfo;
|
||||
mat4 objMatrixIT = scnDesc.i[pushC.instanceId].transfoIT;
|
||||
mat4 objMatrix = sceneDesc.i[pushC.instanceId].transfo;
|
||||
mat4 objMatrixIT = sceneDesc.i[pushC.instanceId].transfoIT;
|
||||
|
||||
vec3 origin = vec3(ubo.viewI * vec4(0, 0, 0, 1));
|
||||
|
||||
|
|
|
|||
|
|
@ -39,12 +39,17 @@ struct WaveFrontMaterial
|
|||
int textureId;
|
||||
};
|
||||
|
||||
struct sceneDesc
|
||||
struct SceneDesc
|
||||
{
|
||||
int objId;
|
||||
int txtOffset;
|
||||
mat4 transfo;
|
||||
mat4 transfoIT;
|
||||
int objId;
|
||||
int txtOffset;
|
||||
|
||||
uint64_t vertexAddress;
|
||||
uint64_t indexAddress;
|
||||
uint64_t materialAddress;
|
||||
uint64_t materialIndexAddress;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ compile_glsl_directory(
|
|||
SRC "${CMAKE_CURRENT_SOURCE_DIR}/shaders"
|
||||
DST "${CMAKE_CURRENT_SOURCE_DIR}/spv"
|
||||
VULKAN_TARGET "vulkan1.2"
|
||||
DEPENDENCY ${VULKAN_BUILD_DEPENDENCIES}
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -52,7 +53,8 @@ target_sources(${PROJNAME} PUBLIC ${GLSL_SOURCES} ${GLSL_HEADERS})
|
|||
source_group("Common" FILES ${COMMON_SOURCE_FILES} ${PACKAGE_SOURCE_FILES})
|
||||
source_group("Sources" FILES ${SOURCE_FILES})
|
||||
source_group("Headers" FILES ${HEADER_FILES})
|
||||
source_group("Shader_Files" FILES ${GLSL_SOURCES} ${GLSL_HEADERS})
|
||||
source_group("Shader Sources" FILES ${GLSL_SOURCES})
|
||||
source_group("Shader Headers" FILES ${GLSL_HEADERS})
|
||||
|
||||
|
||||
#--------------------------------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -290,6 +290,7 @@ This will move each vertex up and down over time.
|
|||
#extension GL_ARB_separate_shader_objects : enable
|
||||
#extension GL_EXT_scalar_block_layout : enable
|
||||
#extension GL_GOOGLE_include_directive : enable
|
||||
#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require
|
||||
#include "wavefront.glsl"
|
||||
|
||||
layout(binding = 0, scalar) buffer Vertices
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
#include "nvvk/pipeline_vk.hpp"
|
||||
#include "nvvk/renderpasses_vk.hpp"
|
||||
#include "nvvk/shaders_vk.hpp"
|
||||
#include "nvvk/buffers_vk.hpp"
|
||||
|
||||
extern std::vector<std::string> defaultSearchPaths;
|
||||
|
||||
|
|
@ -113,26 +114,15 @@ void HelloVulkan::updateUniformBuffer(const VkCommandBuffer& cmdBuf)
|
|||
void HelloVulkan::createDescriptorSetLayout()
|
||||
{
|
||||
auto nbTxt = static_cast<uint32_t>(m_textures.size());
|
||||
auto nbObj = static_cast<uint32_t>(m_objModel.size());
|
||||
|
||||
// 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,
|
||||
// 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 = 3)
|
||||
m_descSetLayoutBind.addBinding(3, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, nbTxt,
|
||||
m_descSetLayoutBind.addBinding(2, 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);
|
||||
|
||||
|
||||
m_descSetLayout = m_descSetLayoutBind.createLayout(m_device);
|
||||
|
|
@ -150,25 +140,9 @@ void HelloVulkan::updateDescriptorSet()
|
|||
// Camera matrices and scene description
|
||||
VkDescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE};
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 0, &dbiUnif));
|
||||
VkDescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 2, &dbiSceneDesc));
|
||||
|
||||
// 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()));
|
||||
VkDescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 1, &dbiSceneDesc));
|
||||
|
||||
// All texture samplers
|
||||
std::vector<VkDescriptorImageInfo> diit;
|
||||
|
|
@ -176,7 +150,7 @@ void HelloVulkan::updateDescriptorSet()
|
|||
{
|
||||
diit.emplace_back(texture.descriptor);
|
||||
}
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 3, diit.data()));
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 2, diit.data()));
|
||||
|
||||
// Writing the information
|
||||
vkUpdateDescriptorSets(m_device, static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
||||
|
|
@ -234,12 +208,6 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
|
|||
m.specular = nvmath::pow(m.specular, 2.2f);
|
||||
}
|
||||
|
||||
ObjInstance instance;
|
||||
instance.objIndex = static_cast<uint32_t>(m_objModel.size());
|
||||
instance.transform = transform;
|
||||
instance.transformIT = nvmath::transpose(nvmath::invert(transform));
|
||||
instance.txtOffset = static_cast<uint32_t>(m_textures.size());
|
||||
|
||||
ObjModel model;
|
||||
model.nbIndices = static_cast<uint32_t>(loader.m_indices.size());
|
||||
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
|
||||
|
|
@ -247,23 +215,35 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
|
|||
// Create the buffers on Device and copy vertices, indices and materials
|
||||
nvvk::CommandPool cmdBufGet(m_device, m_graphicsQueueIndex);
|
||||
VkCommandBuffer cmdBuf = cmdBufGet.createCommandBuffer();
|
||||
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);
|
||||
model.matColorBuffer = m_alloc.createBuffer(cmdBuf, loader.m_materials, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
|
||||
model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
|
||||
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);
|
||||
// Creates all textures found
|
||||
uint32_t txtOffset = static_cast<uint32_t>(m_textures.size());
|
||||
createTextureImages(cmdBuf, loader.m_textures);
|
||||
cmdBufGet.submitAndWait(cmdBuf);
|
||||
m_alloc.finalizeAndReleaseStaging();
|
||||
|
||||
std::string objNb = std::to_string(instance.objIndex);
|
||||
std::string objNb = std::to_string(m_objModel.size());
|
||||
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
|
||||
m_debug.setObjectName(model.indexBuffer.buffer, (std::string("index_" + objNb).c_str()));
|
||||
m_debug.setObjectName(model.matColorBuffer.buffer, (std::string("mat_" + objNb).c_str()));
|
||||
m_debug.setObjectName(model.matIndexBuffer.buffer, (std::string("matIdx_" + objNb).c_str()));
|
||||
|
||||
ObjInstance instance;
|
||||
instance.objIndex = static_cast<uint32_t>(m_objModel.size());
|
||||
instance.transform = transform;
|
||||
instance.transformIT = nvmath::transpose(nvmath::invert(transform));
|
||||
instance.txtOffset = txtOffset;
|
||||
instance.vertices = nvvk::getBufferDeviceAddress(m_device, model.vertexBuffer.buffer);
|
||||
instance.indices = nvvk::getBufferDeviceAddress(m_device, model.indexBuffer.buffer);
|
||||
instance.materials = nvvk::getBufferDeviceAddress(m_device, model.matColorBuffer.buffer);
|
||||
instance.materialIndices = nvvk::getBufferDeviceAddress(m_device, model.matIndexBuffer.buffer);
|
||||
|
||||
m_objModel.emplace_back(model);
|
||||
m_objInstance.emplace_back(instance);
|
||||
}
|
||||
|
|
@ -633,11 +613,8 @@ void HelloVulkan::initRayTracing()
|
|||
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;
|
||||
|
||||
|
|
|
|||
|
|
@ -66,10 +66,14 @@ public:
|
|||
// Instance of the OBJ
|
||||
struct ObjInstance
|
||||
{
|
||||
uint32_t objIndex{0}; // Reference to the `m_objModel`
|
||||
uint32_t txtOffset{0}; // Offset in `m_textures`
|
||||
nvmath::mat4f transform{1}; // Position of the instance
|
||||
nvmath::mat4f transformIT{1}; // Inverse transpose
|
||||
uint32_t objIndex{0}; // Reference to the `m_objModel`
|
||||
uint32_t txtOffset{0}; // Offset in `m_textures`
|
||||
VkDeviceAddress vertices;
|
||||
VkDeviceAddress indices;
|
||||
VkDeviceAddress materials;
|
||||
VkDeviceAddress materialIndices;
|
||||
};
|
||||
|
||||
// Information pushed at each draw call
|
||||
|
|
@ -96,6 +100,7 @@ public:
|
|||
|
||||
nvvk::Buffer m_cameraMat; // Device-Host of the camera matrices
|
||||
nvvk::Buffer m_sceneDesc; // Device buffer of the OBJ instances
|
||||
|
||||
std::vector<nvvk::Texture> m_textures; // vector of all textures of the scene
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -109,33 +109,26 @@ int main(int argc, char** argv)
|
|||
std::string(PROJECT_NAME),
|
||||
};
|
||||
|
||||
// Vulkan required extensions
|
||||
assert(glfwVulkanSupported() == 1);
|
||||
uint32_t count{0};
|
||||
auto reqExtensions = glfwGetRequiredInstanceExtensions(&count);
|
||||
|
||||
// Requesting Vulkan extensions and layers
|
||||
nvvk::ContextCreateInfo contextInfo(true);
|
||||
contextInfo.setVersion(1, 2);
|
||||
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
|
||||
contextInfo.addInstanceExtension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME, true);
|
||||
contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME);
|
||||
#ifdef _WIN32
|
||||
contextInfo.addInstanceExtension(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
|
||||
#else
|
||||
contextInfo.addInstanceExtension(VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
|
||||
contextInfo.addInstanceExtension(VK_KHR_XCB_SURFACE_EXTENSION_NAME);
|
||||
#endif
|
||||
contextInfo.addInstanceExtension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
|
||||
contextInfo.addDeviceExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
|
||||
contextInfo.addDeviceExtension(VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME);
|
||||
contextInfo.addDeviceExtension(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME);
|
||||
contextInfo.addDeviceExtension(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME);
|
||||
contextInfo.addDeviceExtension(VK_EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME);
|
||||
nvvk::ContextCreateInfo contextInfo;
|
||||
contextInfo.setVersion(1, 2); // Using Vulkan 1.2
|
||||
for(uint32_t ext_id = 0; ext_id < count; ext_id++) // Adding required extensions (surface, win32, linux, ..)
|
||||
contextInfo.addInstanceExtension(reqExtensions[ext_id]);
|
||||
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true); // FPS in titlebar
|
||||
contextInfo.addInstanceExtension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME, true); // Allow debug names
|
||||
contextInfo.addDeviceExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME); // Enabling ability to present rendering
|
||||
|
||||
// #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
|
||||
|
||||
// Creating Vulkan base application
|
||||
nvvk::Context vkctx{};
|
||||
|
|
@ -171,7 +164,6 @@ int main(int argc, char** argv)
|
|||
helloVk.m_objInstance.push_back(inst);
|
||||
helloVk.loadModel(nvh::findFile("media/scenes/sphere.obj", defaultSearchPaths, true));
|
||||
|
||||
|
||||
helloVk.createOffscreenRender();
|
||||
helloVk.createDescriptorSetLayout();
|
||||
helloVk.createGraphicsPipeline();
|
||||
|
|
|
|||
|
|
@ -21,9 +21,10 @@
|
|||
#extension GL_ARB_separate_shader_objects : enable
|
||||
#extension GL_EXT_scalar_block_layout : enable
|
||||
#extension GL_GOOGLE_include_directive : enable
|
||||
#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require
|
||||
#include "wavefront.glsl"
|
||||
|
||||
layout(binding = 0, scalar) buffer Vertices
|
||||
layout(binding = 0, scalar) buffer Vertices_
|
||||
{
|
||||
Vertex v[];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,9 @@
|
|||
#extension GL_GOOGLE_include_directive : enable
|
||||
#extension GL_EXT_scalar_block_layout : enable
|
||||
|
||||
#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require
|
||||
#extension GL_EXT_buffer_reference2 : require
|
||||
|
||||
#include "wavefront.glsl"
|
||||
|
||||
|
||||
|
|
@ -37,30 +40,33 @@ pushC;
|
|||
|
||||
// clang-format off
|
||||
// Incoming
|
||||
//layout(location = 0) flat in int matIndex;
|
||||
layout(location = 1) in vec2 fragTexCoord;
|
||||
layout(location = 2) in vec3 fragNormal;
|
||||
layout(location = 3) in vec3 viewDir;
|
||||
layout(location = 4) in vec3 worldPos;
|
||||
// Outgoing
|
||||
layout(location = 0) out vec4 outColor;
|
||||
// Buffers
|
||||
layout(binding = 1, scalar) buffer MatColorBufferObject { WaveFrontMaterial m[]; } materials[];
|
||||
layout(binding = 2, scalar) buffer ScnDesc { sceneDesc i[]; } scnDesc;
|
||||
layout(binding = 3) uniform sampler2D[] textureSamplers;
|
||||
layout(binding = 4, scalar) buffer MatIndex { int i[]; } matIdx[];
|
||||
|
||||
layout(buffer_reference, scalar) buffer Vertices {Vertex v[]; }; // Positions of an object
|
||||
layout(buffer_reference, scalar) buffer Indices {uint 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 = 1, scalar) buffer SceneDesc_ { SceneDesc i[]; } sceneDesc;
|
||||
layout(binding = 2) uniform sampler2D[] textureSamplers;
|
||||
// clang-format on
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
// Object of this instance
|
||||
int objId = scnDesc.i[pushC.instanceId].objId;
|
||||
|
||||
// Material of the object
|
||||
int matIndex = matIdx[nonuniformEXT(objId)].i[gl_PrimitiveID];
|
||||
WaveFrontMaterial mat = materials[nonuniformEXT(objId)].m[matIndex];
|
||||
SceneDesc objResource = sceneDesc.i[pushC.instanceId];
|
||||
MatIndices matIndices = MatIndices(objResource.materialIndexAddress);
|
||||
Materials materials = Materials(objResource.materialAddress);
|
||||
|
||||
int matIndex = matIndices.i[gl_PrimitiveID];
|
||||
WaveFrontMaterial mat = materials.m[matIndex];
|
||||
|
||||
vec3 N = normalize(fragNormal);
|
||||
|
||||
|
|
@ -84,7 +90,7 @@ void main()
|
|||
vec3 diffuse = computeDiffuse(mat, L, N);
|
||||
if(mat.textureId >= 0)
|
||||
{
|
||||
int txtOffset = scnDesc.i[pushC.instanceId].txtOffset;
|
||||
int txtOffset = sceneDesc.i[pushC.instanceId].txtOffset;
|
||||
uint txtId = txtOffset + mat.textureId;
|
||||
vec3 diffuseTxt = texture(textureSamplers[nonuniformEXT(txtId)], fragTexCoord).xyz;
|
||||
diffuse *= diffuseTxt;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,10 @@
|
|||
#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"
|
||||
|
||||
|
|
@ -31,16 +35,13 @@ hitAttributeEXT vec2 attribs;
|
|||
layout(location = 0) rayPayloadInEXT hitPayload prd;
|
||||
layout(location = 1) rayPayloadEXT bool isShadowed;
|
||||
|
||||
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 = 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(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 = 1, set = 1, scalar) buffer SceneDesc_ { SceneDesc i[]; } sceneDesc;
|
||||
layout(binding = 2, set = 1) uniform sampler2D textureSamplers[];
|
||||
// clang-format on
|
||||
|
||||
layout(push_constant) uniform Constants
|
||||
|
|
@ -55,30 +56,33 @@ pushC;
|
|||
|
||||
void main()
|
||||
{
|
||||
// Object of this instance
|
||||
uint objId = scnDesc.i[gl_InstanceCustomIndexEXT].objId;
|
||||
// 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 = 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]); //
|
||||
ivec3 ind = indices.i[gl_PrimitiveID];
|
||||
|
||||
// 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];
|
||||
Vertex v0 = vertices.v[ind.x];
|
||||
Vertex v1 = vertices.v[ind.y];
|
||||
Vertex v2 = vertices.v[ind.z];
|
||||
|
||||
const vec3 barycentrics = vec3(1.0 - attribs.x - attribs.y, attribs.x, attribs.y);
|
||||
|
||||
// Computing the normal at hit position
|
||||
vec3 normal = v0.nrm * barycentrics.x + v1.nrm * barycentrics.y + v2.nrm * barycentrics.z;
|
||||
// Transforming the normal to world space
|
||||
normal = normalize(vec3(scnDesc.i[gl_InstanceCustomIndexEXT].transfoIT * vec4(normal, 0.0)));
|
||||
normal = normalize(vec3(sceneDesc.i[gl_InstanceCustomIndexEXT].transfoIT * vec4(normal, 0.0)));
|
||||
|
||||
|
||||
// Computing the coordinates of the hit position
|
||||
vec3 worldPos = v0.pos * barycentrics.x + v1.pos * barycentrics.y + v2.pos * barycentrics.z;
|
||||
// Transforming the position to world space
|
||||
worldPos = vec3(scnDesc.i[gl_InstanceCustomIndexEXT].transfo * vec4(worldPos, 1.0));
|
||||
worldPos = vec3(sceneDesc.i[gl_InstanceCustomIndexEXT].transfo * vec4(worldPos, 1.0));
|
||||
|
||||
// Vector toward the light
|
||||
vec3 L;
|
||||
|
|
@ -98,17 +102,16 @@ void main()
|
|||
}
|
||||
|
||||
// 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];
|
||||
|
||||
|
||||
// Diffuse
|
||||
vec3 diffuse = computeDiffuse(mat, L, normal);
|
||||
if(mat.textureId >= 0)
|
||||
{
|
||||
uint txtId = mat.textureId + scnDesc.i[gl_InstanceCustomIndexEXT].txtOffset;
|
||||
vec2 texCoord =
|
||||
v0.texCoord * barycentrics.x + v1.texCoord * barycentrics.y + v2.texCoord * barycentrics.z;
|
||||
uint txtId = mat.textureId + sceneDesc.i[gl_InstanceCustomIndexEXT].txtOffset;
|
||||
vec2 texCoord = v0.texCoord * barycentrics.x + v1.texCoord * barycentrics.y + v2.texCoord * barycentrics.z;
|
||||
diffuse *= texture(textureSamplers[nonuniformEXT(txtId)], texCoord).xyz;
|
||||
}
|
||||
|
||||
|
|
@ -122,8 +125,7 @@ void main()
|
|||
float tMax = lightDistance;
|
||||
vec3 origin = gl_WorldRayOriginEXT + gl_WorldRayDirectionEXT * gl_HitTEXT;
|
||||
vec3 rayDir = L;
|
||||
uint flags = gl_RayFlagsTerminateOnFirstHitEXT | gl_RayFlagsOpaqueEXT
|
||||
| gl_RayFlagsSkipClosestHitShaderEXT;
|
||||
uint flags = gl_RayFlagsTerminateOnFirstHitEXT | gl_RayFlagsOpaqueEXT | gl_RayFlagsSkipClosestHitShaderEXT;
|
||||
isShadowed = true;
|
||||
traceRayEXT(topLevelAS, // acceleration structure
|
||||
flags, // rayFlags
|
||||
|
|
|
|||
|
|
@ -22,10 +22,12 @@
|
|||
#extension GL_EXT_scalar_block_layout : enable
|
||||
#extension GL_GOOGLE_include_directive : enable
|
||||
|
||||
#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require
|
||||
|
||||
#include "wavefront.glsl"
|
||||
|
||||
// clang-format off
|
||||
layout(binding = 2, set = 0, scalar) buffer ScnDesc { sceneDesc i[]; } scnDesc;
|
||||
layout(binding = 1, scalar) buffer SceneDesc_ { SceneDesc i[]; } sceneDesc;
|
||||
// clang-format on
|
||||
|
||||
layout(binding = 0) uniform UniformBufferObject
|
||||
|
|
@ -65,8 +67,8 @@ out gl_PerVertex
|
|||
|
||||
void main()
|
||||
{
|
||||
mat4 objMatrix = scnDesc.i[pushC.instanceId].transfo;
|
||||
mat4 objMatrixIT = scnDesc.i[pushC.instanceId].transfoIT;
|
||||
mat4 objMatrix = sceneDesc.i[pushC.instanceId].transfo;
|
||||
mat4 objMatrixIT = sceneDesc.i[pushC.instanceId].transfoIT;
|
||||
|
||||
vec3 origin = vec3(ubo.viewI * vec4(0, 0, 0, 1));
|
||||
|
||||
|
|
|
|||
|
|
@ -39,12 +39,17 @@ struct WaveFrontMaterial
|
|||
int textureId;
|
||||
};
|
||||
|
||||
struct sceneDesc
|
||||
struct SceneDesc
|
||||
{
|
||||
int objId;
|
||||
int txtOffset;
|
||||
mat4 transfo;
|
||||
mat4 transfoIT;
|
||||
int objId;
|
||||
int txtOffset;
|
||||
|
||||
uint64_t vertexAddress;
|
||||
uint64_t indexAddress;
|
||||
uint64_t materialAddress;
|
||||
uint64_t materialIndexAddress;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ compile_glsl_directory(
|
|||
SRC "${CMAKE_CURRENT_SOURCE_DIR}/shaders"
|
||||
DST "${CMAKE_CURRENT_SOURCE_DIR}/spv"
|
||||
VULKAN_TARGET "vulkan1.2"
|
||||
DEPENDENCY ${VULKAN_BUILD_DEPENDENCIES}
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -52,7 +53,8 @@ target_sources(${PROJNAME} PUBLIC ${GLSL_SOURCES} ${GLSL_HEADERS})
|
|||
source_group("Common" FILES ${COMMON_SOURCE_FILES} ${PACKAGE_SOURCE_FILES})
|
||||
source_group("Sources" FILES ${SOURCE_FILES})
|
||||
source_group("Headers" FILES ${HEADER_FILES})
|
||||
source_group("Shader_Files" FILES ${GLSL_SOURCES} ${GLSL_HEADERS})
|
||||
source_group("Shader Sources" FILES ${GLSL_SOURCES})
|
||||
source_group("Shader Headers" FILES ${GLSL_HEADERS})
|
||||
|
||||
|
||||
#--------------------------------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -34,18 +34,20 @@ This shader starts like `raytrace.chit`, but uses less information.
|
|||
#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 "random.glsl"
|
||||
#include "raycommon.glsl"
|
||||
#include "wavefront.glsl"
|
||||
|
||||
// clang-format off
|
||||
layout(location = 0) rayPayloadInEXT hitPayload prd;
|
||||
|
||||
layout(binding = 2, set = 1, scalar) buffer ScnDesc { sceneDesc i[]; } scnDesc;
|
||||
layout(binding = 4, set = 1) buffer MatIndexColorBuffer { int i[]; } matIndex[];
|
||||
layout(binding = 5, set = 1, scalar) buffer Vertices { Vertex v[]; } vertices[];
|
||||
layout(binding = 6, set = 1) buffer Indices { uint i[]; } indices[];
|
||||
layout(binding = 1, set = 1, scalar) buffer MatColorBufferObject { WaveFrontMaterial m[]; } materials[];
|
||||
layout(buffer_reference, scalar) buffer Vertices {Vertex v[]; }; // Positions of an object
|
||||
layout(buffer_reference, scalar) buffer Indices {uint 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 = 1, set = 1, scalar) buffer SceneDesc_ { SceneDesc i[]; } sceneDesc;
|
||||
// clang-format on
|
||||
~~~~
|
||||
|
||||
|
|
@ -59,16 +61,14 @@ opaque, we simply return, which means that the hit will be accepted.
|
|||
~~~~ C++
|
||||
void main()
|
||||
{
|
||||
// Object of this instance
|
||||
uint objId = scnDesc.i[gl_InstanceCustomIndexEXT].objId;
|
||||
// Indices of the triangle
|
||||
uint ind = indices[nonuniformEXT(objId)].i[3 * gl_PrimitiveID + 0];
|
||||
// Vertex of the triangle
|
||||
Vertex v0 = vertices[nonuniformEXT(objId)].v[ind.x];
|
||||
// Object data
|
||||
SceneDesc objResource = sceneDesc.i[gl_InstanceCustomIndexEXT];
|
||||
MatIndices matIndices = MatIndices(objResource.materialIndexAddress);
|
||||
Materials materials = Materials(objResource.materialAddress);
|
||||
|
||||
// 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];
|
||||
|
||||
if (mat.illum != 4)
|
||||
return;
|
||||
|
|
@ -136,33 +136,13 @@ add the Any Hit stage index and push back the shader module to the stages.
|
|||
|
||||
## Give access of the buffers to the Any Hit shader
|
||||
|
||||
In `createDescriptorSetLayout()`, we need to allow the Any Hit shader to access some buffers.
|
||||
|
||||
This is the case for the material and scene description buffers
|
||||
In `createDescriptorSetLayout()`, we need to allow the Any Hit shader to access the scene description buffer
|
||||
|
||||
~~~~ C++
|
||||
// Materials (binding = 1)
|
||||
m_descSetLayoutBind.addBinding(1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, nbObj,
|
||||
// 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 | VK_SHADER_STAGE_ANY_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 | VK_SHADER_STAGE_ANY_HIT_BIT_KHR);
|
||||
~~~~
|
||||
|
||||
and also for the vertex, index and material index buffers:
|
||||
|
||||
~~~~ C++
|
||||
// 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 | VK_SHADER_STAGE_ANY_HIT_BIT_KHR);
|
||||
// Storing vertices (binding = 5)
|
||||
m_descSetLayoutBind.addBinding(5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, nbObj,
|
||||
VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_ANY_HIT_BIT_KHR);
|
||||
// Storing indices (binding = 6)
|
||||
m_descSetLayoutBind.addBinding(6, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, nbObj,
|
||||
VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_ANY_HIT_BIT_KHR);
|
||||
~~~~
|
||||
|
||||
## Opaque Flag
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
#include "nvvk/pipeline_vk.hpp"
|
||||
#include "nvvk/renderpasses_vk.hpp"
|
||||
#include "nvvk/shaders_vk.hpp"
|
||||
#include "nvvk/buffers_vk.hpp"
|
||||
|
||||
extern std::vector<std::string> defaultSearchPaths;
|
||||
|
||||
|
|
@ -113,30 +114,16 @@ void HelloVulkan::updateUniformBuffer(const VkCommandBuffer& cmdBuf)
|
|||
void HelloVulkan::createDescriptorSetLayout()
|
||||
{
|
||||
auto nbTxt = static_cast<uint32_t>(m_textures.size());
|
||||
auto nbObj = static_cast<uint32_t>(m_objModel.size());
|
||||
|
||||
// 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 | VK_SHADER_STAGE_ANY_HIT_BIT_KHR);
|
||||
// Scene description (binding = 2)
|
||||
m_descSetLayoutBind.addBinding(2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1,
|
||||
// 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 | VK_SHADER_STAGE_ANY_HIT_BIT_KHR);
|
||||
// Textures (binding = 3)
|
||||
m_descSetLayoutBind.addBinding(3, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, nbTxt,
|
||||
m_descSetLayoutBind.addBinding(2, 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 | VK_SHADER_STAGE_ANY_HIT_BIT_KHR);
|
||||
// Storing vertices (binding = 5)
|
||||
m_descSetLayoutBind.addBinding(5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, nbObj,
|
||||
VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_ANY_HIT_BIT_KHR);
|
||||
// Storing indices (binding = 6)
|
||||
m_descSetLayoutBind.addBinding(6, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, nbObj,
|
||||
VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_ANY_HIT_BIT_KHR);
|
||||
|
||||
|
||||
m_descSetLayout = m_descSetLayoutBind.createLayout(m_device);
|
||||
|
|
@ -154,25 +141,9 @@ void HelloVulkan::updateDescriptorSet()
|
|||
// Camera matrices and scene description
|
||||
VkDescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE};
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 0, &dbiUnif));
|
||||
VkDescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 2, &dbiSceneDesc));
|
||||
|
||||
// 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()));
|
||||
VkDescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 1, &dbiSceneDesc));
|
||||
|
||||
// All texture samplers
|
||||
std::vector<VkDescriptorImageInfo> diit;
|
||||
|
|
@ -180,7 +151,7 @@ void HelloVulkan::updateDescriptorSet()
|
|||
{
|
||||
diit.emplace_back(texture.descriptor);
|
||||
}
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 3, diit.data()));
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 2, diit.data()));
|
||||
|
||||
// Writing the information
|
||||
vkUpdateDescriptorSets(m_device, static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
||||
|
|
@ -238,12 +209,6 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
|
|||
m.specular = nvmath::pow(m.specular, 2.2f);
|
||||
}
|
||||
|
||||
ObjInstance instance;
|
||||
instance.objIndex = static_cast<uint32_t>(m_objModel.size());
|
||||
instance.transform = transform;
|
||||
instance.transformIT = nvmath::transpose(nvmath::invert(transform));
|
||||
instance.txtOffset = static_cast<uint32_t>(m_textures.size());
|
||||
|
||||
ObjModel model;
|
||||
model.nbIndices = static_cast<uint32_t>(loader.m_indices.size());
|
||||
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
|
||||
|
|
@ -251,23 +216,35 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
|
|||
// Create the buffers on Device and copy vertices, indices and materials
|
||||
nvvk::CommandPool cmdBufGet(m_device, m_graphicsQueueIndex);
|
||||
VkCommandBuffer cmdBuf = cmdBufGet.createCommandBuffer();
|
||||
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);
|
||||
model.matColorBuffer = m_alloc.createBuffer(cmdBuf, loader.m_materials, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
|
||||
model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
|
||||
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);
|
||||
// Creates all textures found
|
||||
uint32_t txtOffset = static_cast<uint32_t>(m_textures.size());
|
||||
createTextureImages(cmdBuf, loader.m_textures);
|
||||
cmdBufGet.submitAndWait(cmdBuf);
|
||||
m_alloc.finalizeAndReleaseStaging();
|
||||
|
||||
std::string objNb = std::to_string(instance.objIndex);
|
||||
std::string objNb = std::to_string(m_objModel.size());
|
||||
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
|
||||
m_debug.setObjectName(model.indexBuffer.buffer, (std::string("index_" + objNb).c_str()));
|
||||
m_debug.setObjectName(model.matColorBuffer.buffer, (std::string("mat_" + objNb).c_str()));
|
||||
m_debug.setObjectName(model.matIndexBuffer.buffer, (std::string("matIdx_" + objNb).c_str()));
|
||||
|
||||
ObjInstance instance;
|
||||
instance.objIndex = static_cast<uint32_t>(m_objModel.size());
|
||||
instance.transform = transform;
|
||||
instance.transformIT = nvmath::transpose(nvmath::invert(transform));
|
||||
instance.txtOffset = txtOffset;
|
||||
instance.vertices = nvvk::getBufferDeviceAddress(m_device, model.vertexBuffer.buffer);
|
||||
instance.indices = nvvk::getBufferDeviceAddress(m_device, model.indexBuffer.buffer);
|
||||
instance.materials = nvvk::getBufferDeviceAddress(m_device, model.matColorBuffer.buffer);
|
||||
instance.materialIndices = nvvk::getBufferDeviceAddress(m_device, model.matIndexBuffer.buffer);
|
||||
|
||||
m_objModel.emplace_back(model);
|
||||
m_objInstance.emplace_back(instance);
|
||||
}
|
||||
|
|
@ -630,11 +607,8 @@ void HelloVulkan::initRayTracing()
|
|||
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;
|
||||
|
||||
|
|
@ -950,9 +924,7 @@ void HelloVulkan::raytrace(const VkCommandBuffer& cmdBuf, const nvmath::vec4f& c
|
|||
uint32_t groupSize = nvh::align_up(m_rtProperties.shaderGroupHandleSize, m_rtProperties.shaderGroupBaseAlignment);
|
||||
uint32_t groupStride = groupSize;
|
||||
|
||||
VkBufferDeviceAddressInfo info{VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO};
|
||||
info.buffer = m_rtSBTBuffer.buffer;
|
||||
VkDeviceAddress sbtAddress = vkGetBufferDeviceAddress(m_device, &info);
|
||||
VkDeviceAddress sbtAddress = nvvk::getBufferDeviceAddress(m_device, m_rtSBTBuffer.buffer);
|
||||
|
||||
using Stride = VkStridedDeviceAddressRegionKHR;
|
||||
std::array<Stride, 4> strideAddresses{Stride{sbtAddress + 0u * groupSize, groupStride, groupSize * 1}, // raygen
|
||||
|
|
|
|||
|
|
@ -65,10 +65,14 @@ public:
|
|||
// Instance of the OBJ
|
||||
struct ObjInstance
|
||||
{
|
||||
uint32_t objIndex{0}; // Reference to the `m_objModel`
|
||||
uint32_t txtOffset{0}; // Offset in `m_textures`
|
||||
nvmath::mat4f transform{1}; // Position of the instance
|
||||
nvmath::mat4f transformIT{1}; // Inverse transpose
|
||||
uint32_t objIndex{0}; // Reference to the `m_objModel`
|
||||
uint32_t txtOffset{0}; // Offset in `m_textures`
|
||||
VkDeviceAddress vertices;
|
||||
VkDeviceAddress indices;
|
||||
VkDeviceAddress materials;
|
||||
VkDeviceAddress materialIndices;
|
||||
};
|
||||
|
||||
// Information pushed at each draw call
|
||||
|
|
@ -95,6 +99,7 @@ public:
|
|||
|
||||
nvvk::Buffer m_cameraMat; // Device-Host of the camera matrices
|
||||
nvvk::Buffer m_sceneDesc; // Device buffer of the OBJ instances
|
||||
|
||||
std::vector<nvvk::Texture> m_textures; // vector of all textures of the scene
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ int main(int argc, char** argv)
|
|||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||
GLFWwindow* window = glfwCreateWindow(SAMPLE_WIDTH, SAMPLE_HEIGHT, PROJECT_NAME, nullptr, nullptr);
|
||||
|
||||
|
||||
// Setup camera
|
||||
CameraManip.setWindowSize(SAMPLE_WIDTH, SAMPLE_HEIGHT);
|
||||
CameraManip.setLookat(nvmath::vec3f(5, 4, -4), nvmath::vec3f(0, 1, 0), nvmath::vec3f(0, 1, 0));
|
||||
|
|
@ -109,34 +110,26 @@ int main(int argc, char** argv)
|
|||
std::string(PROJECT_NAME),
|
||||
};
|
||||
|
||||
// Vulkan required extensions
|
||||
assert(glfwVulkanSupported() == 1);
|
||||
uint32_t count{0};
|
||||
auto reqExtensions = glfwGetRequiredInstanceExtensions(&count);
|
||||
|
||||
// Requesting Vulkan extensions and layers
|
||||
nvvk::ContextCreateInfo contextInfo(true);
|
||||
contextInfo.setVersion(1, 2);
|
||||
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
|
||||
contextInfo.addInstanceExtension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME, true);
|
||||
contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME);
|
||||
#ifdef _WIN32
|
||||
contextInfo.addInstanceExtension(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
|
||||
#else
|
||||
contextInfo.addInstanceExtension(VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
|
||||
contextInfo.addInstanceExtension(VK_KHR_XCB_SURFACE_EXTENSION_NAME);
|
||||
#endif
|
||||
contextInfo.addInstanceExtension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
|
||||
contextInfo.addDeviceExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
|
||||
contextInfo.addDeviceExtension(VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME);
|
||||
contextInfo.addDeviceExtension(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME);
|
||||
contextInfo.addDeviceExtension(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME);
|
||||
contextInfo.addDeviceExtension(VK_EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME);
|
||||
nvvk::ContextCreateInfo contextInfo;
|
||||
contextInfo.setVersion(1, 2); // Using Vulkan 1.2
|
||||
for(uint32_t ext_id = 0; ext_id < count; ext_id++) // Adding required extensions (surface, win32, linux, ..)
|
||||
contextInfo.addInstanceExtension(reqExtensions[ext_id]);
|
||||
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true); // FPS in titlebar
|
||||
contextInfo.addInstanceExtension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME, true); // Allow debug names
|
||||
contextInfo.addDeviceExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME); // Enabling ability to present rendering
|
||||
|
||||
// #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
|
||||
|
||||
// Creating Vulkan base application
|
||||
nvvk::Context vkctx{};
|
||||
|
|
@ -169,7 +162,6 @@ int main(int argc, char** argv)
|
|||
nvmath::scale_mat4(nvmath::vec3f(1.5f)) * nvmath::translation_mat4(nvmath::vec3f(0.0f, 1.0f, 0.0f)));
|
||||
helloVk.loadModel(nvh::findFile("media/scenes/plane.obj", defaultSearchPaths, true));
|
||||
|
||||
|
||||
helloVk.createOffscreenRender();
|
||||
helloVk.createDescriptorSetLayout();
|
||||
helloVk.createGraphicsPipeline();
|
||||
|
|
|
|||
|
|
@ -23,6 +23,9 @@
|
|||
#extension GL_GOOGLE_include_directive : enable
|
||||
#extension GL_EXT_scalar_block_layout : enable
|
||||
|
||||
#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require
|
||||
#extension GL_EXT_buffer_reference2 : require
|
||||
|
||||
#include "wavefront.glsl"
|
||||
|
||||
|
||||
|
|
@ -37,30 +40,32 @@ pushC;
|
|||
|
||||
// clang-format off
|
||||
// Incoming
|
||||
//layout(location = 0) flat in int matIndex;
|
||||
layout(location = 1) in vec2 fragTexCoord;
|
||||
layout(location = 2) in vec3 fragNormal;
|
||||
layout(location = 3) in vec3 viewDir;
|
||||
layout(location = 4) in vec3 worldPos;
|
||||
// Outgoing
|
||||
layout(location = 0) out vec4 outColor;
|
||||
// Buffers
|
||||
layout(binding = 1, scalar) buffer MatColorBufferObject { WaveFrontMaterial m[]; } materials[];
|
||||
layout(binding = 2, scalar) buffer ScnDesc { sceneDesc i[]; } scnDesc;
|
||||
layout(binding = 3) uniform sampler2D[] textureSamplers;
|
||||
layout(binding = 4, scalar) buffer MatIndex { int i[]; } matIdx[];
|
||||
|
||||
layout(buffer_reference, scalar) buffer Vertices {Vertex v[]; }; // Positions of an object
|
||||
layout(buffer_reference, scalar) buffer Indices {uint 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 = 1, scalar) buffer SceneDesc_ { SceneDesc i[]; } sceneDesc;
|
||||
layout(binding = 2) uniform sampler2D[] textureSamplers;
|
||||
// clang-format on
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
// Object of this instance
|
||||
int objId = scnDesc.i[pushC.instanceId].objId;
|
||||
|
||||
// Material of the object
|
||||
int matIndex = matIdx[nonuniformEXT(objId)].i[gl_PrimitiveID];
|
||||
WaveFrontMaterial mat = materials[nonuniformEXT(objId)].m[matIndex];
|
||||
SceneDesc objResource = sceneDesc.i[pushC.instanceId];
|
||||
MatIndices matIndices = MatIndices(objResource.materialIndexAddress);
|
||||
Materials materials = Materials(objResource.materialAddress);
|
||||
|
||||
int matIndex = matIndices.i[gl_PrimitiveID];
|
||||
WaveFrontMaterial mat = materials.m[matIndex];
|
||||
|
||||
vec3 N = normalize(fragNormal);
|
||||
|
||||
|
|
@ -84,7 +89,7 @@ void main()
|
|||
vec3 diffuse = computeDiffuse(mat, L, N);
|
||||
if(mat.textureId >= 0)
|
||||
{
|
||||
int txtOffset = scnDesc.i[pushC.instanceId].txtOffset;
|
||||
int txtOffset = sceneDesc.i[pushC.instanceId].txtOffset;
|
||||
uint txtId = txtOffset + mat.textureId;
|
||||
vec3 diffuseTxt = texture(textureSamplers[nonuniformEXT(txtId)], fragTexCoord).xyz;
|
||||
diffuse *= diffuseTxt;
|
||||
|
|
|
|||
|
|
@ -19,36 +19,35 @@
|
|||
|
||||
#version 460
|
||||
#extension GL_EXT_ray_tracing : require
|
||||
#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 "random.glsl"
|
||||
#include "raycommon.glsl"
|
||||
#include "wavefront.glsl"
|
||||
|
||||
// clang-format off
|
||||
layout(location = 0) rayPayloadInEXT hitPayload prd;
|
||||
|
||||
layout(binding = 2, set = 1, scalar) buffer ScnDesc { sceneDesc i[]; } scnDesc;
|
||||
layout(binding = 4, set = 1) buffer MatIndexColorBuffer { int i[]; } matIndex[];
|
||||
layout(binding = 5, set = 1, scalar) buffer Vertices { Vertex v[]; } vertices[];
|
||||
layout(binding = 6, set = 1) buffer Indices { uint i[]; } indices[];
|
||||
layout(binding = 1, set = 1, scalar) buffer MatColorBufferObject { WaveFrontMaterial m[]; } materials[];
|
||||
layout(buffer_reference, scalar) buffer Vertices {Vertex v[]; }; // Positions of an object
|
||||
layout(buffer_reference, scalar) buffer Indices {uint 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 = 1, set = 1, scalar) buffer SceneDesc_ { SceneDesc i[]; } sceneDesc;
|
||||
// clang-format on
|
||||
|
||||
void main()
|
||||
{
|
||||
// Object of this instance
|
||||
uint objId = scnDesc.i[gl_InstanceCustomIndexEXT].objId;
|
||||
// Indices of the triangle
|
||||
uint ind = indices[nonuniformEXT(objId)].i[3 * gl_PrimitiveID + 0];
|
||||
// Vertex of the triangle
|
||||
Vertex v0 = vertices[nonuniformEXT(objId)].v[ind.x];
|
||||
// Object data
|
||||
SceneDesc objResource = sceneDesc.i[gl_InstanceCustomIndexEXT];
|
||||
MatIndices matIndices = MatIndices(objResource.materialIndexAddress);
|
||||
Materials materials = Materials(objResource.materialAddress);
|
||||
|
||||
// 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];
|
||||
|
||||
if(mat.illum != 4)
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,10 @@
|
|||
#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"
|
||||
|
||||
|
|
@ -31,16 +35,13 @@ hitAttributeEXT vec2 attribs;
|
|||
layout(location = 0) rayPayloadInEXT hitPayload prd;
|
||||
layout(location = 1) rayPayloadEXT shadowPayload prdShadow;
|
||||
|
||||
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 = 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(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 = 1, set = 1, scalar) buffer SceneDesc_ { SceneDesc i[]; } sceneDesc;
|
||||
layout(binding = 2, set = 1) uniform sampler2D textureSamplers[];
|
||||
// clang-format on
|
||||
|
||||
layout(push_constant) uniform Constants
|
||||
|
|
@ -55,30 +56,33 @@ pushC;
|
|||
|
||||
void main()
|
||||
{
|
||||
// Object of this instance
|
||||
uint objId = scnDesc.i[gl_InstanceCustomIndexEXT].objId;
|
||||
// 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 = 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]); //
|
||||
ivec3 ind = indices.i[gl_PrimitiveID];
|
||||
|
||||
// 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];
|
||||
Vertex v0 = vertices.v[ind.x];
|
||||
Vertex v1 = vertices.v[ind.y];
|
||||
Vertex v2 = vertices.v[ind.z];
|
||||
|
||||
const vec3 barycentrics = vec3(1.0 - attribs.x - attribs.y, attribs.x, attribs.y);
|
||||
|
||||
// Computing the normal at hit position
|
||||
vec3 normal = v0.nrm * barycentrics.x + v1.nrm * barycentrics.y + v2.nrm * barycentrics.z;
|
||||
// Transforming the normal to world space
|
||||
normal = normalize(vec3(scnDesc.i[gl_InstanceCustomIndexEXT].transfoIT * vec4(normal, 0.0)));
|
||||
normal = normalize(vec3(sceneDesc.i[gl_InstanceCustomIndexEXT].transfoIT * vec4(normal, 0.0)));
|
||||
|
||||
|
||||
// Computing the coordinates of the hit position
|
||||
vec3 worldPos = v0.pos * barycentrics.x + v1.pos * barycentrics.y + v2.pos * barycentrics.z;
|
||||
// Transforming the position to world space
|
||||
worldPos = vec3(scnDesc.i[gl_InstanceCustomIndexEXT].transfo * vec4(worldPos, 1.0));
|
||||
worldPos = vec3(sceneDesc.i[gl_InstanceCustomIndexEXT].transfo * vec4(worldPos, 1.0));
|
||||
|
||||
// Vector toward the light
|
||||
vec3 L;
|
||||
|
|
@ -98,17 +102,16 @@ void main()
|
|||
}
|
||||
|
||||
// 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];
|
||||
|
||||
|
||||
// Diffuse
|
||||
vec3 diffuse = computeDiffuse(mat, L, normal);
|
||||
if(mat.textureId >= 0)
|
||||
{
|
||||
uint txtId = mat.textureId + scnDesc.i[gl_InstanceCustomIndexEXT].txtOffset;
|
||||
vec2 texCoord =
|
||||
v0.texCoord * barycentrics.x + v1.texCoord * barycentrics.y + v2.texCoord * barycentrics.z;
|
||||
uint txtId = mat.textureId + sceneDesc.i[gl_InstanceCustomIndexEXT].txtOffset;
|
||||
vec2 texCoord = v0.texCoord * barycentrics.x + v1.texCoord * barycentrics.y + v2.texCoord * barycentrics.z;
|
||||
diffuse *= texture(textureSamplers[nonuniformEXT(txtId)], texCoord).xyz;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,9 +19,10 @@
|
|||
|
||||
//#version 460
|
||||
#extension GL_EXT_ray_tracing : require
|
||||
#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 "random.glsl"
|
||||
#include "raycommon.glsl"
|
||||
|
|
@ -34,25 +35,23 @@ layout(location = 0) rayPayloadInEXT hitPayload prd;
|
|||
layout(location = 1) rayPayloadInEXT shadowPayload prd;
|
||||
#endif
|
||||
|
||||
layout(binding = 2, set = 1, scalar) buffer ScnDesc { sceneDesc i[]; } scnDesc;
|
||||
layout(binding = 4, set = 1) buffer MatIndexColorBuffer { int i[]; } matIndex[];
|
||||
layout(binding = 5, set = 1, scalar) buffer Vertices { Vertex v[]; } vertices[];
|
||||
layout(binding = 6, set = 1) buffer Indices { uint i[]; } indices[];
|
||||
layout(binding = 1, set = 1, scalar) buffer MatColorBufferObject { WaveFrontMaterial m[]; } materials[];
|
||||
layout(buffer_reference, scalar) buffer Vertices {Vertex v[]; }; // Positions of an object
|
||||
layout(buffer_reference, scalar) buffer Indices {uint 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 = 1, set = 1, scalar) buffer SceneDesc_ { SceneDesc i[]; } sceneDesc;
|
||||
// clang-format on
|
||||
|
||||
void main()
|
||||
{
|
||||
// Object of this instance
|
||||
uint objId = scnDesc.i[gl_InstanceCustomIndexEXT].objId;
|
||||
// Indices of the triangle
|
||||
uint ind = indices[nonuniformEXT(objId)].i[3 * gl_PrimitiveID + 0];
|
||||
// Vertex of the triangle
|
||||
Vertex v0 = vertices[nonuniformEXT(objId)].v[ind.x];
|
||||
// Object data
|
||||
SceneDesc objResource = sceneDesc.i[gl_InstanceCustomIndexEXT];
|
||||
MatIndices matIndices = MatIndices(objResource.materialIndexAddress);
|
||||
Materials materials = Materials(objResource.materialAddress);
|
||||
|
||||
// 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];
|
||||
|
||||
if(mat.illum != 4)
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -22,10 +22,12 @@
|
|||
#extension GL_EXT_scalar_block_layout : enable
|
||||
#extension GL_GOOGLE_include_directive : enable
|
||||
|
||||
#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require
|
||||
|
||||
#include "wavefront.glsl"
|
||||
|
||||
// clang-format off
|
||||
layout(binding = 2, set = 0, scalar) buffer ScnDesc { sceneDesc i[]; } scnDesc;
|
||||
layout(binding = 1, scalar) buffer SceneDesc_ { SceneDesc i[]; } sceneDesc;
|
||||
// clang-format on
|
||||
|
||||
layout(binding = 0) uniform UniformBufferObject
|
||||
|
|
@ -65,8 +67,8 @@ out gl_PerVertex
|
|||
|
||||
void main()
|
||||
{
|
||||
mat4 objMatrix = scnDesc.i[pushC.instanceId].transfo;
|
||||
mat4 objMatrixIT = scnDesc.i[pushC.instanceId].transfoIT;
|
||||
mat4 objMatrix = sceneDesc.i[pushC.instanceId].transfo;
|
||||
mat4 objMatrixIT = sceneDesc.i[pushC.instanceId].transfoIT;
|
||||
|
||||
vec3 origin = vec3(ubo.viewI * vec4(0, 0, 0, 1));
|
||||
|
||||
|
|
|
|||
|
|
@ -39,12 +39,17 @@ struct WaveFrontMaterial
|
|||
int textureId;
|
||||
};
|
||||
|
||||
struct sceneDesc
|
||||
struct SceneDesc
|
||||
{
|
||||
int objId;
|
||||
int txtOffset;
|
||||
mat4 transfo;
|
||||
mat4 transfoIT;
|
||||
int objId;
|
||||
int txtOffset;
|
||||
|
||||
uint64_t vertexAddress;
|
||||
uint64_t indexAddress;
|
||||
uint64_t materialAddress;
|
||||
uint64_t materialIndexAddress;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ cmake_minimum_required(VERSION 3.9.6 FATAL_ERROR)
|
|||
#--------------------------------------------------------------------------------------------------
|
||||
# Project setting
|
||||
get_filename_component(PROJNAME ${CMAKE_CURRENT_SOURCE_DIR} NAME)
|
||||
SET(PROJNAME vk_${PROJNAME}_KHR)
|
||||
set(PROJNAME vk_${PROJNAME}_KHR)
|
||||
project(${PROJNAME} LANGUAGES C CXX)
|
||||
message(STATUS "-------------------------------")
|
||||
message(STATUS "Processing Project ${PROJNAME}:")
|
||||
|
|
@ -53,8 +53,8 @@ target_sources(${PROJNAME} PUBLIC ${GLSL_SOURCES} ${GLSL_HEADERS})
|
|||
source_group("Common" FILES ${COMMON_SOURCE_FILES} ${PACKAGE_SOURCE_FILES})
|
||||
source_group("Sources" FILES ${SOURCE_FILES})
|
||||
source_group("Headers" FILES ${HEADER_FILES})
|
||||
source_group("Shaders Src" FILES ${GLSL_SOURCES})
|
||||
source_group("Shaders Hdr" FILES ${GLSL_HEADERS})
|
||||
source_group("Shader Sources" FILES ${GLSL_SOURCES})
|
||||
source_group("Shader Headers" FILES ${GLSL_HEADERS})
|
||||
|
||||
|
||||
#--------------------------------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
#include "nvvk/pipeline_vk.hpp"
|
||||
#include "nvvk/renderpasses_vk.hpp"
|
||||
#include "nvvk/shaders_vk.hpp"
|
||||
#include "nvvk/buffers_vk.hpp"
|
||||
|
||||
extern std::vector<std::string> defaultSearchPaths;
|
||||
|
||||
|
|
@ -109,18 +110,13 @@ void HelloVulkan::updateUniformBuffer(const VkCommandBuffer& cmdBuf)
|
|||
void HelloVulkan::createDescriptorSetLayout()
|
||||
{
|
||||
auto nbTxt = static_cast<uint32_t>(m_textures.size());
|
||||
auto nbObj = static_cast<uint32_t>(m_objModel.size());
|
||||
|
||||
// Camera matrices (binding = 0)
|
||||
m_descSetLayoutBind.addBinding(0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT);
|
||||
// Materials (binding = 1)
|
||||
m_descSetLayoutBind.addBinding(1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, nbObj, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
// Scene description (binding = 2)
|
||||
m_descSetLayoutBind.addBinding(2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
// Scene description (binding = 1)
|
||||
m_descSetLayoutBind.addBinding(1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
// Textures (binding = 3)
|
||||
m_descSetLayoutBind.addBinding(3, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, nbTxt, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
// Materials (binding = 4)
|
||||
m_descSetLayoutBind.addBinding(4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, nbObj, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
m_descSetLayoutBind.addBinding(2, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, nbTxt, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
|
||||
|
||||
m_descSetLayout = m_descSetLayoutBind.createLayout(m_device);
|
||||
|
|
@ -138,23 +134,9 @@ void HelloVulkan::updateDescriptorSet()
|
|||
// Camera matrices and scene description
|
||||
VkDescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE};
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 0, &dbiUnif));
|
||||
VkDescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 2, &dbiSceneDesc));
|
||||
|
||||
// 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()));
|
||||
VkDescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 1, &dbiSceneDesc));
|
||||
|
||||
// All texture samplers
|
||||
std::vector<VkDescriptorImageInfo> diit;
|
||||
|
|
@ -162,12 +144,13 @@ void HelloVulkan::updateDescriptorSet()
|
|||
{
|
||||
diit.emplace_back(texture.descriptor);
|
||||
}
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 3, diit.data()));
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 2, diit.data()));
|
||||
|
||||
// Writing the information
|
||||
vkUpdateDescriptorSets(m_device, static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
// Creating the pipeline layout
|
||||
//
|
||||
|
|
@ -224,12 +207,6 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
|
|||
m.specular = nvmath::pow(m.specular, 2.2f);
|
||||
}
|
||||
|
||||
ObjInstance instance;
|
||||
instance.objIndex = static_cast<uint32_t>(m_objModel.size());
|
||||
instance.transform = transform;
|
||||
instance.transformIT = nvmath::transpose(nvmath::invert(transform));
|
||||
instance.txtOffset = static_cast<uint32_t>(m_textures.size());
|
||||
|
||||
ObjModel model;
|
||||
model.nbIndices = static_cast<uint32_t>(loader.m_indices.size());
|
||||
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
|
||||
|
|
@ -237,23 +214,35 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
|
|||
// Create the buffers on Device and copy vertices, indices and materials
|
||||
nvvk::CommandPool cmdBufGet(m_device, m_graphicsQueueIndex);
|
||||
VkCommandBuffer cmdBuf = cmdBufGet.createCommandBuffer();
|
||||
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);
|
||||
model.matColorBuffer = m_alloc.createBuffer(cmdBuf, loader.m_materials, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
|
||||
model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
|
||||
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);
|
||||
// Creates all textures found
|
||||
uint32_t txtOffset = static_cast<uint32_t>(m_textures.size());
|
||||
createTextureImages(cmdBuf, loader.m_textures);
|
||||
cmdBufGet.submitAndWait(cmdBuf);
|
||||
m_alloc.finalizeAndReleaseStaging();
|
||||
|
||||
std::string objNb = std::to_string(instance.objIndex);
|
||||
std::string objNb = std::to_string(m_objModel.size());
|
||||
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
|
||||
m_debug.setObjectName(model.indexBuffer.buffer, (std::string("index_" + objNb).c_str()));
|
||||
m_debug.setObjectName(model.matColorBuffer.buffer, (std::string("mat_" + objNb).c_str()));
|
||||
m_debug.setObjectName(model.matIndexBuffer.buffer, (std::string("matIdx_" + objNb).c_str()));
|
||||
|
||||
ObjInstance instance;
|
||||
instance.objIndex = static_cast<uint32_t>(m_objModel.size());
|
||||
instance.transform = transform;
|
||||
instance.transformIT = nvmath::transpose(nvmath::invert(transform));
|
||||
instance.txtOffset = txtOffset;
|
||||
instance.vertices = nvvk::getBufferDeviceAddress(m_device, model.vertexBuffer.buffer);
|
||||
instance.indices = nvvk::getBufferDeviceAddress(m_device, model.indexBuffer.buffer);
|
||||
instance.materials = nvvk::getBufferDeviceAddress(m_device, model.matColorBuffer.buffer);
|
||||
instance.materialIndices = nvvk::getBufferDeviceAddress(m_device, model.matIndexBuffer.buffer);
|
||||
|
||||
m_objModel.emplace_back(model);
|
||||
m_objInstance.emplace_back(instance);
|
||||
}
|
||||
|
|
@ -653,11 +642,8 @@ void HelloVulkan::initRayTracing()
|
|||
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;
|
||||
|
||||
|
|
|
|||
|
|
@ -76,10 +76,14 @@ public:
|
|||
// Instance of the OBJ
|
||||
struct ObjInstance
|
||||
{
|
||||
uint32_t objIndex{0}; // Reference to the `m_objModel`
|
||||
uint32_t txtOffset{0}; // Offset in `m_textures`
|
||||
nvmath::mat4f transform{1}; // Position of the instance
|
||||
nvmath::mat4f transformIT{1}; // Inverse transpose
|
||||
uint32_t objIndex{0}; // Reference to the `m_objModel`
|
||||
uint32_t txtOffset{0}; // Offset in `m_textures`
|
||||
VkDeviceAddress vertices;
|
||||
VkDeviceAddress indices;
|
||||
VkDeviceAddress materials;
|
||||
VkDeviceAddress materialIndices;
|
||||
};
|
||||
|
||||
// Information pushed at each draw call
|
||||
|
|
@ -106,6 +110,7 @@ public:
|
|||
|
||||
nvvk::Buffer m_cameraMat; // Device-Host of the camera matrices
|
||||
nvvk::Buffer m_sceneDesc; // Device buffer of the OBJ instances
|
||||
|
||||
std::vector<nvvk::Texture> m_textures; // vector of all textures of the scene
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -110,35 +110,26 @@ int main(int argc, char** argv)
|
|||
std::string(PROJECT_NAME),
|
||||
};
|
||||
|
||||
// Vulkan required extensions
|
||||
assert(glfwVulkanSupported() == 1);
|
||||
uint32_t count{0};
|
||||
auto reqExtensions = glfwGetRequiredInstanceExtensions(&count);
|
||||
|
||||
// Requesting Vulkan extensions and layers
|
||||
nvvk::ContextCreateInfo contextInfo(true);
|
||||
contextInfo.setVersion(1, 2);
|
||||
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
|
||||
contextInfo.addInstanceExtension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME, true);
|
||||
contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME);
|
||||
#ifdef _WIN32
|
||||
contextInfo.addInstanceExtension(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
|
||||
#else
|
||||
contextInfo.addInstanceExtension(VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
|
||||
contextInfo.addInstanceExtension(VK_KHR_XCB_SURFACE_EXTENSION_NAME);
|
||||
#endif
|
||||
contextInfo.addInstanceExtension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
|
||||
contextInfo.addDeviceExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
|
||||
contextInfo.addDeviceExtension(VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME);
|
||||
contextInfo.addDeviceExtension(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME);
|
||||
contextInfo.addDeviceExtension(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME);
|
||||
contextInfo.addDeviceExtension(VK_EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME);
|
||||
nvvk::ContextCreateInfo contextInfo;
|
||||
contextInfo.setVersion(1, 2); // Using Vulkan 1.2
|
||||
for(uint32_t ext_id = 0; ext_id < count; ext_id++) // Adding required extensions (surface, win32, linux, ..)
|
||||
contextInfo.addInstanceExtension(reqExtensions[ext_id]);
|
||||
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true); // FPS in titlebar
|
||||
contextInfo.addInstanceExtension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME, true); // Allow debug names
|
||||
contextInfo.addDeviceExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME); // Enabling ability to present rendering
|
||||
|
||||
// #VKRay: Activate the ray tracing extension
|
||||
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);
|
||||
// #VKRay: Activate the ray tracing extension
|
||||
VkPhysicalDeviceAccelerationStructureFeaturesKHR accelFeatures{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR};
|
||||
contextInfo.addDeviceExtension(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME, false, &accelFeatures);
|
||||
VkPhysicalDeviceAccelerationStructureFeaturesKHR accelFeature{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR};
|
||||
contextInfo.addDeviceExtension(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME, false, &accelFeature); // To build acceleration structures
|
||||
VkPhysicalDeviceRayQueryFeaturesKHR rayQueryFeatures{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_QUERY_FEATURES_KHR};
|
||||
contextInfo.addDeviceExtension(VK_KHR_RAY_QUERY_EXTENSION_NAME, false, &rayQueryFeatures);
|
||||
contextInfo.addDeviceExtension(VK_KHR_RAY_QUERY_EXTENSION_NAME, false, &rayQueryFeatures); // Ray tracing in compute shader
|
||||
contextInfo.addDeviceExtension(VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME); // Required by ray tracing pipeline
|
||||
|
||||
// Creating Vulkan base application
|
||||
nvvk::Context vkctx{};
|
||||
|
|
|
|||
|
|
@ -17,17 +17,19 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#version 460
|
||||
#version 450
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
#extension GL_EXT_nonuniform_qualifier : enable
|
||||
#extension GL_GOOGLE_include_directive : enable
|
||||
#extension GL_EXT_scalar_block_layout : enable
|
||||
#extension GL_EXT_ray_tracing : enable
|
||||
#extension GL_EXT_ray_query : enable
|
||||
|
||||
#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require
|
||||
#extension GL_EXT_buffer_reference2 : require
|
||||
|
||||
#include "raycommon.glsl"
|
||||
#include "wavefront.glsl"
|
||||
|
||||
|
||||
layout(push_constant) uniform shaderInformation
|
||||
{
|
||||
vec3 lightPosition;
|
||||
|
|
@ -39,7 +41,6 @@ pushC;
|
|||
|
||||
// clang-format off
|
||||
// Incoming
|
||||
//layout(location = 0) flat in int matIndex;
|
||||
layout(location = 1) in vec2 fragTexCoord;
|
||||
layout(location = 2) in vec3 fragNormal;
|
||||
layout(location = 3) in vec3 viewDir;
|
||||
|
|
@ -47,24 +48,26 @@ layout(location = 4) in vec3 worldPos;
|
|||
// Outgoing
|
||||
layout(location = 0) out vec4 outColor;
|
||||
layout(location = 1) out vec4 outGbuffer;
|
||||
// Buffers
|
||||
layout(binding = 1, scalar) buffer MatColorBufferObject { WaveFrontMaterial m[]; } materials[];
|
||||
layout(binding = 2, scalar) buffer ScnDesc { sceneDesc i[]; } scnDesc;
|
||||
layout(binding = 3) uniform sampler2D[] textureSamplers;
|
||||
layout(binding = 4, scalar) buffer MatIndex { int i[]; } matIdx[];
|
||||
//layout(binding = 7, set = 0) uniform accelerationStructureEXT topLevelAS;
|
||||
|
||||
layout(buffer_reference, scalar) buffer Vertices {Vertex v[]; }; // Positions of an object
|
||||
layout(buffer_reference, scalar) buffer Indices {uint 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 = 1, scalar) buffer SceneDesc_ { SceneDesc i[]; } sceneDesc;
|
||||
layout(binding = 2) uniform sampler2D[] textureSamplers;
|
||||
// clang-format on
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
// Object of this instance
|
||||
int objId = scnDesc.i[pushC.instanceId].objId;
|
||||
|
||||
// Material of the object
|
||||
int matIndex = matIdx[nonuniformEXT(objId)].i[gl_PrimitiveID];
|
||||
WaveFrontMaterial mat = materials[nonuniformEXT(objId)].m[matIndex];
|
||||
SceneDesc objResource = sceneDesc.i[pushC.instanceId];
|
||||
MatIndices matIndices = MatIndices(objResource.materialIndexAddress);
|
||||
Materials materials = Materials(objResource.materialAddress);
|
||||
|
||||
int matIndex = matIndices.i[gl_PrimitiveID];
|
||||
WaveFrontMaterial mat = materials.m[matIndex];
|
||||
|
||||
vec3 N = normalize(fragNormal);
|
||||
|
||||
|
|
@ -92,7 +95,7 @@ void main()
|
|||
diffuse = vec3(1);
|
||||
// if(mat.textureId >= 0)
|
||||
// {
|
||||
// int txtOffset = scnDesc.i[pushC.instanceId].txtOffset;
|
||||
// int txtOffset = sceneDesc.i[pushC.instanceId].txtOffset;
|
||||
// uint txtId = txtOffset + mat.textureId;
|
||||
// vec3 diffuseTxt = texture(textureSamplers[nonuniformEXT(txtId)], fragTexCoord).xyz;
|
||||
// diffuse *= diffuseTxt;
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@
|
|||
*/
|
||||
|
||||
|
||||
|
||||
//-
|
||||
// This utility compresses a normal(x,y,z) to a uint and decompresses it
|
||||
|
||||
|
|
@ -119,8 +118,7 @@ void ComputeDefaultBasis(const vec3 normal, out vec3 x, out vec3 y)
|
|||
// ZAP's default coordinate system for compatibility
|
||||
vec3 z = normal;
|
||||
const float yz = -z.y * z.z;
|
||||
y = normalize(((abs(z.z) > 0.99999f) ? vec3(-z.x * z.y, 1.0f - z.y * z.y, yz) :
|
||||
vec3(-z.x * z.z, yz, 1.0f - z.z * z.z)));
|
||||
y = normalize(((abs(z.z) > 0.99999f) ? vec3(-z.x * z.y, 1.0f - z.y * z.y, yz) : vec3(-z.x * z.z, yz, 1.0f - z.z * z.z)));
|
||||
|
||||
x = cross(y, z);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,10 +22,12 @@
|
|||
#extension GL_EXT_scalar_block_layout : enable
|
||||
#extension GL_GOOGLE_include_directive : enable
|
||||
|
||||
#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require
|
||||
|
||||
#include "wavefront.glsl"
|
||||
|
||||
// clang-format off
|
||||
layout(binding = 2, set = 0, scalar) buffer ScnDesc { sceneDesc i[]; } scnDesc;
|
||||
layout(binding = 1, scalar) buffer SceneDesc_ { SceneDesc i[]; } sceneDesc;
|
||||
// clang-format on
|
||||
|
||||
layout(binding = 0) uniform UniformBufferObject
|
||||
|
|
@ -65,8 +67,8 @@ out gl_PerVertex
|
|||
|
||||
void main()
|
||||
{
|
||||
mat4 objMatrix = scnDesc.i[pushC.instanceId].transfo;
|
||||
mat4 objMatrixIT = scnDesc.i[pushC.instanceId].transfoIT;
|
||||
mat4 objMatrix = sceneDesc.i[pushC.instanceId].transfo;
|
||||
mat4 objMatrixIT = sceneDesc.i[pushC.instanceId].transfoIT;
|
||||
|
||||
vec3 origin = vec3(ubo.viewI * vec4(0, 0, 0, 1));
|
||||
|
||||
|
|
|
|||
|
|
@ -39,12 +39,17 @@ struct WaveFrontMaterial
|
|||
int textureId;
|
||||
};
|
||||
|
||||
struct sceneDesc
|
||||
struct SceneDesc
|
||||
{
|
||||
int objId;
|
||||
int txtOffset;
|
||||
mat4 transfo;
|
||||
mat4 transfoIT;
|
||||
int objId;
|
||||
int txtOffset;
|
||||
|
||||
uint64_t vertexAddress;
|
||||
uint64_t indexAddress;
|
||||
uint64_t materialAddress;
|
||||
uint64_t materialIndexAddress;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ compile_glsl_directory(
|
|||
SRC "${CMAKE_CURRENT_SOURCE_DIR}/shaders"
|
||||
DST "${CMAKE_CURRENT_SOURCE_DIR}/spv"
|
||||
VULKAN_TARGET "vulkan1.2"
|
||||
DEPENDENCY ${VULKAN_BUILD_DEPENDENCIES}
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -52,7 +53,8 @@ target_sources(${PROJNAME} PUBLIC ${GLSL_SOURCES} ${GLSL_HEADERS})
|
|||
source_group("Common" FILES ${COMMON_SOURCE_FILES} ${PACKAGE_SOURCE_FILES})
|
||||
source_group("Sources" FILES ${SOURCE_FILES})
|
||||
source_group("Headers" FILES ${HEADER_FILES})
|
||||
source_group("Shader_Files" FILES ${GLSL_SOURCES} ${GLSL_HEADERS})
|
||||
source_group("Shader Sources" FILES ${GLSL_SOURCES})
|
||||
source_group("Shader Headers" FILES ${GLSL_HEADERS})
|
||||
|
||||
|
||||
#--------------------------------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
#include "nvvk/pipeline_vk.hpp"
|
||||
#include "nvvk/renderpasses_vk.hpp"
|
||||
#include "nvvk/shaders_vk.hpp"
|
||||
#include "nvvk/buffers_vk.hpp"
|
||||
|
||||
extern std::vector<std::string> defaultSearchPaths;
|
||||
|
||||
|
|
@ -113,26 +114,15 @@ void HelloVulkan::updateUniformBuffer(const VkCommandBuffer& cmdBuf)
|
|||
void HelloVulkan::createDescriptorSetLayout()
|
||||
{
|
||||
auto nbTxt = static_cast<uint32_t>(m_textures.size());
|
||||
auto nbObj = static_cast<uint32_t>(m_objModel.size());
|
||||
|
||||
// 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,
|
||||
// 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 = 3)
|
||||
m_descSetLayoutBind.addBinding(3, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, nbTxt,
|
||||
m_descSetLayoutBind.addBinding(2, 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);
|
||||
|
||||
|
||||
m_descSetLayout = m_descSetLayoutBind.createLayout(m_device);
|
||||
|
|
@ -150,25 +140,9 @@ void HelloVulkan::updateDescriptorSet()
|
|||
// Camera matrices and scene description
|
||||
VkDescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE};
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 0, &dbiUnif));
|
||||
VkDescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 2, &dbiSceneDesc));
|
||||
|
||||
// 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()));
|
||||
VkDescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 1, &dbiSceneDesc));
|
||||
|
||||
// All texture samplers
|
||||
std::vector<VkDescriptorImageInfo> diit;
|
||||
|
|
@ -176,7 +150,7 @@ void HelloVulkan::updateDescriptorSet()
|
|||
{
|
||||
diit.emplace_back(texture.descriptor);
|
||||
}
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 3, diit.data()));
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 2, diit.data()));
|
||||
|
||||
// Writing the information
|
||||
vkUpdateDescriptorSets(m_device, static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
||||
|
|
@ -234,12 +208,6 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
|
|||
m.specular = nvmath::pow(m.specular, 2.2f);
|
||||
}
|
||||
|
||||
ObjInstance instance;
|
||||
instance.objIndex = static_cast<uint32_t>(m_objModel.size());
|
||||
instance.transform = transform;
|
||||
instance.transformIT = nvmath::transpose(nvmath::invert(transform));
|
||||
instance.txtOffset = static_cast<uint32_t>(m_textures.size());
|
||||
|
||||
ObjModel model;
|
||||
model.nbIndices = static_cast<uint32_t>(loader.m_indices.size());
|
||||
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
|
||||
|
|
@ -247,23 +215,35 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
|
|||
// Create the buffers on Device and copy vertices, indices and materials
|
||||
nvvk::CommandPool cmdBufGet(m_device, m_graphicsQueueIndex);
|
||||
VkCommandBuffer cmdBuf = cmdBufGet.createCommandBuffer();
|
||||
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);
|
||||
model.matColorBuffer = m_alloc.createBuffer(cmdBuf, loader.m_materials, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
|
||||
model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
|
||||
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);
|
||||
// Creates all textures found
|
||||
uint32_t txtOffset = static_cast<uint32_t>(m_textures.size());
|
||||
createTextureImages(cmdBuf, loader.m_textures);
|
||||
cmdBufGet.submitAndWait(cmdBuf);
|
||||
m_alloc.finalizeAndReleaseStaging();
|
||||
|
||||
std::string objNb = std::to_string(instance.objIndex);
|
||||
std::string objNb = std::to_string(m_objModel.size());
|
||||
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
|
||||
m_debug.setObjectName(model.indexBuffer.buffer, (std::string("index_" + objNb).c_str()));
|
||||
m_debug.setObjectName(model.matColorBuffer.buffer, (std::string("mat_" + objNb).c_str()));
|
||||
m_debug.setObjectName(model.matIndexBuffer.buffer, (std::string("matIdx_" + objNb).c_str()));
|
||||
|
||||
ObjInstance instance;
|
||||
instance.objIndex = static_cast<uint32_t>(m_objModel.size());
|
||||
instance.transform = transform;
|
||||
instance.transformIT = nvmath::transpose(nvmath::invert(transform));
|
||||
instance.txtOffset = txtOffset;
|
||||
instance.vertices = nvvk::getBufferDeviceAddress(m_device, model.vertexBuffer.buffer);
|
||||
instance.indices = nvvk::getBufferDeviceAddress(m_device, model.indexBuffer.buffer);
|
||||
instance.materials = nvvk::getBufferDeviceAddress(m_device, model.matColorBuffer.buffer);
|
||||
instance.materialIndices = nvvk::getBufferDeviceAddress(m_device, model.matIndexBuffer.buffer);
|
||||
|
||||
m_objModel.emplace_back(model);
|
||||
m_objInstance.emplace_back(instance);
|
||||
}
|
||||
|
|
@ -624,11 +604,8 @@ void HelloVulkan::initRayTracing()
|
|||
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;
|
||||
|
||||
|
|
|
|||
|
|
@ -66,10 +66,14 @@ public:
|
|||
// Instance of the OBJ
|
||||
struct ObjInstance
|
||||
{
|
||||
uint32_t objIndex{0}; // Reference to the `m_objModel`
|
||||
uint32_t txtOffset{0}; // Offset in `m_textures`
|
||||
nvmath::mat4f transform{1}; // Position of the instance
|
||||
nvmath::mat4f transformIT{1}; // Inverse transpose
|
||||
uint32_t objIndex{0}; // Reference to the `m_objModel`
|
||||
uint32_t txtOffset{0}; // Offset in `m_textures`
|
||||
VkDeviceAddress vertices;
|
||||
VkDeviceAddress indices;
|
||||
VkDeviceAddress materials;
|
||||
VkDeviceAddress materialIndices;
|
||||
};
|
||||
|
||||
// Information pushed at each draw call
|
||||
|
|
@ -99,6 +103,7 @@ public:
|
|||
|
||||
nvvk::Buffer m_cameraMat; // Device-Host of the camera matrices
|
||||
nvvk::Buffer m_sceneDesc; // Device buffer of the OBJ instances
|
||||
|
||||
std::vector<nvvk::Texture> m_textures; // vector of all textures of the scene
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -104,6 +104,7 @@ int main(int argc, char** argv)
|
|||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||
GLFWwindow* window = glfwCreateWindow(SAMPLE_WIDTH, SAMPLE_HEIGHT, PROJECT_NAME, nullptr, nullptr);
|
||||
|
||||
|
||||
// Setup camera
|
||||
CameraManip.setWindowSize(SAMPLE_WIDTH, SAMPLE_HEIGHT);
|
||||
CameraManip.setLookat(nvmath::vec3f(5, 4, -4), nvmath::vec3f(0, 1, 0), nvmath::vec3f(0, 1, 0));
|
||||
|
|
@ -125,34 +126,26 @@ int main(int argc, char** argv)
|
|||
std::string(PROJECT_NAME),
|
||||
};
|
||||
|
||||
// Vulkan required extensions
|
||||
assert(glfwVulkanSupported() == 1);
|
||||
uint32_t count{0};
|
||||
auto reqExtensions = glfwGetRequiredInstanceExtensions(&count);
|
||||
|
||||
// Requesting Vulkan extensions and layers
|
||||
nvvk::ContextCreateInfo contextInfo(true);
|
||||
contextInfo.setVersion(1, 2);
|
||||
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
|
||||
contextInfo.addInstanceExtension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME, true);
|
||||
contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME);
|
||||
#ifdef _WIN32
|
||||
contextInfo.addInstanceExtension(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
|
||||
#else
|
||||
contextInfo.addInstanceExtension(VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
|
||||
contextInfo.addInstanceExtension(VK_KHR_XCB_SURFACE_EXTENSION_NAME);
|
||||
#endif
|
||||
contextInfo.addInstanceExtension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
|
||||
contextInfo.addDeviceExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
|
||||
contextInfo.addDeviceExtension(VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME);
|
||||
contextInfo.addDeviceExtension(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME);
|
||||
contextInfo.addDeviceExtension(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME);
|
||||
contextInfo.addDeviceExtension(VK_EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME);
|
||||
nvvk::ContextCreateInfo contextInfo;
|
||||
contextInfo.setVersion(1, 2); // Using Vulkan 1.2
|
||||
for(uint32_t ext_id = 0; ext_id < count; ext_id++) // Adding required extensions (surface, win32, linux, ..)
|
||||
contextInfo.addInstanceExtension(reqExtensions[ext_id]);
|
||||
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true); // FPS in titlebar
|
||||
contextInfo.addInstanceExtension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME, true); // Allow debug names
|
||||
contextInfo.addDeviceExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME); // Enabling ability to present rendering
|
||||
|
||||
// #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
|
||||
|
||||
// Creating Vulkan base application
|
||||
nvvk::Context vkctx{};
|
||||
|
|
@ -183,7 +176,6 @@ int main(int argc, char** argv)
|
|||
helloVk.loadModel(nvh::findFile("media/scenes/Medieval_building.obj", defaultSearchPaths, true));
|
||||
helloVk.loadModel(nvh::findFile("media/scenes/plane.obj", defaultSearchPaths, true));
|
||||
|
||||
|
||||
helloVk.createOffscreenRender();
|
||||
helloVk.createDescriptorSetLayout();
|
||||
helloVk.createGraphicsPipeline();
|
||||
|
|
|
|||
|
|
@ -23,6 +23,9 @@
|
|||
#extension GL_GOOGLE_include_directive : enable
|
||||
#extension GL_EXT_scalar_block_layout : enable
|
||||
|
||||
#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require
|
||||
#extension GL_EXT_buffer_reference2 : require
|
||||
|
||||
#include "wavefront.glsl"
|
||||
|
||||
|
||||
|
|
@ -40,37 +43,38 @@ pushC;
|
|||
|
||||
// clang-format off
|
||||
// Incoming
|
||||
//layout(location = 0) flat in int matIndex;
|
||||
layout(location = 1) in vec2 fragTexCoord;
|
||||
layout(location = 2) in vec3 fragNormal;
|
||||
layout(location = 3) in vec3 viewDir;
|
||||
layout(location = 4) in vec3 worldPos;
|
||||
// Outgoing
|
||||
layout(location = 0) out vec4 outColor;
|
||||
// Buffers
|
||||
layout(binding = 1, scalar) buffer MatColorBufferObject { WaveFrontMaterial m[]; } materials[];
|
||||
layout(binding = 2, scalar) buffer ScnDesc { sceneDesc i[]; } scnDesc;
|
||||
layout(binding = 3) uniform sampler2D[] textureSamplers;
|
||||
layout(binding = 4, scalar) buffer MatIndex { int i[]; } matIdx[];
|
||||
|
||||
layout(buffer_reference, scalar) buffer Vertices {Vertex v[]; }; // Positions of an object
|
||||
layout(buffer_reference, scalar) buffer Indices {uint 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 = 1, scalar) buffer SceneDesc_ { SceneDesc i[]; } sceneDesc;
|
||||
layout(binding = 2) uniform sampler2D[] textureSamplers;
|
||||
// clang-format on
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
// Object of this instance
|
||||
int objId = scnDesc.i[pushC.instanceId].objId;
|
||||
|
||||
// Material of the object
|
||||
int matIndex = matIdx[nonuniformEXT(objId)].i[gl_PrimitiveID];
|
||||
WaveFrontMaterial mat = materials[nonuniformEXT(objId)].m[matIndex];
|
||||
SceneDesc objResource = sceneDesc.i[pushC.instanceId];
|
||||
MatIndices matIndices = MatIndices(objResource.materialIndexAddress);
|
||||
Materials materials = Materials(objResource.materialAddress);
|
||||
|
||||
int matIndex = matIndices.i[gl_PrimitiveID];
|
||||
WaveFrontMaterial mat = materials.m[matIndex];
|
||||
|
||||
vec3 N = normalize(fragNormal);
|
||||
|
||||
// Vector toward light
|
||||
vec3 LightDir;
|
||||
float lightIntensity;
|
||||
;
|
||||
|
||||
// Point light
|
||||
if(pushC.lightType == 0)
|
||||
|
|
@ -102,7 +106,7 @@ void main()
|
|||
vec3 diffuse = computeDiffuse(mat, LightDir, N);
|
||||
if(mat.textureId >= 0)
|
||||
{
|
||||
int txtOffset = scnDesc.i[pushC.instanceId].txtOffset;
|
||||
int txtOffset = sceneDesc.i[pushC.instanceId].txtOffset;
|
||||
uint txtId = txtOffset + mat.textureId;
|
||||
vec3 diffuseTxt = texture(textureSamplers[nonuniformEXT(txtId)], fragTexCoord).xyz;
|
||||
diffuse *= diffuseTxt;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,10 @@
|
|||
#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"
|
||||
|
||||
|
|
@ -31,16 +35,13 @@ hitAttributeEXT vec2 attribs;
|
|||
layout(location = 0) rayPayloadInEXT hitPayload prd;
|
||||
layout(location = 1) rayPayloadEXT bool isShadowed;
|
||||
|
||||
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 = 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(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 = 1, set = 1, scalar) buffer SceneDesc_ { SceneDesc i[]; } sceneDesc;
|
||||
layout(binding = 2, set = 1) uniform sampler2D textureSamplers[];
|
||||
// clang-format on
|
||||
|
||||
layout(push_constant) uniform Constants
|
||||
|
|
@ -57,33 +58,35 @@ pushC;
|
|||
|
||||
layout(location = 0) callableDataEXT rayLight cLight;
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
// Object of this instance
|
||||
uint objId = scnDesc.i[gl_InstanceCustomIndexEXT].objId;
|
||||
// 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 = 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]); //
|
||||
ivec3 ind = indices.i[gl_PrimitiveID];
|
||||
|
||||
// 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];
|
||||
Vertex v0 = vertices.v[ind.x];
|
||||
Vertex v1 = vertices.v[ind.y];
|
||||
Vertex v2 = vertices.v[ind.z];
|
||||
|
||||
const vec3 barycentrics = vec3(1.0 - attribs.x - attribs.y, attribs.x, attribs.y);
|
||||
|
||||
// Computing the normal at hit position
|
||||
vec3 normal = v0.nrm * barycentrics.x + v1.nrm * barycentrics.y + v2.nrm * barycentrics.z;
|
||||
// Transforming the normal to world space
|
||||
normal = normalize(vec3(scnDesc.i[gl_InstanceCustomIndexEXT].transfoIT * vec4(normal, 0.0)));
|
||||
normal = normalize(vec3(sceneDesc.i[gl_InstanceCustomIndexEXT].transfoIT * vec4(normal, 0.0)));
|
||||
|
||||
|
||||
// Computing the coordinates of the hit position
|
||||
vec3 worldPos = v0.pos * barycentrics.x + v1.pos * barycentrics.y + v2.pos * barycentrics.z;
|
||||
// Transforming the position to world space
|
||||
worldPos = vec3(scnDesc.i[gl_InstanceCustomIndexEXT].transfo * vec4(worldPos, 1.0));
|
||||
worldPos = vec3(sceneDesc.i[gl_InstanceCustomIndexEXT].transfo * vec4(worldPos, 1.0));
|
||||
|
||||
cLight.inHitPosition = worldPos;
|
||||
//#define DONT_USE_CALLABLE
|
||||
|
|
@ -101,8 +104,7 @@ void main()
|
|||
{
|
||||
vec3 lDir = pushC.lightPosition - cLight.inHitPosition;
|
||||
cLight.outLightDistance = length(lDir);
|
||||
cLight.outIntensity =
|
||||
pushC.lightIntensity / (cLight.outLightDistance * cLight.outLightDistance);
|
||||
cLight.outIntensity = pushC.lightIntensity / (cLight.outLightDistance * cLight.outLightDistance);
|
||||
cLight.outLightDir = normalize(lDir);
|
||||
float theta = dot(cLight.outLightDir, normalize(-pushC.lightDirection));
|
||||
float epsilon = pushC.lightSpotCutoff - pushC.lightSpotOuterCutoff;
|
||||
|
|
@ -120,17 +122,16 @@ void main()
|
|||
#endif
|
||||
|
||||
// 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];
|
||||
|
||||
|
||||
// Diffuse
|
||||
vec3 diffuse = computeDiffuse(mat, cLight.outLightDir, normal);
|
||||
if(mat.textureId >= 0)
|
||||
{
|
||||
uint txtId = mat.textureId + scnDesc.i[gl_InstanceCustomIndexEXT].txtOffset;
|
||||
vec2 texCoord =
|
||||
v0.texCoord * barycentrics.x + v1.texCoord * barycentrics.y + v2.texCoord * barycentrics.z;
|
||||
uint txtId = mat.textureId + sceneDesc.i[gl_InstanceCustomIndexEXT].txtOffset;
|
||||
vec2 texCoord = v0.texCoord * barycentrics.x + v1.texCoord * barycentrics.y + v2.texCoord * barycentrics.z;
|
||||
diffuse *= texture(textureSamplers[nonuniformEXT(txtId)], texCoord).xyz;
|
||||
}
|
||||
|
||||
|
|
@ -144,8 +145,7 @@ void main()
|
|||
float tMax = cLight.outLightDistance;
|
||||
vec3 origin = gl_WorldRayOriginEXT + gl_WorldRayDirectionEXT * gl_HitTEXT;
|
||||
vec3 rayDir = cLight.outLightDir;
|
||||
uint flags = gl_RayFlagsTerminateOnFirstHitEXT | gl_RayFlagsOpaqueEXT
|
||||
| gl_RayFlagsSkipClosestHitShaderEXT;
|
||||
uint flags = gl_RayFlagsTerminateOnFirstHitEXT | gl_RayFlagsOpaqueEXT | gl_RayFlagsSkipClosestHitShaderEXT;
|
||||
isShadowed = true;
|
||||
traceRayEXT(topLevelAS, // acceleration structure
|
||||
flags, // rayFlags
|
||||
|
|
|
|||
|
|
@ -22,10 +22,12 @@
|
|||
#extension GL_EXT_scalar_block_layout : enable
|
||||
#extension GL_GOOGLE_include_directive : enable
|
||||
|
||||
#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require
|
||||
|
||||
#include "wavefront.glsl"
|
||||
|
||||
// clang-format off
|
||||
layout(binding = 2, set = 0, scalar) buffer ScnDesc { sceneDesc i[]; } scnDesc;
|
||||
layout(binding = 1, scalar) buffer SceneDesc_ { SceneDesc i[]; } sceneDesc;
|
||||
// clang-format on
|
||||
|
||||
layout(binding = 0) uniform UniformBufferObject
|
||||
|
|
@ -68,8 +70,8 @@ out gl_PerVertex
|
|||
|
||||
void main()
|
||||
{
|
||||
mat4 objMatrix = scnDesc.i[pushC.instanceId].transfo;
|
||||
mat4 objMatrixIT = scnDesc.i[pushC.instanceId].transfoIT;
|
||||
mat4 objMatrix = sceneDesc.i[pushC.instanceId].transfo;
|
||||
mat4 objMatrixIT = sceneDesc.i[pushC.instanceId].transfoIT;
|
||||
|
||||
vec3 origin = vec3(ubo.viewI * vec4(0, 0, 0, 1));
|
||||
|
||||
|
|
|
|||
|
|
@ -39,12 +39,16 @@ struct WaveFrontMaterial
|
|||
int textureId;
|
||||
};
|
||||
|
||||
struct sceneDesc
|
||||
struct SceneDesc
|
||||
{
|
||||
int objId;
|
||||
int txtOffset;
|
||||
mat4 transfo;
|
||||
mat4 transfoIT;
|
||||
int objId;
|
||||
int txtOffset;
|
||||
uint64_t vertexAddress;
|
||||
uint64_t indexAddress;
|
||||
uint64_t materialAddress;
|
||||
uint64_t materialIndexAddress;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ compile_glsl_directory(
|
|||
SRC "${CMAKE_CURRENT_SOURCE_DIR}/shaders"
|
||||
DST "${CMAKE_CURRENT_SOURCE_DIR}/spv"
|
||||
VULKAN_TARGET "vulkan1.2"
|
||||
DEPENDENCY ${VULKAN_BUILD_DEPENDENCIES}
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -52,7 +53,8 @@ target_sources(${PROJNAME} PUBLIC ${GLSL_SOURCES} ${GLSL_HEADERS})
|
|||
source_group("Common" FILES ${COMMON_SOURCE_FILES} ${PACKAGE_SOURCE_FILES})
|
||||
source_group("Sources" FILES ${SOURCE_FILES})
|
||||
source_group("Headers" FILES ${HEADER_FILES})
|
||||
source_group("Shader_Files" FILES ${GLSL_SOURCES} ${GLSL_HEADERS})
|
||||
source_group("Shader Sources" FILES ${GLSL_SOURCES})
|
||||
source_group("Shader Headers" FILES ${GLSL_HEADERS})
|
||||
|
||||
|
||||
#--------------------------------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -65,6 +65,22 @@ But instead, we will use this following structure to retrieve the information of
|
|||
nvvk::Buffer m_materialBuffer;
|
||||
nvvk::Buffer m_matrixBuffer;
|
||||
nvvk::Buffer m_rtPrimLookup;
|
||||
nvvk::Buffer m_sceneDesc;
|
||||
~~~~
|
||||
|
||||
And a structure to retrieve all buffers of the scene
|
||||
|
||||
~~~~ C++
|
||||
struct SceneDescription
|
||||
{
|
||||
uint64_t vertexAddress;
|
||||
uint64_t normalAddress;
|
||||
uint64_t uvAddress;
|
||||
uint64_t indexAddress;
|
||||
uint64_t materialAddress;
|
||||
uint64_t matrixAddress;
|
||||
uint64_t rtPrimAddress;
|
||||
};
|
||||
~~~~
|
||||
|
||||
## Loading glTF scene
|
||||
|
|
@ -98,27 +114,50 @@ Then we will flatten the scene graph and grab the information we will need using
|
|||
The next part is to allocate the buffers to hold the information, such as the positions, normals, texture coordinates, etc.
|
||||
|
||||
~~~~C
|
||||
m_vertexBuffer =
|
||||
m_alloc.createBuffer(cmdBuf, m_gltfScene.m_positions,
|
||||
vkBU::eVertexBuffer | vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress);
|
||||
m_indexBuffer =
|
||||
m_alloc.createBuffer(cmdBuf, m_gltfScene.m_indices,
|
||||
vkBU::eIndexBuffer | vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress);
|
||||
// Create the buffers on Device and copy vertices, indices and materials
|
||||
nvvk::CommandPool cmdBufGet(m_device, m_graphicsQueueIndex);
|
||||
VkCommandBuffer cmdBuf = cmdBufGet.createCommandBuffer();
|
||||
|
||||
m_vertexBuffer = m_alloc.createBuffer(cmdBuf, m_gltfScene.m_positions,
|
||||
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT
|
||||
| VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR);
|
||||
m_indexBuffer = m_alloc.createBuffer(cmdBuf, m_gltfScene.m_indices,
|
||||
VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT
|
||||
| VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR);
|
||||
m_normalBuffer = m_alloc.createBuffer(cmdBuf, m_gltfScene.m_normals,
|
||||
vkBU::eVertexBuffer | vkBU::eStorageBuffer);
|
||||
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
|
||||
| VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
|
||||
m_uvBuffer = m_alloc.createBuffer(cmdBuf, m_gltfScene.m_texcoords0,
|
||||
vkBU::eVertexBuffer | vkBU::eStorageBuffer);
|
||||
m_materialBuffer = m_alloc.createBuffer(cmdBuf, m_gltfScene.m_materials, vkBU::eStorageBuffer);
|
||||
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
|
||||
| VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
|
||||
~~~~
|
||||
|
||||
We are making a simple material, extracting only a few members from the glTF material.
|
||||
|
||||
~~~~ C++
|
||||
// Copying all materials, only the elements we need
|
||||
std::vector<GltfShadeMaterial> shadeMaterials;
|
||||
for(auto& m : m_gltfScene.m_materials)
|
||||
{
|
||||
shadeMaterials.emplace_back(GltfShadeMaterial{m.baseColorFactor, m.emissiveFactor, m.baseColorTexture});
|
||||
}
|
||||
m_materialBuffer = m_alloc.createBuffer(cmdBuf, shadeMaterials,
|
||||
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
|
||||
~~~~
|
||||
|
||||
|
||||
We could use `push_constant` to set the matrix of the node, but instead, we will push the index of the
|
||||
node to draw and fetch the matrix from a buffer.
|
||||
|
||||
~~~~C
|
||||
// Instance Matrices used by rasterizer
|
||||
std::vector<nvmath::mat4f> nodeMatrices;
|
||||
for(auto& node : m_gltfScene.m_nodes)
|
||||
{
|
||||
nodeMatrices.emplace_back(node.worldMatrix);
|
||||
m_matrixBuffer = m_alloc.createBuffer(cmdBuf, nodeMatrices, vkBU::eStorageBuffer);
|
||||
}
|
||||
m_matrixBuffer = m_alloc.createBuffer(cmdBuf, nodeMatrices,
|
||||
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
|
||||
~~~~
|
||||
|
||||
To find the positions of the triangle hit in the closest hit shader, as well as the other
|
||||
|
|
@ -131,9 +170,47 @@ attributes, we will store the offsets information of that geometry.
|
|||
{
|
||||
primLookup.push_back({primMesh.firstIndex, primMesh.vertexOffset, primMesh.materialIndex});
|
||||
}
|
||||
m_rtPrimLookup = m_alloc.createBuffer(cmdBuf, primLookup, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
|
||||
m_rtPrimLookup =
|
||||
m_alloc.createBuffer(cmdBuf, primLookup, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
|
||||
~~~~
|
||||
|
||||
Finally, we are creating a buffer holding the address of all buffers
|
||||
|
||||
~~~~ C++
|
||||
SceneDescription sceneDesc;
|
||||
sceneDesc.vertexAddress = nvvk::getBufferDeviceAddress(m_device, m_vertexBuffer.buffer);
|
||||
sceneDesc.indexAddress = nvvk::getBufferDeviceAddress(m_device, m_indexBuffer.buffer);
|
||||
sceneDesc.normalAddress = nvvk::getBufferDeviceAddress(m_device, m_normalBuffer.buffer);
|
||||
sceneDesc.uvAddress = nvvk::getBufferDeviceAddress(m_device, m_uvBuffer.buffer);
|
||||
sceneDesc.materialAddress = nvvk::getBufferDeviceAddress(m_device, m_materialBuffer.buffer);
|
||||
sceneDesc.matrixAddress = nvvk::getBufferDeviceAddress(m_device, m_matrixBuffer.buffer);
|
||||
sceneDesc.rtPrimAddress = nvvk::getBufferDeviceAddress(m_device, m_rtPrimLookup.buffer);
|
||||
m_sceneDesc = m_alloc.createBuffer(cmdBuf, sizeof(SceneDescription), &sceneDesc,
|
||||
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
|
||||
~~~~
|
||||
|
||||
Before closing the function, we will create textures (none in default scene) and submitting the command buffer.
|
||||
The finalize and releasing staging is waiting for the copy of all data to the GPU.
|
||||
|
||||
~~~~ C
|
||||
// Creates all textures found
|
||||
createTextureImages(cmdBuf, tmodel);
|
||||
cmdBufGet.submitAndWait(cmdBuf);
|
||||
m_alloc.finalizeAndReleaseStaging();
|
||||
|
||||
|
||||
NAME_VK(m_vertexBuffer.buffer);
|
||||
NAME_VK(m_indexBuffer.buffer);
|
||||
NAME_VK(m_normalBuffer.buffer);
|
||||
NAME_VK(m_uvBuffer.buffer);
|
||||
NAME_VK(m_materialBuffer.buffer);
|
||||
NAME_VK(m_matrixBuffer.buffer);
|
||||
NAME_VK(m_rtPrimLookup.buffer);
|
||||
NAME_VK(m_sceneDesc.buffer);
|
||||
}
|
||||
~~~~
|
||||
|
||||
**NOTE**: the macro `NAME_VK` is a convenience to name Vulkan object to easily identify them in Nsight Graphics and to know where it was created.
|
||||
|
||||
## Converting geometry to BLAS
|
||||
|
||||
|
|
@ -147,11 +224,8 @@ The function is similar, only the input is different.
|
|||
auto HelloVulkan::primitiveToGeometry(const nvh::GltfPrimMesh& prim)
|
||||
{
|
||||
// BLAS builder requires raw device addresses.
|
||||
VkBufferDeviceAddressInfo info{VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO};
|
||||
info.buffer = m_vertexBuffer.buffer;
|
||||
VkDeviceAddress vertexAddress = vkGetBufferDeviceAddress(m_device, &info);
|
||||
info.buffer = m_indexBuffer.buffer;
|
||||
VkDeviceAddress indexAddress = vkGetBufferDeviceAddress(m_device, &info);
|
||||
VkDeviceAddress vertexAddress = nvvk::getBufferDeviceAddress(m_device, m_vertexBuffer.buffer);
|
||||
VkDeviceAddress indexAddress = nvvk::getBufferDeviceAddress(m_device, m_indexBuffer.buffer);
|
||||
|
||||
uint32_t maxPrimitiveCount = prim.indexCount / 3;
|
||||
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@
|
|||
#include "nvh/alignment.hpp"
|
||||
#include "shaders/binding.glsl"
|
||||
#include "shaders/gltf.glsl"
|
||||
#include "nvvk/buffers_vk.hpp"
|
||||
|
||||
extern std::vector<std::string> defaultSearchPaths;
|
||||
|
||||
|
|
@ -120,18 +121,14 @@ void HelloVulkan::createDescriptorSetLayout()
|
|||
auto& bind = m_descSetLayoutBind;
|
||||
// Camera matrices (binding = 0)
|
||||
bind.addBinding(B_CAMERA, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_RAYGEN_BIT_KHR);
|
||||
bind.addBinding(B_VERTICES, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_ANY_HIT_BIT_KHR);
|
||||
bind.addBinding(B_INDICES, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_ANY_HIT_BIT_KHR);
|
||||
bind.addBinding(B_NORMALS, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR);
|
||||
bind.addBinding(B_TEXCOORDS, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR);
|
||||
bind.addBinding(B_MATERIALS, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1,
|
||||
VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_ANY_HIT_BIT_KHR);
|
||||
bind.addBinding(B_MATRICES, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1,
|
||||
VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_ANY_HIT_BIT_KHR);
|
||||
auto nbTextures = static_cast<uint32_t>(m_textures.size());
|
||||
bind.addBinding(B_TEXTURES, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, nbTextures,
|
||||
VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR | VK_SHADER_STAGE_ANY_HIT_BIT_KHR);
|
||||
|
||||
bind.addBinding(B_SCENEDESC, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1,
|
||||
VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR
|
||||
| VK_SHADER_STAGE_ANY_HIT_BIT_KHR);
|
||||
|
||||
m_descSetLayout = m_descSetLayoutBind.createLayout(m_device);
|
||||
m_descPool = m_descSetLayoutBind.createPool(m_device, 1);
|
||||
m_descSet = nvvk::allocateDescriptorSet(m_device, m_descPool, m_descSetLayout);
|
||||
|
|
@ -146,20 +143,10 @@ void HelloVulkan::updateDescriptorSet()
|
|||
|
||||
// Camera matrices and scene description
|
||||
VkDescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE};
|
||||
VkDescriptorBufferInfo vertexDesc{m_vertexBuffer.buffer, 0, VK_WHOLE_SIZE};
|
||||
VkDescriptorBufferInfo indexDesc{m_indexBuffer.buffer, 0, VK_WHOLE_SIZE};
|
||||
VkDescriptorBufferInfo normalDesc{m_normalBuffer.buffer, 0, VK_WHOLE_SIZE};
|
||||
VkDescriptorBufferInfo uvDesc{m_uvBuffer.buffer, 0, VK_WHOLE_SIZE};
|
||||
VkDescriptorBufferInfo materialDesc{m_materialBuffer.buffer, 0, VK_WHOLE_SIZE};
|
||||
VkDescriptorBufferInfo matrixDesc{m_matrixBuffer.buffer, 0, VK_WHOLE_SIZE};
|
||||
VkDescriptorBufferInfo sceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
|
||||
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, B_CAMERA, &dbiUnif));
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, B_VERTICES, &vertexDesc));
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, B_INDICES, &indexDesc));
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, B_NORMALS, &normalDesc));
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, B_TEXCOORDS, &uvDesc));
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, B_MATERIALS, &materialDesc));
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, B_MATRICES, &matrixDesc));
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, B_SCENEDESC, &sceneDesc));
|
||||
|
||||
// All texture samplers
|
||||
std::vector<VkDescriptorImageInfo> diit;
|
||||
|
|
@ -237,17 +224,20 @@ void HelloVulkan::loadScene(const std::string& filename)
|
|||
VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT
|
||||
| VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR);
|
||||
m_normalBuffer = m_alloc.createBuffer(cmdBuf, m_gltfScene.m_normals,
|
||||
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
|
||||
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
|
||||
| VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
|
||||
m_uvBuffer = m_alloc.createBuffer(cmdBuf, m_gltfScene.m_texcoords0,
|
||||
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
|
||||
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
|
||||
| VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
|
||||
|
||||
// Copying all materials, only the elements we need
|
||||
std::vector<GltfShadeMaterial> shadeMaterials;
|
||||
for(auto& m : m_gltfScene.m_materials)
|
||||
{
|
||||
shadeMaterials.emplace_back(GltfShadeMaterial{m.baseColorFactor, m.baseColorTexture, m.emissiveFactor});
|
||||
shadeMaterials.emplace_back(GltfShadeMaterial{m.baseColorFactor, m.emissiveFactor, m.baseColorTexture});
|
||||
}
|
||||
m_materialBuffer = m_alloc.createBuffer(cmdBuf, shadeMaterials, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
|
||||
m_materialBuffer = m_alloc.createBuffer(cmdBuf, shadeMaterials,
|
||||
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
|
||||
|
||||
// Instance Matrices used by rasterizer
|
||||
std::vector<nvmath::mat4f> nodeMatrices;
|
||||
|
|
@ -255,7 +245,8 @@ void HelloVulkan::loadScene(const std::string& filename)
|
|||
{
|
||||
nodeMatrices.emplace_back(node.worldMatrix);
|
||||
}
|
||||
m_matrixBuffer = m_alloc.createBuffer(cmdBuf, nodeMatrices, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
|
||||
m_matrixBuffer = m_alloc.createBuffer(cmdBuf, nodeMatrices,
|
||||
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
|
||||
|
||||
// The following is used to find the primitive mesh information in the CHIT
|
||||
std::vector<RtPrimitiveLookup> primLookup;
|
||||
|
|
@ -263,20 +254,35 @@ void HelloVulkan::loadScene(const std::string& filename)
|
|||
{
|
||||
primLookup.push_back({primMesh.firstIndex, primMesh.vertexOffset, primMesh.materialIndex});
|
||||
}
|
||||
m_rtPrimLookup = m_alloc.createBuffer(cmdBuf, primLookup, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
|
||||
m_rtPrimLookup =
|
||||
m_alloc.createBuffer(cmdBuf, primLookup, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
|
||||
|
||||
|
||||
SceneDescription sceneDesc;
|
||||
sceneDesc.vertexAddress = nvvk::getBufferDeviceAddress(m_device, m_vertexBuffer.buffer);
|
||||
sceneDesc.indexAddress = nvvk::getBufferDeviceAddress(m_device, m_indexBuffer.buffer);
|
||||
sceneDesc.normalAddress = nvvk::getBufferDeviceAddress(m_device, m_normalBuffer.buffer);
|
||||
sceneDesc.uvAddress = nvvk::getBufferDeviceAddress(m_device, m_uvBuffer.buffer);
|
||||
sceneDesc.materialAddress = nvvk::getBufferDeviceAddress(m_device, m_materialBuffer.buffer);
|
||||
sceneDesc.matrixAddress = nvvk::getBufferDeviceAddress(m_device, m_matrixBuffer.buffer);
|
||||
sceneDesc.rtPrimAddress = nvvk::getBufferDeviceAddress(m_device, m_rtPrimLookup.buffer);
|
||||
m_sceneDesc = m_alloc.createBuffer(cmdBuf, sizeof(SceneDescription), &sceneDesc,
|
||||
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
|
||||
|
||||
// Creates all textures found
|
||||
createTextureImages(cmdBuf, tmodel);
|
||||
cmdBufGet.submitAndWait(cmdBuf);
|
||||
m_alloc.finalizeAndReleaseStaging();
|
||||
|
||||
m_debug.setObjectName(m_vertexBuffer.buffer, "Vertex");
|
||||
m_debug.setObjectName(m_indexBuffer.buffer, "Index");
|
||||
m_debug.setObjectName(m_normalBuffer.buffer, "Normal");
|
||||
m_debug.setObjectName(m_uvBuffer.buffer, "TexCoord");
|
||||
m_debug.setObjectName(m_materialBuffer.buffer, "Material");
|
||||
m_debug.setObjectName(m_matrixBuffer.buffer, "Matrix");
|
||||
|
||||
NAME_VK(m_vertexBuffer.buffer);
|
||||
NAME_VK(m_indexBuffer.buffer);
|
||||
NAME_VK(m_normalBuffer.buffer);
|
||||
NAME_VK(m_uvBuffer.buffer);
|
||||
NAME_VK(m_materialBuffer.buffer);
|
||||
NAME_VK(m_matrixBuffer.buffer);
|
||||
NAME_VK(m_rtPrimLookup.buffer);
|
||||
NAME_VK(m_sceneDesc.buffer);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -364,6 +370,7 @@ void HelloVulkan::destroyResources()
|
|||
m_alloc.destroy(m_materialBuffer);
|
||||
m_alloc.destroy(m_matrixBuffer);
|
||||
m_alloc.destroy(m_rtPrimLookup);
|
||||
m_alloc.destroy(m_sceneDesc);
|
||||
|
||||
for(auto& t : m_textures)
|
||||
{
|
||||
|
|
@ -606,11 +613,8 @@ void HelloVulkan::initRayTracing()
|
|||
auto HelloVulkan::primitiveToGeometry(const nvh::GltfPrimMesh& prim)
|
||||
{
|
||||
// BLAS builder requires raw device addresses.
|
||||
VkBufferDeviceAddressInfo info{VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO};
|
||||
info.buffer = m_vertexBuffer.buffer;
|
||||
VkDeviceAddress vertexAddress = vkGetBufferDeviceAddress(m_device, &info);
|
||||
info.buffer = m_indexBuffer.buffer;
|
||||
VkDeviceAddress indexAddress = vkGetBufferDeviceAddress(m_device, &info);
|
||||
VkDeviceAddress vertexAddress = nvvk::getBufferDeviceAddress(m_device, m_vertexBuffer.buffer);
|
||||
VkDeviceAddress indexAddress = nvvk::getBufferDeviceAddress(m_device, m_indexBuffer.buffer);
|
||||
|
||||
uint32_t maxPrimitiveCount = prim.indexCount / 3;
|
||||
|
||||
|
|
|
|||
|
|
@ -61,6 +61,16 @@ public:
|
|||
int materialIndex;
|
||||
};
|
||||
|
||||
struct SceneDescription
|
||||
{
|
||||
uint64_t vertexAddress;
|
||||
uint64_t normalAddress;
|
||||
uint64_t uvAddress;
|
||||
uint64_t indexAddress;
|
||||
uint64_t materialAddress;
|
||||
uint64_t matrixAddress;
|
||||
uint64_t rtPrimAddress;
|
||||
};
|
||||
|
||||
nvh::GltfScene m_gltfScene;
|
||||
nvvk::Buffer m_vertexBuffer;
|
||||
|
|
@ -70,6 +80,7 @@ public:
|
|||
nvvk::Buffer m_materialBuffer;
|
||||
nvvk::Buffer m_matrixBuffer;
|
||||
nvvk::Buffer m_rtPrimLookup;
|
||||
nvvk::Buffer m_sceneDesc;
|
||||
|
||||
// Information pushed at each draw call
|
||||
struct ObjPushConstant
|
||||
|
|
|
|||
|
|
@ -19,10 +19,5 @@
|
|||
|
||||
|
||||
#define B_CAMERA 0
|
||||
#define B_VERTICES 1
|
||||
#define B_NORMALS 2
|
||||
#define B_TEXCOORDS 3
|
||||
#define B_INDICES 4
|
||||
#define B_MATERIALS 5
|
||||
#define B_MATRICES 6
|
||||
#define B_TEXTURES 7
|
||||
#define B_SCENEDESC 1
|
||||
#define B_TEXTURES 2
|
||||
|
|
|
|||
|
|
@ -23,6 +23,9 @@
|
|||
#extension GL_GOOGLE_include_directive : enable
|
||||
#extension GL_EXT_scalar_block_layout : enable
|
||||
|
||||
#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require
|
||||
#extension GL_EXT_buffer_reference2 : require
|
||||
|
||||
#include "binding.glsl"
|
||||
#include "gltf.glsl"
|
||||
|
||||
|
|
@ -39,7 +42,6 @@ pushC;
|
|||
|
||||
// clang-format off
|
||||
// Incoming
|
||||
//layout(location = 0) flat in int matIndex;
|
||||
layout(location = 1) in vec2 fragTexCoord;
|
||||
layout(location = 2) in vec3 fragNormal;
|
||||
layout(location = 3) in vec3 viewDir;
|
||||
|
|
@ -47,16 +49,19 @@ layout(location = 4) in vec3 worldPos;
|
|||
// Outgoing
|
||||
layout(location = 0) out vec4 outColor;
|
||||
// Buffers
|
||||
layout(set = 0, binding = B_MATERIALS) buffer _GltfMaterial { GltfShadeMaterial materials[]; };
|
||||
layout(set = 0, binding = B_TEXTURES) uniform sampler2D[] textureSamplers;
|
||||
|
||||
layout(buffer_reference, scalar) buffer Matrices { mat4 m[]; };
|
||||
layout(buffer_reference, scalar) buffer GltfMaterial { GltfShadeMaterial m[]; };
|
||||
layout(set = 0, binding = B_SCENEDESC ) readonly buffer SceneDesc_ { SceneDesc sceneDesc; } ;
|
||||
layout(set = 0, binding = B_TEXTURES) uniform sampler2D[] textureSamplers;
|
||||
// clang-format on
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
// Material of the object
|
||||
GltfShadeMaterial mat = materials[nonuniformEXT(pushC.matetrialId)];
|
||||
GltfMaterial gltfMat = GltfMaterial(sceneDesc.materialAddress);
|
||||
GltfShadeMaterial mat = gltfMat.m[pushC.matetrialId];
|
||||
|
||||
vec3 N = normalize(fragNormal);
|
||||
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@
|
|||
struct GltfShadeMaterial
|
||||
{
|
||||
vec4 pbrBaseColorFactor;
|
||||
int pbrBaseColorTexture;
|
||||
vec3 emissiveFactor;
|
||||
int pbrBaseColorTexture;
|
||||
};
|
||||
|
||||
#ifndef __cplusplus
|
||||
|
|
@ -32,6 +32,17 @@ struct PrimMeshInfo
|
|||
int materialIndex;
|
||||
};
|
||||
|
||||
struct SceneDesc
|
||||
{
|
||||
uint64_t vertexAddress;
|
||||
uint64_t normalAddress;
|
||||
uint64_t uvAddress;
|
||||
uint64_t indexAddress;
|
||||
uint64_t materialAddress;
|
||||
uint64_t matrixAddress;
|
||||
uint64_t rtPrimAddress;
|
||||
};
|
||||
|
||||
|
||||
vec3 computeDiffuse(GltfShadeMaterial mat, vec3 lightDir, vec3 normal)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -23,6 +23,10 @@
|
|||
#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 "binding.glsl"
|
||||
#include "gltf.glsl"
|
||||
#include "raycommon.glsl"
|
||||
|
|
@ -38,13 +42,15 @@ layout(location = 1) rayPayloadEXT bool isShadowed;
|
|||
layout(set = 0, binding = 0 ) uniform accelerationStructureEXT topLevelAS;
|
||||
layout(set = 0, binding = 2) readonly buffer _InstanceInfo {PrimMeshInfo primInfo[];};
|
||||
|
||||
layout(set = 1, binding = B_VERTICES) readonly buffer _VertexBuf {float vertices[];};
|
||||
layout(set = 1, binding = B_INDICES) readonly buffer _Indices {uint indices[];};
|
||||
layout(set = 1, binding = B_NORMALS) readonly buffer _NormalBuf {float normals[];};
|
||||
layout(set = 1, binding = B_TEXCOORDS) readonly buffer _TexCoordBuf {float texcoord0[];};
|
||||
layout(set = 1, binding = B_MATERIALS) readonly buffer _MaterialBuffer {GltfShadeMaterial materials[];};
|
||||
layout(set = 1, binding = B_TEXTURES) uniform sampler2D texturesMap[]; // all textures
|
||||
|
||||
layout(buffer_reference, scalar) readonly buffer Vertices { vec3 v[]; };
|
||||
layout(buffer_reference, scalar) readonly buffer Indices { ivec3 i[]; };
|
||||
layout(buffer_reference, scalar) readonly buffer Normals { vec3 n[]; };
|
||||
layout(buffer_reference, scalar) readonly buffer TexCoords { vec2 t[]; };
|
||||
layout(buffer_reference, scalar) readonly buffer Materials { GltfShadeMaterial m[]; };
|
||||
|
||||
layout(set = 1, binding = B_SCENEDESC ) readonly buffer SceneDesc_ { SceneDesc sceneDesc; };
|
||||
layout(set = 1, binding = B_TEXTURES) uniform sampler2D texturesMap[]; // all textures
|
||||
|
||||
// clang-format on
|
||||
|
||||
|
|
@ -57,33 +63,6 @@ layout(push_constant) uniform Constants
|
|||
}
|
||||
pushC;
|
||||
|
||||
// Return the vertex position
|
||||
vec3 getVertex(uint index)
|
||||
{
|
||||
vec3 vp;
|
||||
vp.x = vertices[3 * index + 0];
|
||||
vp.y = vertices[3 * index + 1];
|
||||
vp.z = vertices[3 * index + 2];
|
||||
return vp;
|
||||
}
|
||||
|
||||
vec3 getNormal(uint index)
|
||||
{
|
||||
vec3 vp;
|
||||
vp.x = normals[3 * index + 0];
|
||||
vp.y = normals[3 * index + 1];
|
||||
vp.z = normals[3 * index + 2];
|
||||
return vp;
|
||||
}
|
||||
|
||||
vec2 getTexCoord(uint index)
|
||||
{
|
||||
vec2 vp;
|
||||
vp.x = texcoord0[2 * index + 0];
|
||||
vp.y = texcoord0[2 * index + 1];
|
||||
return vp;
|
||||
}
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
|
|
@ -91,42 +70,47 @@ void main()
|
|||
PrimMeshInfo pinfo = primInfo[gl_InstanceCustomIndexEXT];
|
||||
|
||||
// Getting the 'first index' for this mesh (offset of the mesh + offset of the triangle)
|
||||
uint indexOffset = pinfo.indexOffset + (3 * gl_PrimitiveID);
|
||||
uint indexOffset = (pinfo.indexOffset / 3) + gl_PrimitiveID;
|
||||
uint vertexOffset = pinfo.vertexOffset; // Vertex offset as defined in glTF
|
||||
uint matIndex = max(0, pinfo.materialIndex); // material of primitive mesh
|
||||
|
||||
Materials gltfMat = Materials(sceneDesc.materialAddress);
|
||||
Vertices vertices = Vertices(sceneDesc.vertexAddress);
|
||||
Indices indices = Indices(sceneDesc.indexAddress);
|
||||
Normals normals = Normals(sceneDesc.normalAddress);
|
||||
TexCoords texCoords = TexCoords(sceneDesc.uvAddress);
|
||||
Materials materials = Materials(sceneDesc.materialAddress);
|
||||
|
||||
// Getting the 3 indices of the triangle (local)
|
||||
ivec3 triangleIndex = ivec3(indices[nonuniformEXT(indexOffset + 0)], //
|
||||
indices[nonuniformEXT(indexOffset + 1)], //
|
||||
indices[nonuniformEXT(indexOffset + 2)]);
|
||||
ivec3 triangleIndex = indices.i[indexOffset];
|
||||
triangleIndex += ivec3(vertexOffset); // (global)
|
||||
|
||||
const vec3 barycentrics = vec3(1.0 - attribs.x - attribs.y, attribs.x, attribs.y);
|
||||
|
||||
// Vertex of the triangle
|
||||
const vec3 pos0 = getVertex(triangleIndex.x);
|
||||
const vec3 pos1 = getVertex(triangleIndex.y);
|
||||
const vec3 pos2 = getVertex(triangleIndex.z);
|
||||
const vec3 pos0 = vertices.v[triangleIndex.x];
|
||||
const vec3 pos1 = vertices.v[triangleIndex.y];
|
||||
const vec3 pos2 = vertices.v[triangleIndex.z];
|
||||
const vec3 position = pos0 * barycentrics.x + pos1 * barycentrics.y + pos2 * barycentrics.z;
|
||||
const vec3 world_position = vec3(gl_ObjectToWorldEXT * vec4(position, 1.0));
|
||||
|
||||
// Normal
|
||||
const vec3 nrm0 = getNormal(triangleIndex.x);
|
||||
const vec3 nrm1 = getNormal(triangleIndex.y);
|
||||
const vec3 nrm2 = getNormal(triangleIndex.z);
|
||||
const vec3 nrm0 = normals.n[triangleIndex.x];
|
||||
const vec3 nrm1 = normals.n[triangleIndex.y];
|
||||
const vec3 nrm2 = normals.n[triangleIndex.z];
|
||||
vec3 normal = normalize(nrm0 * barycentrics.x + nrm1 * barycentrics.y + nrm2 * barycentrics.z);
|
||||
const vec3 world_normal = normalize(vec3(normal * gl_WorldToObjectEXT));
|
||||
const vec3 geom_normal = normalize(cross(pos1 - pos0, pos2 - pos0));
|
||||
|
||||
// TexCoord
|
||||
const vec2 uv0 = getTexCoord(triangleIndex.x);
|
||||
const vec2 uv1 = getTexCoord(triangleIndex.y);
|
||||
const vec2 uv2 = getTexCoord(triangleIndex.z);
|
||||
const vec2 uv0 = texCoords.t[triangleIndex.x];
|
||||
const vec2 uv1 = texCoords.t[triangleIndex.y];
|
||||
const vec2 uv2 = texCoords.t[triangleIndex.z];
|
||||
const vec2 texcoord0 = uv0 * barycentrics.x + uv1 * barycentrics.y + uv2 * barycentrics.z;
|
||||
|
||||
// https://en.wikipedia.org/wiki/Path_tracing
|
||||
// Material of the object
|
||||
GltfShadeMaterial mat = materials[nonuniformEXT(matIndex)];
|
||||
GltfShadeMaterial mat = materials.m[matIndex];
|
||||
vec3 emittance = mat.emissiveFactor;
|
||||
|
||||
// Pick a random direction from here and keep going.
|
||||
|
|
|
|||
|
|
@ -23,6 +23,10 @@
|
|||
#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 "binding.glsl"
|
||||
#include "gltf.glsl"
|
||||
#include "raycommon.glsl"
|
||||
|
|
@ -36,14 +40,18 @@ layout(location = 1) rayPayloadEXT bool isShadowed;
|
|||
layout(set = 0, binding = 0 ) uniform accelerationStructureEXT topLevelAS;
|
||||
layout(set = 0, binding = 2) readonly buffer _InstanceInfo {PrimMeshInfo primInfo[];};
|
||||
|
||||
layout(set = 1, binding = B_VERTICES) readonly buffer _VertexBuf {float vertices[];};
|
||||
layout(set = 1, binding = B_INDICES) readonly buffer _Indices {uint indices[];};
|
||||
layout(set = 1, binding = B_NORMALS) readonly buffer _NormalBuf {float normals[];};
|
||||
layout(set = 1, binding = B_TEXCOORDS) readonly buffer _TexCoordBuf {float texcoord0[];};
|
||||
layout(set = 1, binding = B_MATERIALS) readonly buffer _MaterialBuffer {GltfShadeMaterial materials[];};
|
||||
layout(set = 1, binding = B_TEXTURES) uniform sampler2D texturesMap[]; // all textures
|
||||
//layout(set = 1, binding = B_MATERIALS) readonly buffer _MaterialBuffer {GltfShadeMaterial materials[];};
|
||||
|
||||
|
||||
layout(buffer_reference, scalar) readonly buffer Vertices { vec3 v[]; };
|
||||
layout(buffer_reference, scalar) readonly buffer Indices { uint i[]; };
|
||||
layout(buffer_reference, scalar) readonly buffer Normals { vec3 n[]; };
|
||||
layout(buffer_reference, scalar) readonly buffer TexCoords { vec2 t[]; };
|
||||
layout(buffer_reference, scalar) readonly buffer Materials { GltfShadeMaterial m[]; };
|
||||
|
||||
layout(set = 1, binding = B_SCENEDESC ) readonly buffer SceneDesc_ { SceneDesc sceneDesc; };
|
||||
layout(set = 1, binding = B_TEXTURES) uniform sampler2D texturesMap[]; // all textures
|
||||
|
||||
// clang-format on
|
||||
|
||||
layout(push_constant) uniform Constants
|
||||
|
|
@ -55,33 +63,6 @@ layout(push_constant) uniform Constants
|
|||
}
|
||||
pushC;
|
||||
|
||||
// Return the vertex position
|
||||
vec3 getVertex(uint index)
|
||||
{
|
||||
vec3 vp;
|
||||
vp.x = vertices[3 * index + 0];
|
||||
vp.y = vertices[3 * index + 1];
|
||||
vp.z = vertices[3 * index + 2];
|
||||
return vp;
|
||||
}
|
||||
|
||||
vec3 getNormal(uint index)
|
||||
{
|
||||
vec3 vp;
|
||||
vp.x = normals[3 * index + 0];
|
||||
vp.y = normals[3 * index + 1];
|
||||
vp.z = normals[3 * index + 2];
|
||||
return vp;
|
||||
}
|
||||
|
||||
vec2 getTexCoord(uint index)
|
||||
{
|
||||
vec2 vp;
|
||||
vp.x = texcoord0[2 * index + 0];
|
||||
vp.y = texcoord0[2 * index + 1];
|
||||
return vp;
|
||||
}
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
|
|
@ -93,33 +74,39 @@ void main()
|
|||
uint vertexOffset = pinfo.vertexOffset; // Vertex offset as defined in glTF
|
||||
uint matIndex = max(0, pinfo.materialIndex); // material of primitive mesh
|
||||
|
||||
Materials gltfMat = Materials(sceneDesc.materialAddress);
|
||||
Vertices vertices = Vertices(sceneDesc.vertexAddress);
|
||||
Indices indices = Indices(sceneDesc.indexAddress);
|
||||
Normals normals = Normals(sceneDesc.normalAddress);
|
||||
TexCoords texCoords = TexCoords(sceneDesc.uvAddress);
|
||||
Materials materials = Materials(sceneDesc.materialAddress);
|
||||
|
||||
|
||||
// Getting the 3 indices of the triangle (local)
|
||||
ivec3 triangleIndex = ivec3(indices[nonuniformEXT(indexOffset + 0)], //
|
||||
indices[nonuniformEXT(indexOffset + 1)], //
|
||||
indices[nonuniformEXT(indexOffset + 2)]);
|
||||
ivec3 triangleIndex = ivec3(indices.i[indexOffset + 0], indices.i[indexOffset + 1], indices.i[indexOffset + 2]);
|
||||
triangleIndex += ivec3(vertexOffset); // (global)
|
||||
|
||||
const vec3 barycentrics = vec3(1.0 - attribs.x - attribs.y, attribs.x, attribs.y);
|
||||
|
||||
// Vertex of the triangle
|
||||
const vec3 pos0 = getVertex(triangleIndex.x);
|
||||
const vec3 pos1 = getVertex(triangleIndex.y);
|
||||
const vec3 pos2 = getVertex(triangleIndex.z);
|
||||
const vec3 pos0 = vertices.v[triangleIndex.x];
|
||||
const vec3 pos1 = vertices.v[triangleIndex.y];
|
||||
const vec3 pos2 = vertices.v[triangleIndex.z];
|
||||
const vec3 position = pos0 * barycentrics.x + pos1 * barycentrics.y + pos2 * barycentrics.z;
|
||||
const vec3 world_position = vec3(gl_ObjectToWorldEXT * vec4(position, 1.0));
|
||||
|
||||
// Normal
|
||||
const vec3 nrm0 = getNormal(triangleIndex.x);
|
||||
const vec3 nrm1 = getNormal(triangleIndex.y);
|
||||
const vec3 nrm2 = getNormal(triangleIndex.z);
|
||||
const vec3 nrm0 = normals.n[triangleIndex.x];
|
||||
const vec3 nrm1 = normals.n[triangleIndex.y];
|
||||
const vec3 nrm2 = normals.n[triangleIndex.z];
|
||||
vec3 normal = normalize(nrm0 * barycentrics.x + nrm1 * barycentrics.y + nrm2 * barycentrics.z);
|
||||
const vec3 world_normal = normalize(vec3(normal * gl_WorldToObjectEXT));
|
||||
const vec3 geom_normal = normalize(cross(pos1 - pos0, pos2 - pos0));
|
||||
|
||||
// TexCoord
|
||||
const vec2 uv0 = getTexCoord(triangleIndex.x);
|
||||
const vec2 uv1 = getTexCoord(triangleIndex.y);
|
||||
const vec2 uv2 = getTexCoord(triangleIndex.z);
|
||||
const vec2 uv0 = texCoords.t[triangleIndex.x];
|
||||
const vec2 uv1 = texCoords.t[triangleIndex.y];
|
||||
const vec2 uv2 = texCoords.t[triangleIndex.z];
|
||||
const vec2 texcoord0 = uv0 * barycentrics.x + uv1 * barycentrics.y + uv2 * barycentrics.z;
|
||||
|
||||
// Vector toward the light
|
||||
|
|
@ -140,7 +127,7 @@ void main()
|
|||
}
|
||||
|
||||
// Material of the object
|
||||
GltfShadeMaterial mat = materials[nonuniformEXT(matIndex)];
|
||||
GltfShadeMaterial mat = materials.m[matIndex];
|
||||
|
||||
// Diffuse
|
||||
vec3 diffuse = computeDiffuse(mat, L, world_normal);
|
||||
|
|
@ -160,8 +147,7 @@ void main()
|
|||
float tMax = lightDistance;
|
||||
vec3 origin = gl_WorldRayOriginEXT + gl_WorldRayDirectionEXT * gl_HitTEXT;
|
||||
vec3 rayDir = L;
|
||||
uint flags = gl_RayFlagsTerminateOnFirstHitEXT | gl_RayFlagsOpaqueEXT
|
||||
| gl_RayFlagsSkipClosestHitShaderEXT;
|
||||
uint flags = gl_RayFlagsTerminateOnFirstHitEXT | gl_RayFlagsOpaqueEXT | gl_RayFlagsSkipClosestHitShaderEXT;
|
||||
isShadowed = true;
|
||||
traceRayEXT(topLevelAS, // acceleration structure
|
||||
flags, // rayFlags
|
||||
|
|
|
|||
|
|
@ -22,10 +22,15 @@
|
|||
#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 "binding.glsl"
|
||||
#include "gltf.glsl"
|
||||
|
||||
// clang-format off
|
||||
layout( set = 0, binding = B_MATRICES) readonly buffer _Matrix { mat4 matrices[]; };
|
||||
layout(buffer_reference, scalar) buffer Matrices { mat4 m[]; };
|
||||
layout( set = 0, binding = B_SCENEDESC ) readonly buffer SceneDesc_ { SceneDesc sceneDesc; };
|
||||
// clang-format on
|
||||
|
||||
layout(binding = 0) uniform UniformBufferObject
|
||||
|
|
@ -65,7 +70,9 @@ out gl_PerVertex
|
|||
|
||||
void main()
|
||||
{
|
||||
mat4 objMatrix = matrices[pushC.instanceId];
|
||||
Matrices matrices = Matrices(sceneDesc.matrixAddress);
|
||||
mat4 objMatrix = matrices.m[pushC.instanceId];
|
||||
|
||||
mat4 objMatrixIT = transpose(inverse(objMatrix));
|
||||
|
||||
vec3 origin = vec3(ubo.viewI * vec4(0, 0, 0, 1));
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ compile_glsl_directory(
|
|||
SRC "${CMAKE_CURRENT_SOURCE_DIR}/shaders"
|
||||
DST "${CMAKE_CURRENT_SOURCE_DIR}/spv"
|
||||
VULKAN_TARGET "vulkan1.2"
|
||||
DEPENDENCY ${VULKAN_BUILD_DEPENDENCIES}
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -52,7 +53,8 @@ target_sources(${PROJNAME} PUBLIC ${GLSL_SOURCES} ${GLSL_HEADERS})
|
|||
source_group("Common" FILES ${COMMON_SOURCE_FILES} ${PACKAGE_SOURCE_FILES})
|
||||
source_group("Sources" FILES ${SOURCE_FILES})
|
||||
source_group("Headers" FILES ${HEADER_FILES})
|
||||
source_group("Shader_Files" FILES ${GLSL_SOURCES} ${GLSL_HEADERS})
|
||||
source_group("Shader Sources" FILES ${GLSL_SOURCES})
|
||||
source_group("Shader Headers" FILES ${GLSL_HEADERS})
|
||||
|
||||
|
||||
#--------------------------------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -114,26 +114,15 @@ void HelloVulkan::updateUniformBuffer(const VkCommandBuffer& cmdBuf)
|
|||
void HelloVulkan::createDescriptorSetLayout()
|
||||
{
|
||||
auto nbTxt = static_cast<uint32_t>(m_textures.size());
|
||||
auto nbObj = static_cast<uint32_t>(m_objModel.size());
|
||||
|
||||
// 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,
|
||||
// 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 = 3)
|
||||
m_descSetLayoutBind.addBinding(3, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, nbTxt,
|
||||
m_descSetLayoutBind.addBinding(2, 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);
|
||||
|
||||
|
||||
m_descSetLayout = m_descSetLayoutBind.createLayout(m_device);
|
||||
|
|
@ -151,25 +140,9 @@ void HelloVulkan::updateDescriptorSet()
|
|||
// Camera matrices and scene description
|
||||
VkDescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE};
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 0, &dbiUnif));
|
||||
VkDescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 2, &dbiSceneDesc));
|
||||
|
||||
// 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()));
|
||||
VkDescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 1, &dbiSceneDesc));
|
||||
|
||||
// All texture samplers
|
||||
std::vector<VkDescriptorImageInfo> diit;
|
||||
|
|
@ -177,7 +150,7 @@ void HelloVulkan::updateDescriptorSet()
|
|||
{
|
||||
diit.emplace_back(texture.descriptor);
|
||||
}
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 3, diit.data()));
|
||||
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 2, diit.data()));
|
||||
|
||||
// Writing the information
|
||||
vkUpdateDescriptorSets(m_device, static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
||||
|
|
@ -235,12 +208,6 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
|
|||
m.specular = nvmath::pow(m.specular, 2.2f);
|
||||
}
|
||||
|
||||
ObjInstance instance;
|
||||
instance.objIndex = static_cast<uint32_t>(m_objModel.size());
|
||||
instance.transform = transform;
|
||||
instance.transformIT = nvmath::transpose(nvmath::invert(transform));
|
||||
instance.txtOffset = static_cast<uint32_t>(m_textures.size());
|
||||
|
||||
ObjModel model;
|
||||
model.nbIndices = static_cast<uint32_t>(loader.m_indices.size());
|
||||
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
|
||||
|
|
@ -248,23 +215,35 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
|
|||
// Create the buffers on Device and copy vertices, indices and materials
|
||||
nvvk::CommandPool cmdBufGet(m_device, m_graphicsQueueIndex);
|
||||
VkCommandBuffer cmdBuf = cmdBufGet.createCommandBuffer();
|
||||
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);
|
||||
model.matColorBuffer = m_alloc.createBuffer(cmdBuf, loader.m_materials, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
|
||||
model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
|
||||
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);
|
||||
// Creates all textures found
|
||||
uint32_t txtOffset = static_cast<uint32_t>(m_textures.size());
|
||||
createTextureImages(cmdBuf, loader.m_textures);
|
||||
cmdBufGet.submitAndWait(cmdBuf);
|
||||
m_alloc.finalizeAndReleaseStaging();
|
||||
|
||||
std::string objNb = std::to_string(instance.objIndex);
|
||||
std::string objNb = std::to_string(m_objModel.size());
|
||||
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
|
||||
m_debug.setObjectName(model.indexBuffer.buffer, (std::string("index_" + objNb).c_str()));
|
||||
m_debug.setObjectName(model.matColorBuffer.buffer, (std::string("mat_" + objNb).c_str()));
|
||||
m_debug.setObjectName(model.matIndexBuffer.buffer, (std::string("matIdx_" + objNb).c_str()));
|
||||
|
||||
ObjInstance instance;
|
||||
instance.objIndex = static_cast<uint32_t>(m_objModel.size());
|
||||
instance.transform = transform;
|
||||
instance.transformIT = nvmath::transpose(nvmath::invert(transform));
|
||||
instance.txtOffset = txtOffset;
|
||||
instance.vertices = nvvk::getBufferDeviceAddress(m_device, model.vertexBuffer.buffer);
|
||||
instance.indices = nvvk::getBufferDeviceAddress(m_device, model.indexBuffer.buffer);
|
||||
instance.materials = nvvk::getBufferDeviceAddress(m_device, model.matColorBuffer.buffer);
|
||||
instance.materialIndices = nvvk::getBufferDeviceAddress(m_device, model.matIndexBuffer.buffer);
|
||||
|
||||
m_objModel.emplace_back(model);
|
||||
m_objInstance.emplace_back(instance);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,10 +76,14 @@ public:
|
|||
// Instance of the OBJ
|
||||
struct ObjInstance
|
||||
{
|
||||
uint32_t objIndex{0}; // Reference to the `m_objModel`
|
||||
uint32_t txtOffset{0}; // Offset in `m_textures`
|
||||
nvmath::mat4f transform{1}; // Position of the instance
|
||||
nvmath::mat4f transformIT{1}; // Inverse transpose
|
||||
uint32_t objIndex{0}; // Reference to the `m_objModel`
|
||||
uint32_t txtOffset{0}; // Offset in `m_textures`
|
||||
VkDeviceAddress vertices;
|
||||
VkDeviceAddress indices;
|
||||
VkDeviceAddress materials;
|
||||
VkDeviceAddress materialIndices;
|
||||
};
|
||||
|
||||
// Information pushed at each draw call
|
||||
|
|
@ -134,6 +138,7 @@ public:
|
|||
|
||||
nvvk::Buffer m_cameraMat; // Device-Host of the camera matrices
|
||||
nvvk::Buffer m_sceneDesc; // Device buffer of the OBJ instances
|
||||
|
||||
std::vector<nvvk::Texture> m_textures; // vector of all textures of the scene
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -89,6 +89,7 @@ int main(int argc, char** argv)
|
|||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||
GLFWwindow* window = glfwCreateWindow(SAMPLE_WIDTH, SAMPLE_HEIGHT, PROJECT_NAME, nullptr, nullptr);
|
||||
|
||||
|
||||
// Setup camera
|
||||
CameraManip.setWindowSize(SAMPLE_WIDTH, SAMPLE_HEIGHT);
|
||||
CameraManip.setLookat(nvmath::vec3f(5, 4, -4), nvmath::vec3f(0, 1, 0), nvmath::vec3f(0, 1, 0));
|
||||
|
|
@ -110,34 +111,26 @@ int main(int argc, char** argv)
|
|||
std::string(PROJECT_NAME),
|
||||
};
|
||||
|
||||
// Vulkan required extensions
|
||||
assert(glfwVulkanSupported() == 1);
|
||||
uint32_t count{0};
|
||||
auto reqExtensions = glfwGetRequiredInstanceExtensions(&count);
|
||||
|
||||
// Requesting Vulkan extensions and layers
|
||||
nvvk::ContextCreateInfo contextInfo(true);
|
||||
contextInfo.setVersion(1, 2);
|
||||
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
|
||||
contextInfo.addInstanceExtension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME, true);
|
||||
contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME);
|
||||
#ifdef _WIN32
|
||||
contextInfo.addInstanceExtension(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
|
||||
#else
|
||||
contextInfo.addInstanceExtension(VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
|
||||
contextInfo.addInstanceExtension(VK_KHR_XCB_SURFACE_EXTENSION_NAME);
|
||||
#endif
|
||||
contextInfo.addInstanceExtension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
|
||||
contextInfo.addDeviceExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
|
||||
contextInfo.addDeviceExtension(VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME);
|
||||
contextInfo.addDeviceExtension(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME);
|
||||
contextInfo.addDeviceExtension(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME);
|
||||
contextInfo.addDeviceExtension(VK_EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME);
|
||||
nvvk::ContextCreateInfo contextInfo;
|
||||
contextInfo.setVersion(1, 2); // Using Vulkan 1.2
|
||||
for(uint32_t ext_id = 0; ext_id < count; ext_id++) // Adding required extensions (surface, win32, linux, ..)
|
||||
contextInfo.addInstanceExtension(reqExtensions[ext_id]);
|
||||
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true); // FPS in titlebar
|
||||
contextInfo.addInstanceExtension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME, true); // Allow debug names
|
||||
contextInfo.addDeviceExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME); // Enabling ability to present rendering
|
||||
|
||||
// #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
|
||||
|
||||
// Creating Vulkan base application
|
||||
nvvk::Context vkctx{};
|
||||
|
|
|
|||
|
|
@ -23,6 +23,9 @@
|
|||
#extension GL_GOOGLE_include_directive : enable
|
||||
#extension GL_EXT_scalar_block_layout : enable
|
||||
|
||||
#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require
|
||||
#extension GL_EXT_buffer_reference2 : require
|
||||
|
||||
#include "wavefront.glsl"
|
||||
|
||||
|
||||
|
|
@ -37,30 +40,32 @@ pushC;
|
|||
|
||||
// clang-format off
|
||||
// Incoming
|
||||
//layout(location = 0) flat in int matIndex;
|
||||
layout(location = 1) in vec2 fragTexCoord;
|
||||
layout(location = 2) in vec3 fragNormal;
|
||||
layout(location = 3) in vec3 viewDir;
|
||||
layout(location = 4) in vec3 worldPos;
|
||||
// Outgoing
|
||||
layout(location = 0) out vec4 outColor;
|
||||
// Buffers
|
||||
layout(binding = 1, scalar) buffer MatColorBufferObject { WaveFrontMaterial m[]; } materials[];
|
||||
layout(binding = 2, scalar) buffer ScnDesc { sceneDesc i[]; } scnDesc;
|
||||
layout(binding = 3) uniform sampler2D[] textureSamplers;
|
||||
layout(binding = 4, scalar) buffer MatIndex { int i[]; } matIdx[];
|
||||
|
||||
layout(buffer_reference, scalar) buffer Vertices {Vertex v[]; }; // Positions of an object
|
||||
layout(buffer_reference, scalar) buffer Indices {uint 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 = 1, scalar) buffer SceneDesc_ { SceneDesc i[]; } sceneDesc;
|
||||
layout(binding = 2) uniform sampler2D[] textureSamplers;
|
||||
// clang-format on
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
// Object of this instance
|
||||
int objId = scnDesc.i[pushC.instanceId].objId;
|
||||
|
||||
// Material of the object
|
||||
int matIndex = matIdx[nonuniformEXT(objId)].i[gl_PrimitiveID];
|
||||
WaveFrontMaterial mat = materials[nonuniformEXT(objId)].m[matIndex];
|
||||
SceneDesc objResource = sceneDesc.i[pushC.instanceId];
|
||||
MatIndices matIndices = MatIndices(objResource.materialIndexAddress);
|
||||
Materials materials = Materials(objResource.materialAddress);
|
||||
|
||||
int matIndex = matIndices.i[gl_PrimitiveID];
|
||||
WaveFrontMaterial mat = materials.m[matIndex];
|
||||
|
||||
vec3 N = normalize(fragNormal);
|
||||
|
||||
|
|
@ -84,7 +89,7 @@ void main()
|
|||
vec3 diffuse = computeDiffuse(mat, L, N);
|
||||
if(mat.textureId >= 0)
|
||||
{
|
||||
int txtOffset = scnDesc.i[pushC.instanceId].txtOffset;
|
||||
int txtOffset = sceneDesc.i[pushC.instanceId].txtOffset;
|
||||
uint txtId = txtOffset + mat.textureId;
|
||||
vec3 diffuseTxt = texture(textureSamplers[nonuniformEXT(txtId)], fragTexCoord).xyz;
|
||||
diffuse *= diffuseTxt;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,10 @@
|
|||
#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"
|
||||
|
||||
|
|
@ -32,44 +36,46 @@ layout(location = 0) rayPayloadInEXT hitPayload prd;
|
|||
layout(location = 1) rayPayloadEXT bool isShadowed;
|
||||
layout(location = 2) rayPayloadEXT int hitLanternInstance;
|
||||
|
||||
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 = 2, set = 0) buffer LanternArray { LanternIndirectEntry lanterns[]; } lanterns;
|
||||
|
||||
layout(binding = 1, set = 1, scalar) buffer MatColorBufferObject { WaveFrontMaterial m[]; } materials[];
|
||||
layout(binding = 2, set = 1, scalar) buffer ScnDesc { sceneDesc i[]; } scnDesc;
|
||||
layout(binding = 3, set = 1) uniform sampler2D textureSamplers[];
|
||||
layout(binding = 4, set = 1) buffer MatIndexColorBuffer { int i[]; } matIndex[];
|
||||
layout(binding = 5, set = 1, scalar) buffer Vertices { Vertex v[]; } vertices[];
|
||||
layout(binding = 6, set = 1) buffer Indices { uint i[]; } indices[];
|
||||
|
||||
layout(binding = 1, set = 1, scalar) buffer SceneDesc_ { SceneDesc i[]; } sceneDesc;
|
||||
layout(binding = 2, set = 1) uniform sampler2D textureSamplers[];
|
||||
// clang-format on
|
||||
|
||||
void main()
|
||||
{
|
||||
// Object of this instance
|
||||
uint objId = scnDesc.i[gl_InstanceCustomIndexEXT].objId;
|
||||
// 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 = 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]); //
|
||||
ivec3 ind = indices.i[gl_PrimitiveID];
|
||||
|
||||
// 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];
|
||||
Vertex v0 = vertices.v[ind.x];
|
||||
Vertex v1 = vertices.v[ind.y];
|
||||
Vertex v2 = vertices.v[ind.z];
|
||||
|
||||
const vec3 barycentrics = vec3(1.0 - attribs.x - attribs.y, attribs.x, attribs.y);
|
||||
|
||||
// Computing the normal at hit position
|
||||
vec3 normal = v0.nrm * barycentrics.x + v1.nrm * barycentrics.y + v2.nrm * barycentrics.z;
|
||||
// Transforming the normal to world space
|
||||
normal = normalize(vec3(scnDesc.i[gl_InstanceCustomIndexEXT].transfoIT * vec4(normal, 0.0)));
|
||||
normal = normalize(vec3(sceneDesc.i[gl_InstanceCustomIndexEXT].transfoIT * vec4(normal, 0.0)));
|
||||
|
||||
|
||||
// Computing the coordinates of the hit position
|
||||
vec3 worldPos = v0.pos * barycentrics.x + v1.pos * barycentrics.y + v2.pos * barycentrics.z;
|
||||
// Transforming the position to world space
|
||||
worldPos = vec3(scnDesc.i[gl_InstanceCustomIndexEXT].transfo * vec4(worldPos, 1.0));
|
||||
worldPos = vec3(sceneDesc.i[gl_InstanceCustomIndexEXT].transfo * vec4(worldPos, 1.0));
|
||||
|
||||
// Vector toward the light
|
||||
vec3 L;
|
||||
|
|
@ -86,10 +92,7 @@ void main()
|
|||
// Lantern light decreases linearly. Not physically accurate, but looks good
|
||||
// and avoids a hard "edge" at the radius limit. Use a constant value
|
||||
// if lantern debug is enabled to clearly see the covered screen rectangle.
|
||||
float distanceFade =
|
||||
pushC.lanternDebug != 0
|
||||
? 0.3
|
||||
: max(0, (lantern.radius - lightDistance) / lantern.radius);
|
||||
float distanceFade = pushC.lanternDebug != 0 ? 0.3 : max(0, (lantern.radius - lightDistance) / lantern.radius);
|
||||
colorIntensity = color * lantern.brightness * distanceFade;
|
||||
L = normalize(lDir);
|
||||
}
|
||||
|
|
@ -107,17 +110,16 @@ void main()
|
|||
}
|
||||
|
||||
// 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];
|
||||
|
||||
|
||||
// Diffuse
|
||||
vec3 diffuse = computeDiffuse(mat, L, normal);
|
||||
if(mat.textureId >= 0)
|
||||
{
|
||||
uint txtId = mat.textureId + scnDesc.i[gl_InstanceCustomIndexEXT].txtOffset;
|
||||
vec2 texCoord =
|
||||
v0.texCoord * barycentrics.x + v1.texCoord * barycentrics.y + v2.texCoord * barycentrics.z;
|
||||
uint txtId = mat.textureId + sceneDesc.i[gl_InstanceCustomIndexEXT].txtOffset;
|
||||
vec2 texCoord = v0.texCoord * barycentrics.x + v1.texCoord * barycentrics.y + v2.texCoord * barycentrics.z;
|
||||
diffuse *= texture(textureSamplers[nonuniformEXT(txtId)], texCoord).xyz;
|
||||
}
|
||||
|
||||
|
|
@ -133,10 +135,10 @@ void main()
|
|||
vec3 rayDir = L;
|
||||
|
||||
// Ordinary shadow from the simple tutorial.
|
||||
if (pushC.lanternPassNumber < 0) {
|
||||
if(pushC.lanternPassNumber < 0)
|
||||
{
|
||||
isShadowed = true;
|
||||
uint flags = gl_RayFlagsTerminateOnFirstHitEXT | gl_RayFlagsOpaqueEXT
|
||||
| gl_RayFlagsSkipClosestHitShaderEXT;
|
||||
uint flags = gl_RayFlagsTerminateOnFirstHitEXT | gl_RayFlagsOpaqueEXT | gl_RayFlagsSkipClosestHitShaderEXT;
|
||||
traceRayEXT(topLevelAS, // acceleration structure
|
||||
flags, // rayFlags
|
||||
0xFF, // cullMask
|
||||
|
|
@ -153,12 +155,15 @@ void main()
|
|||
// Lantern shadow ray. Cast a ray towards the lantern whose lighting is being
|
||||
// added this pass. Only the closest hit shader for lanterns will set
|
||||
// hitLanternInstance (payload 2) to non-negative value.
|
||||
else {
|
||||
else
|
||||
{
|
||||
// Skip ray if no light would be added anyway.
|
||||
if (colorIntensity == vec3(0)) {
|
||||
if(colorIntensity == vec3(0))
|
||||
{
|
||||
isShadowed = true;
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
uint flags = gl_RayFlagsOpaqueEXT;
|
||||
hitLanternInstance = -1;
|
||||
traceRayEXT(topLevelAS, // acceleration structure
|
||||
|
|
|
|||
|
|
@ -36,7 +36,11 @@ layout(binding = 0, set = 1) uniform CameraProperties
|
|||
}
|
||||
cam;
|
||||
|
||||
layout(binding = 2, set = 0) buffer LanternArray { LanternIndirectEntry lanterns[]; } lanterns;
|
||||
layout(binding = 2, set = 0) buffer LanternArray
|
||||
{
|
||||
LanternIndirectEntry lanterns[];
|
||||
}
|
||||
lanterns;
|
||||
|
||||
void main()
|
||||
{
|
||||
|
|
@ -83,7 +87,8 @@ void main()
|
|||
// Either add to or replace output image color based on prd.additiveBlending.
|
||||
// Global pass always replaces color as it is the first pass.
|
||||
vec3 oldColor = vec3(0);
|
||||
if (prd.additiveBlending && pushC.lanternPassNumber >= 0) {
|
||||
if(prd.additiveBlending && pushC.lanternPassNumber >= 0)
|
||||
{
|
||||
oldColor = imageLoad(image, pixelIntCoord).rgb;
|
||||
}
|
||||
imageStore(image, pixelIntCoord, vec4(prd.hitValue + oldColor, 1.0));
|
||||
|
|
|
|||
|
|
@ -22,10 +22,12 @@
|
|||
#extension GL_EXT_scalar_block_layout : enable
|
||||
#extension GL_GOOGLE_include_directive : enable
|
||||
|
||||
#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require
|
||||
|
||||
#include "wavefront.glsl"
|
||||
|
||||
// clang-format off
|
||||
layout(binding = 2, set = 0, scalar) buffer ScnDesc { sceneDesc i[]; } scnDesc;
|
||||
layout(binding = 1, scalar) buffer SceneDesc_ { SceneDesc i[]; } sceneDesc;
|
||||
// clang-format on
|
||||
|
||||
layout(binding = 0) uniform UniformBufferObject
|
||||
|
|
@ -65,8 +67,8 @@ out gl_PerVertex
|
|||
|
||||
void main()
|
||||
{
|
||||
mat4 objMatrix = scnDesc.i[pushC.instanceId].transfo;
|
||||
mat4 objMatrixIT = scnDesc.i[pushC.instanceId].transfoIT;
|
||||
mat4 objMatrix = sceneDesc.i[pushC.instanceId].transfo;
|
||||
mat4 objMatrixIT = sceneDesc.i[pushC.instanceId].transfoIT;
|
||||
|
||||
vec3 origin = vec3(ubo.viewI * vec4(0, 0, 0, 1));
|
||||
|
||||
|
|
|
|||
|
|
@ -39,12 +39,16 @@ struct WaveFrontMaterial
|
|||
int textureId;
|
||||
};
|
||||
|
||||
struct sceneDesc
|
||||
struct SceneDesc
|
||||
{
|
||||
int objId;
|
||||
int txtOffset;
|
||||
mat4 transfo;
|
||||
mat4 transfoIT;
|
||||
int objId;
|
||||
int txtOffset;
|
||||
uint64_t vertexAddress;
|
||||
uint64_t indexAddress;
|
||||
uint64_t materialAddress;
|
||||
uint64_t materialIndexAddress;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ compile_glsl_directory(
|
|||
SRC "${CMAKE_CURRENT_SOURCE_DIR}/shaders"
|
||||
DST "${CMAKE_CURRENT_SOURCE_DIR}/spv"
|
||||
VULKAN_TARGET "vulkan1.2"
|
||||
DEPENDENCY ${VULKAN_BUILD_DEPENDENCIES}
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -52,7 +53,8 @@ target_sources(${PROJNAME} PUBLIC ${GLSL_SOURCES} ${GLSL_HEADERS})
|
|||
source_group("Common" FILES ${COMMON_SOURCE_FILES} ${PACKAGE_SOURCE_FILES})
|
||||
source_group("Sources" FILES ${SOURCE_FILES})
|
||||
source_group("Headers" FILES ${HEADER_FILES})
|
||||
source_group("Shader_Files" FILES ${GLSL_SOURCES} ${GLSL_HEADERS})
|
||||
source_group("Shader Sources" FILES ${GLSL_SOURCES})
|
||||
source_group("Shader Headers" FILES ${GLSL_HEADERS})
|
||||
|
||||
|
||||
#--------------------------------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -41,9 +41,7 @@ Then replace the calls to `helloVk.loadModel` in `main()` by
|
|||
|
||||
for(int n = 0; n < 2000; ++n)
|
||||
{
|
||||
HelloVulkan::ObjInstance inst;
|
||||
inst.objIndex = n % 2;
|
||||
inst.txtOffset = 0;
|
||||
HelloVulkan::ObjInstance inst = helloVk.m_objInstance[n % 2];;
|
||||
float scale = fabsf(disn(gen));
|
||||
nvmath::mat4f mat =
|
||||
nvmath::translation_mat4(nvmath::vec3f{dis(gen), 2.0f + dis(gen), dis(gen)});
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue