framework update 4/29/2020

This commit is contained in:
Christoph Kubisch 2020-04-29 13:59:03 +02:00
parent 21fc655237
commit 60103dd1ce
62 changed files with 2931 additions and 2743 deletions

View file

@ -76,12 +76,15 @@ Next, we update the buffer that describes the scene, which is used by the raster
memcpy(gInst, m_objInstance.data(), bufferSize); memcpy(gInst, m_objInstance.data(), bufferSize);
m_alloc.unmap(stagingBuffer); m_alloc.unmap(stagingBuffer);
// Copy staging buffer to the Scene Description buffer // Copy staging buffer to the Scene Description buffer
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex); nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer(); vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
cmdBuf.copyBuffer(stagingBuffer.buffer, m_sceneDesc.buffer, vk::BufferCopy(0, 0, bufferSize)); cmdBuf.copyBuffer(stagingBuffer.buffer, m_sceneDesc.buffer, vk::BufferCopy(0, 0, bufferSize));
m_debug.endLabel(cmdBuf); m_debug.endLabel(cmdBuf);
genCmdBuf.flushCommandBuffer(cmdBuf); genCmdBuf.submitAndWait(cmdBuf);
m_alloc.destroy(stagingBuffer); m_alloc.destroy(stagingBuffer);
m_rtBuilder.updateTlasMatrices(m_tlas);
m_rtBuilder.updateBlas(2);
} }
~~~~ ~~~~
<script type="preformatted"> <script type="preformatted">
@ -114,10 +117,10 @@ they will still be at their original positions in the ray traced version. We wil
Since we want to update the transformation matrices in the TLAS, we need to keep some of the objects used to create it. Since we want to update the transformation matrices in the TLAS, we need to keep some of the objects used to create it.
First, move the vector of `nvvkpp::RaytracingBuilder::Instance` objects from `HelloVulkan::createTopLevelAS()` to the First, move the vector of `nvvk::RaytracingBuilder::Instance` objects from `HelloVulkan::createTopLevelAS()` to the
`HelloVulkan` class. `HelloVulkan` class.
~~~~ C++ ~~~~ C++
std::vector<nvvkpp::RaytracingBuilder::Instance> m_tlas; std::vector<nvvk::RaytracingBuilder::Instance> m_tlas;
~~~~ ~~~~
Make sure to rename it to `m_tlas`, instead of `tlas`. Make sure to rename it to `m_tlas`, instead of `tlas`.
@ -131,12 +134,12 @@ void HelloVulkan::createTopLevelAS()
m_tlas.reserve(m_objInstance.size()); m_tlas.reserve(m_objInstance.size());
for(int i = 0; i < static_cast<int>(m_objInstance.size()); i++) for(int i = 0; i < static_cast<int>(m_objInstance.size()); i++)
{ {
nvvkpp::RaytracingBuilder::Instance rayInst; nvvk::RaytracingBuilder::Instance rayInst;
rayInst.transform = m_objInstance[i].transform; // Position of the instance rayInst.transform = m_objInstance[i].transform; // Position of the instance
rayInst.instanceId = i; // gl_InstanceID rayInst.instanceId = i; // gl_InstanceID
rayInst.blasId = m_objInstance[i].objIndex; rayInst.blasId = m_objInstance[i].objIndex;
rayInst.hitGroupId = m_objInstance[i].hitgroup; rayInst.hitGroupId = m_objInstance[i].hitgroup;
rayInst.flags = vk::GeometryInstanceFlagBitsKHR::eTriangleCullDisable; rayInst.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_CULL_DISABLE_BIT_NV;
m_tlas.emplace_back(rayInst); m_tlas.emplace_back(rayInst);
} }
m_rtBuilder.buildTlas(m_tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace m_rtBuilder.buildTlas(m_tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace
@ -145,12 +148,12 @@ void HelloVulkan::createTopLevelAS()
~~~~ ~~~~
Back in `HelloVulkan::animationInstances()`, we need to copy the new computed transformation Back in `HelloVulkan::animationInstances()`, we need to copy the new computed transformation
matrices to the vector of `nvvkpp::RaytracingBuilder::Instance` objects. matrices to the vector of `nvvk::RaytracingBuilder::Instance` objects.
In the `for` loop, add at the end In the `for` loop, add at the end
~~~~ C++ ~~~~ C++
nvvkpp::RaytracingBuilder::Instance& tinst = m_tlas[wusonIdx]; nvvk::RaytracingBuilder::Instance& tinst = m_tlas[wusonIdx];
tinst.transform = inst.transform; tinst.transform = inst.transform;
~~~~ ~~~~
@ -162,12 +165,12 @@ m_rtBuilder.updateTlasMatrices(m_tlas);
![](Images/animation1.gif) ![](Images/animation1.gif)
## nvvkpp::RaytracingBuilder::updateTlasMatrices (Implementation) ## nvvk::RaytracingBuilder::updateTlasMatrices (Implementation)
We currently use `nvvkpp::RaytracingBuilder` to update the matrices for convenience, but We currently use `nvvk::RaytracingBuilder` to update the matrices for convenience, but
this could be done more efficiently if one kept some of the buffer and memory references. Using a this could be done more efficiently if one kept some of the buffer and memory references. Using a
memory allocator, such as the one described in the [Many Objects Tutorial](vkrt_tuto_instances.md.htm), memory allocator, such as the one described in the [Many Objects Tutorial](vkrt_tuto_instances.md.htm),
could also be an alternative for avoiding multiple reallocations. Here's the implementation of `nvvkpp::RaytracingBuilder::updateTlasMatrices`. could also be an alternative for avoiding multiple reallocations. Here's the implementation of `nvvk::RaytracingBuilder::updateTlasMatrices`.
### Staging Buffer ### Staging Buffer
@ -177,18 +180,18 @@ building the TLAS.
~~~~ C++ ~~~~ C++
void updateTlasMatrices(const std::vector<Instance>& instances) void updateTlasMatrices(const std::vector<Instance>& instances)
{ {
VkDeviceSize bufferSize = instances.size() * sizeof(vk::AccelerationStructureInstanceKHR); VkDeviceSize bufferSize = instances.size() * sizeof(VkAccelerationStructureInstanceKHR);
// Create a staging buffer on the host to upload the new instance data // Create a staging buffer on the host to upload the new instance data
nvvkBuffer stagingBuffer = m_alloc.createBuffer(bufferSize, vk::BufferUsageFlagBits::eTransferSrc, nvvkBuffer stagingBuffer = m_alloc.createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
#if defined(ALLOC_VMA) #if defined(ALLOC_VMA)
VmaMemoryUsage::VMA_MEMORY_USAGE_CPU_TO_GPU VmaMemoryUsage::VMA_MEMORY_USAGE_CPU_TO_GPU
#else #else
vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
#endif #endif
); );
// Copy the instance data into the staging buffer // Copy the instance data into the staging buffer
auto* gInst = reinterpret_cast<vk::AccelerationStructureInstanceKHR*>(m_alloc.map(stagingBuffer)); auto* gInst = reinterpret_cast<VkAccelerationStructureInstanceKHR*>(m_alloc.map(stagingBuffer));
for(int i = 0; i < instances.size(); i++) for(int i = 0; i < instances.size(); i++)
{ {
gInst[i] = instanceToVkGeometryInstanceKHR(instances[i]); gInst[i] = instanceToVkGeometryInstanceKHR(instances[i]);
@ -201,16 +204,23 @@ Building the TLAS always needs scratch memory, and so we need to request it. If
we hadn't set the `eAllowUpdate` flag, the returned size would be zero and the rest of the code we hadn't set the `eAllowUpdate` flag, the returned size would be zero and the rest of the code
would fail. would fail.
~~~~ C++ ~~~~ C++
// Compute the amount of scratch memory required by the AS builder to update the TLAS // Compute the amount of scratch memory required by the AS builder to update
vk::AccelerationStructureMemoryRequirementsInfoKHR memoryRequirementsInfo{ VkAccelerationStructureMemoryRequirementsInfoKHR memoryRequirementsInfo{
vk::AccelerationStructureMemoryRequirementsTypeKHR::eUpdateScratch, VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_KHR};
vk::AccelerationStructureBuildTypeKHR::eDevice, m_tlas.as.accel}; memoryRequirementsInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_KHR;
vk::DeviceSize scratchSize = memoryRequirementsInfo.accelerationStructure = m_tlas.as.accel;
m_device.getAccelerationStructureMemoryRequirementsKHR(memoryRequirementsInfo).memoryRequirements.size; memoryRequirementsInfo.buildType = VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR;
// Allocate the scratch buffer
nvvkBuffer scratchBuffer = m_alloc.createBuffer(scratchSize, vk::BufferUsageFlagBits::eRayTracingKHR VkMemoryRequirements2 reqMem{VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2};
| vk::BufferUsageFlagBits::eShaderDeviceAddress); vkGetAccelerationStructureMemoryRequirementsKHR(m_device, &memoryRequirementsInfo, &reqMem);
vk::DeviceAddress scratchAddress = m_device.getBufferAddress({scratchBuffer.buffer}); VkDeviceSize scratchSize = reqMem.memoryRequirements.size;
// Allocate the scratch buffer
nvvkBuffer scratchBuffer =
m_alloc.createBuffer(scratchSize, VK_BUFFER_USAGE_RAY_TRACING_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
VkBufferDeviceAddressInfo bufferInfo{VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO};
bufferInfo.buffer = scratchBuffer.buffer;
VkDeviceAddress scratchAddress = vkGetBufferDeviceAddress(m_device, &bufferInfo);
~~~~ ~~~~
### Update the Buffer ### Update the Buffer
@ -218,19 +228,25 @@ In a new command buffer, we copy the staging buffer to the device buffer and
add a barrier to make sure the memory finishes copying before updating the TLAS. add a barrier to make sure the memory finishes copying before updating the TLAS.
~~~~ C++ ~~~~ C++
// Update the instance buffer on the device side and build the TLAS // Update the instance buffer on the device side and build the TLAS
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_queueIndex); nvvk::CommandPool genCmdBuf(m_device, m_queueIndex);
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer(); VkCommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
cmdBuf.copyBuffer(stagingBuffer.buffer, m_instBuffer.buffer, vk::BufferCopy(0, 0, bufferSize)); VkBufferCopy region{0, 0, bufferSize};
vkCmdCopyBuffer(cmdBuf, stagingBuffer.buffer, m_instBuffer.buffer, 1, &region);
vk::DeviceAddress instanceAddress = m_device.getBufferAddress(m_instBuffer.buffer); //VkBufferDeviceAddressInfo bufferInfo{VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO};
bufferInfo.buffer = m_instBuffer.buffer;
VkDeviceAddress instanceAddress = vkGetBufferDeviceAddress(m_device, &bufferInfo);
// Make sure the copy of the instance buffer are copied before triggering the
// acceleration structure build // Make sure the copy of the instance buffer are copied before triggering the
vk::MemoryBarrier barrier(vk::AccessFlagBits::eTransferWrite, vk::AccessFlagBits::eAccelerationStructureWriteKHR); // acceleration structure build
cmdBuf.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eAccelerationStructureBuildKHR, VkMemoryBarrier barrier{VK_STRUCTURE_TYPE_MEMORY_BARRIER};
vk::DependencyFlags(), {barrier}, {}, {}); barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR;
vkCmdPipelineBarrier(cmdBuf, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR,
0, 1, &barrier, 0, nullptr, 0, nullptr);
~~~~ ~~~~
### Update Acceleration Structure ### Update Acceleration Structure
@ -239,30 +255,36 @@ We update the TLAS using the same acceleration structure for source and
destination to update it in place, and using the VK_TRUE parameter to trigger the update. destination to update it in place, and using the VK_TRUE parameter to trigger the update.
~~~~ C++ ~~~~ C++
vk::AccelerationStructureGeometryKHR topASGeometry{vk::GeometryTypeKHR::eInstances}; VkAccelerationStructureGeometryDataKHR geometry{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR};
topASGeometry.geometry.instances.arrayOfPointers = VK_FALSE; geometry.instances.arrayOfPointers = VK_FALSE;
topASGeometry.geometry.instances.data = instanceAddress; geometry.instances.data.deviceAddress = instanceAddress;
const vk::AccelerationStructureGeometryKHR* pGeometry = &topASGeometry; VkAccelerationStructureGeometryKHR topASGeometry{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR};
topASGeometry.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR;
topASGeometry.geometry = geometry;
const VkAccelerationStructureGeometryKHR* pGeometry = &topASGeometry;
vk::AccelerationStructureBuildGeometryInfoKHR topASInfo; VkAccelerationStructureBuildGeometryInfoKHR topASInfo{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR};
topASInfo.setFlags(m_tlas.flags); topASInfo.flags = m_tlas.flags;
topASInfo.setUpdate(VK_TRUE); topASInfo.update = VK_TRUE;
topASInfo.setSrcAccelerationStructure(m_tlas.as.accel); topASInfo.srcAccelerationStructure = m_tlas.as.accel;
topASInfo.setDstAccelerationStructure(m_tlas.as.accel); topASInfo.dstAccelerationStructure = m_tlas.as.accel;
topASInfo.setGeometryArrayOfPointers(VK_FALSE); topASInfo.geometryArrayOfPointers = VK_FALSE;
topASInfo.setGeometryCount(1); topASInfo.geometryCount = 1;
topASInfo.setPpGeometries(&pGeometry); topASInfo.ppGeometries = &pGeometry;
topASInfo.setScratchData(scratchAddress); topASInfo.scratchData.deviceAddress = scratchAddress;
uint32_t nbInstances = (uint32_t)instances.size(); uint32_t nbInstances = (uint32_t)instances.size();
vk::AccelerationStructureBuildOffsetInfoKHR buildOffsetInfo = {nbInstances, 0, 0, 0}; VkAccelerationStructureBuildOffsetInfoKHR buildOffsetInfo = {nbInstances, 0, 0, 0};
const vk::AccelerationStructureBuildOffsetInfoKHR* pBuildOffsetInfo = &buildOffsetInfo; const VkAccelerationStructureBuildOffsetInfoKHR* pBuildOffsetInfo = &buildOffsetInfo;
// Update the acceleration structure. Note the VK_TRUE parameter to trigger the update, // Build the TLAS
// and the existing TLAS being passed and updated in place
cmdBuf.buildAccelerationStructureKHR(1, &topASInfo, &pBuildOffsetInfo); // Update the acceleration structure. Note the VK_TRUE parameter to trigger the update,
genCmdBuf.flushCommandBuffer(cmdBuf); // and the existing TLAS being passed and updated in place
vkCmdBuildAccelerationStructureKHR(cmdBuf, 1, &topASInfo, &pBuildOffsetInfo);
genCmdBuf.submitAndWait(cmdBuf);
~~~~ ~~~~
### Cleanup ### Cleanup
@ -310,12 +332,12 @@ Add all of the following members to the `HelloVulkan` class:
void updateCompDescriptors(nvvkBuffer& vertex); void updateCompDescriptors(nvvkBuffer& vertex);
void createCompPipelines(); void createCompPipelines();
std::vector<vk::DescriptorSetLayoutBinding> m_compDescSetLayoutBind; nvvk::DescriptorSetBindings m_compDescSetLayoutBind;
vk::DescriptorPool m_compDescPool; vk::DescriptorPool m_compDescPool;
vk::DescriptorSetLayout m_compDescSetLayout; vk::DescriptorSetLayout m_compDescSetLayout;
vk::DescriptorSet m_compDescSet; vk::DescriptorSet m_compDescSet;
vk::Pipeline m_compPipeline; vk::Pipeline m_compPipeline;
vk::PipelineLayout m_compPipelineLayout; vk::PipelineLayout m_compPipelineLayout;
~~~~ ~~~~
The compute shader will work on a single `VertexObj` buffer. The compute shader will work on a single `VertexObj` buffer.
@ -323,12 +345,12 @@ The compute shader will work on a single `VertexObj` buffer.
~~~~ C++ ~~~~ C++
void HelloVulkan::createCompDescriptors() void HelloVulkan::createCompDescriptors()
{ {
m_compDescSetLayoutBind.emplace_back(vk::DescriptorSetLayoutBinding( m_compDescSetLayoutBind.addBinding(vk::DescriptorSetLayoutBinding(
0, vk::DescriptorType::eStorageBuffer, 1, vk::ShaderStageFlagBits::eCompute)); 0, vk::DescriptorType::eStorageBuffer, 1, vk::ShaderStageFlagBits::eCompute));
m_compDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_compDescSetLayoutBind); m_compDescSetLayout = m_compDescSetLayoutBind.createLayout(m_device);
m_compDescPool = nvvkpp::util::createDescriptorPool(m_device, m_compDescSetLayoutBind, 1); m_compDescPool = m_compDescSetLayoutBind.createPool(m_device, 1);
m_compDescSet = nvvkpp::util::createDescriptorSet(m_device, m_compDescPool, m_compDescSetLayout); m_compDescSet = nvvk::allocateDescriptorSet(m_device, m_compDescPool, m_compDescSetLayout);
} }
~~~~ ~~~~
@ -339,8 +361,7 @@ void HelloVulkan::updateCompDescriptors(nvvkBuffer& vertex)
{ {
std::vector<vk::WriteDescriptorSet> writes; std::vector<vk::WriteDescriptorSet> writes;
vk::DescriptorBufferInfo dbiUnif{vertex.buffer, 0, VK_WHOLE_SIZE}; vk::DescriptorBufferInfo dbiUnif{vertex.buffer, 0, VK_WHOLE_SIZE};
writes.emplace_back( writes.emplace_back(m_compDescSetLayoutBind.makeWrite(m_compDescSet, 0, dbiUnif));
nvvkpp::util::createWrite(m_compDescSet, m_compDescSetLayoutBind[0], &dbiUnif));
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr); m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
} }
~~~~ ~~~~
@ -358,10 +379,10 @@ void HelloVulkan::createCompPipelines()
vk::ComputePipelineCreateInfo computePipelineCreateInfo{{}, {}, m_compPipelineLayout}; vk::ComputePipelineCreateInfo computePipelineCreateInfo{{}, {}, m_compPipelineLayout};
computePipelineCreateInfo.stage = computePipelineCreateInfo.stage =
nvvkpp::util::loadShader(m_device, nvvk::createShaderStageInfo(m_device,
nvh::loadFile("shaders/anim.comp.spv", true, defaultSearchPaths), nvh::loadFile("shaders/anim.comp.spv", true, defaultSearchPaths),
vk::ShaderStageFlagBits::eCompute); VK_SHADER_STAGE_COMPUTE_BIT);
m_compPipeline = m_device.createComputePipelines({}, computePipelineCreateInfo, nullptr)[0]; m_compPipeline = m_device.createComputePipeline({}, computePipelineCreateInfo, nullptr);
m_device.destroy(computePipelineCreateInfo.stage.module); m_device.destroy(computePipelineCreateInfo.stage.module);
} }
~~~~ ~~~~
@ -445,8 +466,8 @@ void HelloVulkan::animationObject(float time)
updateCompDescriptors(model.vertexBuffer); updateCompDescriptors(model.vertexBuffer);
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex); nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer(); vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
cmdBuf.bindPipeline(vk::PipelineBindPoint::eCompute, m_compPipeline); cmdBuf.bindPipeline(vk::PipelineBindPoint::eCompute, m_compPipeline);
cmdBuf.bindDescriptorSets(vk::PipelineBindPoint::eCompute, m_compPipelineLayout, 0, cmdBuf.bindDescriptorSets(vk::PipelineBindPoint::eCompute, m_compPipelineLayout, 0,
@ -454,7 +475,7 @@ void HelloVulkan::animationObject(float time)
cmdBuf.pushConstants(m_compPipelineLayout, vk::ShaderStageFlagBits::eCompute, 0, sizeof(float), cmdBuf.pushConstants(m_compPipelineLayout, vk::ShaderStageFlagBits::eCompute, 0, sizeof(float),
&time); &time);
cmdBuf.dispatch(model.nbVertices, 1, 1); cmdBuf.dispatch(model.nbVertices, 1, 1);
genCmdBuf.flushCommandBuffer(cmdBuf); genCmdBuf.submitAndWait(cmdBuf);
} }
~~~~ ~~~~
@ -478,7 +499,7 @@ In the rendering loop, after the call to `animationInstances`, call the object a
## Update BLAS ## Update BLAS
In `nvvkpp::RaytracingBuilder` in `raytrace_vkpp.hpp`, we can add a function to update a BLAS whose vertex buffer was previously updated. This function is very similar to the one used for instances, but in this case, there is no buffer transfer to do. In `nvvk::RaytracingBuilder` in `raytrace_vkpp.hpp`, we can add a function to update a BLAS whose vertex buffer was previously updated. This function is very similar to the one used for instances, but in this case, there is no buffer transfer to do.
~~~~ C++ ~~~~ C++
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -488,57 +509,63 @@ In `nvvkpp::RaytracingBuilder` in `raytrace_vkpp.hpp`, we can add a function to
{ {
Blas& blas = m_blas[blasIdx]; Blas& blas = m_blas[blasIdx];
// Compute the amount of scratch memory required by the AS builder to update the TLAS // Compute the amount of scratch memory required by the AS builder to update the BLAS
vk::AccelerationStructureMemoryRequirementsInfoKHR memoryRequirementsInfo{ VkAccelerationStructureMemoryRequirementsInfoKHR memoryRequirementsInfo{
vk::AccelerationStructureMemoryRequirementsTypeKHR::eUpdateScratch, VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_KHR};
vk::AccelerationStructureBuildTypeKHR::eDevice, blas.as.accel}; memoryRequirementsInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_KHR;
vk::DeviceSize scratchSize = memoryRequirementsInfo.accelerationStructure = blas.as.accel;
m_device.getAccelerationStructureMemoryRequirementsKHR(memoryRequirementsInfo).memoryRequirements.size; memoryRequirementsInfo.buildType = VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR;
VkMemoryRequirements2 reqMem{VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2};
vkGetAccelerationStructureMemoryRequirementsKHR(m_device, &memoryRequirementsInfo, &reqMem);
VkDeviceSize scratchSize = reqMem.memoryRequirements.size;
// Allocate the scratch buffer // Allocate the scratch buffer
nvvkBuffer scratchBuffer = m_alloc.createBuffer(scratchSize, vk::BufferUsageFlagBits::eRayTracingKHR nvvkBuffer scratchBuffer =
| vk::BufferUsageFlagBits::eShaderDeviceAddress); m_alloc.createBuffer(scratchSize, VK_BUFFER_USAGE_RAY_TRACING_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
vk::DeviceAddress scratchAddress = m_device.getBufferAddress({scratchBuffer.buffer}); VkBufferDeviceAddressInfo bufferInfo{VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO};
bufferInfo.buffer = scratchBuffer.buffer;
VkDeviceAddress scratchAddress = vkGetBufferDeviceAddress(m_device, &bufferInfo);
const vk::AccelerationStructureGeometryKHR* pGeometry = blas.asGeometry.data(); const VkAccelerationStructureGeometryKHR* pGeometry = blas.asGeometry.data();
vk::AccelerationStructureBuildGeometryInfoKHR asInfo{vk::AccelerationStructureTypeKHR::eBottomLevel}; VkAccelerationStructureBuildGeometryInfoKHR asInfo{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR};
asInfo.setFlags(blas.flags); asInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;
asInfo.setUpdate(VK_TRUE); asInfo.flags = blas.flags;
asInfo.setSrcAccelerationStructure(blas.as.accel); asInfo.update = VK_TRUE;
asInfo.setDstAccelerationStructure(blas.as.accel); asInfo.srcAccelerationStructure = blas.as.accel;
asInfo.setGeometryArrayOfPointers(VK_FALSE); asInfo.dstAccelerationStructure = blas.as.accel;
asInfo.setGeometryCount((uint32_t)blas.asGeometry.size()); asInfo.geometryArrayOfPointers = VK_FALSE;
asInfo.setPpGeometries(&pGeometry); asInfo.geometryCount = (uint32_t)blas.asGeometry.size();
asInfo.setScratchData(scratchAddress); asInfo.ppGeometries = &pGeometry;
asInfo.scratchData.deviceAddress = scratchAddress;
std::vector<const VkAccelerationStructureBuildOffsetInfoKHR*> pBuildOffset(blas.asBuildOffsetInfo.size());
std::vector<const vk::AccelerationStructureBuildOffsetInfoKHR*> pBuildOffset(blas.asBuildOffsetInfo.size());
for(size_t i = 0; i < blas.asBuildOffsetInfo.size(); i++) for(size_t i = 0; i < blas.asBuildOffsetInfo.size(); i++)
pBuildOffset[i] = &blas.asBuildOffsetInfo[i]; pBuildOffset[i] = &blas.asBuildOffsetInfo[i];
// Update the instance buffer on the device side and build the TLAS // Update the instance buffer on the device side and build the TLAS
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_queueIndex); nvvk::CommandPool genCmdBuf(m_device, m_queueIndex);
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer(); VkCommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
// Update the acceleration structure. Note the VK_TRUE parameter to trigger the update, // Update the acceleration structure. Note the VK_TRUE parameter to trigger the update,
// and the existing BLAS being passed and updated in place // and the existing BLAS being passed and updated in place
cmdBuf.buildAccelerationStructureKHR(asInfo, pBuildOffset); vkCmdBuildAccelerationStructureKHR(cmdBuf, 1, &asInfo, pBuildOffset.data());
genCmdBuf.submitAndWait(cmdBuf);
genCmdBuf.flushCommandBuffer(cmdBuf);
m_alloc.destroy(scratchBuffer); m_alloc.destroy(scratchBuffer);
} }
~~~~ ~~~~
The previous function (`updateBlas`) uses geometry information stored in `m_blas`. The previous function (`updateBlas`) uses geometry information stored in `m_blas`.
To be able to re-use this information, we need to keep the structure of `nvvkpp::RaytracingBuilderKHR::Blas` objects To be able to re-use this information, we need to keep the structure of `nvvk::RaytracingBuilderKHR::Blas` objects
used for its creation. used for its creation.
Move the `nvvkpp::RaytracingBuilderKHR::Blas` vector from `HelloVulkan::createBottomLevelAS()` to the `HelloVulkan` class, renaming it to `m_blas`. Move the `nvvk::RaytracingBuilderKHR::Blas` vector from `HelloVulkan::createBottomLevelAS()` to the `HelloVulkan` class, renaming it to `m_blas`.
~~~~ C++ ~~~~ C++
std::vector<nvvkpp::RaytracingBuilderKHR::Blas> m_blas; std::vector<nvvk::RaytracingBuilderKHR::Blas> m_blas;
~~~~ ~~~~
As with the TLAS, the BLAS needs to allow updates. We will also enable the As with the TLAS, the BLAS needs to allow updates. We will also enable the

View file

@ -111,8 +111,8 @@ In `createRtPipeline()`, after loading `raytrace.rchit.spv`, load `raytrace.rahi
~~~~ C++ ~~~~ C++
vk::ShaderModule ahitSM = vk::ShaderModule ahitSM =
nvvkpp::util::createShaderModule(m_device, // nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rahit.spv", true, paths)); nvh::loadFile("shaders/raytrace.rahit.spv", true, paths));
~~~~ ~~~~
add the any hit shader to the hit group add the any hit shader to the hit group

View file

@ -65,30 +65,29 @@ In `HelloVulkan::createRtPipeline()`, immediately after adding the closest-hit s
3 callable shaders, for each type of light. 3 callable shaders, for each type of light.
~~~~ C++ ~~~~ C++
// Callable shaders // Callable shaders
vk::RayTracingShaderGroupCreateInfoKHR callGroup{vk::RayTracingShaderGroupTypeKHR::eGeneral, vk::RayTracingShaderGroupCreateInfoKHR callGroup{vk::RayTracingShaderGroupTypeKHR::eGeneral,
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR,
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR}; VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR};
vk::ShaderModule call0 = vk::ShaderModule call0 =
nvvkpp::util::createShaderModule(m_device, nvvk::createShaderModule(m_device,
nvh::loadFile("shaders/light_point.rcall.spv", true, paths)); nvh::loadFile("shaders/light_point.rcall.spv", true, paths));
vk::ShaderModule call1 = vk::ShaderModule call1 =
nvvkpp::util::createShaderModule(m_device, nvvk::createShaderModule(m_device,
nvh::loadFile("shaders/light_spot.rcall.spv", true, paths)); nvh::loadFile("shaders/light_spot.rcall.spv", true, paths));
vk::ShaderModule call2 = vk::ShaderModule call2 =
nvvkpp::util::createShaderModule(m_device, nvvk::createShaderModule(m_device, nvh::loadFile("shaders/light_inf.rcall.spv", true, paths));
nvh::loadFile("shaders/light_inf.rcall.spv", true, paths));
stages.push_back({{}, vk::ShaderStageFlagBits::eCallableKHR, call0, "main"}); stages.push_back({{}, vk::ShaderStageFlagBits::eCallableKHR, call0, "main"});
callGroup.setGeneralShader(static_cast<uint32_t>(stages.size() - 1)); callGroup.setGeneralShader(static_cast<uint32_t>(stages.size() - 1));
m_rtShaderGroups.push_back(callGroup); m_rtShaderGroups.push_back(callGroup);
stages.push_back({{}, vk::ShaderStageFlagBits::eCallableKHR, call1, "main"}); stages.push_back({{}, vk::ShaderStageFlagBits::eCallableKHR, call1, "main"});
callGroup.setGeneralShader(static_cast<uint32_t>(stages.size() - 1)); callGroup.setGeneralShader(static_cast<uint32_t>(stages.size() - 1));
m_rtShaderGroups.push_back(callGroup); m_rtShaderGroups.push_back(callGroup);
stages.push_back({{}, vk::ShaderStageFlagBits::eCallableKHR, call2, "main"}); stages.push_back({{}, vk::ShaderStageFlagBits::eCallableKHR, call2, "main"});
callGroup.setGeneralShader(static_cast<uint32_t>(stages.size() - 1)); callGroup.setGeneralShader(static_cast<uint32_t>(stages.size() - 1));
m_rtShaderGroups.push_back(callGroup); m_rtShaderGroups.push_back(callGroup);
~~~~ ~~~~
And at the end of the function, delete the shaders. And at the end of the function, delete the shaders.

View file

@ -117,13 +117,13 @@ Replace the definition of buffers and textures and include the right allocator.
~~~~ C++ ~~~~ C++
#if defined(ALLOC_DEDICATED) #if defined(ALLOC_DEDICATED)
#include "nvvkpp/allocator_dedicated_vkpp.hpp" #include "nvvk/allocator_dedicated_vk.hpp"
using nvvkBuffer = nvvkpp::BufferDedicated; using nvvkBuffer = nvvk::BufferDedicated;
using nvvkTexture = nvvkpp::TextureDedicated; using nvvkTexture = nvvk::TextureDedicated;
#elif defined(ALLOC_DMA) #elif defined(ALLOC_DMA)
#include "nvvkpp/allocator_dma_vkpp.hpp" #include "nvvk/allocator_dma_vk.hpp"
using nvvkBuffer = nvvkpp::BufferDma; using nvvkBuffer = nvvk::BufferDma;
using nvvkTexture = nvvkpp::TextureDma; using nvvkTexture = nvvk::TextureDma;
#endif #endif
~~~~ ~~~~
@ -131,10 +131,11 @@ And do the same for the allocator
~~~~ C++ ~~~~ C++
#if defined(ALLOC_DEDICATED) #if defined(ALLOC_DEDICATED)
nvvkpp::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures nvvk::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures
#elif defined(ALLOC_DMA) #elif defined(ALLOC_DMA)
nvvkpp::AllocatorDma m_alloc; // Allocator for buffer, images, acceleration structures nvvk::AllocatorDma m_alloc; // Allocator for buffer, images, acceleration structures
nvvk::DeviceMemoryAllocator m_dmaAllocator; nvvk::DeviceMemoryAllocator m_memAllocator;
nvvk::StagingMemoryManagerDma m_staging;
#endif #endif
~~~~ ~~~~
@ -148,34 +149,24 @@ DMA needs to be initialized, which will be done in the `setup()` function:
#if defined(ALLOC_DEDICATED) #if defined(ALLOC_DEDICATED)
m_alloc.init(device, physicalDevice); m_alloc.init(device, physicalDevice);
#elif defined(ALLOC_DMA) #elif defined(ALLOC_DMA)
m_dmaAllocator.init(device, physicalDevice); m_memAllocator.init(device, physicalDevice);
m_alloc.init(device, &m_dmaAllocator); m_memAllocator.setAllocateFlags(VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR, true);
m_staging.init(m_memAllocator);
m_alloc.init(device, m_memAllocator, m_staging);
#endif #endif
~~~~ ~~~~
When using DMA, memory buffer mapping is done through the DMA interface (instead of the VKDevice). Therefore, change the lines at the end of `updateUniformBuffer()` to When using DMA, memory buffer mapping is done through the DMA interface (instead of the VKDevice).
Therefore, change the lines at the end of `updateUniformBuffer()` to use the common allocator interface.
~~~~ C++ ~~~~ C++
#if defined(ALLOC_DEDICATED) void* data = m_alloc.map(m_cameraMat);
void* data = m_device.mapMemory(m_cameraMat.allocation, 0, sizeof(CameraMatrices)); memcpy(data, &ubo, sizeof(ubo));
memcpy(data, &ubo, sizeof(ubo)); m_alloc.unmap(m_cameraMat);
m_device.unmapMemory(m_cameraMat.allocation);
#elif defined(ALLOC_DMA)
void* data = m_dmaAllocator.map(m_cameraMat.allocation);
memcpy(data, &ubo, sizeof(ubo));
m_dmaAllocator.unmap(m_cameraMat.allocation);
#endif
~~~~ ~~~~
The RaytracerBuilder was made to allow various allocators, but we still need to pass the right one in its setup function. Change the last line of `initRayTracing()` to The RaytracerBuilder was made to allow various allocators, therefore nothing to change in the call to `m_rtBuilder.setup()`
~~~~ C++
#if defined(ALLOC_DEDICATED)
m_rtBuilder.setup(m_device, m_physicalDevice, m_graphicsQueueIndex);
#elif defined(ALLOC_DMA)
m_rtBuilder.setup(m_device, m_dmaAllocator, m_graphicsQueueIndex);
#endif
~~~~
## Destruction ## Destruction
@ -204,7 +195,7 @@ We can also modify the code to use the [Vulkan Memory Allocator](https://github.
Download [vk_mem_alloc.h](https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator/blob/master/src/vk_mem_alloc.h) from GitHub and add this to the `shared_sources` folder. Download [vk_mem_alloc.h](https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator/blob/master/src/vk_mem_alloc.h) from GitHub and add this to the `shared_sources` folder.
There is already a variation of the allocator for VMA, which is located under [nvpro-samples](https://github.com/nvpro-samples/shared_sources/tree/master/nvvkpp). This allocator has the same simple interface as the `AllocatorDedicated` class in `allocator_dedicated_vkpp.hpp`, but will use VMA for memory management. There is already a variation of the allocator for VMA, which is located under [nvpro-samples](https://github.com/nvpro-samples/shared_sources/tree/master/nvvk). This allocator has the same simple interface as the `AllocatorDedicated` class in `allocator_dedicated_vkpp.hpp`, but will use VMA for memory management.
VMA might use dedicated memory, which we do, so you need to add the following extension to the VMA might use dedicated memory, which we do, so you need to add the following extension to the
creation of the context in `main.cpp`. creation of the context in `main.cpp`.
@ -223,15 +214,16 @@ Follow the changes done before and add the following
~~~~ C++ ~~~~ C++
#elif defined(ALLOC_VMA) #elif defined(ALLOC_VMA)
#include "nvvkpp/allocator_vma_vkpp.hpp" #include "nvvk/allocator_vma_vk.hpp"
using nvvkBuffer = nvvkpp::BufferVma; using nvvkBuffer = nvvk::BufferVma;
using nvvkTexture = nvvkpp::TextureVma; using nvvkTexture = nvvk::TextureVma;
~~~~ ~~~~
~~~~ C++ ~~~~ C++
#elif defined(ALLOC_VMA) #elif defined(ALLOC_VMA)
nvvkpp::AllocatorVma m_alloc; // Allocator for buffer, images, acceleration structures nvvk::AllocatorVma m_alloc; // Allocator for buffer, images, acceleration structures
VmaAllocator m_vmaAllocator; nvvk::StagingMemoryManagerVma m_staging;
VmaAllocator m_memAllocator;
~~~~ ~~~~
@ -247,21 +239,13 @@ In `setup()`
~~~~ C++ ~~~~ C++
#elif defined(ALLOC_VMA) #elif defined(ALLOC_VMA)
VmaAllocatorCreateInfo allocatorInfo = {}; VmaAllocatorCreateInfo allocatorInfo = {};
allocatorInfo.instance = instance;
allocatorInfo.physicalDevice = physicalDevice; allocatorInfo.physicalDevice = physicalDevice;
allocatorInfo.device = device; allocatorInfo.device = device;
allocatorInfo.flags = VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT; allocatorInfo.flags = VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT;
vmaCreateAllocator(&allocatorInfo, &m_vmaAllocator); vmaCreateAllocator(&allocatorInfo, &m_memAllocator);
m_alloc.init(device, m_vmaAllocator); m_staging.init(device, physicalDevice, m_memAllocator);
~~~~ m_alloc.init(device, m_memAllocator, m_staging);
In `updateUniformBuffer()`
~~~~ C++
#elif defined(ALLOC_VMA)
void* data;
vmaMapMemory(m_vmaAllocator, m_cameraMat.allocation, &data);
memcpy(data, &ubo, sizeof(ubo));
vmaUnmapMemory(m_vmaAllocator, m_cameraMat.allocation);
~~~~ ~~~~
In `destroyResources()` In `destroyResources()`
@ -271,25 +255,6 @@ In `destroyResources()`
vmaDestroyAllocator(m_vmaAllocator); vmaDestroyAllocator(m_vmaAllocator);
~~~~ ~~~~
In `initRayTracing()`
~~~~ C++
#elif defined(ALLOC_VMA)
m_rtBuilder.setup(m_device, m_vmaAllocator, m_graphicsQueueIndex);
~~~~
Additionally, VMA has its own usage flags, so since `VMA_MEMORY_USAGE_CPU_TO_GPU` maps to `vkMP::eHostVisible` and `vkMP::eHostCoherent`, change the call to `m_alloc.createBuffer` in `HelloVulkan::createUniformBuffer()` to
~~~~ C++
m_cameraMat = m_alloc.createBuffer(sizeof(CameraMatrices), vkBU::eUniformBuffer,
#if defined(ALLOC_DEDICATED) || defined(ALLOC_DMA)
vkMP::eHostVisible | vkMP::eHostCoherent
#elif defined(ALLOC_VMA)
VMA_MEMORY_USAGE_CPU_TO_GPU
#endif
);
~~~~
# Final Code # Final Code

View file

@ -65,8 +65,8 @@ All the information will need to be hold in buffers, which will be available to
Finally, there are two functions, one to create the spheres, and one that will create the intermediate structure for the BLAS. Finally, there are two functions, one to create the spheres, and one that will create the intermediate structure for the BLAS.
~~~~ C++ ~~~~ C++
void createSpheres(); void createSpheres();
nvvkpp::RaytracingBuilderKHR::Blas sphereToVkGeometryKHR(); nvvk::RaytracingBuilderKHR::Blas sphereToVkGeometryKHR();
~~~~ ~~~~
The following implementation will create 2.000.000 spheres at random positions and radius. It will create the Aabb from the sphere definition, two materials which will be assigned alternatively to each object. All the created information will be moved to Vulkan buffers to be accessed by the intersection and closest shaders. The following implementation will create 2.000.000 spheres at random positions and radius. It will create the Aabb from the sphere definition, two materials which will be assigned alternatively to each object. All the created information will be moved to Vulkan buffers to be accessed by the intersection and closest shaders.
@ -120,13 +120,13 @@ void HelloVulkan::createSpheres()
// Creating all buffers // Creating all buffers
using vkBU = vk::BufferUsageFlagBits; using vkBU = vk::BufferUsageFlagBits;
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex); nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
auto cmdBuf = genCmdBuf.createCommandBuffer(); auto cmdBuf = genCmdBuf.createCommandBuffer();
m_spheresBuffer = m_alloc.createBuffer(cmdBuf, m_spheres, vkBU::eStorageBuffer); m_spheresBuffer = m_alloc.createBuffer(cmdBuf, m_spheres, vkBU::eStorageBuffer);
m_spheresAabbBuffer = m_alloc.createBuffer(cmdBuf, aabbs); m_spheresAabbBuffer = m_alloc.createBuffer(cmdBuf, aabbs, vkBU::eShaderDeviceAddress);
m_spheresMatIndexBuffer = m_alloc.createBuffer(cmdBuf, matIdx, vkBU::eStorageBuffer); m_spheresMatIndexBuffer = m_alloc.createBuffer(cmdBuf, matIdx, vkBU::eStorageBuffer);
m_spheresMatColorBuffer = m_alloc.createBuffer(cmdBuf, materials, vkBU::eStorageBuffer); m_spheresMatColorBuffer = m_alloc.createBuffer(cmdBuf, materials, vkBU::eStorageBuffer);
genCmdBuf.flushCommandBuffer(cmdBuf); genCmdBuf.submitAndWait(cmdBuf);
// Debug information // Debug information
m_debug.setObjectName(m_spheresBuffer.buffer, "spheres"); m_debug.setObjectName(m_spheresBuffer.buffer, "spheres");
@ -153,7 +153,7 @@ What is changing compare to triangle primitive is the Aabb data (see Aabb struct
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Returning the ray tracing geometry used for the BLAS, containing all spheres // Returning the ray tracing geometry used for the BLAS, containing all spheres
// //
nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::sphereToVkGeometryKHR() nvvk::RaytracingBuilderKHR::Blas HelloVulkan::sphereToVkGeometryKHR()
{ {
vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate; vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate;
asCreate.setGeometryType(vk::GeometryTypeKHR::eAabbs); asCreate.setGeometryType(vk::GeometryTypeKHR::eAabbs);
@ -181,7 +181,7 @@ nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::sphereToVkGeometryKHR()
offset.setPrimitiveOffset(0); offset.setPrimitiveOffset(0);
offset.setTransformOffset(0); offset.setTransformOffset(0);
nvvkpp::RaytracingBuilderKHR::Blas blas; nvvk::RaytracingBuilderKHR::Blas blas;
blas.asGeometry.emplace_back(asGeom); blas.asGeometry.emplace_back(asGeom);
blas.asCreateGeometryInfo.emplace_back(asCreate); blas.asCreateGeometryInfo.emplace_back(asCreate);
blas.asBuildOffsetInfo.emplace_back(offset); blas.asBuildOffsetInfo.emplace_back(offset);
@ -217,7 +217,7 @@ The function `createBottomLevelAS()` is creating a BLAS per OBJ, the following m
void HelloVulkan::createBottomLevelAS() void HelloVulkan::createBottomLevelAS()
{ {
// BLAS - Storing each primitive in a geometry // BLAS - Storing each primitive in a geometry
std::vector<nvvkpp::RaytracingBuilderKHR::Blas> allBlas; std::vector<nvvk::RaytracingBuilderKHR::Blas> allBlas;
allBlas.reserve(m_objModel.size()); allBlas.reserve(m_objModel.size());
for(const auto& obj : m_objModel) for(const auto& obj : m_objModel)
{ {
@ -248,7 +248,7 @@ Just before building the TLAS, we need to add the following
~~~~ C++ ~~~~ C++
// Add the blas containing all spheres // Add the blas containing all spheres
{ {
nvvkpp::RaytracingBuilder::Instance rayInst; nvvk::RaytracingBuilder::Instance rayInst;
rayInst.transform = m_objInstance[0].transform; // Position of the instance rayInst.transform = m_objInstance[0].transform; // Position of the instance
rayInst.instanceId = static_cast<uint32_t>(tlas.size()); // gl_InstanceID rayInst.instanceId = static_cast<uint32_t>(tlas.size()); // gl_InstanceID
rayInst.blasId = static_cast<uint32_t>(m_objModel.size()); rayInst.blasId = static_cast<uint32_t>(m_objModel.size());
@ -301,7 +301,7 @@ Then write the buffer for the spheres
~~~~ C++ ~~~~ C++
vk::DescriptorBufferInfo dbiSpheres{m_spheresBuffer.buffer, 0, VK_WHOLE_SIZE}; vk::DescriptorBufferInfo dbiSpheres{m_spheresBuffer.buffer, 0, VK_WHOLE_SIZE};
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[7], &dbiSpheres)); writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 7, dbiSpheres));
~~~~ ~~~~
## Intersection Shader ## Intersection Shader
@ -313,13 +313,13 @@ Here is how the two hit group looks like:
~~~~ C++ ~~~~ C++
// Hit Group0 - Closest Hit // Hit Group0 - Closest Hit
vk::ShaderModule chitSM = vk::ShaderModule chitSM =
nvvkpp::util::createShaderModule(m_device, // nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rchit.spv", true, paths)); nvh::loadFile("shaders/raytrace.rchit.spv", true, paths));
{ {
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup, vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup,
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR,
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR}; VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR};
stages.push_back({{}, vk::ShaderStageFlagBits::eClosestHitKHR, chitSM, "main"}); stages.push_back({{}, vk::ShaderStageFlagBits::eClosestHitKHR, chitSM, "main"});
hg.setClosestHitShader(static_cast<uint32_t>(stages.size() - 1)); hg.setClosestHitShader(static_cast<uint32_t>(stages.size() - 1));
m_rtShaderGroups.push_back(hg); m_rtShaderGroups.push_back(hg);
@ -327,15 +327,15 @@ Here is how the two hit group looks like:
// Hit Group1 - Closest Hit + Intersection (procedural) // Hit Group1 - Closest Hit + Intersection (procedural)
vk::ShaderModule chit2SM = vk::ShaderModule chit2SM =
nvvkpp::util::createShaderModule(m_device, // nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace2.rchit.spv", true, paths)); nvh::loadFile("shaders/raytrace2.rchit.spv", true, paths));
vk::ShaderModule rintSM = vk::ShaderModule rintSM =
nvvkpp::util::createShaderModule(m_device, // nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rint.spv", true, paths)); nvh::loadFile("shaders/raytrace.rint.spv", true, paths));
{ {
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eProceduralHitGroup, vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eProceduralHitGroup,
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR,
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR}; VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR};
stages.push_back({{}, vk::ShaderStageFlagBits::eClosestHitKHR, chit2SM, "main"}); stages.push_back({{}, vk::ShaderStageFlagBits::eClosestHitKHR, chit2SM, "main"});
hg.setClosestHitShader(static_cast<uint32_t>(stages.size() - 1)); hg.setClosestHitShader(static_cast<uint32_t>(stages.size() - 1));
stages.push_back({{}, vk::ShaderStageFlagBits::eIntersectionKHR, rintSM, "main"}); stages.push_back({{}, vk::ShaderStageFlagBits::eIntersectionKHR, rintSM, "main"});

View file

@ -60,8 +60,8 @@ This new shader needs to be added to the raytracing pipeline. So, in `createRtPi
~~~~ C++ ~~~~ C++
vk::ShaderModule chit2SM = vk::ShaderModule chit2SM =
nvvkpp::util::createShaderModule(m_device, // nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace2.rchit.spv", true, paths)); nvh::loadFile("shaders/raytrace2.rchit.spv", true, paths));
~~~~ ~~~~
Then add a new hit group group immediately after adding the first hit group: Then add a new hit group group immediately after adding the first hit group:

View file

@ -30,13 +30,13 @@ Remove most functions and members to keep only what is need to create the accele
~~~~ C++ ~~~~ C++
// #VKRay // #VKRay
void initRayTracing(); void initRayTracing();
nvvkpp::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model); nvvk::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
void createBottomLevelAS(); void createBottomLevelAS();
void createTopLevelAS(); void createTopLevelAS();
vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties; vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties;
nvvkpp::RaytracingBuilderKHR m_rtBuilder; nvvk::RaytracingBuilderKHR m_rtBuilder;
~~~~ ~~~~
## hello_vulkan (source) ## hello_vulkan (source)
@ -61,10 +61,11 @@ m_descSetLayoutBind.emplace_back( //
In `HelloVulkan::updateDescriptorSet`, write the value to the descriptor set. In `HelloVulkan::updateDescriptorSet`, write the value to the descriptor set.
~~~~ C++ ~~~~ C++
vk::WriteDescriptorSetAccelerationStructureKHR descASInfo; vk::AccelerationStructureKHR tlas = m_rtBuilder.getAccelerationStructure();
descASInfo.setAccelerationStructureCount(1); vk::WriteDescriptorSetAccelerationStructureKHR descASInfo;
descASInfo.setPAccelerationStructures(&m_rtBuilder.getAccelerationStructure()); descASInfo.setAccelerationStructureCount(1);
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[7], &descASInfo)); descASInfo.setPAccelerationStructures(&tlas);
writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 7, descASInfo));
~~~~ ~~~~

View file

@ -14,11 +14,14 @@ methods and functions. The sections are organized by components, with subsection
![Final Result](Images/resultRaytraceShadowMedieval.png width="350px") ![Final Result](Images/resultRaytraceShadowMedieval.png width="350px")
!!! Note GitHub repository
https://github.com/nvpro-samples/vk_raytracing_tutorial_KHR
# Introduction # Introduction
<script type="preformatted"> <script type="preformatted">
This tutorial highlights the steps to add ray tracing to an existing Vulkan application, and assumes a working knowledge This tutorial highlights the steps to add ray tracing to an existing Vulkan application, and assumes a working knowledge
of Vulkan in general. The code verbosity of classical components such as swapchain management, render passes etc. is of Vulkan in general. The code verbosity of classical components such as swapchain management, render passes etc. is
reduced using [C++ API helpers](https://github.com/nvpro-samples/shared_sources/tree/master/nvvkpp) and reduced using [C++ API helpers](https://github.com/nvpro-samples/shared_sources/tree/master/nvvk) and
NVIDIA's [nvpro-samples](https://github.com/nvpro-samples/build_all) framework. This framework contains many advanced NVIDIA's [nvpro-samples](https://github.com/nvpro-samples/build_all) framework. This framework contains many advanced
examples and best practices for Vulkan and OpenGL. We also use a helper for the creation of the ray tracing acceleration examples and best practices for Vulkan and OpenGL. We also use a helper for the creation of the ray tracing acceleration
structures, but we will document its contents extensively in this tutorial. The code is further simplified by using the structures, but we will document its contents extensively in this tutorial. The code is further simplified by using the
@ -36,17 +39,15 @@ verbosity and its potential for errors.
## Beta Installation ## Beta Installation
If you are in the Beta period, install and compile all of the following The SDK 1.2.135 and up which can be found under https://vulkan.lunarg.com/sdk/home will work with this project.
Nevertheless, if you are in the Beta period, it is suggested to install and compile all of the following and replace
with the current environment.
* Latest driver: https://developer.nvidia.com/vulkan-driver * Latest driver: https://developer.nvidia.com/vulkan-driver
* Latest Vulkan headers: https://github.com/KhronosGroup/Vulkan-Headers * Latest Vulkan headers: https://github.com/KhronosGroup/Vulkan-Headers
* Latest glslangValidator: https://github.com/KhronosGroup/glslang * Latest glslangValidator: https://github.com/KhronosGroup/glslang
!!! Warning Beta
Copy/replace `glslangValidator.exe` in the VulkanSDK bin directory.<br>
Ex: `C:\VulkanSDK\1.2.131.1\Bin`
## Structure ## Structure
This tutorial is a modification of [`ray_tracing__before`](https://github.com/nvpro-samples/vk_raytracing_tutorial_KHR/tree/master/ray_tracing__before), which loads are render OBJ scenes with Vulkan rasterizer. This tutorial is a modification of [`ray_tracing__before`](https://github.com/nvpro-samples/vk_raytracing_tutorial_KHR/tree/master/ray_tracing__before), which loads are render OBJ scenes with Vulkan rasterizer.
@ -83,6 +84,10 @@ The directory structure should be looking like:
!!! Warning Beta !!! Warning Beta
Modify `VULKAN > VULKAN_HEADERS_OVERRIDE_INCLUDE_DIR` to the path to beta vulkan headers. Modify `VULKAN > VULKAN_HEADERS_OVERRIDE_INCLUDE_DIR` to the path to beta vulkan headers.
!!! Tip Visual Assist
To get auto-completion, edit vulkan.hpp and change two places from:<br>
`namespace VULKAN_HPP_NAMESPACE` to `namespace vk`
The starting project is a simple framework allowing us to load OBJ files and rasterize them The starting project is a simple framework allowing us to load OBJ files and rasterize them
using Vulkan. using Vulkan.
@ -93,7 +98,7 @@ using Vulkan.
# Ray Tracing Setup # Ray Tracing Setup
Go to the `main` function of the `main.cpp` file, and find where we request Vulkan extensions with Go to the `main` function of the `main.cpp` file, and find where we request Vulkan extensions with
`nvvkpp::ContextCreateInfo`. `nvvk::ContextCreateInfo`.
To request ray tracing capabilities, we need to explicitly To request ray tracing capabilities, we need to explicitly
add the add the
[VK_KHR_ray_tracing](https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#VK_KHR_ray_tracing) [VK_KHR_ray_tracing](https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#VK_KHR_ray_tracing)
@ -183,32 +188,32 @@ In the header file, include the`raytrace_vkpp` helper
```` C ```` C
// #VKRay // #VKRay
#define ALLOC_DEDICATED #define ALLOC_DEDICATED
#include "nvvkpp/raytrace_vkpp.hpp" #include "nvvk/raytrace_vk.hpp"
```` ````
so that we can add that helper as a member in the `HelloVulkan` class, so that we can add that helper as a member in the `HelloVulkan` class,
```` C ```` C
nvvkpp::RaytracingBuilder m_rtBuilder; nvvk::RaytracingBuilder m_rtBuilder;
```` ````
and initialize it at the end of `initRaytracing()`: and initialize it at the end of `initRaytracing()`:
```` C ```` C
m_rtBuilder.setup(m_device, m_physicalDevice, m_graphicsQueueIndex); m_rtBuilder.setup(m_device, m_alloc, m_graphicsQueueIndex);
```` ````
## Bottom-Level Acceleration Structure ## Bottom-Level Acceleration Structure
The first step of building a BLAS object consists in converting the geometry data of an `ObjModel` into a The first step of building a BLAS object consists in converting the geometry data of an `ObjModel` into a
multiple structures than can be used by the AS builder. We are holding all those structure under multiple structures than can be used by the AS builder. We are holding all those structure under
`nvvkpp::RaytracingBuilderKHR::Blas` `nvvk::RaytracingBuilderKHR::Blas`
Add a new method to the `HelloVulkan` Add a new method to the `HelloVulkan`
class: class:
```` C ```` C
nvvkpp::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model); nvvk::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
```` ````
Its implementation will fill three structures Its implementation will fill three structures
@ -226,7 +231,7 @@ potential optimization.
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Converting a OBJ primitive to the ray tracing geometry used for the BLAS // Converting a OBJ primitive to the ray tracing geometry used for the BLAS
// //
nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model) nvvk::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model)
{ {
// Setting up the creation info of acceleration structure // Setting up the creation info of acceleration structure
vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate; vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate;
@ -263,7 +268,7 @@ nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjM
offset.setTransformOffset(0); offset.setTransformOffset(0);
// Our blas is only one geometry, but could be made of many geometries // Our blas is only one geometry, but could be made of many geometries
nvvkpp::RaytracingBuilderKHR::Blas blas; nvvk::RaytracingBuilderKHR::Blas blas;
blas.asGeometry.emplace_back(asGeom); blas.asGeometry.emplace_back(asGeom);
blas.asCreateGeometryInfo.emplace_back(asCreate); blas.asCreateGeometryInfo.emplace_back(asCreate);
blas.asBuildOffsetInfo.emplace_back(offset); blas.asBuildOffsetInfo.emplace_back(offset);
@ -273,13 +278,13 @@ nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjM
```` ````
In the `HelloVulkan` class declaration, we can now add the `createBottomLevelAS()` method that will generate a In the `HelloVulkan` class declaration, we can now add the `createBottomLevelAS()` method that will generate a
`nvvkpp::RaytracingBuilderKHR::Blas` for each object, and trigger a BLAS build: `nvvk::RaytracingBuilderKHR::Blas` for each object, and trigger a BLAS build:
```` C ```` C
void createBottomLevelAS(); void createBottomLevelAS();
```` ````
The implementation loops over all the loaded models and fills in an array of `nvvkpp::RaytracingBuilderKHR::Blas` before The implementation loops over all the loaded models and fills in an array of `nvvk::RaytracingBuilderKHR::Blas` before
triggering a build of all BLAS's in a batch. The resulting acceleration structures will be stored triggering a build of all BLAS's in a batch. The resulting acceleration structures will be stored
within the helper in the order of construction, so that they can be directly referenced by index later. within the helper in the order of construction, so that they can be directly referenced by index later.
@ -287,7 +292,7 @@ within the helper in the order of construction, so that they can be directly ref
void HelloVulkan::createBottomLevelAS() void HelloVulkan::createBottomLevelAS()
{ {
// BLAS - Storing each primitive in a geometry // BLAS - Storing each primitive in a geometry
std::vector<nvvkpp::RaytracingBuilderKHR::Blas> allBlas; std::vector<nvvk::RaytracingBuilderKHR::Blas> allBlas;
allBlas.reserve(m_objModel.size()); allBlas.reserve(m_objModel.size());
for(const auto& obj : m_objModel) for(const auto& obj : m_objModel)
{ {
@ -308,27 +313,34 @@ part of the set of helpers provided by the [nvpro-samples](https://github.com/nv
will generate one BLAS for each `RaytracingBuilderKHR::Blas`: will generate one BLAS for each `RaytracingBuilderKHR::Blas`:
```` C ```` C
void buildBlas(const std::vector<RaytracingBuilderKHR::Blas>& blas_, void buildBlas(const std::vector<RaytracingBuilderKHR::Blas>& blas_,
vk::BuildAccelerationStructureFlagsKHR flags = vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace) VkBuildAccelerationStructureFlagsKHR flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR)
{
m_blas = blas_; // Keeping a copy
vk::DeviceSize maxScratch{0};
// Iterate over the groups of geometries, creating one BLAS for each group
int idx{0};
for(auto& blas : m_blas)
{ {
m_blas = blas_; // Keeping a copy
VkDeviceSize maxScratch{0}; // Largest scratch buffer for our BLAS
// Is compaction requested?
bool doCompaction = (flags & VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR)
== VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR;
std::vector<VkDeviceSize> originalSizes;
originalSizes.resize(m_blas.size());
// Iterate over the groups of geometries, creating one BLAS for each group
int idx{0};
for(auto& blas : m_blas)
{
```` ````
The creation of the acceleration structure needs all `vk::AccelerationStructureCreateGeometryTypeInfoKHR` previously set and The creation of the acceleration structure needs all `vk::AccelerationStructureCreateGeometryTypeInfoKHR` previously set and
set into `vk::AccelerationStructureCreateInfoKHR`. set into `vk::AccelerationStructureCreateInfoKHR`.
```` C ```` C
vk::AccelerationStructureCreateInfoKHR asCreateInfo{{}, vk::AccelerationStructureTypeKHR::eBottomLevel}; VkAccelerationStructureCreateInfoKHR asCreateInfo{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR};
asCreateInfo.setFlags(flags); asCreateInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;
asCreateInfo.setMaxGeometryCount((uint32_t)blas.asCreateGeometryInfo.size()); asCreateInfo.flags = flags;
asCreateInfo.setPGeometryInfos(blas.asCreateGeometryInfo.data()); asCreateInfo.maxGeometryCount = (uint32_t)blas.asCreateGeometryInfo.size();
asCreateInfo.pGeometryInfos = blas.asCreateGeometryInfo.data();
```` ````
The creation information is then passed to the allocator, that will internally create an acceleration structure handle. The creation information is then passed to the allocator, that will internally create an acceleration structure handle.
@ -336,88 +348,186 @@ It will also query `vk::Device::getAccelerationStructureMemoryRequirementsKHR` t
and allocate memory accordingly. and allocate memory accordingly.
```` C ```` C
// Create an acceleration structure identifier and allocate memory to store the // Create an acceleration structure identifier and allocate memory to
// resulting structure data // store the resulting structure data
blas.as = m_alloc.createAcceleration(createinfo); blas.as = m_alloc.createAcceleration(asCreateInfo);
m_debug.setObjectName(blas.as.accel, (std::string("Blas" + std::to_string(idx)).c_str())); m_debug.setObjectName(blas.as.accel, (std::string("Blas" + std::to_string(idx)).c_str()));
```` ````
The acceleration structure builder requires some scratch memory to generate the BLAS. Since we generate all the The acceleration structure builder requires some scratch memory to generate the BLAS. Since we generate all the
BLAS's in a batch, we query the scratch memory requirements for each BLAS, and find the maximum such requirement. BLAS's in a batch, we query the scratch memory requirements for each BLAS, and find the maximum such requirement.
```` C ```` C
// Estimate the amount of scratch memory required to build the BLAS, and update the // Estimate the amount of scratch memory required to build the BLAS, and
// size of the scratch buffer that will be allocated to sequentially build all BLASes // update the size of the scratch buffer that will be allocated to
vk::AccelerationStructureMemoryRequirementsInfoKHR memoryRequirementsInfo{ // sequentially build all BLASes
vk::AccelerationStructureMemoryRequirementsTypeKHR::eBuildScratch, VkAccelerationStructureMemoryRequirementsInfoKHR memoryRequirementsInfo{
vk::AccelerationStructureBuildTypeKHR::eDevice, blas.as.accel}; VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_KHR};
vk::DeviceSize scratchSize = memoryRequirementsInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_KHR;
m_device.getAccelerationStructureMemoryRequirementsKHR(memoryRequirementsInfo).memoryRequirements.size; memoryRequirementsInfo.accelerationStructure = blas.as.accel;
memoryRequirementsInfo.buildType = VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR;
blas.flags = flags;
maxScratch = std::max(maxScratch, scratchSize); VkMemoryRequirements2 reqMem{VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2};
idx++; vkGetAccelerationStructureMemoryRequirementsKHR(m_device, &memoryRequirementsInfo, &reqMem);
} VkDeviceSize scratchSize = reqMem.memoryRequirements.size;
blas.flags = flags;
maxScratch = std::max(maxScratch, scratchSize);
// Original size
memoryRequirementsInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_KHR;
vkGetAccelerationStructureMemoryRequirementsKHR(m_device, &memoryRequirementsInfo, &reqMem);
originalSizes[idx] = reqMem.memoryRequirements.size;
idx++;
}
```` ````
Once that maximum has been found, we allocate a scratch buffer. Once that maximum has been found, we allocate a scratch buffer.
```` C ```` C
// Allocate the scratch buffers holding the temporary data of the acceleration structure builder // Allocate the scratch buffers holding the temporary data of the acceleration structure builder
nvvkBuffer scratchBuffer = m_alloc.createBuffer(maxScratch, vk::BufferUsageFlagBits::eRayTracingKHR nvvkBuffer scratchBuffer =
| vk::BufferUsageFlagBits::eShaderDeviceAddress); m_alloc.createBuffer(maxScratch, VK_BUFFER_USAGE_RAY_TRACING_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
vk::DeviceAddress scratchAddress = m_device.getBufferAddress({scratchBuffer.buffer}); VkBufferDeviceAddressInfo bufferInfo{VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO};
bufferInfo.buffer = scratchBuffer.buffer;
VkDeviceAddress scratchAddress = vkGetBufferDeviceAddress(m_device, &bufferInfo);
```` ````
To know the size that the BLAS is really taking, we use queries.
```` C
// Query size of compact BLAS
VkQueryPoolCreateInfo qpci{VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO};
qpci.queryCount = (uint32_t)m_blas.size();
qpci.queryType = VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR;
VkQueryPool queryPool;
vkCreateQueryPool(m_device, &qpci, nullptr, &queryPool);
````
We then use a one-time command buffer to launch all the BLAS builds. Note the barrier after each We then use a one-time command buffer to launch all the BLAS builds. Note the barrier after each
build call: this is required as we reuse the scratch space across builds, and hence need to ensure build call: this is required as we reuse the scratch space across builds, and hence need to ensure
the previous build has completed before starting the next. the previous build has completed before starting the next.
```` C ```` C
// Create a command buffer containing all the BLAS builds // Query size of compact BLAS
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_queueIndex); VkQueryPoolCreateInfo qpci{VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO};
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer(); qpci.queryCount = (uint32_t)m_blas.size();
qpci.queryType = VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR;
VkQueryPool queryPool;
vkCreateQueryPool(m_device, &qpci, nullptr, &queryPool);
// Create a command buffer containing all the BLAS builds
nvvk::CommandPool genCmdBuf(m_device, m_queueIndex);
VkCommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
int ctr{0};
for(auto& blas : m_blas) for(auto& blas : m_blas)
{ {
const vk::AccelerationStructureGeometryKHR* pGeometry = blas.asGeometry.data(); const VkAccelerationStructureGeometryKHR* pGeometry = blas.asGeometry.data();
vk::AccelerationStructureBuildGeometryInfoKHR bottomASInfo{vk::AccelerationStructureTypeKHR::eBottomLevel}; VkAccelerationStructureBuildGeometryInfoKHR bottomASInfo{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR};
bottomASInfo.setFlags(flags); bottomASInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;
bottomASInfo.setUpdate(VK_FALSE); bottomASInfo.flags = flags;
bottomASInfo.setSrcAccelerationStructure({}); bottomASInfo.update = VK_FALSE;
bottomASInfo.setDstAccelerationStructure(blas.as.accel); bottomASInfo.srcAccelerationStructure = VK_NULL_HANDLE;
bottomASInfo.setGeometryArrayOfPointers(VK_FALSE); bottomASInfo.dstAccelerationStructure = blas.as.accel;
bottomASInfo.setGeometryCount((uint32_t)blas.asGeometry.size()); bottomASInfo.geometryArrayOfPointers = VK_FALSE;
bottomASInfo.setPpGeometries(&pGeometry); bottomASInfo.geometryCount = (uint32_t)blas.asGeometry.size();
bottomASInfo.setScratchData(scratchAddress); bottomASInfo.ppGeometries = &pGeometry;
bottomASInfo.scratchData.deviceAddress = scratchAddress;
// Pointers of offset // Pointers of offset
std::vector<const vk::AccelerationStructureBuildOffsetInfoKHR*> pBuildOffset(blas.asBuildOffsetInfo.size()); std::vector<const VkAccelerationStructureBuildOffsetInfoKHR*> pBuildOffset(blas.asBuildOffsetInfo.size());
for(size_t i = 0; i < blas.asBuildOffsetInfo.size(); i++) for(size_t i = 0; i < blas.asBuildOffsetInfo.size(); i++)
pBuildOffset[i] = &blas.asBuildOffsetInfo[i]; pBuildOffset[i] = &blas.asBuildOffsetInfo[i];
// Building the AS // Building the AS
cmdBuf.buildAccelerationStructureKHR(bottomASInfo, pBuildOffset); vkCmdBuildAccelerationStructureKHR(cmdBuf, 1, &bottomASInfo, pBuildOffset.data());
// Since the scratch buffer is reused across builds, we need a barrier to ensure one build // Since the scratch buffer is reused across builds, we need a barrier to ensure one build
// is finished before starting the next one // is finished before starting the next one
vk::MemoryBarrier barrier(vk::AccessFlagBits::eAccelerationStructureWriteKHR, vk::AccessFlagBits::eAccelerationStructureWriteKHR); VkMemoryBarrier barrier{VK_STRUCTURE_TYPE_MEMORY_BARRIER};
cmdBuf.pipelineBarrier(vk::PipelineStageFlagBits::eAccelerationStructureBuildKHR, barrier.srcAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR;
vk::PipelineStageFlagBits::eAccelerationStructureBuildKHR, {}, {barrier}, {}, {}); barrier.dstAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR;
vkCmdPipelineBarrier(cmdBuf, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR,
VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, 0, 1, &barrier, 0, nullptr, 0, nullptr);
// Query the compact size
if(doCompaction)
{
vkCmdWriteAccelerationStructuresPropertiesKHR(cmdBuf, 1, &blas.as.accel,
VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, queryPool, ctr++);
}
}
genCmdBuf.submitAndWait(cmdBuf);
````
While this approach has the advantage of keeping all BLAS's independent, building many BLAS's efficiently would
require allocating a larger scratch buffer, and launch several builds simultaneously. This tutorial also
does not use compaction, which could reduce significantly the memory footprint of the acceleration structures. Both
of those aspects will be part of a future advanced tutorial.
We finally execute the command buffer and clean up the allocator's scratch memory and staging buffer:
This part, which is optional, will compact the BLAS in the memory that it is really using. It needs to wait that all BLASes
are constructred, to make a copy in the more fitted memory space.
```` C
// Compacting all BLAS
if(doCompaction)
{
cmdBuf = genCmdBuf.createCommandBuffer();
// Get the size result back
std::vector<VkDeviceSize> compactSizes(m_blas.size());
vkGetQueryPoolResults(m_device, queryPool, 0, (uint32_t)compactSizes.size(), compactSizes.size() * sizeof(VkDeviceSize),
compactSizes.data(), sizeof(VkDeviceSize), VK_QUERY_RESULT_WAIT_BIT);
// Compacting
std::vector<nvvkAccel> cleanupAS(m_blas.size());
uint32_t totOriginalSize{0}, totCompactSize{0};
for(int i = 0; i < m_blas.size(); i++)
{
LOGI("Reducing %i, from %d to %d \n", i, originalSizes[i], compactSizes[i]);
totOriginalSize += (uint32_t)originalSizes[i];
totCompactSize += (uint32_t)compactSizes[i];
// Creating a compact version of the AS
VkAccelerationStructureCreateInfoKHR asCreateInfo{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR};
asCreateInfo.compactedSize = compactSizes[i];
asCreateInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;
asCreateInfo.flags = flags;
auto as = m_alloc.createAcceleration(asCreateInfo);
// Copy the original BLAS to a compact version
VkCopyAccelerationStructureInfoKHR copyInfo{VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_INFO_KHR};
copyInfo.src = m_blas[i].as.accel;
copyInfo.dst = as.accel;
copyInfo.mode = VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR;
vkCmdCopyAccelerationStructureKHR(cmdBuf, &copyInfo);
cleanupAS[i] = m_blas[i].as;
m_blas[i].as = as;
}
genCmdBuf.submitAndWait(cmdBuf);
// Destroying the previous version
for(auto as : cleanupAS)
m_alloc.destroy(as);
LOGI("------------------\n");
LOGI("Total: %d -> %d = %d (%2.2f%s smaller) \n", totOriginalSize, totCompactSize,
totOriginalSize - totCompactSize, (totOriginalSize - totCompactSize) / float(totOriginalSize) * 100.f, "%%");
} }
```` ````
While this approach has the advantage of keeping all BLAS's independent, building many BLAS's efficiently would Finally, destroying what was allocated.
require allocating a larger scratch buffer, and launch several builds simultaneously. This tutorial also
does not use compaction, which could reduce significantly the memory footprint of the acceleration structures. Both
of those aspects will be part of a future advanced tutorial.
We finally execute the command buffer and clean up the allocator's scratch memory and staging buffer:
```` C ```` C
genCmdBuf.flushCommandBuffer(cmdBuf); vkDestroyQueryPool(m_device, queryPool, nullptr);
m_alloc.destroy(scratchBuffer); m_alloc.destroy(scratchBuffer);
m_alloc.flushStaging(); m_alloc.finalizeAndReleaseStaging();
} }
```` ````
@ -430,7 +540,7 @@ to the `HelloVulkan` class:
void createTopLevelAS(); void createTopLevelAS();
```` ````
An instance is represented by a `nvvkpp::RaytracingBuilder::Instance`, which stores its transform matrix (`transform`) An instance is represented by a `nvvk::RaytracingBuilder::Instance`, which stores its transform matrix (`transform`)
and the identifier of its corresponding BLAS (`blasId`). It also contains an instance identifier that will be available and the identifier of its corresponding BLAS (`blasId`). It also contains an instance identifier that will be available
during shading as `gl_InstanceCustomIndex`, as well as the index of the hit group that represents the shaders that will be during shading as `gl_InstanceCustomIndex`, as well as the index of the hit group that represents the shaders that will be
invoked upon hitting the object (`hitGroupId`). invoked upon hitting the object (`hitGroupId`).
@ -447,16 +557,16 @@ optimized for tracing performance (rather than AS size, for example).
```` C ```` C
void HelloVulkan::createTopLevelAS() void HelloVulkan::createTopLevelAS()
{ {
std::vector<nvvkpp::RaytracingBuilderKHR::Instance> tlas; std::vector<nvvk::RaytracingBuilderKHR::Instance> tlas;
tlas.reserve(m_objInstance.size()); tlas.reserve(m_objInstance.size());
for(int i = 0; i < static_cast<int>(m_objInstance.size()); i++) for(int i = 0; i < static_cast<int>(m_objInstance.size()); i++)
{ {
nvvkpp::RaytracingBuilderKHR::Instance rayInst; nvvk::RaytracingBuilderKHR::Instance rayInst;
rayInst.transform = m_objInstance[i].transform; // Position of the instance rayInst.transform = m_objInstance[i].transform; // Position of the instance
rayInst.instanceId = i; // gl_InstanceID rayInst.instanceId = i; // gl_InstanceID
rayInst.blasId = m_objInstance[i].objIndex; rayInst.blasId = m_objInstance[i].objIndex;
rayInst.hitGroupId = 0; // We will use the same hit group for all objects rayInst.hitGroupId = 0; // We will use the same hit group for all objects
rayInst.flags = vk::GeometryInstanceFlagBitsKHR::eTriangleCullDisable; rayInst.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
tlas.emplace_back(rayInst); tlas.emplace_back(rayInst);
} }
m_rtBuilder.buildTlas(tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace); m_rtBuilder.buildTlas(tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace);
@ -480,21 +590,21 @@ the number of instances it will hold, and flags indicating preferences for the b
builds or better performance. builds or better performance.
```` C ```` C
void buildTlas(const std::vector<Instance>& instances, void buildTlas(const std::vector<Instance>& instances,
vk::BuildAccelerationStructureFlagsKHR flags = VkBuildAccelerationStructureFlagsKHR flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR)
vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace)
{
m_tlas.flags = flags;
{ {
vk::AccelerationStructureCreateGeometryTypeInfoKHR geometryCreate{vk::GeometryTypeKHR::eInstances}; m_tlas.flags = flags;
geometryCreate.setMaxPrimitiveCount(static_cast<uint32_t>(instances.size()));
geometryCreate.setAllowsTransforms(VK_TRUE); VkAccelerationStructureCreateGeometryTypeInfoKHR geometryCreate{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_GEOMETRY_TYPE_INFO_KHR};
geometryCreate.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR;
vk::AccelerationStructureCreateInfoKHR asCreateInfo{{}, vk::AccelerationStructureTypeKHR::eTopLevel}; geometryCreate.maxPrimitiveCount = (static_cast<uint32_t>(instances.size()));
asCreateInfo.setFlags(flags); geometryCreate.allowsTransforms = (VK_TRUE);
asCreateInfo.setMaxGeometryCount(1);
asCreateInfo.setPGeometryInfos(&geometryCreate); VkAccelerationStructureCreateInfoKHR asCreateInfo{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR};
asCreateInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR;
asCreateInfo.flags = flags;
asCreateInfo.maxGeometryCount = 1;
asCreateInfo.pGeometryInfos = &geometryCreate;
```` ````
We then call the allocator, which will create an acceleration structure handle for the TLAS. It will also query the We then call the allocator, which will create an acceleration structure handle for the TLAS. It will also query the
@ -502,10 +612,10 @@ resulting size of the TLAS using `vk::Device::getAccelerationStructureMemoryRequ
amount of memory: amount of memory:
```` C ```` C
// Create the acceleration structure object and allocate the memory required to hold the TLAS data // Create the acceleration structure object and allocate the memory
m_tlas.as = m_alloc.createAcceleration(asCreateInfo); // required to hold the TLAS data
m_debug.setObjectName(m_tlas.as.accel, "Tlas"); m_tlas.as = m_alloc.createAcceleration(asCreateInfo);
} m_debug.setObjectName(m_tlas.as.accel, "Tlas");
```` ````
As with the BLAS, we also query the amount of scratch memory required by the builder to generate the TLAS, As with the BLAS, we also query the amount of scratch memory required by the builder to generate the TLAS,
@ -514,18 +624,23 @@ one buffer and thus saved an allocation. However, for the purpose of this tutori
independent. independent.
```` C ```` C
// Compute the amount of scratch memory required by the acceleration structure builder // Compute the amount of scratch memory required by the acceleration structure builder
vk::AccelerationStructureMemoryRequirementsInfoKHR memoryRequirementsInfo{ VkAccelerationStructureMemoryRequirementsInfoKHR memoryRequirementsInfo{
vk::AccelerationStructureMemoryRequirementsTypeKHR::eBuildScratch, VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_KHR};
vk::AccelerationStructureBuildTypeKHR::eDevice, m_tlas.as.accel}; memoryRequirementsInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_KHR;
vk::DeviceSize scratchSize = memoryRequirementsInfo.accelerationStructure = m_tlas.as.accel;
m_device.getAccelerationStructureMemoryRequirementsKHR(memoryRequirementsInfo).memoryRequirements.size; memoryRequirementsInfo.buildType = VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR;
// Allocate the scratch memory VkMemoryRequirements2 reqMem{VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2};
nvvkBuffer scratchBuffer = m_alloc.createBuffer(scratchSize, vk::BufferUsageFlagBits::eRayTracingKHR vkGetAccelerationStructureMemoryRequirementsKHR(m_device, &memoryRequirementsInfo, &reqMem);
| vk::BufferUsageFlagBits::eShaderDeviceAddress); VkDeviceSize scratchSize = reqMem.memoryRequirements.size;
vk::DeviceAddress scratchAddress = m_device.getBufferAddress({scratchBuffer.buffer});
// Allocate the scratch memory
nvvkBuffer scratchBuffer =
m_alloc.createBuffer(scratchSize, VK_BUFFER_USAGE_RAY_TRACING_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
VkBufferDeviceAddressInfo bufferInfo{VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO};
bufferInfo.buffer = scratchBuffer.buffer;
VkDeviceAddress scratchAddress = vkGetBufferDeviceAddress(m_device, &bufferInfo);
```` ````
An `Instance` object is nearly identical to a `VkGeometryInstanceKHR` object: the only difference is the transform An `Instance` object is nearly identical to a `VkGeometryInstanceKHR` object: the only difference is the transform
@ -535,13 +650,13 @@ application side allows us to use the more intuitive $4\times4$ matrices, making
TLAS we then convert all the `Instance` objects to `VkGeometryInstanceKHR`: TLAS we then convert all the `Instance` objects to `VkGeometryInstanceKHR`:
```` C ```` C
// For each instance, build the corresponding instance descriptor // For each instance, build the corresponding instance descriptor
std::vector<vk::AccelerationStructureInstanceKHR> geometryInstances; std::vector<VkAccelerationStructureInstanceKHR> geometryInstances;
geometryInstances.reserve(instances.size()); geometryInstances.reserve(instances.size());
for(const auto& inst : instances) for(const auto& inst : instances)
{ {
geometryInstances.push_back(instanceToVkGeometryInstanceKHR(inst)); geometryInstances.push_back(instanceToVkGeometryInstanceKHR(inst));
} }
```` ````
We then upload the instance descriptions to the device using a one-time command buffer. This command buffer will also be We then upload the instance descriptions to the device using a one-time command buffer. This command buffer will also be
@ -549,54 +664,65 @@ used to generate the TLAS itself, and so we add a barrier after the copy to ensu
TLAS build. TLAS build.
```` C ```` C
// Building the TLAS // Building the TLAS
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_queueIndex); nvvk::CommandPool genCmdBuf(m_device, m_queueIndex);
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer(); VkCommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
// Create a buffer holding the actual instance data for use by the AS builder // Create a buffer holding the actual instance data for use by the AS
VkDeviceSize instanceDescsSizeInBytes = instances.size() * sizeof(vk::AccelerationStructureInstanceKHR); // builder
VkDeviceSize instanceDescsSizeInBytes = instances.size() * sizeof(VkAccelerationStructureInstanceKHR);
// Allocate the instance buffer and copy its contents from host to device memory // Allocate the instance buffer and copy its contents from host to device
m_instBuffer = m_alloc.createBuffer(cmdBuf, geometryInstances, // memory
vk::BufferUsageFlagBits::eRayTracingKHR | vk::BufferUsageFlagBits::eShaderDeviceAddress); m_instBuffer = m_alloc.createBuffer(cmdBuf, geometryInstances,
m_debug.setObjectName(m_instBuffer.buffer, "TLASInstances"); VK_BUFFER_USAGE_RAY_TRACING_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
vk::DeviceAddress instanceAddress = m_device.getBufferAddress(m_instBuffer.buffer); m_debug.setObjectName(m_instBuffer.buffer, "TLASInstances");
//VkBufferDeviceAddressInfo bufferInfo{VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO};
bufferInfo.buffer = m_instBuffer.buffer;
VkDeviceAddress instanceAddress = vkGetBufferDeviceAddress(m_device, &bufferInfo);
// Make sure the copy of the instance buffer are copied before triggering the // Make sure the copy of the instance buffer are copied before triggering the
// acceleration structure build // acceleration structure build
vk::MemoryBarrier barrier(vk::AccessFlagBits::eTransferWrite, vk::AccessFlagBits::eAccelerationStructureWriteKHR); VkMemoryBarrier barrier{VK_STRUCTURE_TYPE_MEMORY_BARRIER};
cmdBuf.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eAccelerationStructureBuildKHR, barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
vk::DependencyFlags(), {barrier}, {}, {}); barrier.dstAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR;
vkCmdPipelineBarrier(cmdBuf, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR,
0, 1, &barrier, 0, nullptr, 0, nullptr);
```` ````
The build is then triggered, and we execute the command buffer before destroying the temporary buffers. The build is then triggered, and we execute the command buffer before destroying the temporary buffers.
```` C ```` C
// Build the TLAS // Build the TLAS
vk::AccelerationStructureGeometryKHR topASGeometry{vk::GeometryTypeKHR::eInstances}; VkAccelerationStructureGeometryDataKHR geometry{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR};
topASGeometry.geometry.instances.setArrayOfPointers(VK_FALSE); geometry.instances.arrayOfPointers = VK_FALSE;
topASGeometry.geometry.instances.setData(instanceAddress); geometry.instances.data.deviceAddress = instanceAddress;
VkAccelerationStructureGeometryKHR topASGeometry{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR};
topASGeometry.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR;
topASGeometry.geometry = geometry;
const vk::AccelerationStructureGeometryKHR* pGeometry = &topASGeometry;
vk::AccelerationStructureBuildGeometryInfoKHR topASInfo; const VkAccelerationStructureGeometryKHR* pGeometry = &topASGeometry;
topASInfo.setFlags(flags); VkAccelerationStructureBuildGeometryInfoKHR topASInfo{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR};
topASInfo.setUpdate(VK_FALSE); topASInfo.flags = flags;
topASInfo.setSrcAccelerationStructure({}); topASInfo.update = VK_FALSE;
topASInfo.setDstAccelerationStructure(m_tlas.as.accel); topASInfo.srcAccelerationStructure = VK_NULL_HANDLE;
topASInfo.setGeometryArrayOfPointers(VK_FALSE); topASInfo.dstAccelerationStructure = m_tlas.as.accel;
topASInfo.setGeometryCount(1); topASInfo.geometryArrayOfPointers = VK_FALSE;
topASInfo.setPpGeometries(&pGeometry); topASInfo.geometryCount = 1;
topASInfo.setScratchData(scratchAddress); topASInfo.ppGeometries = &pGeometry;
topASInfo.scratchData.deviceAddress = scratchAddress;
// Build Offsets info: n instances // Build Offsets info: n instances
vk::AccelerationStructureBuildOffsetInfoKHR buildOffsetInfo{static_cast<uint32_t>(instances.size()), 0, 0, 0}; VkAccelerationStructureBuildOffsetInfoKHR buildOffsetInfo{static_cast<uint32_t>(instances.size()), 0, 0, 0};
const vk::AccelerationStructureBuildOffsetInfoKHR* pBuildOffsetInfo = &buildOffsetInfo; const VkAccelerationStructureBuildOffsetInfoKHR* pBuildOffsetInfo = &buildOffsetInfo;
// Build the TLAS // Build the TLAS
cmdBuf.buildAccelerationStructureKHR(1, &topASInfo, &pBuildOffsetInfo); vkCmdBuildAccelerationStructureKHR(cmdBuf, 1, &topASInfo, &pBuildOffsetInfo);
genCmdBuf.flushCommandBuffer(cmdBuf);
m_alloc.flushStaging(); genCmdBuf.submitAndWait(cmdBuf);
m_alloc.finalizeAndReleaseStaging();
m_alloc.destroy(scratchBuffer); m_alloc.destroy(scratchBuffer);
} }
```` ````
@ -633,7 +759,7 @@ In the header, we declare the objects related to this additional descriptor set:
```` C ```` C
void createRtDescriptorSet(); void createRtDescriptorSet();
std::vector<vk::DescriptorSetLayoutBinding> m_rtDescSetLayoutBind; nvvk::DescriptorSetBindings m_rtDescSetLayoutBind;
vk::DescriptorPool m_rtDescPool; vk::DescriptorPool m_rtDescPool;
vk::DescriptorSetLayout m_rtDescSetLayout; vk::DescriptorSetLayout m_rtDescSetLayout;
vk::DescriptorSet m_rtDescSet; vk::DescriptorSet m_rtDescSet;
@ -654,25 +780,25 @@ void HelloVulkan::createRtDescriptorSet()
using vkSS = vk::ShaderStageFlagBits; using vkSS = vk::ShaderStageFlagBits;
using vkDSLB = vk::DescriptorSetLayoutBinding; using vkDSLB = vk::DescriptorSetLayoutBinding;
m_rtDescSetLayoutBind.emplace_back( m_rtDescSetLayoutBind.addBinding(vkDSLB(0, vkDT::eAccelerationStructureKHR, 1,
vkDSLB(0, vkDT::eAccelerationStructureKHR, 1, vkSS::eRaygenKHR )); // TLAS vkSS::eRaygenKHR | vkSS::eClosestHitKHR)); // TLAS
m_rtDescSetLayoutBind.emplace_back( m_rtDescSetLayoutBind.addBinding(
vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image
m_rtDescPool = nvvkpp::util::createDescriptorPool(m_device, m_rtDescSetLayoutBind); m_rtDescPool = m_rtDescSetLayoutBind.createPool(m_device);
m_rtDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_rtDescSetLayoutBind); m_rtDescSetLayout = m_rtDescSetLayoutBind.createLayout(m_device);
m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0]; m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0];
vk::AccelerationStructureKHR tlas = m_rtBuilder.getAccelerationStructure();
vk::WriteDescriptorSetAccelerationStructureKHR descASInfo; vk::WriteDescriptorSetAccelerationStructureKHR descASInfo;
descASInfo.setAccelerationStructureCount(1); descASInfo.setAccelerationStructureCount(1);
descASInfo.setPAccelerationStructures(&m_rtBuilder.getAccelerationStructure()); descASInfo.setPAccelerationStructures(&tlas);
vk::DescriptorImageInfo imageInfo{ vk::DescriptorImageInfo imageInfo{
{}, m_offscreenColor.descriptor.imageView, vk::ImageLayout::eGeneral}; {}, m_offscreenColor.descriptor.imageView, vk::ImageLayout::eGeneral};
std::vector<vk::WriteDescriptorSet> writes; std::vector<vk::WriteDescriptorSet> writes;
writes.emplace_back( writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 0, descASInfo));
nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[0], &descASInfo)); writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 1, imageInfo));
writes.emplace_back(nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[1], &imageInfo));
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr); m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
} }
```` ````
@ -687,25 +813,25 @@ descriptor set as they semantically fit the Scene descriptor set.
```` C ```` C
// Camera matrices (binding = 0) // Camera matrices (binding = 0)
m_descSetLayoutBind.emplace_back( m_descSetLayoutBind.addBinding(
vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR)); vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR));
// Materials (binding = 1) // Materials (binding = 1)
m_descSetLayoutBind.emplace_back( m_descSetLayoutBind.addBinding(
vkDS(1, vkDT::eStorageBuffer, nbObj, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR)); vkDS(1, vkDT::eStorageBuffer, nbObj, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
// Scene description (binding = 2) // Scene description (binding = 2)
m_descSetLayoutBind.emplace_back( // m_descSetLayoutBind.addBinding( //
vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR)); vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
// Textures (binding = 3) // Textures (binding = 3)
m_descSetLayoutBind.emplace_back( m_descSetLayoutBind.addBinding(
vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR)); vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR));
// Materials (binding = 4) // Materials (binding = 4)
m_descSetLayoutBind.emplace_back( m_descSetLayoutBind.addBinding(
vkDS(4, vkDT::eStorageBuffer, nbObj, vkSS::eFragment | vkSS::eClosestHitKHR)); vkDS(4, vkDT::eStorageBuffer, nbObj, vkSS::eFragment | vkSS::eClosestHitKHR));
// Storing vertices (binding = 5) // Storing vertices (binding = 5)
m_descSetLayoutBind.emplace_back( // m_descSetLayoutBind.addBinding( //
vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR)); vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
// Storing indices (binding = 6) // Storing indices (binding = 6)
m_descSetLayoutBind.emplace_back( // m_descSetLayoutBind.addBinding( //
vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR)); vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
```` ````
@ -724,11 +850,10 @@ We set the actual contents of the descriptor set by adding those buffers in `upd
dbiVert.push_back({m_objModel[i].vertexBuffer.buffer, 0, VK_WHOLE_SIZE}); dbiVert.push_back({m_objModel[i].vertexBuffer.buffer, 0, VK_WHOLE_SIZE});
dbiIdx.push_back({m_objModel[i].indexBuffer.buffer, 0, VK_WHOLE_SIZE}); dbiIdx.push_back({m_objModel[i].indexBuffer.buffer, 0, VK_WHOLE_SIZE});
} }
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[1], dbiMat.data())); writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 1, dbiMat.data()));
writes.emplace_back( writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 4, dbiMatIdx.data()));
nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[4], dbiMatIdx.data())); writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 5, dbiVert.data()));
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[5], dbiVert.data())); writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 6, dbiIdx.data()));
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[6], dbiIdx.data()));
```` ````
Originally the buffers containing the vertices and indices were only used by the rasterization pipeline. The ray tracing Originally the buffers containing the vertices and indices were only used by the rasterization pipeline. The ray tracing
@ -922,11 +1047,11 @@ void HelloVulkan::createRtPipeline()
std::vector<std::string> paths = defaultSearchPaths; std::vector<std::string> paths = defaultSearchPaths;
vk::ShaderModule raygenSM = vk::ShaderModule raygenSM =
nvvkpp::util::createShaderModule(m_device, // nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rgen.spv", true, paths)); nvh::loadFile("shaders/raytrace.rgen.spv", true, paths));
vk::ShaderModule missSM = vk::ShaderModule missSM =
nvvkpp::util::createShaderModule(m_device, // nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths)); nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths));
std::vector<vk::PipelineShaderStageCreateInfo> stages; std::vector<vk::PipelineShaderStageCreateInfo> stages;
@ -960,8 +1085,8 @@ shaders.
```` C ```` C
// Hit Group - Closest Hit + AnyHit // Hit Group - Closest Hit + AnyHit
vk::ShaderModule chitSM = vk::ShaderModule chitSM =
nvvkpp::util::createShaderModule(m_device, // nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rchit.spv", true, paths)); nvh::loadFile("shaders/raytrace.rchit.spv", true, paths));
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup, vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup,
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR,
@ -1137,19 +1262,19 @@ copy the handles into the SBT:
```` C ```` C
std::vector<uint8_t> shaderHandleStorage(sbtSize); std::vector<uint8_t> shaderHandleStorage(sbtSize);
m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize, m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize,
shaderHandleStorage.data()); shaderHandleStorage.data());
// Write the handles in the SBT // Write the handles in the SBT
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex); nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer(); vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
m_rtSBTBuffer = m_rtSBTBuffer =
m_alloc.createBuffer(cmdBuf, shaderHandleStorage, vk::BufferUsageFlagBits::eRayTracingKHR); m_alloc.createBuffer(cmdBuf, shaderHandleStorage, vk::BufferUsageFlagBits::eRayTracingKHR);
m_debug.setObjectName(m_rtSBTBuffer.buffer, "SBT"); m_debug.setObjectName(m_rtSBTBuffer.buffer, "SBT");
genCmdBuf.flushCommandBuffer(cmdBuf); genCmdBuf.submitAndWait(cmdBuf);
m_alloc.flushStaging(); m_alloc.finalizeAndReleaseStaging();
} }
```` ````
@ -1696,8 +1821,9 @@ In the body of `createRtPipeline`, we need to define the new miss shader right a
```` C ```` C
// The second miss shader is invoked when a shadow ray misses the geometry. It // The second miss shader is invoked when a shadow ray misses the geometry. It
// simply indicates that no occlusion has been found // simply indicates that no occlusion has been found
vk::ShaderModule shadowmissSM = nvvkpp::util::createShaderModule( vk::ShaderModule shadowmissSM =
m_device, nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths)); nvvk::createShaderModule(m_device,
nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
```` ````

View file

@ -30,19 +30,22 @@
extern std::vector<std::string> defaultSearchPaths; extern std::vector<std::string> defaultSearchPaths;
#define VMA_IMPLEMENTATION
#define STB_IMAGE_IMPLEMENTATION #define STB_IMAGE_IMPLEMENTATION
#include "fileformats/stb_image.h" #include "fileformats/stb_image.h"
#include "obj_loader.h" #include "obj_loader.h"
#include "hello_vulkan.h" #include "hello_vulkan.h"
#include "nvh//cameramanipulator.hpp" #include "nvh//cameramanipulator.hpp"
#include "nvvkpp/descriptorsets_vkpp.hpp" #include "nvvk/descriptorsets_vk.hpp"
#include "nvvkpp/pipeline_vkpp.hpp" #include "nvvk/pipeline_vk.hpp"
#include "nvh/fileoperations.hpp" #include "nvh/fileoperations.hpp"
#include "nvvkpp/commands_vkpp.hpp" #include "nvvk/commands_vk.hpp"
#include "nvvkpp/renderpass_vkpp.hpp" #include "nvvk/renderpasses_vk.hpp"
#include "nvvkpp/utilities_vkpp.hpp"
// Holding the camera matrices // Holding the camera matrices
struct CameraMatrices struct CameraMatrices
@ -58,31 +61,32 @@ struct CameraMatrices
// Keep the handle on the device // Keep the handle on the device
// Initialize the tool to do all our allocations: buffers, images // Initialize the tool to do all our allocations: buffers, images
// //
void HelloVulkan::setup(const vk::Device& device, void HelloVulkan::setup(const vk::Instance& instance,
const vk::Device& device,
const vk::PhysicalDevice& physicalDevice, const vk::PhysicalDevice& physicalDevice,
uint32_t queueFamily) uint32_t queueFamily)
{ {
AppBase::setup(device, physicalDevice, queueFamily); AppBase::setup(instance, device, physicalDevice, queueFamily);
#if defined(ALLOC_DEDICATED) #if defined(NVVK_ALLOC_DEDICATED)
m_alloc.init(device, physicalDevice); m_alloc.init(device, physicalDevice);
#elif defined(ALLOC_DMA) #elif defined(NVVK_ALLOC_DMA)
m_memAllocator.init(device, physicalDevice); m_memAllocator.init(device, physicalDevice);
m_memAllocator.setAllocateFlags(VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR, true); m_memAllocator.setAllocateFlags(VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT, true);
m_alloc.init(device, &m_memAllocator); m_alloc.init(device, physicalDevice, &m_memAllocator);
#elif defined(ALLOC_VMA) #elif defined(NVVK_ALLOC_VMA)
VmaAllocatorCreateInfo allocatorInfo = {}; VmaAllocatorCreateInfo allocatorInfo = {};
allocatorInfo.physicalDevice = physicalDevice; allocatorInfo.physicalDevice = physicalDevice;
allocatorInfo.instance = instance;
allocatorInfo.device = device; allocatorInfo.device = device;
allocatorInfo.flags |= allocatorInfo.flags = VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT;
VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT | VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT;
vmaCreateAllocator(&allocatorInfo, &m_memAllocator); vmaCreateAllocator(&allocatorInfo, &m_memAllocator);
m_alloc.init(device, m_memAllocator); m_alloc.init(device, physicalDevice, m_memAllocator);
#endif #endif
m_debug.setup(m_device); m_debug.setup(m_device);
m_offscreen.setup(device, m_memAllocator, queueFamily); m_offscreen.setup(device, &m_alloc, queueFamily);
m_raytrace.setup(device, physicalDevice, m_memAllocator, queueFamily); m_raytrace.setup(device, physicalDevice, &m_alloc, queueFamily);
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -100,15 +104,15 @@ void HelloVulkan::updateUniformBuffer()
// #VKRay // #VKRay
ubo.projInverse = nvmath::invert(ubo.proj); ubo.projInverse = nvmath::invert(ubo.proj);
#if defined(ALLOC_DEDICATED) #if defined(NVVK_ALLOC_DEDICATED)
void* data = m_device.mapMemory(m_cameraMat.allocation, 0, sizeof(CameraMatrices)); void* data = m_device.mapMemory(m_cameraMat.allocation, 0, sizeof(CameraMatrices));
memcpy(data, &ubo, sizeof(ubo)); memcpy(data, &ubo, sizeof(ubo));
m_device.unmapMemory(m_cameraMat.allocation); m_device.unmapMemory(m_cameraMat.allocation);
#elif defined(ALLOC_DMA) #elif defined(NVVK_ALLOC_DMA)
void* data = m_memAllocator.map(m_cameraMat.allocation); void* data = m_memAllocator.map(m_cameraMat.allocation);
memcpy(data, &ubo, sizeof(ubo)); memcpy(data, &ubo, sizeof(ubo));
m_memAllocator.unmap(m_cameraMat.allocation); m_memAllocator.unmap(m_cameraMat.allocation);
#elif defined(ALLOC_VMA) #elif defined(NVVK_ALLOC_VMA)
void* data; void* data;
vmaMapMemory(m_memAllocator, m_cameraMat.allocation, &data); vmaMapMemory(m_memAllocator, m_cameraMat.allocation, &data);
memcpy(data, &ubo, sizeof(ubo)); memcpy(data, &ubo, sizeof(ubo));
@ -128,37 +132,37 @@ void HelloVulkan::createDescriptorSetLayout()
uint32_t nbObj = static_cast<uint32_t>(m_objModel.size()); uint32_t nbObj = static_cast<uint32_t>(m_objModel.size());
// Camera matrices (binding = 0) // Camera matrices (binding = 0)
m_descSetLayoutBind.emplace_back( m_descSetLayoutBind.addBinding(
vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR)); vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR));
// Materials (binding = 1) // Materials (binding = 1)
m_descSetLayoutBind.emplace_back( m_descSetLayoutBind.addBinding(
vkDS(1, vkDT::eStorageBuffer, nbObj + 1, // Adding Implicit mat too vkDS(1, vkDT::eStorageBuffer, nbObj + 1, // Adding Implicit mat too
vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR | vkSS::eAnyHitKHR)); vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR | vkSS::eAnyHitKHR));
// Scene description (binding = 2) // Scene description (binding = 2)
m_descSetLayoutBind.emplace_back( // m_descSetLayoutBind.addBinding( //
vkDS(2, vkDT::eStorageBuffer, 1, vkDS(2, vkDT::eStorageBuffer, 1,
vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR | vkSS::eAnyHitKHR)); vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR | vkSS::eAnyHitKHR));
// Textures (binding = 3) // Textures (binding = 3)
m_descSetLayoutBind.emplace_back( m_descSetLayoutBind.addBinding(
vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR)); vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR));
// Materials (binding = 4) // Materials (binding = 4)
m_descSetLayoutBind.emplace_back(vkDS(4, vkDT::eStorageBuffer, nbObj, m_descSetLayoutBind.addBinding(vkDS(4, vkDT::eStorageBuffer, nbObj,
vkSS::eFragment | vkSS::eClosestHitKHR | vkSS::eAnyHitKHR)); vkSS::eFragment | vkSS::eClosestHitKHR | vkSS::eAnyHitKHR));
// Storing vertices (binding = 5) // Storing vertices (binding = 5)
m_descSetLayoutBind.emplace_back( // m_descSetLayoutBind.addBinding( //
vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR | vkSS::eAnyHitKHR)); vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR | vkSS::eAnyHitKHR));
// Storing indices (binding = 6) // Storing indices (binding = 6)
m_descSetLayoutBind.emplace_back( // m_descSetLayoutBind.addBinding( //
vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR | vkSS::eAnyHitKHR)); vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR | vkSS::eAnyHitKHR));
// Storing implicit obj (binding = 7) // Storing implicit obj (binding = 7)
m_descSetLayoutBind.emplace_back( // m_descSetLayoutBind.addBinding( //
vkDS(7, vkDT::eStorageBuffer, 1, vkDS(7, vkDT::eStorageBuffer, 1,
vkSS::eClosestHitKHR | vkSS::eIntersectionKHR | vkSS::eAnyHitKHR)); vkSS::eClosestHitKHR | vkSS::eIntersectionKHR | vkSS::eAnyHitKHR));
m_descSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_descSetLayoutBind); m_descSetLayout = m_descSetLayoutBind.createLayout(m_device);
m_descPool = nvvkpp::util::createDescriptorPool(m_device, m_descSetLayoutBind, 1); m_descPool = m_descSetLayoutBind.createPool(m_device, 1);
m_descSet = nvvkpp::util::createDescriptorSet(m_device, m_descPool, m_descSetLayout); m_descSet = nvvk::allocateDescriptorSet(m_device, m_descPool, m_descSetLayout);
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -170,9 +174,9 @@ void HelloVulkan::updateDescriptorSet()
// Camera matrices and scene description // Camera matrices and scene description
vk::DescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE}; vk::DescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE};
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[0], &dbiUnif)); writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 0, &dbiUnif));
vk::DescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE}; vk::DescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[2], &dbiSceneDesc)); writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 2, &dbiSceneDesc));
// All material buffers, 1 buffer per OBJ // All material buffers, 1 buffer per OBJ
std::vector<vk::DescriptorBufferInfo> dbiMat; std::vector<vk::DescriptorBufferInfo> dbiMat;
@ -187,11 +191,10 @@ void HelloVulkan::updateDescriptorSet()
dbiIdx.emplace_back(model.indexBuffer.buffer, 0, VK_WHOLE_SIZE); dbiIdx.emplace_back(model.indexBuffer.buffer, 0, VK_WHOLE_SIZE);
} }
dbiMat.emplace_back(m_implObjects.implMatBuf.buffer, 0, VK_WHOLE_SIZE); // Adding implicit mat dbiMat.emplace_back(m_implObjects.implMatBuf.buffer, 0, VK_WHOLE_SIZE); // Adding implicit mat
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[1], dbiMat.data())); writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 1, dbiMat.data()));
writes.emplace_back( writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 4, dbiMatIdx.data()));
nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[4], dbiMatIdx.data())); writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 5, dbiVert.data()));
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[5], dbiVert.data())); writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 6, dbiIdx.data()));
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[6], dbiIdx.data()));
// All texture samplers // All texture samplers
std::vector<vk::DescriptorImageInfo> diit; std::vector<vk::DescriptorImageInfo> diit;
@ -199,10 +202,10 @@ void HelloVulkan::updateDescriptorSet()
{ {
diit.push_back(texture.descriptor); diit.push_back(texture.descriptor);
} }
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[3], diit.data())); writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 3, diit.data()));
vk::DescriptorBufferInfo dbiImplDesc{m_implObjects.implBuf.buffer, 0, VK_WHOLE_SIZE}; vk::DescriptorBufferInfo dbiImplDesc{m_implObjects.implBuf.buffer, 0, VK_WHOLE_SIZE};
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[7], &dbiImplDesc)); writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 7, &dbiImplDesc));
// Writing the information // Writing the information
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr); m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
@ -228,19 +231,19 @@ void HelloVulkan::createGraphicsPipeline()
m_pipelineLayout = m_device.createPipelineLayout(pipelineLayoutCreateInfo); m_pipelineLayout = m_device.createPipelineLayout(pipelineLayoutCreateInfo);
// Creating the Pipeline // Creating the Pipeline
std::vector<std::string> paths = defaultSearchPaths; std::vector<std::string> paths = defaultSearchPaths;
nvvkpp::GraphicsPipelineGenerator gpb(m_device, m_pipelineLayout, m_offscreen.renderPass()); nvvk::GraphicsPipelineGeneratorCombined gpb(m_device, m_pipelineLayout, m_offscreen.renderPass());
gpb.depthStencilState = {true}; gpb.depthStencilState.depthTestEnable = true;
gpb.addShader(nvh::loadFile("shaders/vert_shader.vert.spv", true, paths), vkSS::eVertex); gpb.addShader(nvh::loadFile("shaders/vert_shader.vert.spv", true, paths), vkSS::eVertex);
gpb.addShader(nvh::loadFile("shaders/frag_shader.frag.spv", true, paths), vkSS::eFragment); gpb.addShader(nvh::loadFile("shaders/frag_shader.frag.spv", true, paths), vkSS::eFragment);
gpb.vertexInputState.bindingDescriptions = {{0, sizeof(VertexObj)}}; gpb.addBindingDescription({0, sizeof(VertexObj)});
gpb.vertexInputState.attributeDescriptions = { gpb.addAttributeDescriptions(std::vector<vk::VertexInputAttributeDescription>{
{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)}, {0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
{1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)}, {1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)},
{2, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, color)}, {2, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, color)},
{3, 0, vk::Format::eR32G32Sfloat, offsetof(VertexObj, texCoord)}}; {3, 0, vk::Format::eR32G32Sfloat, offsetof(VertexObj, texCoord)}});
m_graphicsPipeline = gpb.create(); m_graphicsPipeline = gpb.createPipeline();
m_debug.setObjectName(m_graphicsPipeline, "Graphics"); m_debug.setObjectName(m_graphicsPipeline, "Graphics");
} }
@ -273,8 +276,8 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size()); model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
// Create the buffers on Device and copy vertices, indices and materials // Create the buffers on Device and copy vertices, indices and materials
nvvkpp::SingleCommandBuffer cmdBufGet(m_device, m_graphicsQueueIndex); nvvk::CommandPool cmdBufGet(m_device, m_graphicsQueueIndex);
vk::CommandBuffer cmdBuf = cmdBufGet.createCommandBuffer(); vk::CommandBuffer cmdBuf = cmdBufGet.createCommandBuffer();
model.vertexBuffer = model.vertexBuffer =
m_alloc.createBuffer(cmdBuf, loader.m_vertices, m_alloc.createBuffer(cmdBuf, loader.m_vertices,
vkBU::eVertexBuffer | vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress); vkBU::eVertexBuffer | vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress);
@ -285,8 +288,8 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, vkBU::eStorageBuffer); model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, vkBU::eStorageBuffer);
// Creates all textures found // Creates all textures found
createTextureImages(cmdBuf, loader.m_textures); createTextureImages(cmdBuf, loader.m_textures);
cmdBufGet.flushCommandBuffer(cmdBuf); cmdBufGet.submitAndWait(cmdBuf);
m_alloc.flushStaging(); m_alloc.finalizeAndReleaseStaging();
std::string objNb = std::to_string(instance.objIndex); std::string objNb = std::to_string(instance.objIndex);
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str())); m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
@ -308,7 +311,11 @@ void HelloVulkan::createUniformBuffer()
using vkMP = vk::MemoryPropertyFlagBits; using vkMP = vk::MemoryPropertyFlagBits;
m_cameraMat = m_alloc.createBuffer(sizeof(CameraMatrices), vkBU::eUniformBuffer, m_cameraMat = m_alloc.createBuffer(sizeof(CameraMatrices), vkBU::eUniformBuffer,
#ifndef NVVK_ALLOC_VMA
vkMP::eHostVisible | vkMP::eHostCoherent); vkMP::eHostVisible | vkMP::eHostCoherent);
#else
VMA_MEMORY_USAGE_CPU_TO_GPU);
#endif // _DEBUG
m_debug.setObjectName(m_cameraMat.buffer, "cameraMat"); m_debug.setObjectName(m_cameraMat.buffer, "cameraMat");
} }
@ -321,12 +328,12 @@ void HelloVulkan::createUniformBuffer()
void HelloVulkan::createSceneDescriptionBuffer() void HelloVulkan::createSceneDescriptionBuffer()
{ {
using vkBU = vk::BufferUsageFlagBits; using vkBU = vk::BufferUsageFlagBits;
nvvkpp::SingleCommandBuffer cmdGen(m_device, m_graphicsQueueIndex); nvvk::CommandPool cmdGen(m_device, m_graphicsQueueIndex);
auto cmdBuf = cmdGen.createCommandBuffer(); auto cmdBuf = cmdGen.createCommandBuffer();
m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer); m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer);
cmdGen.flushCommandBuffer(cmdBuf); cmdGen.submitAndWait(cmdBuf);
m_alloc.flushStaging(); m_alloc.finalizeAndReleaseStaging();
m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc"); m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc");
} }
@ -346,21 +353,21 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
// If no textures are present, create a dummy one to accommodate the pipeline layout // If no textures are present, create a dummy one to accommodate the pipeline layout
if(textures.empty() && m_textures.empty()) if(textures.empty() && m_textures.empty())
{ {
nvvkTexture texture; nvvk::Texture texture;
std::array<uint8_t, 4> color{255u, 255u, 255u, 255u}; std::array<uint8_t, 4> color{255u, 255u, 255u, 255u};
vk::DeviceSize bufferSize = sizeof(color); vk::DeviceSize bufferSize = sizeof(color);
auto imgSize = vk::Extent2D(1, 1); auto imgSize = vk::Extent2D(1, 1);
auto imageCreateInfo = nvvkpp::image::create2DInfo(imgSize, format); auto imageCreateInfo = nvvk::makeImage2DCreateInfo(imgSize, format);
// Creating the VKImage // Creating the VKImage
texture = m_alloc.createImage(cmdBuf, bufferSize, color.data(), imageCreateInfo); nvvk::Image image = m_alloc.createImage(cmdBuf, bufferSize, color.data(), imageCreateInfo);
// Setting up the descriptor used by the shader vk::ImageViewCreateInfo ivInfo = nvvk::makeImageViewCreateInfo(image.image, imageCreateInfo);
texture.descriptor = texture = m_alloc.createTexture(image, ivInfo, samplerCreateInfo);
nvvkpp::image::create2DDescriptor(m_device, texture.image, samplerCreateInfo, format);
// The image format must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL // The image format must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
nvvkpp::image::setImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined, nvvk::cmdBarrierImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eShaderReadOnlyOptimal); vk::ImageLayout::eShaderReadOnlyOptimal);
m_textures.push_back(texture); m_textures.push_back(texture);
} }
else else
@ -387,16 +394,15 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4; vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4;
auto imgSize = vk::Extent2D(texWidth, texHeight); auto imgSize = vk::Extent2D(texWidth, texHeight);
auto imageCreateInfo = nvvkpp::image::create2DInfo(imgSize, format, vkIU::eSampled, true); auto imageCreateInfo = nvvk::makeImage2DCreateInfo(imgSize, format, vkIU::eSampled, true);
{ {
nvvkTexture texture; nvvk::Image image = m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo);
texture = m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo); nvvk::cmdGenerateMipmaps(cmdBuf, image.image, format, imgSize, imageCreateInfo.mipLevels);
vk::ImageViewCreateInfo ivInfo =
nvvk::makeImageViewCreateInfo(image.image, imageCreateInfo);
nvvk::Texture texture = m_alloc.createTexture(image, ivInfo, samplerCreateInfo);
nvvkpp::image::generateMipmaps(cmdBuf, texture.image, format, imgSize,
imageCreateInfo.mipLevels);
texture.descriptor =
nvvkpp::image::create2DDescriptor(m_device, texture.image, samplerCreateInfo, format);
m_textures.push_back(texture); m_textures.push_back(texture);
} }
} }
@ -436,7 +442,12 @@ void HelloVulkan::destroyResources()
// #VKRay // #VKRay
m_raytrace.destroy(); m_raytrace.destroy();
m_alloc.deinit();
#ifdef NVVK_ALLOC_DMA
m_memAllocator.deinit(); m_memAllocator.deinit();
#elif defined(NVVK_ALLOC_VMA)
vmaDestroyAllocator(m_memAllocator);
#endif // NVVK_ALLOC_DMA
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -465,7 +476,7 @@ void HelloVulkan::rasterize(const vk::CommandBuffer& cmdBuf)
cmdBuf.pushConstants<ObjPushConstants>(m_pipelineLayout, vkSS::eVertex | vkSS::eFragment, 0, cmdBuf.pushConstants<ObjPushConstants>(m_pipelineLayout, vkSS::eVertex | vkSS::eFragment, 0,
m_pushConstants); m_pushConstants);
cmdBuf.bindVertexBuffers(0, 1, &model.vertexBuffer.buffer, &offset); cmdBuf.bindVertexBuffers(0, {model.vertexBuffer.buffer}, {offset});
cmdBuf.bindIndexBuffer(model.indexBuffer.buffer, 0, vk::IndexType::eUint32); cmdBuf.bindIndexBuffer(model.indexBuffer.buffer, 0, vk::IndexType::eUint32);
cmdBuf.drawIndexed(model.nbIndices, 1, 0, 0, 0); cmdBuf.drawIndexed(model.nbIndices, 1, 0, 0, 0);
} }
@ -574,7 +585,7 @@ void HelloVulkan::addImplMaterial(const MaterialObj& mat)
void HelloVulkan::createImplictBuffers() void HelloVulkan::createImplictBuffers()
{ {
using vkBU = vk::BufferUsageFlagBits; using vkBU = vk::BufferUsageFlagBits;
nvvkpp::SingleCommandBuffer cmdGen(m_device, m_graphicsQueueIndex); nvvk::CommandPool cmdGen(m_device, m_graphicsQueueIndex);
// Not allowing empty buffers // Not allowing empty buffers
if(m_implObjects.objImpl.empty()) if(m_implObjects.objImpl.empty())
@ -587,8 +598,8 @@ void HelloVulkan::createImplictBuffers()
vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress); vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress);
m_implObjects.implMatBuf = m_implObjects.implMatBuf =
m_alloc.createBuffer(cmdBuf, m_implObjects.implMat, vkBU::eStorageBuffer); m_alloc.createBuffer(cmdBuf, m_implObjects.implMat, vkBU::eStorageBuffer);
cmdGen.flushCommandBuffer(cmdBuf); cmdGen.submitAndWait(cmdBuf);
m_alloc.flushStaging(); m_alloc.finalizeAndReleaseStaging();
m_debug.setObjectName(m_implObjects.implBuf.buffer, "implicitObj"); m_debug.setObjectName(m_implObjects.implBuf.buffer, "implicitObj");
m_debug.setObjectName(m_implObjects.implMatBuf.buffer, "implicitMat"); m_debug.setObjectName(m_implObjects.implMatBuf.buffer, "implicitMat");
} }

View file

@ -28,12 +28,12 @@
#include "vkalloc.hpp" #include "vkalloc.hpp"
#include "nvvkpp/allocator_dedicated_vkpp.hpp" #include "nvvk/allocator_dedicated_vk.hpp"
#include "nvvkpp/appbase_vkpp.hpp" #include "nvvk/appbase_vkpp.hpp"
#include "nvvkpp/debug_util_vkpp.hpp" #include "nvvk/debug_util_vk.hpp"
// #VKRay // #VKRay
#include "nvvkpp/raytraceKHR_vkpp.hpp" #include "nvvk/raytraceKHR_vk.hpp"
#include "offscreen.hpp" #include "offscreen.hpp"
#include "obj.hpp" #include "obj.hpp"
@ -46,10 +46,11 @@
// - Rendering is done in an offscreen framebuffer // - Rendering is done in an offscreen framebuffer
// - The image of the framebuffer is displayed in post-process in a full-screen quad // - The image of the framebuffer is displayed in post-process in a full-screen quad
// //
class HelloVulkan : public nvvkpp::AppBase class HelloVulkan : public nvvk::AppBase
{ {
public: public:
void setup(const vk::Device& device, void setup(const vk::Instance& instance,
const vk::Device& device,
const vk::PhysicalDevice& physicalDevice, const vk::PhysicalDevice& physicalDevice,
uint32_t queueFamily) override; uint32_t queueFamily) override;
void createDescriptorSetLayout(); void createDescriptorSetLayout();
@ -76,26 +77,25 @@ public:
// Graphic pipeline // Graphic pipeline
vk::PipelineLayout m_pipelineLayout; vk::PipelineLayout m_pipelineLayout;
vk::Pipeline m_graphicsPipeline; vk::Pipeline m_graphicsPipeline;
std::vector<vk::DescriptorSetLayoutBinding> m_descSetLayoutBind; nvvk::DescriptorSetBindings m_descSetLayoutBind;
vk::DescriptorPool m_descPool; vk::DescriptorPool m_descPool;
vk::DescriptorSetLayout m_descSetLayout; vk::DescriptorSetLayout m_descSetLayout;
vk::DescriptorSet m_descSet; vk::DescriptorSet m_descSet;
int m_maxFrames{10}; int m_maxFrames{10};
void resetFrame(); void resetFrame();
void updateFrame(); void updateFrame();
nvvkBuffer m_cameraMat; // Device-Host of the camera matrices nvvk::Buffer m_cameraMat; // Device-Host of the camera matrices
nvvkBuffer m_sceneDesc; // Device buffer of the OBJ instances nvvk::Buffer m_sceneDesc; // Device buffer of the OBJ instances
std::vector<nvvkTexture> m_textures; // vector of all textures of the scene std::vector<nvvk::Texture> m_textures; // vector of all textures of the scene
nvvkpp::DebugUtil m_debug; // Utility to name objects nvvk::DebugUtil m_debug; // Utility to name objects
nvvkAllocator m_alloc; // Allocator for buffer, images, acceleration structures
nvvkMemAllocator m_memAllocator;
nvvk::Allocator m_alloc; // Allocator for buffer, images, acceleration structures
nvvk::MemAllocator m_memAllocator;
// #Post // #Post
Offscreen m_offscreen; Offscreen m_offscreen;

View file

@ -31,6 +31,7 @@
#include <array> #include <array>
#include <vulkan/vulkan.hpp> #include <vulkan/vulkan.hpp>
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
#include "imgui.h" #include "imgui.h"
#include "imgui_impl_glfw.h" #include "imgui_impl_glfw.h"
@ -39,10 +40,10 @@
#include "nvh/cameramanipulator.hpp" #include "nvh/cameramanipulator.hpp"
#include "nvh/fileoperations.hpp" #include "nvh/fileoperations.hpp"
#include "nvpsystem.hpp" #include "nvpsystem.hpp"
#include "nvvkpp/appbase_vkpp.hpp" #include "nvvk/appbase_vkpp.hpp"
#include "nvvkpp/commands_vkpp.hpp" #include "nvvk/commands_vk.hpp"
#include "nvvkpp/context_vkpp.hpp" #include "nvvk/context_vk.hpp"
#include "nvvkpp/utilities_vkpp.hpp"
#include <random> #include <random>
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -157,7 +158,7 @@ int main(int argc, char** argv)
vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature; vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature;
// Requesting Vulkan extensions and layers // Requesting Vulkan extensions and layers
nvvkpp::ContextCreateInfo contextInfo(true); nvvk::ContextCreateInfo contextInfo(true);
contextInfo.setVersion(1, 2); contextInfo.setVersion(1, 2);
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true); contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME); contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME);
@ -181,7 +182,7 @@ int main(int argc, char** argv)
contextInfo.addDeviceExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME); contextInfo.addDeviceExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
// Creating Vulkan base application // Creating Vulkan base application
nvvkpp::Context vkctx{}; nvvk::Context vkctx{};
vkctx.initInstance(contextInfo); vkctx.initInstance(contextInfo);
// Find all compatible devices // Find all compatible devices
auto compatibleDevices = vkctx.getCompatibleDevices(contextInfo); auto compatibleDevices = vkctx.getCompatibleDevices(contextInfo);
@ -196,7 +197,8 @@ int main(int argc, char** argv)
const vk::SurfaceKHR surface = helloVk.getVkSurface(vkctx.m_instance, window); const vk::SurfaceKHR surface = helloVk.getVkSurface(vkctx.m_instance, window);
vkctx.setGCTQueueWithPresent(surface); vkctx.setGCTQueueWithPresent(surface);
helloVk.setup(vkctx.m_device, vkctx.m_physicalDevice, vkctx.m_queueGCT.familyIndex); helloVk.setup(vkctx.m_instance, vkctx.m_device, vkctx.m_physicalDevice,
vkctx.m_queueGCT.familyIndex);
helloVk.createSurface(surface, SAMPLE_WIDTH, SAMPLE_HEIGHT); helloVk.createSurface(surface, SAMPLE_WIDTH, SAMPLE_HEIGHT);
helloVk.createDepthBuffer(); helloVk.createDepthBuffer();
helloVk.createRenderPass(); helloVk.createRenderPass();
@ -316,7 +318,8 @@ int main(int argc, char** argv)
// Clearing screen // Clearing screen
vk::ClearValue clearValues[2]; vk::ClearValue clearValues[2];
clearValues[0].setColor(nvvkpp::util::clearColor(clearColor)); clearValues[0].setColor(
std::array<float, 4>({clearColor[0], clearColor[1], clearColor[2], clearColor[3]}));
clearValues[1].setDepthStencil({1.0f, 0}); clearValues[1].setDepthStencil({1.0f, 0});
// Offscreen render pass // Offscreen render pass
@ -368,7 +371,6 @@ int main(int argc, char** argv)
helloVk.destroyResources(); helloVk.destroyResources();
helloVk.destroy(); helloVk.destroy();
vkctx.m_instance.destroySurfaceKHR(surface);
vkctx.deinit(); vkctx.deinit();
glfwDestroyWindow(window); glfwDestroyWindow(window);

View file

@ -6,10 +6,10 @@ struct ObjModel
{ {
uint32_t nbIndices{0}; uint32_t nbIndices{0};
uint32_t nbVertices{0}; uint32_t nbVertices{0};
nvvkBuffer vertexBuffer; // Device buffer of all 'Vertex' nvvk::Buffer vertexBuffer; // Device buffer of all 'Vertex'
nvvkBuffer indexBuffer; // Device buffer of the indices forming triangles nvvk::Buffer indexBuffer; // Device buffer of the indices forming triangles
nvvkBuffer matColorBuffer; // Device buffer of array of 'Wavefront material' nvvk::Buffer matColorBuffer; // Device buffer of array of 'Wavefront material'
nvvkBuffer matIndexBuffer; // Device buffer of array of 'Wavefront material' nvvk::Buffer matIndexBuffer; // Device buffer of array of 'Wavefront material'
}; };
// Instance of the OBJ // Instance of the OBJ
@ -54,8 +54,8 @@ struct ImplInst
{ {
std::vector<ObjImplicit> objImpl; // All objects std::vector<ObjImplicit> objImpl; // All objects
std::vector<MaterialObj> implMat; // All materials used by implicit obj std::vector<MaterialObj> implMat; // All materials used by implicit obj
nvvkBuffer implBuf; // Buffer of objects nvvk::Buffer implBuf; // Buffer of objects
nvvkBuffer implMatBuf; // Buffer of material nvvk::Buffer implMatBuf; // Buffer of material
int blasId; int blasId;
nvmath::mat4f transform{1}; nvmath::mat4f transform{1};
}; };

View file

@ -28,10 +28,10 @@
#include "offscreen.hpp" #include "offscreen.hpp"
#include "nvh/fileoperations.hpp" #include "nvh/fileoperations.hpp"
#include "nvvkpp/commands_vkpp.hpp" #include "nvvk/commands_vk.hpp"
#include "nvvkpp/descriptorsets_vkpp.hpp" #include "nvvk/descriptorsets_vk.hpp"
#include "nvvkpp/pipeline_vkpp.hpp" #include "nvvk/pipeline_vk.hpp"
#include "nvvkpp/renderpass_vkpp.hpp" #include "nvvk/renderpasses_vk.hpp"
extern std::vector<std::string> defaultSearchPaths; extern std::vector<std::string> defaultSearchPaths;
@ -39,10 +39,10 @@ extern std::vector<std::string> defaultSearchPaths;
// Post-processing // Post-processing
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
void Offscreen::setup(const vk::Device& device, nvvkMemAllocator& memAlloc, uint32_t queueFamily) void Offscreen::setup(const vk::Device& device, nvvk::Allocator* allocator, uint32_t queueFamily)
{ {
m_device = device; m_device = device;
m_alloc.init(device, &memAlloc); m_alloc = allocator;
m_graphicsQueueIndex = queueFamily; m_graphicsQueueIndex = queueFamily;
m_debug.setup(m_device); m_debug.setup(m_device);
} }
@ -53,8 +53,8 @@ void Offscreen::destroy()
m_device.destroy(m_pipelineLayout); m_device.destroy(m_pipelineLayout);
m_device.destroy(m_descPool); m_device.destroy(m_descPool);
m_device.destroy(m_dsetLayout); m_device.destroy(m_dsetLayout);
m_alloc.destroy(m_colorTexture); m_alloc->destroy(m_colorTexture);
m_alloc.destroy(m_depthTexture); m_alloc->destroy(m_depthTexture);
m_device.destroy(m_renderPass); m_device.destroy(m_renderPass);
m_device.destroy(m_framebuffer); m_device.destroy(m_framebuffer);
} }
@ -64,52 +64,57 @@ void Offscreen::destroy()
// //
void Offscreen::createFramebuffer(VkExtent2D& size) void Offscreen::createFramebuffer(VkExtent2D& size)
{ {
m_alloc.destroy(m_colorTexture); m_alloc->destroy(m_colorTexture);
m_alloc.destroy(m_depthTexture); m_alloc->destroy(m_depthTexture);
// Creating the color image // Creating the color image
auto colorCreateInfo = nvvkpp::image::create2DInfo(size, m_colorFormat, {
vk::ImageUsageFlagBits::eColorAttachment auto colorCreateInfo = nvvk::makeImage2DCreateInfo(size, m_colorFormat,
| vk::ImageUsageFlagBits::eSampled vk::ImageUsageFlagBits::eColorAttachment
| vk::ImageUsageFlagBits::eStorage); | vk::ImageUsageFlagBits::eSampled
m_colorTexture = m_alloc.createImage(colorCreateInfo); | vk::ImageUsageFlagBits::eStorage);
nvvk::Image image = m_alloc->createImage(colorCreateInfo);
vk::ImageViewCreateInfo ivInfo = nvvk::makeImageViewCreateInfo(image.image, colorCreateInfo);
m_colorTexture = m_alloc->createTexture(image, ivInfo, vk::SamplerCreateInfo());
m_colorTexture.descriptor.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
}
m_colorTexture.descriptor =
nvvkpp::image::create2DDescriptor(m_device, m_colorTexture.image, vk::SamplerCreateInfo{},
m_colorFormat, vk::ImageLayout::eGeneral);
// Creating the depth buffer // Creating the depth buffer
auto depthCreateInfo = {
nvvkpp::image::create2DInfo(size, m_depthFormat, auto depthCreateInfo =
vk::ImageUsageFlagBits::eDepthStencilAttachment); nvvk::makeImage2DCreateInfo(size, m_depthFormat,
m_depthTexture = m_alloc.createImage(depthCreateInfo); vk::ImageUsageFlagBits::eDepthStencilAttachment);
nvvk::Image image = m_alloc->createImage(depthCreateInfo);
vk::ImageViewCreateInfo depthStencilView; vk::ImageViewCreateInfo depthStencilView;
depthStencilView.setViewType(vk::ImageViewType::e2D); depthStencilView.setViewType(vk::ImageViewType::e2D);
depthStencilView.setFormat(m_depthFormat); depthStencilView.setFormat(m_depthFormat);
depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1}); depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1});
depthStencilView.setImage(m_depthTexture.image); depthStencilView.setImage(image.image);
m_depthTexture.descriptor.imageView = m_device.createImageView(depthStencilView);
m_depthTexture = m_alloc->createTexture(image, depthStencilView);
}
// Setting the image layout for both color and depth // Setting the image layout for both color and depth
{ {
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex); nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
auto cmdBuf = genCmdBuf.createCommandBuffer(); auto cmdBuf = genCmdBuf.createCommandBuffer();
nvvkpp::image::setImageLayout(cmdBuf, m_colorTexture.image, vk::ImageLayout::eUndefined, nvvk::cmdBarrierImageLayout(cmdBuf, m_colorTexture.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eGeneral); vk::ImageLayout::eGeneral);
nvvkpp::image::setImageLayout(cmdBuf, m_depthTexture.image, vk::ImageAspectFlagBits::eDepth, nvvk::cmdBarrierImageLayout(cmdBuf, m_depthTexture.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eUndefined, vk::ImageLayout::eDepthStencilAttachmentOptimal,
vk::ImageLayout::eDepthStencilAttachmentOptimal); vk::ImageAspectFlagBits::eDepth);
genCmdBuf.flushCommandBuffer(cmdBuf); genCmdBuf.submitAndWait(cmdBuf);
} }
// Creating a renderpass for the offscreen // Creating a renderpass for the offscreen
if(!m_renderPass) if(!m_renderPass)
{ {
m_renderPass = m_renderPass = nvvk::createRenderPass(m_device, {m_colorFormat}, m_depthFormat, 1, true, true,
nvvkpp::util::createRenderPass(m_device, {m_colorFormat}, m_depthFormat, 1, true, true, vk::ImageLayout::eGeneral, vk::ImageLayout::eGeneral);
vk::ImageLayout::eGeneral, vk::ImageLayout::eGeneral);
} }
// Creating the frame buffer for offscreen // Creating the frame buffer for offscreen
@ -147,13 +152,13 @@ void Offscreen::createPipeline(vk::RenderPass& renderPass)
// Pipeline: completely generic, no vertices // Pipeline: completely generic, no vertices
std::vector<std::string> paths = defaultSearchPaths; std::vector<std::string> paths = defaultSearchPaths;
nvvkpp::GraphicsPipelineGenerator pipelineGenerator(m_device, m_pipelineLayout, renderPass); nvvk::GraphicsPipelineGeneratorCombined pipelineGenerator(m_device, m_pipelineLayout, renderPass);
pipelineGenerator.addShader(nvh::loadFile("shaders/passthrough.vert.spv", true, paths), pipelineGenerator.addShader(nvh::loadFile("shaders/passthrough.vert.spv", true, paths),
vk::ShaderStageFlagBits::eVertex); vk::ShaderStageFlagBits::eVertex);
pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths), pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths),
vk::ShaderStageFlagBits::eFragment); vk::ShaderStageFlagBits::eFragment);
pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone); pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone);
m_pipeline = pipelineGenerator.create(); m_pipeline = pipelineGenerator.createPipeline();
m_debug.setObjectName(m_pipeline, "post"); m_debug.setObjectName(m_pipeline, "post");
} }
@ -167,10 +172,10 @@ void Offscreen::createDescriptor()
using vkDT = vk::DescriptorType; using vkDT = vk::DescriptorType;
using vkSS = vk::ShaderStageFlagBits; using vkSS = vk::ShaderStageFlagBits;
m_dsetLayoutBinding.emplace_back(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment)); m_dsetLayoutBinding.addBinding(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
m_dsetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_dsetLayoutBinding); m_dsetLayout = m_dsetLayoutBinding.createLayout(m_device);
m_descPool = nvvkpp::util::createDescriptorPool(m_device, m_dsetLayoutBinding); m_descPool = m_dsetLayoutBinding.createPool(m_device);
m_dset = nvvkpp::util::createDescriptorSet(m_device, m_descPool, m_dsetLayout); m_dset = nvvk::allocateDescriptorSet(m_device, m_descPool, m_dsetLayout);
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -179,7 +184,7 @@ void Offscreen::createDescriptor()
void Offscreen::updateDescriptorSet() void Offscreen::updateDescriptorSet()
{ {
vk::WriteDescriptorSet writeDescriptorSets = vk::WriteDescriptorSet writeDescriptorSets =
nvvkpp::util::createWrite(m_dset, m_dsetLayoutBinding[0], &m_colorTexture.descriptor); m_dsetLayoutBinding.makeWrite(m_dset, 0, &m_colorTexture.descriptor);
m_device.updateDescriptorSets(writeDescriptorSets, nullptr); m_device.updateDescriptorSets(writeDescriptorSets, nullptr);
} }

View file

@ -27,7 +27,8 @@
#include <vulkan/vulkan.hpp> #include <vulkan/vulkan.hpp>
#include "nvvkpp/debug_util_vkpp.hpp" #include "nvvk/debug_util_vk.hpp"
#include "nvvk/descriptorsets_vk.hpp"
#include "vkalloc.hpp" #include "vkalloc.hpp"
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -39,7 +40,7 @@
class Offscreen class Offscreen
{ {
public: public:
void setup(const vk::Device& device, nvvkMemAllocator& memAlloc, uint32_t queueFamily); void setup(const vk::Device& device, nvvk::Allocator* allocator, uint32_t queueFamily);
void destroy(); void destroy();
void createFramebuffer(VkExtent2D& size); void createFramebuffer(VkExtent2D& size);
@ -50,25 +51,25 @@ public:
const vk::RenderPass& renderPass() { return m_renderPass; } const vk::RenderPass& renderPass() { return m_renderPass; }
const vk::Framebuffer& frameBuffer() { return m_framebuffer; } const vk::Framebuffer& frameBuffer() { return m_framebuffer; }
const nvvkTexture& colorTexture() { return m_colorTexture; } const nvvk::Texture& colorTexture() { return m_colorTexture; }
private: private:
std::vector<vk::DescriptorSetLayoutBinding> m_dsetLayoutBinding; nvvk::DescriptorSetBindings m_dsetLayoutBinding;
vk::DescriptorPool m_descPool; vk::DescriptorPool m_descPool;
vk::DescriptorSetLayout m_dsetLayout; vk::DescriptorSetLayout m_dsetLayout;
vk::DescriptorSet m_dset; vk::DescriptorSet m_dset;
vk::Pipeline m_pipeline; vk::Pipeline m_pipeline;
vk::PipelineLayout m_pipelineLayout; vk::PipelineLayout m_pipelineLayout;
vk::RenderPass m_renderPass; vk::RenderPass m_renderPass;
vk::Framebuffer m_framebuffer; vk::Framebuffer m_framebuffer;
nvvkTexture m_colorTexture; nvvk::Texture m_colorTexture;
vk::Format m_colorFormat{vk::Format::eR32G32B32A32Sfloat}; vk::Format m_colorFormat{vk::Format::eR32G32B32A32Sfloat};
nvvkTexture m_depthTexture; nvvk::Texture m_depthTexture;
vk::Format m_depthFormat{vk::Format::eD32Sfloat}; vk::Format m_depthFormat{vk::Format::eD32Sfloat};
nvvkAllocator m_alloc; // Allocator for buffer, images, acceleration structures nvvk::Allocator* m_alloc; // Allocator for buffer, images, acceleration structures
vk::Device m_device; vk::Device m_device;
int m_graphicsQueueIndex{0}; int m_graphicsQueueIndex{0};
nvvkpp::DebugUtil m_debug; // Utility to name objects nvvk::DebugUtil m_debug; // Utility to name objects
}; };

View file

@ -28,8 +28,9 @@
#include "raytrace.hpp" #include "raytrace.hpp"
#include "nvh/fileoperations.hpp" #include "nvh/fileoperations.hpp"
#include "nvvkpp/descriptorsets_vkpp.hpp" #include "nvvk/descriptorsets_vk.hpp"
#include "nvvkpp/utilities_vkpp.hpp"
#include "nvvk/shaders_vk.hpp"
#include "obj_loader.h" #include "obj_loader.h"
extern std::vector<std::string> defaultSearchPaths; extern std::vector<std::string> defaultSearchPaths;
@ -37,25 +38,19 @@ extern std::vector<std::string> defaultSearchPaths;
void Raytracer::setup(const vk::Device& device, void Raytracer::setup(const vk::Device& device,
const vk::PhysicalDevice& physicalDevice, const vk::PhysicalDevice& physicalDevice,
nvvkMemAllocator& memAlloc, nvvk::Allocator* allocator,
uint32_t queueFamily) uint32_t queueFamily)
{ {
m_device = device; m_device = device;
m_physicalDevice = physicalDevice; m_physicalDevice = physicalDevice;
m_alloc.init(device, &memAlloc); m_alloc = allocator;
m_graphicsQueueIndex = queueFamily; m_graphicsQueueIndex = queueFamily;
// Requesting ray tracing properties // Requesting ray tracing properties
auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2, auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2,
vk::PhysicalDeviceRayTracingPropertiesKHR>(); vk::PhysicalDeviceRayTracingPropertiesKHR>();
m_rtProperties = properties.get<vk::PhysicalDeviceRayTracingPropertiesKHR>(); m_rtProperties = properties.get<vk::PhysicalDeviceRayTracingPropertiesKHR>();
#if defined(ALLOC_DEDICATED) m_rtBuilder.setup(m_device, allocator, m_graphicsQueueIndex);
m_rtBuilder.setup(m_device, m_physicalDevice, m_graphicsQueueIndex);
#elif defined(ALLOC_DMA)
m_rtBuilder.setup(m_device, memAlloc, m_graphicsQueueIndex);
#elif defined(ALLOC_VMA)
m_rtBuilder.setup(m_device, memAlloc, m_graphicsQueueIndex);
#endif
m_debug.setup(device); m_debug.setup(device);
} }
@ -68,13 +63,13 @@ void Raytracer::destroy()
m_device.destroy(m_rtDescSetLayout); m_device.destroy(m_rtDescSetLayout);
m_device.destroy(m_rtPipeline); m_device.destroy(m_rtPipeline);
m_device.destroy(m_rtPipelineLayout); m_device.destroy(m_rtPipelineLayout);
m_alloc.destroy(m_rtSBTBuffer); m_alloc->destroy(m_rtSBTBuffer);
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Converting a OBJ primitive to the ray tracing geometry used for the BLAS // Converting a OBJ primitive to the ray tracing geometry used for the BLAS
// //
nvvkpp::RaytracingBuilderKHR::Blas Raytracer::objectToVkGeometryKHR(const ObjModel& model) nvvk::RaytracingBuilderKHR::Blas Raytracer::objectToVkGeometryKHR(const ObjModel& model)
{ {
// Setting up the creation info of acceleration structure // Setting up the creation info of acceleration structure
vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate; vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate;
@ -110,7 +105,7 @@ nvvkpp::RaytracingBuilderKHR::Blas Raytracer::objectToVkGeometryKHR(const ObjMod
offset.setPrimitiveOffset(0); offset.setPrimitiveOffset(0);
offset.setTransformOffset(0); offset.setTransformOffset(0);
nvvkpp::RaytracingBuilderKHR::Blas blas; nvvk::RaytracingBuilderKHR::Blas blas;
blas.asGeometry.emplace_back(asGeom); blas.asGeometry.emplace_back(asGeom);
blas.asCreateGeometryInfo.emplace_back(asCreate); blas.asCreateGeometryInfo.emplace_back(asCreate);
blas.asBuildOffsetInfo.emplace_back(offset); blas.asBuildOffsetInfo.emplace_back(offset);
@ -121,7 +116,7 @@ nvvkpp::RaytracingBuilderKHR::Blas Raytracer::objectToVkGeometryKHR(const ObjMod
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Returning the ray tracing geometry used for the BLAS, containing all spheres // Returning the ray tracing geometry used for the BLAS, containing all spheres
// //
nvvkpp::RaytracingBuilderKHR::Blas Raytracer::implicitToVkGeometryKHR(const ImplInst& implicitObj) nvvk::RaytracingBuilderKHR::Blas Raytracer::implicitToVkGeometryKHR(const ImplInst& implicitObj)
{ {
// Setting up the creation info of acceleration structure // Setting up the creation info of acceleration structure
@ -152,7 +147,7 @@ nvvkpp::RaytracingBuilderKHR::Blas Raytracer::implicitToVkGeometryKHR(const Impl
offset.setPrimitiveOffset(0); offset.setPrimitiveOffset(0);
offset.setTransformOffset(0); offset.setTransformOffset(0);
nvvkpp::RaytracingBuilderKHR::Blas blas; nvvk::RaytracingBuilderKHR::Blas blas;
blas.asGeometry.emplace_back(asGeom); blas.asGeometry.emplace_back(asGeom);
blas.asCreateGeometryInfo.emplace_back(asCreate); blas.asCreateGeometryInfo.emplace_back(asCreate);
blas.asBuildOffsetInfo.emplace_back(offset); blas.asBuildOffsetInfo.emplace_back(offset);
@ -163,7 +158,7 @@ nvvkpp::RaytracingBuilderKHR::Blas Raytracer::implicitToVkGeometryKHR(const Impl
void Raytracer::createBottomLevelAS(std::vector<ObjModel>& models, ImplInst& implicitObj) void Raytracer::createBottomLevelAS(std::vector<ObjModel>& models, ImplInst& implicitObj)
{ {
// BLAS - Storing each primitive in a geometry // BLAS - Storing each primitive in a geometry
std::vector<nvvkpp::RaytracingBuilderKHR::Blas> allBlas; std::vector<nvvk::RaytracingBuilderKHR::Blas> allBlas;
allBlas.reserve(models.size()); allBlas.reserve(models.size());
for(const auto& obj : models) for(const auto& obj : models)
{ {
@ -182,33 +177,34 @@ void Raytracer::createBottomLevelAS(std::vector<ObjModel>& models, ImplInst& imp
} }
m_rtBuilder.buildBlas(allBlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace); m_rtBuilder.buildBlas(allBlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace
| vk::BuildAccelerationStructureFlagBitsKHR::eAllowCompaction);
} }
void Raytracer::createTopLevelAS(std::vector<ObjInstance>& instances, ImplInst& implicitObj) void Raytracer::createTopLevelAS(std::vector<ObjInstance>& instances, ImplInst& implicitObj)
{ {
std::vector<nvvkpp::RaytracingBuilderKHR::Instance> tlas; std::vector<nvvk::RaytracingBuilderKHR::Instance> tlas;
tlas.reserve(instances.size()); tlas.reserve(instances.size());
for(int i = 0; i < static_cast<int>(instances.size()); i++) for(int i = 0; i < static_cast<int>(instances.size()); i++)
{ {
nvvkpp::RaytracingBuilderKHR::Instance rayInst; nvvk::RaytracingBuilderKHR::Instance rayInst;
rayInst.transform = instances[i].transform; // Position of the instance rayInst.transform = instances[i].transform; // Position of the instance
rayInst.instanceId = i; // gl_InstanceID rayInst.instanceId = i; // gl_InstanceID
rayInst.blasId = instances[i].objIndex; rayInst.blasId = instances[i].objIndex;
rayInst.hitGroupId = 0; // We will use the same hit group for all objects rayInst.hitGroupId = 0; // We will use the same hit group for all objects
rayInst.flags = vk::GeometryInstanceFlagBitsKHR::eTriangleCullDisable; rayInst.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
tlas.emplace_back(rayInst); tlas.emplace_back(rayInst);
} }
// Add the blas containing all implicit // Add the blas containing all implicit
if(!implicitObj.objImpl.empty()) if(!implicitObj.objImpl.empty())
{ {
nvvkpp::RaytracingBuilderKHR::Instance rayInst; nvvk::RaytracingBuilderKHR::Instance rayInst;
rayInst.transform = implicitObj.transform; // Position of the instance rayInst.transform = implicitObj.transform; // Position of the instance
rayInst.instanceId = static_cast<uint32_t>(implicitObj.blasId); // Same for material index rayInst.instanceId = static_cast<uint32_t>(implicitObj.blasId); // Same for material index
rayInst.blasId = static_cast<uint32_t>(implicitObj.blasId); 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.hitGroupId = 1; // We will use the same hit group for all objects (the second one)
rayInst.flags = vk::GeometryInstanceFlagBitsKHR::eTriangleCullDisable; rayInst.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
tlas.emplace_back(rayInst); tlas.emplace_back(rayInst);
} }
@ -224,24 +220,24 @@ void Raytracer::createRtDescriptorSet(const vk::ImageView& outputImage)
using vkSS = vk::ShaderStageFlagBits; using vkSS = vk::ShaderStageFlagBits;
using vkDSLB = vk::DescriptorSetLayoutBinding; using vkDSLB = vk::DescriptorSetLayoutBinding;
m_rtDescSetLayoutBind.emplace_back(vkDSLB(0, vkDT::eAccelerationStructureKHR, 1, m_rtDescSetLayoutBind.addBinding(vkDSLB(0, vkDT::eAccelerationStructureKHR, 1,
vkSS::eRaygenKHR | vkSS::eClosestHitKHR)); // TLAS vkSS::eRaygenKHR | vkSS::eClosestHitKHR)); // TLAS
m_rtDescSetLayoutBind.emplace_back( m_rtDescSetLayoutBind.addBinding(
vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image
m_rtDescPool = nvvkpp::util::createDescriptorPool(m_device, m_rtDescSetLayoutBind); m_rtDescPool = m_rtDescSetLayoutBind.createPool(m_device);
m_rtDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_rtDescSetLayoutBind); m_rtDescSetLayout = m_rtDescSetLayoutBind.createLayout(m_device);
m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0]; m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0];
vk::AccelerationStructureKHR tlas = m_rtBuilder.getAccelerationStructure();
vk::WriteDescriptorSetAccelerationStructureKHR descASInfo; vk::WriteDescriptorSetAccelerationStructureKHR descASInfo;
descASInfo.setAccelerationStructureCount(1); descASInfo.setAccelerationStructureCount(1);
descASInfo.setPAccelerationStructures(&m_rtBuilder.getAccelerationStructure()); descASInfo.setPAccelerationStructures(&tlas);
vk::DescriptorImageInfo imageInfo{{}, outputImage, vk::ImageLayout::eGeneral}; vk::DescriptorImageInfo imageInfo{{}, outputImage, vk::ImageLayout::eGeneral};
std::vector<vk::WriteDescriptorSet> writes; std::vector<vk::WriteDescriptorSet> writes;
writes.emplace_back( writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 0, &descASInfo));
nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[0], &descASInfo)); writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 1, &imageInfo));
writes.emplace_back(nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[1], &imageInfo));
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr); m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
} }
@ -269,16 +265,17 @@ void Raytracer::createRtPipeline(vk::DescriptorSetLayout& sceneDescLayout)
std::vector<std::string> paths = defaultSearchPaths; std::vector<std::string> paths = defaultSearchPaths;
vk::ShaderModule raygenSM = vk::ShaderModule raygenSM =
nvvkpp::util::createShaderModule(m_device, // nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rgen.spv", true, paths)); nvh::loadFile("shaders/raytrace.rgen.spv", true, paths));
vk::ShaderModule missSM = vk::ShaderModule missSM =
nvvkpp::util::createShaderModule(m_device, // nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths)); nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths));
// The second miss shader is invoked when a shadow ray misses the geometry. It // The second miss shader is invoked when a shadow ray misses the geometry. It
// simply indicates that no occlusion has been found // simply indicates that no occlusion has been found
vk::ShaderModule shadowmissSM = nvvkpp::util::createShaderModule( vk::ShaderModule shadowmissSM =
m_device, nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths)); nvvk::createShaderModule(m_device,
nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
std::vector<vk::PipelineShaderStageCreateInfo> stages; std::vector<vk::PipelineShaderStageCreateInfo> stages;
@ -305,11 +302,11 @@ void Raytracer::createRtPipeline(vk::DescriptorSetLayout& sceneDescLayout)
// Hit Group0 - Closest Hit + AnyHit // Hit Group0 - Closest Hit + AnyHit
vk::ShaderModule chitSM = vk::ShaderModule chitSM =
nvvkpp::util::createShaderModule(m_device, // nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rchit.spv", true, paths)); nvh::loadFile("shaders/raytrace.rchit.spv", true, paths));
vk::ShaderModule ahitSM = vk::ShaderModule ahitSM =
nvvkpp::util::createShaderModule(m_device, // nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rahit.spv", true, paths)); nvh::loadFile("shaders/raytrace.rahit.spv", true, paths));
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup, vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup,
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR,
@ -323,14 +320,14 @@ void Raytracer::createRtPipeline(vk::DescriptorSetLayout& sceneDescLayout)
// Hit Group1 - Closest Hit + Intersection (procedural) // Hit Group1 - Closest Hit + Intersection (procedural)
vk::ShaderModule chit2SM = vk::ShaderModule chit2SM =
nvvkpp::util::createShaderModule(m_device, // nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace2.rchit.spv", true, paths)); nvh::loadFile("shaders/raytrace2.rchit.spv", true, paths));
vk::ShaderModule ahit2SM = vk::ShaderModule ahit2SM =
nvvkpp::util::createShaderModule(m_device, // nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace2.rahit.spv", true, paths)); nvh::loadFile("shaders/raytrace2.rahit.spv", true, paths));
vk::ShaderModule rintSM = vk::ShaderModule rintSM =
nvvkpp::util::createShaderModule(m_device, // nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rint.spv", true, paths)); nvh::loadFile("shaders/raytrace.rint.spv", true, paths));
{ {
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eProceduralHitGroup, vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eProceduralHitGroup,
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR,
@ -350,14 +347,13 @@ void Raytracer::createRtPipeline(vk::DescriptorSetLayout& sceneDescLayout)
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR}; VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR};
vk::ShaderModule call0 = vk::ShaderModule call0 =
nvvkpp::util::createShaderModule(m_device, nvvk::createShaderModule(m_device,
nvh::loadFile("shaders/light_point.rcall.spv", true, paths)); nvh::loadFile("shaders/light_point.rcall.spv", true, paths));
vk::ShaderModule call1 = vk::ShaderModule call1 =
nvvkpp::util::createShaderModule(m_device, nvvk::createShaderModule(m_device,
nvh::loadFile("shaders/light_spot.rcall.spv", true, paths)); nvh::loadFile("shaders/light_spot.rcall.spv", true, paths));
vk::ShaderModule call2 = vk::ShaderModule call2 =
nvvkpp::util::createShaderModule(m_device, nvvk::createShaderModule(m_device, nvh::loadFile("shaders/light_inf.rcall.spv", true, paths));
nvh::loadFile("shaders/light_inf.rcall.spv", true, paths));
stages.push_back({{}, vk::ShaderStageFlagBits::eCallableKHR, call0, "main"}); stages.push_back({{}, vk::ShaderStageFlagBits::eCallableKHR, call0, "main"});
callGroup.setGeneralShader(static_cast<uint32_t>(stages.size() - 1)); callGroup.setGeneralShader(static_cast<uint32_t>(stages.size() - 1));
@ -433,17 +429,17 @@ void Raytracer::createRtShaderBindingTable()
m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize, m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize,
shaderHandleStorage.data()); shaderHandleStorage.data());
// Write the handles in the SBT // Write the handles in the SBT
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex); nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer(); vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
m_rtSBTBuffer = m_rtSBTBuffer =
m_alloc.createBuffer(cmdBuf, shaderHandleStorage, vk::BufferUsageFlagBits::eRayTracingKHR); m_alloc->createBuffer(cmdBuf, shaderHandleStorage, vk::BufferUsageFlagBits::eRayTracingKHR);
m_debug.setObjectName(m_rtSBTBuffer.buffer, "SBT"); m_debug.setObjectName(m_rtSBTBuffer.buffer, "SBT");
genCmdBuf.flushCommandBuffer(cmdBuf); genCmdBuf.submitAndWait(cmdBuf);
m_alloc.flushStaging(); m_alloc->finalizeAndReleaseStaging();
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------

View file

@ -27,10 +27,11 @@
#include <vulkan/vulkan.hpp> #include <vulkan/vulkan.hpp>
#include "nvvk/descriptorsets_vk.hpp"
#include "vkalloc.hpp" #include "vkalloc.hpp"
#include "nvmath/nvmath.h" #include "nvmath/nvmath.h"
#include "nvvkpp/raytraceKHR_vkpp.hpp" #include "nvvk/raytraceKHR_vk.hpp"
#include "obj.hpp" #include "obj.hpp"
class Raytracer class Raytracer
@ -38,12 +39,12 @@ class Raytracer
public: public:
void setup(const vk::Device& device, void setup(const vk::Device& device,
const vk::PhysicalDevice& physicalDevice, const vk::PhysicalDevice& physicalDevice,
nvvkMemAllocator& memAlloc, nvvk::Allocator* allocator,
uint32_t queueFamily); uint32_t queueFamily);
void destroy(); void destroy();
nvvkpp::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model); nvvk::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
nvvkpp::RaytracingBuilderKHR::Blas implicitToVkGeometryKHR(const ImplInst& implicitObj); nvvk::RaytracingBuilderKHR::Blas implicitToVkGeometryKHR(const ImplInst& implicitObj);
void createBottomLevelAS(std::vector<ObjModel>& models, ImplInst& implicitObj); void createBottomLevelAS(std::vector<ObjModel>& models, ImplInst& implicitObj);
void createTopLevelAS(std::vector<ObjInstance>& instances, ImplInst& implicitObj); void createTopLevelAS(std::vector<ObjInstance>& instances, ImplInst& implicitObj);
void createRtDescriptorSet(const vk::ImageView& outputImage); void createRtDescriptorSet(const vk::ImageView& outputImage);
@ -57,23 +58,23 @@ public:
ObjPushConstants& sceneConstants); ObjPushConstants& sceneConstants);
private: private:
nvvkAllocator m_alloc; // Allocator for buffer, images, acceleration structures nvvk::Allocator* m_alloc; // Allocator for buffer, images, acceleration structures
vk::PhysicalDevice m_physicalDevice; vk::PhysicalDevice m_physicalDevice;
vk::Device m_device; vk::Device m_device;
int m_graphicsQueueIndex{0}; int m_graphicsQueueIndex{0};
nvvkpp::DebugUtil m_debug; // Utility to name objects nvvk::DebugUtil m_debug; // Utility to name objects
vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties; vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties;
nvvkpp::RaytracingBuilderKHR m_rtBuilder; nvvk::RaytracingBuilderKHR m_rtBuilder;
std::vector<vk::DescriptorSetLayoutBinding> m_rtDescSetLayoutBind; nvvk::DescriptorSetBindings m_rtDescSetLayoutBind;
vk::DescriptorPool m_rtDescPool; vk::DescriptorPool m_rtDescPool;
vk::DescriptorSetLayout m_rtDescSetLayout; vk::DescriptorSetLayout m_rtDescSetLayout;
vk::DescriptorSet m_rtDescSet; vk::DescriptorSet m_rtDescSet;
std::vector<vk::RayTracingShaderGroupCreateInfoKHR> m_rtShaderGroups; std::vector<vk::RayTracingShaderGroupCreateInfoKHR> m_rtShaderGroups;
vk::PipelineLayout m_rtPipelineLayout; vk::PipelineLayout m_rtPipelineLayout;
vk::Pipeline m_rtPipeline; vk::Pipeline m_rtPipeline;
nvvkBuffer m_rtSBTBuffer; nvvk::Buffer m_rtSBTBuffer;
struct RtPushConstants struct RtPushConstants
{ {

View file

@ -6,7 +6,7 @@
#include "raycommon.glsl" #include "raycommon.glsl"
#include "wavefront.glsl" #include "wavefront.glsl"
hitAttributeEXT vec3 attribs; hitAttributeEXT vec2 attribs;
// clang-format off // clang-format off
layout(location = 0) rayPayloadInEXT hitPayload prd; layout(location = 0) rayPayloadInEXT hitPayload prd;

View file

@ -6,7 +6,7 @@
#include "raycommon.glsl" #include "raycommon.glsl"
#include "wavefront.glsl" #include "wavefront.glsl"
hitAttributeEXT vec3 attribs; hitAttributeEXT vec2 attribs;
// clang-format off // clang-format off
layout(location = 0) rayPayloadInEXT hitPayload prd; layout(location = 0) rayPayloadInEXT hitPayload prd;

View file

@ -1,24 +1,6 @@
//#define ALLOC_DEDICATED //#define NVVK_ALLOC_DEDICATED
#define ALLOC_DMA #define NVVK_ALLOC_DMA
//#define ALLOC_VMA //#define NVVK_ALLOC_VMA
#if defined(ALLOC_DEDICATED) #include <nvvk/allocator_vk.hpp>
#include "nvvkpp/allocator_dedicated_vkpp.hpp"
using nvvkBuffer = nvvkpp::BufferDedicated;
using nvvkTexture = nvvkpp::TextureDedicated;
using nvvkAllocator = nvvkpp::AllocatorDedicated;
#elif defined(ALLOC_DMA)
#include "nvvkpp/allocator_dma_vkpp.hpp"
using nvvkBuffer = nvvkpp::BufferDma;
using nvvkTexture = nvvkpp::TextureDma;
using nvvkAllocator = nvvkpp::AllocatorDma;
using nvvkMemAllocator = nvvk::DeviceMemoryAllocator;
#elif defined(ALLOC_VMA)
#include "nvvkpp/allocator_vma_vkpp.hpp"
using nvvkBuffer = nvvkpp::BufferVma;
using nvvkTexture = nvvkpp::TextureVma;
using nvvkAllocator = nvvkpp::AllocatorVma;
using nvvkMemAllocator = VmaAllocator;
#endif

View file

@ -36,13 +36,13 @@ extern std::vector<std::string> defaultSearchPaths;
#include "hello_vulkan.h" #include "hello_vulkan.h"
#include "nvh//cameramanipulator.hpp" #include "nvh//cameramanipulator.hpp"
#include "nvvkpp/descriptorsets_vkpp.hpp" #include "nvvk/descriptorsets_vk.hpp"
#include "nvvkpp/pipeline_vkpp.hpp" #include "nvvk/pipeline_vk.hpp"
#include "nvh/fileoperations.hpp" #include "nvh/fileoperations.hpp"
#include "nvvkpp/commands_vkpp.hpp" #include "nvvk/commands_vk.hpp"
#include "nvvkpp/renderpass_vkpp.hpp" #include "nvvk/renderpasses_vk.hpp"
#include "nvvkpp/utilities_vkpp.hpp"
// Holding the camera matrices // Holding the camera matrices
struct CameraMatrices struct CameraMatrices
@ -56,9 +56,12 @@ struct CameraMatrices
// Keep the handle on the device // Keep the handle on the device
// Initialize the tool to do all our allocations: buffers, images // Initialize the tool to do all our allocations: buffers, images
// //
void HelloVulkan::setup(const vk::Device& device, const vk::PhysicalDevice& physicalDevice, uint32_t queueFamily) void HelloVulkan::setup(const vk::Instance& instance,
const vk::Device& device,
const vk::PhysicalDevice& physicalDevice,
uint32_t queueFamily)
{ {
AppBase::setup(device, physicalDevice, queueFamily); AppBase::setup(instance, device, physicalDevice, queueFamily);
m_alloc.init(device, physicalDevice); m_alloc.init(device, physicalDevice);
m_debug.setup(m_device); m_debug.setup(m_device);
} }
@ -92,22 +95,23 @@ void HelloVulkan::createDescriptorSetLayout()
uint32_t nbObj = static_cast<uint32_t>(m_objModel.size()); uint32_t nbObj = static_cast<uint32_t>(m_objModel.size());
// Camera matrices (binding = 0) // Camera matrices (binding = 0)
m_descSetLayoutBind.emplace_back(vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex)); m_descSetLayoutBind.addBinding(vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex));
// Materials (binding = 1) // Materials (binding = 1)
m_descSetLayoutBind.emplace_back(vkDS(1, vkDT::eStorageBuffer, nbObj, vkSS::eVertex | vkSS::eFragment)); m_descSetLayoutBind.addBinding(
vkDS(1, vkDT::eStorageBuffer, nbObj, vkSS::eVertex | vkSS::eFragment));
// Scene description (binding = 2) // Scene description (binding = 2)
m_descSetLayoutBind.emplace_back( // m_descSetLayoutBind.addBinding( //
vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment)); vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment));
// Textures (binding = 3) // Textures (binding = 3)
m_descSetLayoutBind.emplace_back(vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment)); m_descSetLayoutBind.addBinding(vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment));
// Materials (binding = 4) // Materials (binding = 4)
m_descSetLayoutBind.emplace_back(vkDS(4, vkDT::eStorageBuffer, nbObj, vkSS::eFragment)); m_descSetLayoutBind.addBinding(vkDS(4, vkDT::eStorageBuffer, nbObj, vkSS::eFragment));
m_descSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_descSetLayoutBind); m_descSetLayout = m_descSetLayoutBind.createLayout(m_device);
m_descPool = nvvkpp::util::createDescriptorPool(m_device, m_descSetLayoutBind, 1); m_descPool = m_descSetLayoutBind.createPool(m_device, 1);
m_descSet = nvvkpp::util::createDescriptorSet(m_device, m_descPool, m_descSetLayout); m_descSet = nvvk::allocateDescriptorSet(m_device, m_descPool, m_descSetLayout);
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -119,9 +123,9 @@ void HelloVulkan::updateDescriptorSet()
// Camera matrices and scene description // Camera matrices and scene description
vk::DescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE}; vk::DescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE};
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[0], &dbiUnif)); writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 0, &dbiUnif));
vk::DescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE}; vk::DescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[2], &dbiSceneDesc)); writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 2, &dbiSceneDesc));
// All material buffers, 1 buffer per OBJ // All material buffers, 1 buffer per OBJ
std::vector<vk::DescriptorBufferInfo> dbiMat; std::vector<vk::DescriptorBufferInfo> dbiMat;
@ -131,8 +135,8 @@ void HelloVulkan::updateDescriptorSet()
dbiMat.push_back({m_objModel[i].matColorBuffer.buffer, 0, VK_WHOLE_SIZE}); dbiMat.push_back({m_objModel[i].matColorBuffer.buffer, 0, VK_WHOLE_SIZE});
dbiMatIdx.push_back({m_objModel[i].matIndexBuffer.buffer, 0, VK_WHOLE_SIZE}); dbiMatIdx.push_back({m_objModel[i].matIndexBuffer.buffer, 0, VK_WHOLE_SIZE});
} }
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[1], dbiMat.data())); writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 1, dbiMat.data()));
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[4], dbiMatIdx.data())); writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 4, dbiMatIdx.data()));
// All texture samplers // All texture samplers
std::vector<vk::DescriptorImageInfo> diit; std::vector<vk::DescriptorImageInfo> diit;
@ -140,7 +144,7 @@ void HelloVulkan::updateDescriptorSet()
{ {
diit.push_back(m_textures[i].descriptor); diit.push_back(m_textures[i].descriptor);
} }
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[3], diit.data())); writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 3, diit.data()));
// Writing the information // Writing the information
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr); m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
@ -154,7 +158,8 @@ void HelloVulkan::createGraphicsPipeline()
{ {
using vkSS = vk::ShaderStageFlagBits; using vkSS = vk::ShaderStageFlagBits;
vk::PushConstantRange pushConstantRanges = {vkSS::eVertex | vkSS::eFragment, 0, sizeof(ObjPushConstant)}; vk::PushConstantRange pushConstantRanges = {vkSS::eVertex | vkSS::eFragment, 0,
sizeof(ObjPushConstant)};
// Creating the Pipeline Layout // Creating the Pipeline Layout
vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo; vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo;
@ -166,18 +171,19 @@ void HelloVulkan::createGraphicsPipeline()
m_pipelineLayout = m_device.createPipelineLayout(pipelineLayoutCreateInfo); m_pipelineLayout = m_device.createPipelineLayout(pipelineLayoutCreateInfo);
// Creating the Pipeline // Creating the Pipeline
std::vector<std::string> paths = defaultSearchPaths; std::vector<std::string> paths = defaultSearchPaths;
nvvkpp::GraphicsPipelineGenerator gpb(m_device, m_pipelineLayout, m_offscreenRenderPass); nvvk::GraphicsPipelineGeneratorCombined gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
gpb.depthStencilState = {true}; gpb.depthStencilState.depthTestEnable = true;
gpb.addShader(nvh::loadFile("shaders/vert_shader.vert.spv", true, paths), vkSS::eVertex); gpb.addShader(nvh::loadFile("shaders/vert_shader.vert.spv", true, paths), vkSS::eVertex);
gpb.addShader(nvh::loadFile("shaders/frag_shader.frag.spv", true, paths), vkSS::eFragment); gpb.addShader(nvh::loadFile("shaders/frag_shader.frag.spv", true, paths), vkSS::eFragment);
gpb.vertexInputState.bindingDescriptions = {{0, sizeof(VertexObj)}}; gpb.addBindingDescription({0, sizeof(VertexObj)});
gpb.vertexInputState.attributeDescriptions = {{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)}, gpb.addAttributeDescriptions(std::vector<vk::VertexInputAttributeDescription>{
{1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)}, {0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
{2, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, color)}, {1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)},
{3, 0, vk::Format::eR32G32Sfloat, offsetof(VertexObj, texCoord)}}; {2, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, color)},
{3, 0, vk::Format::eR32G32Sfloat, offsetof(VertexObj, texCoord)}});
m_graphicsPipeline = gpb.create(); m_graphicsPipeline = gpb.createPipeline();
m_debug.setObjectName(m_graphicsPipeline, "Graphics"); m_debug.setObjectName(m_graphicsPipeline, "Graphics");
} }
@ -210,16 +216,16 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size()); model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
// Create the buffers on Device and copy vertices, indices and materials // Create the buffers on Device and copy vertices, indices and materials
nvvkpp::SingleCommandBuffer cmdBufGet(m_device, m_graphicsQueueIndex); nvvk::CommandPool cmdBufGet(m_device, m_graphicsQueueIndex);
vk::CommandBuffer cmdBuf = cmdBufGet.createCommandBuffer(); vk::CommandBuffer cmdBuf = cmdBufGet.createCommandBuffer();
model.vertexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_vertices, vkBU::eVertexBuffer); model.vertexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_vertices, vkBU::eVertexBuffer);
model.indexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_indices, vkBU::eIndexBuffer); model.indexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_indices, vkBU::eIndexBuffer);
model.matColorBuffer = m_alloc.createBuffer(cmdBuf, loader.m_materials, vkBU::eStorageBuffer); model.matColorBuffer = m_alloc.createBuffer(cmdBuf, loader.m_materials, vkBU::eStorageBuffer);
model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, vkBU::eStorageBuffer); model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, vkBU::eStorageBuffer);
// Creates all textures found // Creates all textures found
createTextureImages(cmdBuf, loader.m_textures); createTextureImages(cmdBuf, loader.m_textures);
cmdBufGet.flushCommandBuffer(cmdBuf); cmdBufGet.submitAndWait(cmdBuf);
m_alloc.flushStaging(); m_alloc.finalizeAndReleaseStaging();
std::string objNb = std::to_string(instance.objIndex); std::string objNb = std::to_string(instance.objIndex);
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str())); m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
@ -241,7 +247,8 @@ void HelloVulkan::createUniformBuffer()
using vkBU = vk::BufferUsageFlagBits; using vkBU = vk::BufferUsageFlagBits;
using vkMP = vk::MemoryPropertyFlagBits; using vkMP = vk::MemoryPropertyFlagBits;
m_cameraMat = m_alloc.createBuffer(sizeof(CameraMatrices), vkBU::eUniformBuffer, vkMP::eHostVisible | vkMP::eHostCoherent); m_cameraMat = m_alloc.createBuffer(sizeof(CameraMatrices), vkBU::eUniformBuffer,
vkMP::eHostVisible | vkMP::eHostCoherent);
m_debug.setObjectName(m_cameraMat.buffer, "cameraMat"); m_debug.setObjectName(m_cameraMat.buffer, "cameraMat");
} }
@ -254,42 +261,46 @@ void HelloVulkan::createUniformBuffer()
void HelloVulkan::createSceneDescriptionBuffer() void HelloVulkan::createSceneDescriptionBuffer()
{ {
using vkBU = vk::BufferUsageFlagBits; using vkBU = vk::BufferUsageFlagBits;
nvvkpp::SingleCommandBuffer cmdGen(m_device, m_graphicsQueueIndex); nvvk::CommandPool cmdGen(m_device, m_graphicsQueueIndex);
auto cmdBuf = cmdGen.createCommandBuffer(); auto cmdBuf = cmdGen.createCommandBuffer();
m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer); m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer);
cmdGen.flushCommandBuffer(cmdBuf); cmdGen.submitAndWait(cmdBuf);
m_alloc.flushStaging(); m_alloc.finalizeAndReleaseStaging();
m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc"); m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc");
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Creating all textures and samplers // Creating all textures and samplers
// //
void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf, const std::vector<std::string>& textures) void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
const std::vector<std::string>& textures)
{ {
using vkIU = vk::ImageUsageFlagBits; using vkIU = vk::ImageUsageFlagBits;
vk::SamplerCreateInfo samplerCreateInfo{{}, vk::Filter::eLinear, vk::Filter::eLinear, vk::SamplerMipmapMode::eLinear}; vk::SamplerCreateInfo samplerCreateInfo{
{}, vk::Filter::eLinear, vk::Filter::eLinear, vk::SamplerMipmapMode::eLinear};
samplerCreateInfo.setMaxLod(FLT_MAX); samplerCreateInfo.setMaxLod(FLT_MAX);
vk::Format format = vk::Format::eR8G8B8A8Srgb; vk::Format format = vk::Format::eR8G8B8A8Srgb;
// If no textures are present, create a dummy one to accommodate the pipeline layout // If no textures are present, create a dummy one to accommodate the pipeline layout
if(textures.empty() && m_textures.empty()) if(textures.empty() && m_textures.empty())
{ {
nvvkTexture texture; nvvk::Texture texture;
std::array<uint8_t, 4> color{255u, 255u, 255u, 255u}; std::array<uint8_t, 4> color{255u, 255u, 255u, 255u};
vk::DeviceSize bufferSize = sizeof(color); vk::DeviceSize bufferSize = sizeof(color);
auto imgSize = vk::Extent2D(1, 1); auto imgSize = vk::Extent2D(1, 1);
auto imageCreateInfo = nvvkpp::image::create2DInfo(imgSize, format); auto imageCreateInfo = nvvk::makeImage2DCreateInfo(imgSize, format);
// Creating the dummy texure
nvvk::Image image = m_alloc.createImage(cmdBuf, bufferSize, color.data(), imageCreateInfo);
vk::ImageViewCreateInfo ivInfo = nvvk::makeImageViewCreateInfo(image.image, imageCreateInfo);
texture = m_alloc.createTexture(image, ivInfo, samplerCreateInfo);
// Creating the VKImage
texture = m_alloc.createImage(cmdBuf, bufferSize, color.data(), imageCreateInfo);
// Setting up the descriptor used by the shader
texture.descriptor = nvvkpp::image::create2DDescriptor(m_device, texture.image, samplerCreateInfo, format);
// The image format must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL // The image format must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
nvvkpp::image::setImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined, vk::ImageLayout::eShaderReadOnlyOptimal); nvvk::cmdBarrierImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eShaderReadOnlyOptimal);
m_textures.push_back(texture); m_textures.push_back(texture);
} }
else else
@ -302,7 +313,8 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf, const std
o << "media/textures/" << texture; o << "media/textures/" << texture;
std::string txtFile = nvh::findFile(o.str(), defaultSearchPaths); std::string txtFile = nvh::findFile(o.str(), defaultSearchPaths);
stbi_uc* pixels = stbi_load(txtFile.c_str(), &texWidth, &texHeight, &texChannels, STBI_rgb_alpha); stbi_uc* pixels =
stbi_load(txtFile.c_str(), &texWidth, &texHeight, &texChannels, STBI_rgb_alpha);
// Handle failure // Handle failure
if(!pixels) if(!pixels)
@ -313,16 +325,18 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf, const std
pixels = reinterpret_cast<stbi_uc*>(color.data()); pixels = reinterpret_cast<stbi_uc*>(color.data());
} }
vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4; vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4;
auto imgSize = vk::Extent2D(texWidth, texHeight); auto imgSize = vk::Extent2D(texWidth, texHeight);
auto imageCreateInfo = nvvkpp::image::create2DInfo(imgSize, format, vkIU::eSampled, true); auto imageCreateInfo = nvvk::makeImage2DCreateInfo(imgSize, format, vkIU::eSampled, true);
{ {
nvvkTexture texture; nvvk::ImageDedicated image =
texture = m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo); m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo);
nvvk::cmdGenerateMipmaps(cmdBuf, image.image, format, imgSize, imageCreateInfo.mipLevels);
vk::ImageViewCreateInfo ivInfo =
nvvk::makeImageViewCreateInfo(image.image, imageCreateInfo);
nvvk::Texture texture = m_alloc.createTexture(image, ivInfo, samplerCreateInfo);
nvvkpp::image::generateMipmaps(cmdBuf, texture.image, format, imgSize, imageCreateInfo.mipLevels);
texture.descriptor = nvvkpp::image::create2DDescriptor(m_device, texture.image, samplerCreateInfo, format);
m_textures.push_back(texture); m_textures.push_back(texture);
} }
} }
@ -389,9 +403,10 @@ void HelloVulkan::rasterize(const vk::CommandBuffer& cmdBuf)
auto& inst = m_objInstance[i]; auto& inst = m_objInstance[i];
auto& model = m_objModel[inst.objIndex]; auto& model = m_objModel[inst.objIndex];
m_pushConstant.instanceId = i; // Telling which instance is drawn m_pushConstant.instanceId = i; // Telling which instance is drawn
cmdBuf.pushConstants<ObjPushConstant>(m_pipelineLayout, vkSS::eVertex | vkSS::eFragment, 0, m_pushConstant); cmdBuf.pushConstants<ObjPushConstant>(m_pipelineLayout, vkSS::eVertex | vkSS::eFragment, 0,
m_pushConstant);
cmdBuf.bindVertexBuffers(0, 1, &model.vertexBuffer.buffer, &offset); cmdBuf.bindVertexBuffers(0, {model.vertexBuffer.buffer}, {offset});
cmdBuf.bindIndexBuffer(model.indexBuffer.buffer, 0, vk::IndexType::eUint32); cmdBuf.bindIndexBuffer(model.indexBuffer.buffer, 0, vk::IndexType::eUint32);
cmdBuf.drawIndexed(model.nbIndices, 1, 0, 0, 0); cmdBuf.drawIndexed(model.nbIndices, 1, 0, 0, 0);
} }
@ -422,48 +437,60 @@ void HelloVulkan::createOffscreenRender()
m_alloc.destroy(m_offscreenDepth); m_alloc.destroy(m_offscreenDepth);
// Creating the color image // Creating the color image
auto colorCreateInfo = nvvkpp::image::create2DInfo(m_size, m_offscreenColorFormat, {
vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eSampled auto colorCreateInfo = nvvk::makeImage2DCreateInfo(m_size, m_offscreenColorFormat,
| vk::ImageUsageFlagBits::eStorage); vk::ImageUsageFlagBits::eColorAttachment
m_offscreenColor = m_alloc.createImage(colorCreateInfo); | vk::ImageUsageFlagBits::eSampled
| vk::ImageUsageFlagBits::eStorage);
m_offscreenColor.descriptor = nvvkpp::image::create2DDescriptor(m_device, m_offscreenColor.image, vk::SamplerCreateInfo{}, nvvk::ImageDedicated image = m_alloc.createImage(colorCreateInfo);
m_offscreenColorFormat, vk::ImageLayout::eGeneral); vk::ImageViewCreateInfo ivInfo = nvvk::makeImageViewCreateInfo(image.image, colorCreateInfo);
m_offscreenColor = m_alloc.createTexture(image, ivInfo, vk::SamplerCreateInfo());
m_offscreenColor.descriptor.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
}
// Creating the depth buffer // Creating the depth buffer
auto depthCreateInfo = auto depthCreateInfo =
nvvkpp::image::create2DInfo(m_size, m_offscreenDepthFormat, vk::ImageUsageFlagBits::eDepthStencilAttachment); nvvk::makeImage2DCreateInfo(m_size, m_offscreenDepthFormat,
m_offscreenDepth = m_alloc.createImage(depthCreateInfo); vk::ImageUsageFlagBits::eDepthStencilAttachment);
{
nvvk::Image image = m_alloc.createImage(depthCreateInfo);
vk::ImageViewCreateInfo depthStencilView; vk::ImageViewCreateInfo depthStencilView;
depthStencilView.setViewType(vk::ImageViewType::e2D); depthStencilView.setViewType(vk::ImageViewType::e2D);
depthStencilView.setFormat(m_offscreenDepthFormat); depthStencilView.setFormat(m_offscreenDepthFormat);
depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1}); depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1});
depthStencilView.setImage(m_offscreenDepth.image); depthStencilView.setImage(image.image);
m_offscreenDepth.descriptor.imageView = m_device.createImageView(depthStencilView);
m_offscreenDepth = m_alloc.createTexture(image, depthStencilView);
}
// Setting the image layout for both color and depth // Setting the image layout for both color and depth
{ {
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex); nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
auto cmdBuf = genCmdBuf.createCommandBuffer(); auto cmdBuf = genCmdBuf.createCommandBuffer();
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined, vk::ImageLayout::eGeneral); nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined,
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageAspectFlagBits::eDepth, vk::ImageLayout::eGeneral);
vk::ImageLayout::eUndefined, vk::ImageLayout::eDepthStencilAttachmentOptimal); nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eDepthStencilAttachmentOptimal,
vk::ImageAspectFlagBits::eDepth);
genCmdBuf.flushCommandBuffer(cmdBuf); genCmdBuf.submitAndWait(cmdBuf);
} }
// Creating a renderpass for the offscreen // Creating a renderpass for the offscreen
if(!m_offscreenRenderPass) if(!m_offscreenRenderPass)
{ {
m_offscreenRenderPass = nvvkpp::util::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat, 1, m_offscreenRenderPass =
true, true, vk::ImageLayout::eGeneral, vk::ImageLayout::eGeneral); nvvk::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat, 1, true,
true, vk::ImageLayout::eGeneral, vk::ImageLayout::eGeneral);
} }
// Creating the frame buffer for offscreen // Creating the frame buffer for offscreen
std::vector<vk::ImageView> attachments = {m_offscreenColor.descriptor.imageView, m_offscreenDepth.descriptor.imageView}; std::vector<vk::ImageView> attachments = {m_offscreenColor.descriptor.imageView,
m_offscreenDepth.descriptor.imageView};
m_device.destroy(m_offscreenFramebuffer); m_device.destroy(m_offscreenFramebuffer);
vk::FramebufferCreateInfo info; vk::FramebufferCreateInfo info;
@ -495,11 +522,14 @@ void HelloVulkan::createPostPipeline()
// Pipeline: completely generic, no vertices // Pipeline: completely generic, no vertices
std::vector<std::string> paths = defaultSearchPaths; std::vector<std::string> paths = defaultSearchPaths;
nvvkpp::GraphicsPipelineGenerator pipelineGenerator(m_device, m_postPipelineLayout, m_renderPass); nvvk::GraphicsPipelineGeneratorCombined pipelineGenerator(m_device, m_postPipelineLayout,
pipelineGenerator.addShader(nvh::loadFile("shaders/passthrough.vert.spv", true, paths), vk::ShaderStageFlagBits::eVertex); m_renderPass);
pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths), vk::ShaderStageFlagBits::eFragment); pipelineGenerator.addShader(nvh::loadFile("shaders/passthrough.vert.spv", true, paths),
vk::ShaderStageFlagBits::eVertex);
pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths),
vk::ShaderStageFlagBits::eFragment);
pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone); pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone);
m_postPipeline = pipelineGenerator.create(); m_postPipeline = pipelineGenerator.createPipeline();
m_debug.setObjectName(m_postPipeline, "post"); m_debug.setObjectName(m_postPipeline, "post");
} }
@ -513,10 +543,10 @@ void HelloVulkan::createPostDescriptor()
using vkDT = vk::DescriptorType; using vkDT = vk::DescriptorType;
using vkSS = vk::ShaderStageFlagBits; using vkSS = vk::ShaderStageFlagBits;
m_postDescSetLayoutBind.emplace_back(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment)); m_postDescSetLayoutBind.addBinding(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
m_postDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_postDescSetLayoutBind); m_postDescSetLayout = m_postDescSetLayoutBind.createLayout(m_device);
m_postDescPool = nvvkpp::util::createDescriptorPool(m_device, m_postDescSetLayoutBind); m_postDescPool = m_postDescSetLayoutBind.createPool(m_device);
m_postDescSet = nvvkpp::util::createDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout); m_postDescSet = nvvk::allocateDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
} }
@ -526,7 +556,7 @@ void HelloVulkan::createPostDescriptor()
void HelloVulkan::updatePostDescriptorSet() void HelloVulkan::updatePostDescriptorSet()
{ {
vk::WriteDescriptorSet writeDescriptorSets = vk::WriteDescriptorSet writeDescriptorSets =
nvvkpp::util::createWrite(m_postDescSet, m_postDescSetLayoutBind[0], &m_offscreenColor.descriptor); m_postDescSetLayoutBind.makeWrite(m_postDescSet, 0, &m_offscreenColor.descriptor);
m_device.updateDescriptorSets(writeDescriptorSets, nullptr); m_device.updateDescriptorSets(writeDescriptorSets, nullptr);
} }
@ -541,9 +571,11 @@ void HelloVulkan::drawPost(vk::CommandBuffer cmdBuf)
cmdBuf.setScissor(0, {{{0, 0}, {m_size.width, m_size.height}}}); cmdBuf.setScissor(0, {{{0, 0}, {m_size.width, m_size.height}}});
auto aspectRatio = static_cast<float>(m_size.width) / static_cast<float>(m_size.height); auto aspectRatio = static_cast<float>(m_size.width) / static_cast<float>(m_size.height);
cmdBuf.pushConstants<float>(m_postPipelineLayout, vk::ShaderStageFlagBits::eFragment, 0, aspectRatio); cmdBuf.pushConstants<float>(m_postPipelineLayout, vk::ShaderStageFlagBits::eFragment, 0,
aspectRatio);
cmdBuf.bindPipeline(vk::PipelineBindPoint::eGraphics, m_postPipeline); cmdBuf.bindPipeline(vk::PipelineBindPoint::eGraphics, m_postPipeline);
cmdBuf.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, m_postPipelineLayout, 0, m_postDescSet, {}); cmdBuf.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, m_postPipelineLayout, 0,
m_postDescSet, {});
cmdBuf.draw(3, 1, 0, 0); cmdBuf.draw(3, 1, 0, 0);
m_debug.endLabel(cmdBuf); m_debug.endLabel(cmdBuf);

View file

@ -26,13 +26,11 @@
*/ */
#pragma once #pragma once
#include "nvvkpp/allocator_dedicated_vkpp.hpp" #define NVVK_ALLOC_DEDICATED
#include "nvvkpp/appbase_vkpp.hpp" #include "nvvk/allocator_vk.hpp"
#include "nvvkpp/debug_util_vkpp.hpp" #include "nvvk/appbase_vkpp.hpp"
#include "nvvk/debug_util_vk.hpp"
#include "nvvk/descriptorsets_vk.hpp"
using nvvkBuffer = nvvkpp::BufferDedicated;
using nvvkTexture = nvvkpp::TextureDedicated;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Simple rasterizer of OBJ objects // Simple rasterizer of OBJ objects
@ -41,17 +39,21 @@ using nvvkTexture = nvvkpp::TextureDedicated;
// - Rendering is done in an offscreen framebuffer // - Rendering is done in an offscreen framebuffer
// - The image of the framebuffer is displayed in post-process in a full-screen quad // - The image of the framebuffer is displayed in post-process in a full-screen quad
// //
class HelloVulkan : public nvvkpp::AppBase class HelloVulkan : public nvvk::AppBase
{ {
public: public:
void setup(const vk::Device& device, const vk::PhysicalDevice& physicalDevice, uint32_t queueFamily) override; void setup(const vk::Instance& instance,
const vk::Device& device,
const vk::PhysicalDevice& physicalDevice,
uint32_t queueFamily) override;
void createDescriptorSetLayout(); void createDescriptorSetLayout();
void createGraphicsPipeline(); void createGraphicsPipeline();
void loadModel(const std::string& filename, nvmath::mat4f transform = nvmath::mat4f(1)); void loadModel(const std::string& filename, nvmath::mat4f transform = nvmath::mat4f(1));
void updateDescriptorSet(); void updateDescriptorSet();
void createUniformBuffer(); void createUniformBuffer();
void createSceneDescriptionBuffer(); void createSceneDescriptionBuffer();
void createTextureImages(const vk::CommandBuffer& cmdBuf, const std::vector<std::string>& textures); void createTextureImages(const vk::CommandBuffer& cmdBuf,
const std::vector<std::string>& textures);
void updateUniformBuffer(); void updateUniformBuffer();
void onResize(int /*w*/, int /*h*/) override; void onResize(int /*w*/, int /*h*/) override;
void destroyResources(); void destroyResources();
@ -62,10 +64,10 @@ public:
{ {
uint32_t nbIndices{0}; uint32_t nbIndices{0};
uint32_t nbVertices{0}; uint32_t nbVertices{0};
nvvkBuffer vertexBuffer; // Device buffer of all 'Vertex' nvvk::Buffer vertexBuffer; // Device buffer of all 'Vertex'
nvvkBuffer indexBuffer; // Device buffer of the indices forming triangles nvvk::Buffer indexBuffer; // Device buffer of the indices forming triangles
nvvkBuffer matColorBuffer; // Device buffer of array of 'Wavefront material' nvvk::Buffer matColorBuffer; // Device buffer of array of 'Wavefront material'
nvvkBuffer matIndexBuffer; // Device buffer of array of 'Wavefront material' nvvk::Buffer matIndexBuffer; // Device buffer of array of 'Wavefront material'
}; };
// Instance of the OBJ // Instance of the OBJ
@ -92,20 +94,20 @@ public:
std::vector<ObjInstance> m_objInstance; std::vector<ObjInstance> m_objInstance;
// Graphic pipeline // Graphic pipeline
vk::PipelineLayout m_pipelineLayout; vk::PipelineLayout m_pipelineLayout;
vk::Pipeline m_graphicsPipeline; vk::Pipeline m_graphicsPipeline;
std::vector<vk::DescriptorSetLayoutBinding> m_descSetLayoutBind; nvvk::DescriptorSetBindings m_descSetLayoutBind;
vk::DescriptorPool m_descPool; vk::DescriptorPool m_descPool;
vk::DescriptorSetLayout m_descSetLayout; vk::DescriptorSetLayout m_descSetLayout;
vk::DescriptorSet m_descSet; vk::DescriptorSet m_descSet;
nvvkBuffer m_cameraMat; // Device-Host of the camera matrices nvvk::Buffer m_cameraMat; // Device-Host of the camera matrices
nvvkBuffer m_sceneDesc; // Device buffer of the OBJ instances nvvk::Buffer m_sceneDesc; // Device buffer of the OBJ instances
std::vector<nvvkTexture> m_textures; // vector of all textures of the scene std::vector<nvvk::Texture> m_textures; // vector of all textures of the scene
nvvkpp::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures nvvk::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures
nvvkpp::DebugUtil m_debug; // Utility to name objects nvvk::DebugUtil m_debug; // Utility to name objects
// #Post // #Post
@ -115,16 +117,16 @@ public:
void updatePostDescriptorSet(); void updatePostDescriptorSet();
void drawPost(vk::CommandBuffer cmdBuf); void drawPost(vk::CommandBuffer cmdBuf);
std::vector<vk::DescriptorSetLayoutBinding> m_postDescSetLayoutBind; nvvk::DescriptorSetBindings m_postDescSetLayoutBind;
vk::DescriptorPool m_postDescPool; vk::DescriptorPool m_postDescPool;
vk::DescriptorSetLayout m_postDescSetLayout; vk::DescriptorSetLayout m_postDescSetLayout;
vk::DescriptorSet m_postDescSet; vk::DescriptorSet m_postDescSet;
vk::Pipeline m_postPipeline; vk::Pipeline m_postPipeline;
vk::PipelineLayout m_postPipelineLayout; vk::PipelineLayout m_postPipelineLayout;
vk::RenderPass m_offscreenRenderPass; vk::RenderPass m_offscreenRenderPass;
vk::Framebuffer m_offscreenFramebuffer; vk::Framebuffer m_offscreenFramebuffer;
nvvkTexture m_offscreenColor; nvvk::Texture m_offscreenColor;
vk::Format m_offscreenColorFormat{vk::Format::eR32G32B32A32Sfloat}; vk::Format m_offscreenColorFormat{vk::Format::eR32G32B32A32Sfloat};
nvvkTexture m_offscreenDepth; nvvk::Texture m_offscreenDepth;
vk::Format m_offscreenDepthFormat{vk::Format::eD32Sfloat}; vk::Format m_offscreenDepthFormat{vk::Format::eD32Sfloat};
}; };

View file

@ -31,6 +31,7 @@
#include <array> #include <array>
#include <vulkan/vulkan.hpp> #include <vulkan/vulkan.hpp>
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
#include "imgui.h" #include "imgui.h"
#include "imgui_impl_glfw.h" #include "imgui_impl_glfw.h"
@ -39,10 +40,10 @@
#include "nvh/cameramanipulator.hpp" #include "nvh/cameramanipulator.hpp"
#include "nvh/fileoperations.hpp" #include "nvh/fileoperations.hpp"
#include "nvpsystem.hpp" #include "nvpsystem.hpp"
#include "nvvkpp/appbase_vkpp.hpp" #include "nvvk/appbase_vkpp.hpp"
#include "nvvkpp/commands_vkpp.hpp" #include "nvvk/commands_vk.hpp"
#include "nvvkpp/context_vkpp.hpp" #include "nvvk/context_vk.hpp"
#include "nvvkpp/utilities_vkpp.hpp"
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
#define UNUSED(x) (void)(x) #define UNUSED(x) (void)(x)
@ -97,12 +98,14 @@ int main(int argc, char** argv)
return 1; return 1;
} }
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
GLFWwindow* window = glfwCreateWindow(SAMPLE_WIDTH, SAMPLE_HEIGHT, "NVIDIA Vulkan Raytracing Tutorial", nullptr, nullptr); GLFWwindow* window = glfwCreateWindow(SAMPLE_WIDTH, SAMPLE_HEIGHT,
"NVIDIA Vulkan Raytracing Tutorial", nullptr, nullptr);
// Setup camera // Setup camera
CameraManip.setWindowSize(SAMPLE_WIDTH, SAMPLE_HEIGHT); CameraManip.setWindowSize(SAMPLE_WIDTH, SAMPLE_HEIGHT);
CameraManip.setLookat(nvmath::vec3f(2.0f, 2.0f, 2.0f), nvmath::vec3f(0, 0, 0), nvmath::vec3f(0, 1, 0)); CameraManip.setLookat(nvmath::vec3f(2.0f, 2.0f, 2.0f), nvmath::vec3f(0, 0, 0),
nvmath::vec3f(0, 1, 0));
// Setup Vulkan // Setup Vulkan
if(!glfwVulkanSupported()) if(!glfwVulkanSupported())
@ -127,7 +130,7 @@ int main(int argc, char** argv)
vk::PhysicalDeviceScalarBlockLayoutFeaturesEXT scalarFeature; vk::PhysicalDeviceScalarBlockLayoutFeaturesEXT scalarFeature;
// Requesting Vulkan extensions and layers // Requesting Vulkan extensions and layers
nvvkpp::ContextCreateInfo contextInfo; nvvk::ContextCreateInfo contextInfo;
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true); contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME); contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME);
#ifdef _WIN32 #ifdef _WIN32
@ -144,7 +147,7 @@ int main(int argc, char** argv)
contextInfo.addDeviceExtension(VK_EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME, false, &scalarFeature); contextInfo.addDeviceExtension(VK_EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME, false, &scalarFeature);
// Creating Vulkan base application // Creating Vulkan base application
nvvkpp::Context vkctx{}; nvvk::Context vkctx{};
vkctx.initInstance(contextInfo); vkctx.initInstance(contextInfo);
// Find all compatible devices // Find all compatible devices
auto compatibleDevices = vkctx.getCompatibleDevices(contextInfo); auto compatibleDevices = vkctx.getCompatibleDevices(contextInfo);
@ -159,7 +162,8 @@ int main(int argc, char** argv)
const vk::SurfaceKHR surface = helloVk.getVkSurface(vkctx.m_instance, window); const vk::SurfaceKHR surface = helloVk.getVkSurface(vkctx.m_instance, window);
vkctx.setGCTQueueWithPresent(surface); vkctx.setGCTQueueWithPresent(surface);
helloVk.setup(vkctx.m_device, vkctx.m_physicalDevice, vkctx.m_queueGCT.familyIndex); helloVk.setup(vkctx.m_instance, vkctx.m_device, vkctx.m_physicalDevice,
vkctx.m_queueGCT.familyIndex);
helloVk.createSurface(surface, SAMPLE_WIDTH, SAMPLE_HEIGHT); helloVk.createSurface(surface, SAMPLE_WIDTH, SAMPLE_HEIGHT);
helloVk.createDepthBuffer(); helloVk.createDepthBuffer();
helloVk.createRenderPass(); helloVk.createRenderPass();
@ -206,7 +210,8 @@ int main(int argc, char** argv)
{ {
ImGui::ColorEdit3("Clear color", reinterpret_cast<float*>(&clearColor)); ImGui::ColorEdit3("Clear color", reinterpret_cast<float*>(&clearColor));
renderUI(helloVk); renderUI(helloVk);
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); ImGui::Text("Application average %.3f ms/frame (%.1f FPS)",
1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
ImGui::Render(); ImGui::Render();
} }
@ -221,7 +226,8 @@ int main(int argc, char** argv)
// Clearing screen // Clearing screen
vk::ClearValue clearValues[2]; vk::ClearValue clearValues[2];
clearValues[0].setColor(nvvkpp::util::clearColor(clearColor)); clearValues[0].setColor(
std::array<float, 4>({clearColor[0], clearColor[1], clearColor[2], clearColor[3]}));
clearValues[1].setDepthStencil({1.0f, 0}); clearValues[1].setDepthStencil({1.0f, 0});
// Offscreen render pass // Offscreen render pass
@ -266,8 +272,6 @@ int main(int argc, char** argv)
helloVk.getDevice().waitIdle(); helloVk.getDevice().waitIdle();
helloVk.destroyResources(); helloVk.destroyResources();
helloVk.destroy(); helloVk.destroy();
vkctx.m_instance.destroySurfaceKHR(surface);
vkctx.deinit(); vkctx.deinit();
glfwDestroyWindow(window); glfwDestroyWindow(window);

View file

@ -35,14 +35,14 @@ extern std::vector<std::string> defaultSearchPaths;
#include "obj_loader.h" #include "obj_loader.h"
#include "hello_vulkan.h" #include "hello_vulkan.h"
#include "nvh//cameramanipulator.hpp" #include "nvh/cameramanipulator.hpp"
#include "nvvkpp/descriptorsets_vkpp.hpp"
#include "nvvkpp/pipeline_vkpp.hpp"
#include "nvh/fileoperations.hpp" #include "nvh/fileoperations.hpp"
#include "nvvkpp/commands_vkpp.hpp" #include "nvvk/commands_vk.hpp"
#include "nvvkpp/renderpass_vkpp.hpp" #include "nvvk/descriptorsets_vk.hpp"
#include "nvvkpp/utilities_vkpp.hpp" #include "nvvk/pipeline_vk.hpp"
#include "nvvk/renderpasses_vk.hpp"
#include "nvvk/shaders_vk.hpp"
// Holding the camera matrices // Holding the camera matrices
struct CameraMatrices struct CameraMatrices
@ -58,11 +58,12 @@ struct CameraMatrices
// Keep the handle on the device // Keep the handle on the device
// Initialize the tool to do all our allocations: buffers, images // Initialize the tool to do all our allocations: buffers, images
// //
void HelloVulkan::setup(const vk::Device& device, void HelloVulkan::setup(const vk::Instance& instance,
const vk::Device& device,
const vk::PhysicalDevice& physicalDevice, const vk::PhysicalDevice& physicalDevice,
uint32_t queueFamily) uint32_t queueFamily)
{ {
AppBase::setup(device, physicalDevice, queueFamily); AppBase::setup(instance, device, physicalDevice, queueFamily);
m_alloc.init(device, physicalDevice); m_alloc.init(device, physicalDevice);
m_debug.setup(m_device); m_debug.setup(m_device);
} }
@ -99,31 +100,31 @@ void HelloVulkan::createDescriptorSetLayout()
uint32_t nbObj = static_cast<uint32_t>(m_objModel.size()); uint32_t nbObj = static_cast<uint32_t>(m_objModel.size());
// Camera matrices (binding = 0) // Camera matrices (binding = 0)
m_descSetLayoutBind.emplace_back( m_descSetLayoutBind.addBinding(
vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR)); vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR));
// Materials (binding = 1) // Materials (binding = 1)
m_descSetLayoutBind.emplace_back( m_descSetLayoutBind.addBinding(
vkDS(1, vkDT::eStorageBuffer, nbObj, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR)); vkDS(1, vkDT::eStorageBuffer, nbObj, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
// Scene description (binding = 2) // Scene description (binding = 2)
m_descSetLayoutBind.emplace_back( // m_descSetLayoutBind.addBinding( //
vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR)); vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
// Textures (binding = 3) // Textures (binding = 3)
m_descSetLayoutBind.emplace_back( m_descSetLayoutBind.addBinding(
vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR)); vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR));
// Materials (binding = 4) // Materials (binding = 4)
m_descSetLayoutBind.emplace_back( m_descSetLayoutBind.addBinding(
vkDS(4, vkDT::eStorageBuffer, nbObj, vkSS::eFragment | vkSS::eClosestHitKHR)); vkDS(4, vkDT::eStorageBuffer, nbObj, vkSS::eFragment | vkSS::eClosestHitKHR));
// Storing vertices (binding = 5) // Storing vertices (binding = 5)
m_descSetLayoutBind.emplace_back( // m_descSetLayoutBind.addBinding( //
vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR)); vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
// Storing indices (binding = 6) // Storing indices (binding = 6)
m_descSetLayoutBind.emplace_back( // m_descSetLayoutBind.addBinding( //
vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR)); vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
m_descSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_descSetLayoutBind); m_descSetLayout = m_descSetLayoutBind.createLayout(m_device);
m_descPool = nvvkpp::util::createDescriptorPool(m_device, m_descSetLayoutBind, 1); m_descPool = m_descSetLayoutBind.createPool(m_device, 1);
m_descSet = nvvkpp::util::createDescriptorSet(m_device, m_descPool, m_descSetLayout); m_descSet = nvvk::allocateDescriptorSet(m_device, m_descPool, m_descSetLayout);
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -135,27 +136,26 @@ void HelloVulkan::updateDescriptorSet()
// Camera matrices and scene description // Camera matrices and scene description
vk::DescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE}; vk::DescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE};
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[0], &dbiUnif)); writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 0, &dbiUnif));
vk::DescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE}; vk::DescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[2], &dbiSceneDesc)); writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 2, &dbiSceneDesc));
// All material buffers, 1 buffer per OBJ // All material buffers, 1 buffer per OBJ
std::vector<vk::DescriptorBufferInfo> dbiMat; std::vector<vk::DescriptorBufferInfo> dbiMat;
std::vector<vk::DescriptorBufferInfo> dbiMatIdx; std::vector<vk::DescriptorBufferInfo> dbiMatIdx;
std::vector<vk::DescriptorBufferInfo> dbiVert; std::vector<vk::DescriptorBufferInfo> dbiVert;
std::vector<vk::DescriptorBufferInfo> dbiIdx; std::vector<vk::DescriptorBufferInfo> dbiIdx;
for(auto& obj : m_objModel) for(size_t i = 0; i < m_objModel.size(); ++i)
{ {
dbiMat.emplace_back(obj.matColorBuffer.buffer, 0, VK_WHOLE_SIZE); dbiMat.push_back({m_objModel[i].matColorBuffer.buffer, 0, VK_WHOLE_SIZE});
dbiMatIdx.emplace_back(obj.matIndexBuffer.buffer, 0, VK_WHOLE_SIZE); dbiMatIdx.push_back({m_objModel[i].matIndexBuffer.buffer, 0, VK_WHOLE_SIZE});
dbiVert.emplace_back(obj.vertexBuffer.buffer, 0, VK_WHOLE_SIZE); dbiVert.push_back({m_objModel[i].vertexBuffer.buffer, 0, VK_WHOLE_SIZE});
dbiIdx.emplace_back(obj.indexBuffer.buffer, 0, VK_WHOLE_SIZE); dbiIdx.push_back({m_objModel[i].indexBuffer.buffer, 0, VK_WHOLE_SIZE});
} }
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[1], dbiMat.data())); writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 1, dbiMat.data()));
writes.emplace_back( writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 4, dbiMatIdx.data()));
nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[4], dbiMatIdx.data())); writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 5, dbiVert.data()));
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[5], dbiVert.data())); writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 6, dbiIdx.data()));
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[6], dbiIdx.data()));
// All texture samplers // All texture samplers
std::vector<vk::DescriptorImageInfo> diit; std::vector<vk::DescriptorImageInfo> diit;
@ -163,7 +163,7 @@ void HelloVulkan::updateDescriptorSet()
{ {
diit.push_back(texture.descriptor); diit.push_back(texture.descriptor);
} }
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[3], diit.data())); writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 3, diit.data()));
// Writing the information // Writing the information
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr); m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
@ -189,19 +189,19 @@ void HelloVulkan::createGraphicsPipeline()
m_pipelineLayout = m_device.createPipelineLayout(pipelineLayoutCreateInfo); m_pipelineLayout = m_device.createPipelineLayout(pipelineLayoutCreateInfo);
// Creating the Pipeline // Creating the Pipeline
std::vector<std::string> paths = defaultSearchPaths; std::vector<std::string> paths = defaultSearchPaths;
nvvkpp::GraphicsPipelineGenerator gpb(m_device, m_pipelineLayout, m_offscreenRenderPass); nvvk::GraphicsPipelineGeneratorCombined gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
gpb.depthStencilState = {true}; gpb.depthStencilState.depthTestEnable = true;
gpb.addShader(nvh::loadFile("shaders/vert_shader.vert.spv", true, paths), vkSS::eVertex); gpb.addShader(nvh::loadFile("shaders/vert_shader.vert.spv", true, paths), vkSS::eVertex);
gpb.addShader(nvh::loadFile("shaders/frag_shader.frag.spv", true, paths), vkSS::eFragment); gpb.addShader(nvh::loadFile("shaders/frag_shader.frag.spv", true, paths), vkSS::eFragment);
gpb.vertexInputState.bindingDescriptions = {{0, sizeof(VertexObj)}}; gpb.addBindingDescription({0, sizeof(VertexObj)});
gpb.vertexInputState.attributeDescriptions = { gpb.addAttributeDescriptions(std::vector<vk::VertexInputAttributeDescription>{
{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)}, {0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
{1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)}, {1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)},
{2, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, color)}, {2, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, color)},
{3, 0, vk::Format::eR32G32Sfloat, offsetof(VertexObj, texCoord)}}; {3, 0, vk::Format::eR32G32Sfloat, offsetof(VertexObj, texCoord)}});
m_graphicsPipeline = gpb.create(); m_graphicsPipeline = gpb.createPipeline();
m_debug.setObjectName(m_graphicsPipeline, "Graphics"); m_debug.setObjectName(m_graphicsPipeline, "Graphics");
} }
@ -234,8 +234,8 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size()); model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
// Create the buffers on Device and copy vertices, indices and materials // Create the buffers on Device and copy vertices, indices and materials
nvvkpp::SingleCommandBuffer cmdBufGet(m_device, m_graphicsQueueIndex); nvvk::CommandPool cmdBufGet(m_device, m_graphicsQueueIndex);
vk::CommandBuffer cmdBuf = cmdBufGet.createCommandBuffer(); vk::CommandBuffer cmdBuf = cmdBufGet.createCommandBuffer();
model.vertexBuffer = model.vertexBuffer =
m_alloc.createBuffer(cmdBuf, loader.m_vertices, m_alloc.createBuffer(cmdBuf, loader.m_vertices,
vkBU::eVertexBuffer | vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress); vkBU::eVertexBuffer | vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress);
@ -246,8 +246,8 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, vkBU::eStorageBuffer); model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, vkBU::eStorageBuffer);
// Creates all textures found // Creates all textures found
createTextureImages(cmdBuf, loader.m_textures); createTextureImages(cmdBuf, loader.m_textures);
cmdBufGet.flushCommandBuffer(cmdBuf); cmdBufGet.submitAndWait(cmdBuf);
m_alloc.flushStaging(); m_alloc.finalizeAndReleaseStaging();
std::string objNb = std::to_string(instance.objIndex); std::string objNb = std::to_string(instance.objIndex);
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str())); m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
@ -282,12 +282,12 @@ void HelloVulkan::createUniformBuffer()
void HelloVulkan::createSceneDescriptionBuffer() void HelloVulkan::createSceneDescriptionBuffer()
{ {
using vkBU = vk::BufferUsageFlagBits; using vkBU = vk::BufferUsageFlagBits;
nvvkpp::SingleCommandBuffer cmdGen(m_device, m_graphicsQueueIndex); nvvk::CommandPool cmdGen(m_device, m_graphicsQueueIndex);
auto cmdBuf = cmdGen.createCommandBuffer(); auto cmdBuf = cmdGen.createCommandBuffer();
m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer); m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer);
cmdGen.flushCommandBuffer(cmdBuf); cmdGen.submitAndWait(cmdBuf);
m_alloc.flushStaging(); m_alloc.finalizeAndReleaseStaging();
m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc"); m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc");
} }
@ -307,21 +307,21 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
// If no textures are present, create a dummy one to accommodate the pipeline layout // If no textures are present, create a dummy one to accommodate the pipeline layout
if(textures.empty() && m_textures.empty()) if(textures.empty() && m_textures.empty())
{ {
nvvkTexture texture; nvvk::Texture texture;
std::array<uint8_t, 4> color{255u, 255u, 255u, 255u}; std::array<uint8_t, 4> color{255u, 255u, 255u, 255u};
vk::DeviceSize bufferSize = sizeof(color); vk::DeviceSize bufferSize = sizeof(color);
auto imgSize = vk::Extent2D(1, 1); auto imgSize = vk::Extent2D(1, 1);
auto imageCreateInfo = nvvkpp::image::create2DInfo(imgSize, format); auto imageCreateInfo = nvvk::makeImage2DCreateInfo(imgSize, format);
// Creating the dummy texure
nvvk::Image image = m_alloc.createImage(cmdBuf, bufferSize, color.data(), imageCreateInfo);
vk::ImageViewCreateInfo ivInfo = nvvk::makeImageViewCreateInfo(image.image, imageCreateInfo);
texture = m_alloc.createTexture(image, ivInfo, samplerCreateInfo);
// Creating the VKImage
texture = m_alloc.createImage(cmdBuf, bufferSize, color.data(), imageCreateInfo);
// Setting up the descriptor used by the shader
texture.descriptor =
nvvkpp::image::create2DDescriptor(m_device, texture.image, samplerCreateInfo, format);
// The image format must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL // The image format must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
nvvkpp::image::setImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined, nvvk::cmdBarrierImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eShaderReadOnlyOptimal); vk::ImageLayout::eShaderReadOnlyOptimal);
m_textures.push_back(texture); m_textures.push_back(texture);
} }
else else
@ -348,16 +348,16 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4; vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4;
auto imgSize = vk::Extent2D(texWidth, texHeight); auto imgSize = vk::Extent2D(texWidth, texHeight);
auto imageCreateInfo = nvvkpp::image::create2DInfo(imgSize, format, vkIU::eSampled, true); auto imageCreateInfo = nvvk::makeImage2DCreateInfo(imgSize, format, vkIU::eSampled, true);
{ {
nvvkTexture texture; nvvk::ImageDedicated image =
texture = m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo); m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo);
nvvk::cmdGenerateMipmaps(cmdBuf, image.image, format, imgSize, imageCreateInfo.mipLevels);
vk::ImageViewCreateInfo ivInfo =
nvvk::makeImageViewCreateInfo(image.image, imageCreateInfo);
nvvk::Texture texture = m_alloc.createTexture(image, ivInfo, samplerCreateInfo);
nvvkpp::image::generateMipmaps(cmdBuf, texture.image, format, imgSize,
imageCreateInfo.mipLevels);
texture.descriptor =
nvvkpp::image::create2DDescriptor(m_device, texture.image, samplerCreateInfo, format);
m_textures.push_back(texture); m_textures.push_back(texture);
} }
} }
@ -434,7 +434,7 @@ void HelloVulkan::rasterize(const vk::CommandBuffer& cmdBuf)
cmdBuf.pushConstants<ObjPushConstant>(m_pipelineLayout, vkSS::eVertex | vkSS::eFragment, 0, cmdBuf.pushConstants<ObjPushConstant>(m_pipelineLayout, vkSS::eVertex | vkSS::eFragment, 0,
m_pushConstant); m_pushConstant);
cmdBuf.bindVertexBuffers(0, 1, &model.vertexBuffer.buffer, &offset); cmdBuf.bindVertexBuffers(0, {model.vertexBuffer.buffer}, {offset});
cmdBuf.bindIndexBuffer(model.indexBuffer.buffer, 0, vk::IndexType::eUint32); cmdBuf.bindIndexBuffer(model.indexBuffer.buffer, 0, vk::IndexType::eUint32);
cmdBuf.drawIndexed(model.nbIndices, 1, 0, 0, 0); cmdBuf.drawIndexed(model.nbIndices, 1, 0, 0, 0);
} }
@ -464,49 +464,54 @@ void HelloVulkan::createOffscreenRender()
m_alloc.destroy(m_offscreenDepth); m_alloc.destroy(m_offscreenDepth);
// Creating the color image // Creating the color image
auto colorCreateInfo = nvvkpp::image::create2DInfo(m_size, m_offscreenColorFormat, {
vk::ImageUsageFlagBits::eColorAttachment auto colorCreateInfo = nvvk::makeImage2DCreateInfo(m_size, m_offscreenColorFormat,
| vk::ImageUsageFlagBits::eSampled vk::ImageUsageFlagBits::eColorAttachment
| vk::ImageUsageFlagBits::eStorage); | vk::ImageUsageFlagBits::eSampled
m_offscreenColor = m_alloc.createImage(colorCreateInfo); | vk::ImageUsageFlagBits::eStorage);
m_offscreenColor.descriptor =
nvvkpp::image::create2DDescriptor(m_device, m_offscreenColor.image, vk::SamplerCreateInfo{}, nvvk::Image image = m_alloc.createImage(colorCreateInfo);
m_offscreenColorFormat, vk::ImageLayout::eGeneral); vk::ImageViewCreateInfo ivInfo = nvvk::makeImageViewCreateInfo(image.image, colorCreateInfo);
m_offscreenColor = m_alloc.createTexture(image, ivInfo, vk::SamplerCreateInfo());
m_offscreenColor.descriptor.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
}
// Creating the depth buffer // Creating the depth buffer
auto depthCreateInfo = auto depthCreateInfo =
nvvkpp::image::create2DInfo(m_size, m_offscreenDepthFormat, nvvk::makeImage2DCreateInfo(m_size, m_offscreenDepthFormat,
vk::ImageUsageFlagBits::eDepthStencilAttachment); vk::ImageUsageFlagBits::eDepthStencilAttachment);
m_offscreenDepth = m_alloc.createImage(depthCreateInfo); {
nvvk::Image image = m_alloc.createImage(depthCreateInfo);
vk::ImageViewCreateInfo depthStencilView; vk::ImageViewCreateInfo depthStencilView;
depthStencilView.setViewType(vk::ImageViewType::e2D); depthStencilView.setViewType(vk::ImageViewType::e2D);
depthStencilView.setFormat(m_offscreenDepthFormat); depthStencilView.setFormat(m_offscreenDepthFormat);
depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1}); depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1});
depthStencilView.setImage(m_offscreenDepth.image); depthStencilView.setImage(image.image);
m_offscreenDepth.descriptor.imageView = m_device.createImageView(depthStencilView);
m_offscreenDepth = m_alloc.createTexture(image, depthStencilView);
}
// Setting the image layout for both color and depth // Setting the image layout for both color and depth
{ {
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex); nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
auto cmdBuf = genCmdBuf.createCommandBuffer(); auto cmdBuf = genCmdBuf.createCommandBuffer();
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined, nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eGeneral); vk::ImageLayout::eGeneral);
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageAspectFlagBits::eDepth, nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eUndefined, vk::ImageLayout::eDepthStencilAttachmentOptimal,
vk::ImageLayout::eDepthStencilAttachmentOptimal); vk::ImageAspectFlagBits::eDepth);
genCmdBuf.flushCommandBuffer(cmdBuf); genCmdBuf.submitAndWait(cmdBuf);
} }
// Creating a renderpass for the offscreen // Creating a renderpass for the offscreen
if(!m_offscreenRenderPass) if(!m_offscreenRenderPass)
{ {
m_offscreenRenderPass = m_offscreenRenderPass =
nvvkpp::util::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat, nvvk::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat, 1, true,
1, true, true, vk::ImageLayout::eGeneral, true, vk::ImageLayout::eGeneral, vk::ImageLayout::eGeneral);
vk::ImageLayout::eGeneral);
} }
// Creating the frame buffer for offscreen // Creating the frame buffer for offscreen
@ -543,13 +548,14 @@ void HelloVulkan::createPostPipeline()
// Pipeline: completely generic, no vertices // Pipeline: completely generic, no vertices
std::vector<std::string> paths = defaultSearchPaths; std::vector<std::string> paths = defaultSearchPaths;
nvvkpp::GraphicsPipelineGenerator pipelineGenerator(m_device, m_postPipelineLayout, m_renderPass); nvvk::GraphicsPipelineGeneratorCombined pipelineGenerator(m_device, m_postPipelineLayout,
m_renderPass);
pipelineGenerator.addShader(nvh::loadFile("shaders/passthrough.vert.spv", true, paths), pipelineGenerator.addShader(nvh::loadFile("shaders/passthrough.vert.spv", true, paths),
vk::ShaderStageFlagBits::eVertex); vk::ShaderStageFlagBits::eVertex);
pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths), pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths),
vk::ShaderStageFlagBits::eFragment); vk::ShaderStageFlagBits::eFragment);
pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone); pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone);
m_postPipeline = pipelineGenerator.create(); m_postPipeline = pipelineGenerator.createPipeline();
m_debug.setObjectName(m_postPipeline, "post"); m_debug.setObjectName(m_postPipeline, "post");
} }
@ -563,10 +569,10 @@ void HelloVulkan::createPostDescriptor()
using vkDT = vk::DescriptorType; using vkDT = vk::DescriptorType;
using vkSS = vk::ShaderStageFlagBits; using vkSS = vk::ShaderStageFlagBits;
m_postDescSetLayoutBind.emplace_back(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment)); m_postDescSetLayoutBind.addBinding(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
m_postDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_postDescSetLayoutBind); m_postDescSetLayout = m_postDescSetLayoutBind.createLayout(m_device);
m_postDescPool = nvvkpp::util::createDescriptorPool(m_device, m_postDescSetLayoutBind); m_postDescPool = m_postDescSetLayoutBind.createPool(m_device);
m_postDescSet = nvvkpp::util::createDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout); m_postDescSet = nvvk::allocateDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -575,8 +581,7 @@ void HelloVulkan::createPostDescriptor()
void HelloVulkan::updatePostDescriptorSet() void HelloVulkan::updatePostDescriptorSet()
{ {
vk::WriteDescriptorSet writeDescriptorSets = vk::WriteDescriptorSet writeDescriptorSets =
nvvkpp::util::createWrite(m_postDescSet, m_postDescSetLayoutBind[0], m_postDescSetLayoutBind.makeWrite(m_postDescSet, 0, &m_offscreenColor.descriptor);
&m_offscreenColor.descriptor);
m_device.updateDescriptorSets(writeDescriptorSets, nullptr); m_device.updateDescriptorSets(writeDescriptorSets, nullptr);
} }
@ -614,13 +619,13 @@ void HelloVulkan::initRayTracing()
auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2, auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2,
vk::PhysicalDeviceRayTracingPropertiesKHR>(); vk::PhysicalDeviceRayTracingPropertiesKHR>();
m_rtProperties = properties.get<vk::PhysicalDeviceRayTracingPropertiesKHR>(); m_rtProperties = properties.get<vk::PhysicalDeviceRayTracingPropertiesKHR>();
m_rtBuilder.setup(m_device, m_physicalDevice, m_graphicsQueueIndex); m_rtBuilder.setup(m_device, &m_alloc, m_graphicsQueueIndex);
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Converting a OBJ primitive to the ray tracing geometry used for the BLAS // Converting a OBJ primitive to the ray tracing geometry used for the BLAS
// //
nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model) nvvk::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model)
{ {
// Setting up the creation info of acceleration structure // Setting up the creation info of acceleration structure
vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate; vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate;
@ -657,7 +662,7 @@ nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjM
offset.setTransformOffset(0); offset.setTransformOffset(0);
// Our blas is only one geometry, but could be made of many geometries // Our blas is only one geometry, but could be made of many geometries
nvvkpp::RaytracingBuilderKHR::Blas blas; nvvk::RaytracingBuilderKHR::Blas blas;
blas.asGeometry.emplace_back(asGeom); blas.asGeometry.emplace_back(asGeom);
blas.asCreateGeometryInfo.emplace_back(asCreate); blas.asCreateGeometryInfo.emplace_back(asCreate);
blas.asBuildOffsetInfo.emplace_back(offset); blas.asBuildOffsetInfo.emplace_back(offset);
@ -671,7 +676,7 @@ nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjM
void HelloVulkan::createBottomLevelAS() void HelloVulkan::createBottomLevelAS()
{ {
// BLAS - Storing each primitive in a geometry // BLAS - Storing each primitive in a geometry
std::vector<nvvkpp::RaytracingBuilderKHR::Blas> allBlas; std::vector<nvvk::RaytracingBuilderKHR::Blas> allBlas;
allBlas.reserve(m_objModel.size()); allBlas.reserve(m_objModel.size());
for(const auto& obj : m_objModel) for(const auto& obj : m_objModel)
{ {
@ -685,16 +690,16 @@ void HelloVulkan::createBottomLevelAS()
void HelloVulkan::createTopLevelAS() void HelloVulkan::createTopLevelAS()
{ {
std::vector<nvvkpp::RaytracingBuilderKHR::Instance> tlas; std::vector<nvvk::RaytracingBuilderKHR::Instance> tlas;
tlas.reserve(m_objInstance.size()); tlas.reserve(m_objInstance.size());
for(int i = 0; i < static_cast<int>(m_objInstance.size()); i++) for(int i = 0; i < static_cast<int>(m_objInstance.size()); i++)
{ {
nvvkpp::RaytracingBuilderKHR::Instance rayInst; nvvk::RaytracingBuilderKHR::Instance rayInst;
rayInst.transform = m_objInstance[i].transform; // Position of the instance rayInst.transform = m_objInstance[i].transform; // Position of the instance
rayInst.instanceId = i; // gl_InstanceID rayInst.instanceId = i; // gl_InstanceID
rayInst.blasId = m_objInstance[i].objIndex; rayInst.blasId = m_objInstance[i].objIndex;
rayInst.hitGroupId = 0; // We will use the same hit group for all objects rayInst.hitGroupId = 0; // We will use the same hit group for all objects
rayInst.flags = vk::GeometryInstanceFlagBitsKHR::eTriangleCullDisable; rayInst.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
tlas.emplace_back(rayInst); tlas.emplace_back(rayInst);
} }
m_rtBuilder.buildTlas(tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace); m_rtBuilder.buildTlas(tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace);
@ -709,25 +714,25 @@ void HelloVulkan::createRtDescriptorSet()
using vkSS = vk::ShaderStageFlagBits; using vkSS = vk::ShaderStageFlagBits;
using vkDSLB = vk::DescriptorSetLayoutBinding; using vkDSLB = vk::DescriptorSetLayoutBinding;
m_rtDescSetLayoutBind.emplace_back(vkDSLB(0, vkDT::eAccelerationStructureKHR, 1, m_rtDescSetLayoutBind.addBinding(vkDSLB(0, vkDT::eAccelerationStructureKHR, 1,
vkSS::eRaygenKHR | vkSS::eClosestHitKHR)); // TLAS vkSS::eRaygenKHR | vkSS::eClosestHitKHR)); // TLAS
m_rtDescSetLayoutBind.emplace_back( m_rtDescSetLayoutBind.addBinding(
vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image
m_rtDescPool = nvvkpp::util::createDescriptorPool(m_device, m_rtDescSetLayoutBind); m_rtDescPool = m_rtDescSetLayoutBind.createPool(m_device);
m_rtDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_rtDescSetLayoutBind); m_rtDescSetLayout = m_rtDescSetLayoutBind.createLayout(m_device);
m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0]; m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0];
vk::AccelerationStructureKHR tlas = m_rtBuilder.getAccelerationStructure();
vk::WriteDescriptorSetAccelerationStructureKHR descASInfo; vk::WriteDescriptorSetAccelerationStructureKHR descASInfo;
descASInfo.setAccelerationStructureCount(1); descASInfo.setAccelerationStructureCount(1);
descASInfo.setPAccelerationStructures(&m_rtBuilder.getAccelerationStructure()); descASInfo.setPAccelerationStructures(&tlas);
vk::DescriptorImageInfo imageInfo{ vk::DescriptorImageInfo imageInfo{
{}, m_offscreenColor.descriptor.imageView, vk::ImageLayout::eGeneral}; {}, m_offscreenColor.descriptor.imageView, vk::ImageLayout::eGeneral};
std::vector<vk::WriteDescriptorSet> writes; std::vector<vk::WriteDescriptorSet> writes;
writes.emplace_back( writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 0, &descASInfo));
nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[0], &descASInfo)); writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 1, &imageInfo));
writes.emplace_back(nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[1], &imageInfo));
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr); m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
} }
@ -756,16 +761,17 @@ void HelloVulkan::createRtPipeline()
std::vector<std::string> paths = defaultSearchPaths; std::vector<std::string> paths = defaultSearchPaths;
vk::ShaderModule raygenSM = vk::ShaderModule raygenSM =
nvvkpp::util::createShaderModule(m_device, // nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rgen.spv", true, paths)); nvh::loadFile("shaders/raytrace.rgen.spv", true, paths));
vk::ShaderModule missSM = vk::ShaderModule missSM =
nvvkpp::util::createShaderModule(m_device, // nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths)); nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths));
// The second miss shader is invoked when a shadow ray misses the geometry. It // The second miss shader is invoked when a shadow ray misses the geometry. It
// simply indicates that no occlusion has been found // simply indicates that no occlusion has been found
vk::ShaderModule shadowmissSM = nvvkpp::util::createShaderModule( vk::ShaderModule shadowmissSM =
m_device, nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths)); nvvk::createShaderModule(m_device,
nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
std::vector<vk::PipelineShaderStageCreateInfo> stages; std::vector<vk::PipelineShaderStageCreateInfo> stages;
@ -791,8 +797,8 @@ void HelloVulkan::createRtPipeline()
// Hit Group - Closest Hit + AnyHit // Hit Group - Closest Hit + AnyHit
vk::ShaderModule chitSM = vk::ShaderModule chitSM =
nvvkpp::util::createShaderModule(m_device, // nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rchit.spv", true, paths)); nvh::loadFile("shaders/raytrace.rchit.spv", true, paths));
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup, vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup,
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR,
@ -857,17 +863,17 @@ void HelloVulkan::createRtShaderBindingTable()
m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize, m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize,
shaderHandleStorage.data()); shaderHandleStorage.data());
// Write the handles in the SBT // Write the handles in the SBT
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex); nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer(); vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
m_rtSBTBuffer = m_rtSBTBuffer =
m_alloc.createBuffer(cmdBuf, shaderHandleStorage, vk::BufferUsageFlagBits::eRayTracingKHR); m_alloc.createBuffer(cmdBuf, shaderHandleStorage, vk::BufferUsageFlagBits::eRayTracingKHR);
m_debug.setObjectName(m_rtSBTBuffer.buffer, "SBT"); m_debug.setObjectName(m_rtSBTBuffer.buffer, "SBT");
genCmdBuf.flushCommandBuffer(cmdBuf); genCmdBuf.submitAndWait(cmdBuf);
m_alloc.flushStaging(); m_alloc.finalizeAndReleaseStaging();
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------

View file

@ -25,17 +25,16 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#pragma once #pragma once
#include <vulkan/vulkan.hpp>
#include "nvvkpp/allocator_dedicated_vkpp.hpp" #define NVVK_ALLOC_DEDICATED
#include "nvvkpp/appbase_vkpp.hpp" #include "nvvk/allocator_vk.hpp"
#include "nvvkpp/debug_util_vkpp.hpp" #include "nvvk/appbase_vkpp.hpp"
#include "nvvk/debug_util_vk.hpp"
#include "nvvk/descriptorsets_vk.hpp"
// #VKRay // #VKRay
#define ALLOC_DEDICATED #include "nvvk/raytraceKHR_vk.hpp"
#include "nvvkpp/raytraceKHR_vkpp.hpp"
using nvvkBuffer = nvvkpp::BufferDedicated;
using nvvkTexture = nvvkpp::TextureDedicated;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Simple rasterizer of OBJ objects // Simple rasterizer of OBJ objects
@ -44,10 +43,11 @@ using nvvkTexture = nvvkpp::TextureDedicated;
// - Rendering is done in an offscreen framebuffer // - Rendering is done in an offscreen framebuffer
// - The image of the framebuffer is displayed in post-process in a full-screen quad // - The image of the framebuffer is displayed in post-process in a full-screen quad
// //
class HelloVulkan : public nvvkpp::AppBase class HelloVulkan : public nvvk::AppBase
{ {
public: public:
void setup(const vk::Device& device, void setup(const vk::Instance& instance,
const vk::Device& device,
const vk::PhysicalDevice& physicalDevice, const vk::PhysicalDevice& physicalDevice,
uint32_t queueFamily) override; uint32_t queueFamily) override;
void createDescriptorSetLayout(); void createDescriptorSetLayout();
@ -66,12 +66,12 @@ public:
// The OBJ model // The OBJ model
struct ObjModel struct ObjModel
{ {
uint32_t nbIndices{0}; uint32_t nbIndices{0};
uint32_t nbVertices{0}; uint32_t nbVertices{0};
nvvkBuffer vertexBuffer; // Device buffer of all 'Vertex' nvvk::Buffer vertexBuffer; // Device buffer of all 'Vertex'
nvvkBuffer indexBuffer; // Device buffer of the indices forming triangles nvvk::Buffer indexBuffer; // Device buffer of the indices forming triangles
nvvkBuffer matColorBuffer; // Device buffer of array of 'Wavefront material' nvvk::Buffer matColorBuffer; // Device buffer of array of 'Wavefront material'
nvvkBuffer matIndexBuffer; // Device buffer of array of 'Wavefront material' nvvk::Buffer matIndexBuffer; // Device buffer of array of 'Wavefront material'
}; };
// Instance of the OBJ // Instance of the OBJ
@ -98,19 +98,19 @@ public:
std::vector<ObjInstance> m_objInstance; std::vector<ObjInstance> m_objInstance;
// Graphic pipeline // Graphic pipeline
vk::PipelineLayout m_pipelineLayout; vk::PipelineLayout m_pipelineLayout;
vk::Pipeline m_graphicsPipeline; vk::Pipeline m_graphicsPipeline;
std::vector<vk::DescriptorSetLayoutBinding> m_descSetLayoutBind; nvvk::DescriptorSetBindings m_descSetLayoutBind;
vk::DescriptorPool m_descPool; vk::DescriptorPool m_descPool;
vk::DescriptorSetLayout m_descSetLayout; vk::DescriptorSetLayout m_descSetLayout;
vk::DescriptorSet m_descSet; vk::DescriptorSet m_descSet;
nvvkBuffer m_cameraMat; // Device-Host of the camera matrices nvvk::Buffer m_cameraMat; // Device-Host of the camera matrices
nvvkBuffer m_sceneDesc; // Device buffer of the OBJ instances nvvk::Buffer m_sceneDesc; // Device buffer of the OBJ instances
std::vector<nvvkTexture> m_textures; // vector of all textures of the scene std::vector<nvvk::Texture> m_textures; // vector of all textures of the scene
nvvkpp::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures nvvk::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures
nvvkpp::DebugUtil m_debug; // Utility to name objects nvvk::DebugUtil m_debug; // Utility to name objects
// #Post // #Post
void createOffscreenRender(); void createOffscreenRender();
@ -119,41 +119,41 @@ public:
void updatePostDescriptorSet(); void updatePostDescriptorSet();
void drawPost(vk::CommandBuffer cmdBuf); void drawPost(vk::CommandBuffer cmdBuf);
std::vector<vk::DescriptorSetLayoutBinding> m_postDescSetLayoutBind; nvvk::DescriptorSetBindings m_postDescSetLayoutBind;
vk::DescriptorPool m_postDescPool; vk::DescriptorPool m_postDescPool;
vk::DescriptorSetLayout m_postDescSetLayout; vk::DescriptorSetLayout m_postDescSetLayout;
vk::DescriptorSet m_postDescSet; vk::DescriptorSet m_postDescSet;
vk::Pipeline m_postPipeline; vk::Pipeline m_postPipeline;
vk::PipelineLayout m_postPipelineLayout; vk::PipelineLayout m_postPipelineLayout;
vk::RenderPass m_offscreenRenderPass; vk::RenderPass m_offscreenRenderPass;
vk::Framebuffer m_offscreenFramebuffer; vk::Framebuffer m_offscreenFramebuffer;
nvvkTexture m_offscreenColor; nvvk::Texture m_offscreenColor;
vk::Format m_offscreenColorFormat{vk::Format::eR32G32B32A32Sfloat}; vk::Format m_offscreenColorFormat{vk::Format::eR32G32B32A32Sfloat};
nvvkTexture m_offscreenDepth; nvvk::Texture m_offscreenDepth;
vk::Format m_offscreenDepthFormat{vk::Format::eD32Sfloat}; vk::Format m_offscreenDepthFormat{vk::Format::eD32Sfloat};
// #VKRay // #VKRay
void initRayTracing(); void initRayTracing();
nvvkpp::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model); nvvk::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
void createBottomLevelAS(); void createBottomLevelAS();
void createTopLevelAS(); void createTopLevelAS();
void createRtDescriptorSet(); void createRtDescriptorSet();
void updateRtDescriptorSet(); void updateRtDescriptorSet();
void createRtPipeline(); void createRtPipeline();
void createRtShaderBindingTable(); void createRtShaderBindingTable();
void raytrace(const vk::CommandBuffer& cmdBuf, const nvmath::vec4f& clearColor); void raytrace(const vk::CommandBuffer& cmdBuf, const nvmath::vec4f& clearColor);
vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties; vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties;
nvvkpp::RaytracingBuilderKHR m_rtBuilder; nvvk::RaytracingBuilderKHR m_rtBuilder;
std::vector<vk::DescriptorSetLayoutBinding> m_rtDescSetLayoutBind; nvvk::DescriptorSetBindings m_rtDescSetLayoutBind;
vk::DescriptorPool m_rtDescPool; vk::DescriptorPool m_rtDescPool;
vk::DescriptorSetLayout m_rtDescSetLayout; vk::DescriptorSetLayout m_rtDescSetLayout;
vk::DescriptorSet m_rtDescSet; vk::DescriptorSet m_rtDescSet;
std::vector<vk::RayTracingShaderGroupCreateInfoKHR> m_rtShaderGroups; std::vector<vk::RayTracingShaderGroupCreateInfoKHR> m_rtShaderGroups;
vk::PipelineLayout m_rtPipelineLayout; vk::PipelineLayout m_rtPipelineLayout;
vk::Pipeline m_rtPipeline; vk::Pipeline m_rtPipeline;
nvvkBuffer m_rtSBTBuffer; nvvk::Buffer m_rtSBTBuffer;
struct RtPushConstant struct RtPushConstant
{ {

View file

@ -30,8 +30,8 @@
// at the top of imgui.cpp. // at the top of imgui.cpp.
#include <array> #include <array>
#include <vulkan/vulkan.hpp> #include <vulkan/vulkan.hpp>
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
#include "imgui.h" #include "imgui.h"
#include "imgui_impl_glfw.h" #include "imgui_impl_glfw.h"
@ -40,10 +40,10 @@
#include "nvh/cameramanipulator.hpp" #include "nvh/cameramanipulator.hpp"
#include "nvh/fileoperations.hpp" #include "nvh/fileoperations.hpp"
#include "nvpsystem.hpp" #include "nvpsystem.hpp"
#include "nvvkpp/appbase_vkpp.hpp" #include "nvvk/appbase_vkpp.hpp"
#include "nvvkpp/commands_vkpp.hpp" #include "nvvk/commands_vk.hpp"
#include "nvvkpp/context_vkpp.hpp" #include "nvvk/context_vk.hpp"
#include "nvvkpp/utilities_vkpp.hpp"
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
#define UNUSED(x) (void)(x) #define UNUSED(x) (void)(x)
@ -125,7 +125,7 @@ int main(int argc, char** argv)
vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature; vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature;
// Requesting Vulkan extensions and layers // Requesting Vulkan extensions and layers
nvvkpp::ContextCreateInfo contextInfo(true); nvvk::ContextCreateInfo contextInfo(true);
contextInfo.setVersion(1, 2); contextInfo.setVersion(1, 2);
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true); contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME); contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME);
@ -148,7 +148,7 @@ int main(int argc, char** argv)
// Creating Vulkan base application // Creating Vulkan base application
nvvkpp::Context vkctx{}; nvvk::Context vkctx{};
vkctx.initInstance(contextInfo); vkctx.initInstance(contextInfo);
// Find all compatible devices // Find all compatible devices
auto compatibleDevices = vkctx.getCompatibleDevices(contextInfo); auto compatibleDevices = vkctx.getCompatibleDevices(contextInfo);
@ -164,7 +164,8 @@ int main(int argc, char** argv)
const vk::SurfaceKHR surface = helloVk.getVkSurface(vkctx.m_instance, window); const vk::SurfaceKHR surface = helloVk.getVkSurface(vkctx.m_instance, window);
vkctx.setGCTQueueWithPresent(surface); vkctx.setGCTQueueWithPresent(surface);
helloVk.setup(vkctx.m_device, vkctx.m_physicalDevice, vkctx.m_queueGCT.familyIndex); helloVk.setup(vkctx.m_instance, vkctx.m_device, vkctx.m_physicalDevice,
vkctx.m_queueGCT.familyIndex);
helloVk.createSurface(surface, SAMPLE_WIDTH, SAMPLE_HEIGHT); helloVk.createSurface(surface, SAMPLE_WIDTH, SAMPLE_HEIGHT);
helloVk.createDepthBuffer(); helloVk.createDepthBuffer();
helloVk.createRenderPass(); helloVk.createRenderPass();
@ -174,8 +175,8 @@ int main(int argc, char** argv)
helloVk.initGUI(0); // Using sub-pass 0 helloVk.initGUI(0); // Using sub-pass 0
// Creation of the example // Creation of the example
helloVk.loadModel(nvh::findFile("media/scenes/plane.obj", defaultSearchPaths));
helloVk.loadModel(nvh::findFile("media/scenes/Medieval_building.obj", defaultSearchPaths)); helloVk.loadModel(nvh::findFile("media/scenes/Medieval_building.obj", defaultSearchPaths));
helloVk.loadModel(nvh::findFile("media/scenes/plane.obj", defaultSearchPaths));
helloVk.createOffscreenRender(); helloVk.createOffscreenRender();
@ -242,7 +243,8 @@ int main(int argc, char** argv)
// Clearing screen // Clearing screen
vk::ClearValue clearValues[2]; vk::ClearValue clearValues[2];
clearValues[0].setColor(nvvkpp::util::clearColor(clearColor)); clearValues[0].setColor(
std::array<float, 4>({clearColor[0], clearColor[1], clearColor[2], clearColor[3]}));
clearValues[1].setDepthStencil({1.0f, 0}); clearValues[1].setDepthStencil({1.0f, 0});
// Offscreen render pass // Offscreen render pass
@ -294,7 +296,6 @@ int main(int argc, char** argv)
helloVk.destroyResources(); helloVk.destroyResources();
helloVk.destroy(); helloVk.destroy();
vkctx.m_instance.destroySurfaceKHR(surface);
vkctx.deinit(); vkctx.deinit();
glfwDestroyWindow(window); glfwDestroyWindow(window);

View file

@ -6,7 +6,7 @@
#include "raycommon.glsl" #include "raycommon.glsl"
#include "wavefront.glsl" #include "wavefront.glsl"
hitAttributeEXT vec3 attribs; hitAttributeEXT vec2 attribs;
// clang-format off // clang-format off
layout(location = 0) rayPayloadInEXT hitPayload prd; layout(location = 0) rayPayloadInEXT hitPayload prd;

View file

@ -36,13 +36,14 @@ extern std::vector<std::string> defaultSearchPaths;
#include "hello_vulkan.h" #include "hello_vulkan.h"
#include "nvh//cameramanipulator.hpp" #include "nvh//cameramanipulator.hpp"
#include "nvvkpp/descriptorsets_vkpp.hpp" #include "nvvk/descriptorsets_vk.hpp"
#include "nvvkpp/pipeline_vkpp.hpp" #include "nvvk/pipeline_vk.hpp"
#include "nvh/fileoperations.hpp" #include "nvh/fileoperations.hpp"
#include "nvvkpp/commands_vkpp.hpp" #include "nvvk/commands_vk.hpp"
#include "nvvkpp/renderpass_vkpp.hpp" #include "nvvk/renderpasses_vk.hpp"
#include "nvvkpp/utilities_vkpp.hpp" #include "nvvk/shaders_vk.hpp"
// Holding the camera matrices // Holding the camera matrices
struct CameraMatrices struct CameraMatrices
@ -58,11 +59,12 @@ struct CameraMatrices
// Keep the handle on the device // Keep the handle on the device
// Initialize the tool to do all our allocations: buffers, images // Initialize the tool to do all our allocations: buffers, images
// //
void HelloVulkan::setup(const vk::Device& device, void HelloVulkan::setup(const vk::Instance& instance,
const vk::Device& device,
const vk::PhysicalDevice& physicalDevice, const vk::PhysicalDevice& physicalDevice,
uint32_t queueFamily) uint32_t queueFamily)
{ {
AppBase::setup(device, physicalDevice, queueFamily); AppBase::setup(instance, device, physicalDevice, queueFamily);
m_alloc.init(device, physicalDevice); m_alloc.init(device, physicalDevice);
m_debug.setup(m_device); m_debug.setup(m_device);
} }
@ -99,31 +101,31 @@ void HelloVulkan::createDescriptorSetLayout()
uint32_t nbObj = static_cast<uint32_t>(m_objModel.size()); uint32_t nbObj = static_cast<uint32_t>(m_objModel.size());
// Camera matrices (binding = 0) // Camera matrices (binding = 0)
m_descSetLayoutBind.emplace_back( m_descSetLayoutBind.addBinding(
vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR)); vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR));
// Materials (binding = 1) // Materials (binding = 1)
m_descSetLayoutBind.emplace_back( m_descSetLayoutBind.addBinding(
vkDS(1, vkDT::eStorageBuffer, nbObj, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR)); vkDS(1, vkDT::eStorageBuffer, nbObj, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
// Scene description (binding = 2) // Scene description (binding = 2)
m_descSetLayoutBind.emplace_back( // m_descSetLayoutBind.addBinding( //
vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR)); vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
// Textures (binding = 3) // Textures (binding = 3)
m_descSetLayoutBind.emplace_back( m_descSetLayoutBind.addBinding(
vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR)); vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR));
// Materials (binding = 4) // Materials (binding = 4)
m_descSetLayoutBind.emplace_back( m_descSetLayoutBind.addBinding(
vkDS(4, vkDT::eStorageBuffer, nbObj, vkSS::eFragment | vkSS::eClosestHitKHR)); vkDS(4, vkDT::eStorageBuffer, nbObj, vkSS::eFragment | vkSS::eClosestHitKHR));
// Storing vertices (binding = 5) // Storing vertices (binding = 5)
m_descSetLayoutBind.emplace_back( // m_descSetLayoutBind.addBinding( //
vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR)); vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
// Storing indices (binding = 6) // Storing indices (binding = 6)
m_descSetLayoutBind.emplace_back( // m_descSetLayoutBind.addBinding( //
vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR)); vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
m_descSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_descSetLayoutBind); m_descSetLayout = m_descSetLayoutBind.createLayout(m_device);
m_descPool = nvvkpp::util::createDescriptorPool(m_device, m_descSetLayoutBind, 1); m_descPool = m_descSetLayoutBind.createPool(m_device, 1);
m_descSet = nvvkpp::util::createDescriptorSet(m_device, m_descPool, m_descSetLayout); m_descSet = nvvk::allocateDescriptorSet(m_device, m_descPool, m_descSetLayout);
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -135,9 +137,9 @@ void HelloVulkan::updateDescriptorSet()
// Camera matrices and scene description // Camera matrices and scene description
vk::DescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE}; vk::DescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE};
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[0], &dbiUnif)); writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 0, &dbiUnif));
vk::DescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE}; vk::DescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[2], &dbiSceneDesc)); writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 2, &dbiSceneDesc));
// All material buffers, 1 buffer per OBJ // All material buffers, 1 buffer per OBJ
std::vector<vk::DescriptorBufferInfo> dbiMat; std::vector<vk::DescriptorBufferInfo> dbiMat;
@ -151,11 +153,10 @@ void HelloVulkan::updateDescriptorSet()
dbiVert.emplace_back(obj.vertexBuffer.buffer, 0, VK_WHOLE_SIZE); dbiVert.emplace_back(obj.vertexBuffer.buffer, 0, VK_WHOLE_SIZE);
dbiIdx.emplace_back(obj.indexBuffer.buffer, 0, VK_WHOLE_SIZE); dbiIdx.emplace_back(obj.indexBuffer.buffer, 0, VK_WHOLE_SIZE);
} }
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[1], dbiMat.data())); writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 1, dbiMat.data()));
writes.emplace_back( writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 4, dbiMatIdx.data()));
nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[4], dbiMatIdx.data())); writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 5, dbiVert.data()));
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[5], dbiVert.data())); writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 6, dbiIdx.data()));
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[6], dbiIdx.data()));
// All texture samplers // All texture samplers
std::vector<vk::DescriptorImageInfo> diit; std::vector<vk::DescriptorImageInfo> diit;
@ -163,7 +164,7 @@ void HelloVulkan::updateDescriptorSet()
{ {
diit.push_back(texture.descriptor); diit.push_back(texture.descriptor);
} }
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[3], diit.data())); writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 3, diit.data()));
// Writing the information // Writing the information
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr); m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
@ -189,19 +190,18 @@ void HelloVulkan::createGraphicsPipeline()
m_pipelineLayout = m_device.createPipelineLayout(pipelineLayoutCreateInfo); m_pipelineLayout = m_device.createPipelineLayout(pipelineLayoutCreateInfo);
// Creating the Pipeline // Creating the Pipeline
std::vector<std::string> paths = defaultSearchPaths; std::vector<std::string> paths = defaultSearchPaths;
nvvkpp::GraphicsPipelineGenerator gpb(m_device, m_pipelineLayout, m_offscreenRenderPass); nvvk::GraphicsPipelineGeneratorCombined gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
gpb.depthStencilState = {true}; gpb.depthStencilState.depthTestEnable = true;
gpb.addShader(nvh::loadFile("shaders/vert_shader.vert.spv", true, paths), vkSS::eVertex); gpb.addShader(nvh::loadFile("shaders/vert_shader.vert.spv", true, paths), vkSS::eVertex);
gpb.addShader(nvh::loadFile("shaders/frag_shader.frag.spv", true, paths), vkSS::eFragment); gpb.addShader(nvh::loadFile("shaders/frag_shader.frag.spv", true, paths), vkSS::eFragment);
gpb.vertexInputState.bindingDescriptions = {{0, sizeof(VertexObj)}}; gpb.addBindingDescription({0, sizeof(VertexObj)});
gpb.vertexInputState.attributeDescriptions = { gpb.addAttributeDescriptions({{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)}, {1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)},
{1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)}, {2, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, color)},
{2, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, color)}, {3, 0, vk::Format::eR32G32Sfloat, offsetof(VertexObj, texCoord)}});
{3, 0, vk::Format::eR32G32Sfloat, offsetof(VertexObj, texCoord)}};
m_graphicsPipeline = gpb.create(); m_graphicsPipeline = gpb.createPipeline();
m_debug.setObjectName(m_graphicsPipeline, "Graphics"); m_debug.setObjectName(m_graphicsPipeline, "Graphics");
} }
@ -234,8 +234,8 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size()); model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
// Create the buffers on Device and copy vertices, indices and materials // Create the buffers on Device and copy vertices, indices and materials
nvvkpp::SingleCommandBuffer cmdBufGet(m_device, m_graphicsQueueIndex); nvvk::CommandPool cmdBufGet(m_device, m_graphicsQueueIndex);
vk::CommandBuffer cmdBuf = cmdBufGet.createCommandBuffer(); vk::CommandBuffer cmdBuf = cmdBufGet.createCommandBuffer();
model.vertexBuffer = model.vertexBuffer =
m_alloc.createBuffer(cmdBuf, loader.m_vertices, m_alloc.createBuffer(cmdBuf, loader.m_vertices,
vkBU::eVertexBuffer | vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress); vkBU::eVertexBuffer | vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress);
@ -246,8 +246,8 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, vkBU::eStorageBuffer); model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, vkBU::eStorageBuffer);
// Creates all textures found // Creates all textures found
createTextureImages(cmdBuf, loader.m_textures); createTextureImages(cmdBuf, loader.m_textures);
cmdBufGet.flushCommandBuffer(cmdBuf); cmdBufGet.submitAndWait(cmdBuf);
m_alloc.flushStaging(); m_alloc.finalizeAndReleaseStaging();
std::string objNb = std::to_string(instance.objIndex); std::string objNb = std::to_string(instance.objIndex);
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str())); m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
@ -282,12 +282,12 @@ void HelloVulkan::createUniformBuffer()
void HelloVulkan::createSceneDescriptionBuffer() void HelloVulkan::createSceneDescriptionBuffer()
{ {
using vkBU = vk::BufferUsageFlagBits; using vkBU = vk::BufferUsageFlagBits;
nvvkpp::SingleCommandBuffer cmdGen(m_device, m_graphicsQueueIndex); nvvk::CommandPool cmdGen(m_device, m_graphicsQueueIndex);
auto cmdBuf = cmdGen.createCommandBuffer(); auto cmdBuf = cmdGen.createCommandBuffer();
m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer); m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer);
cmdGen.flushCommandBuffer(cmdBuf); cmdGen.submitAndWait(cmdBuf);
m_alloc.flushStaging(); m_alloc.finalizeAndReleaseStaging();
m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc"); m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc");
} }
@ -307,21 +307,21 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
// If no textures are present, create a dummy one to accommodate the pipeline layout // If no textures are present, create a dummy one to accommodate the pipeline layout
if(textures.empty() && m_textures.empty()) if(textures.empty() && m_textures.empty())
{ {
nvvkTexture texture; nvvk::Texture texture;
std::array<uint8_t, 4> color{255u, 255u, 255u, 255u}; std::array<uint8_t, 4> color{255u, 255u, 255u, 255u};
vk::DeviceSize bufferSize = sizeof(color); vk::DeviceSize bufferSize = sizeof(color);
auto imgSize = vk::Extent2D(1, 1); auto imgSize = vk::Extent2D(1, 1);
auto imageCreateInfo = nvvkpp::image::create2DInfo(imgSize, format); auto imageCreateInfo = nvvk::makeImage2DCreateInfo(imgSize, format);
// Creating the dummy texure
nvvk::Image image = m_alloc.createImage(cmdBuf, bufferSize, color.data(), imageCreateInfo);
vk::ImageViewCreateInfo ivInfo = nvvk::makeImageViewCreateInfo(image.image, imageCreateInfo);
texture = m_alloc.createTexture(image, ivInfo, samplerCreateInfo);
// Creating the VKImage
texture = m_alloc.createImage(cmdBuf, bufferSize, color.data(), imageCreateInfo);
// Setting up the descriptor used by the shader
texture.descriptor =
nvvkpp::image::create2DDescriptor(m_device, texture.image, samplerCreateInfo, format);
// The image format must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL // The image format must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
nvvkpp::image::setImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined, nvvk::cmdBarrierImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eShaderReadOnlyOptimal); vk::ImageLayout::eShaderReadOnlyOptimal);
m_textures.push_back(texture); m_textures.push_back(texture);
} }
else else
@ -348,16 +348,16 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4; vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4;
auto imgSize = vk::Extent2D(texWidth, texHeight); auto imgSize = vk::Extent2D(texWidth, texHeight);
auto imageCreateInfo = nvvkpp::image::create2DInfo(imgSize, format, vkIU::eSampled, true); auto imageCreateInfo = nvvk::makeImage2DCreateInfo(imgSize, format, vkIU::eSampled, true);
{ {
nvvkTexture texture; nvvk::ImageDedicated image =
texture = m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo); m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo);
nvvk::cmdGenerateMipmaps(cmdBuf, image.image, format, imgSize, imageCreateInfo.mipLevels);
vk::ImageViewCreateInfo ivInfo =
nvvk::makeImageViewCreateInfo(image.image, imageCreateInfo);
nvvk::Texture texture = m_alloc.createTexture(image, ivInfo, samplerCreateInfo);
nvvkpp::image::generateMipmaps(cmdBuf, texture.image, format, imgSize,
imageCreateInfo.mipLevels);
texture.descriptor =
nvvkpp::image::create2DDescriptor(m_device, texture.image, samplerCreateInfo, format);
m_textures.push_back(texture); m_textures.push_back(texture);
} }
} }
@ -441,7 +441,7 @@ void HelloVulkan::rasterize(const vk::CommandBuffer& cmdBuf)
cmdBuf.pushConstants<ObjPushConstant>(m_pipelineLayout, vkSS::eVertex | vkSS::eFragment, 0, cmdBuf.pushConstants<ObjPushConstant>(m_pipelineLayout, vkSS::eVertex | vkSS::eFragment, 0,
m_pushConstant); m_pushConstant);
cmdBuf.bindVertexBuffers(0, 1, &model.vertexBuffer.buffer, &offset); cmdBuf.bindVertexBuffers(0, {model.vertexBuffer.buffer}, {offset});
cmdBuf.bindIndexBuffer(model.indexBuffer.buffer, 0, vk::IndexType::eUint32); cmdBuf.bindIndexBuffer(model.indexBuffer.buffer, 0, vk::IndexType::eUint32);
cmdBuf.drawIndexed(model.nbIndices, 1, 0, 0, 0); cmdBuf.drawIndexed(model.nbIndices, 1, 0, 0, 0);
} }
@ -471,49 +471,54 @@ void HelloVulkan::createOffscreenRender()
m_alloc.destroy(m_offscreenDepth); m_alloc.destroy(m_offscreenDepth);
// Creating the color image // Creating the color image
auto colorCreateInfo = nvvkpp::image::create2DInfo(m_size, m_offscreenColorFormat, {
vk::ImageUsageFlagBits::eColorAttachment auto colorCreateInfo = nvvk::makeImage2DCreateInfo(m_size, m_offscreenColorFormat,
| vk::ImageUsageFlagBits::eSampled vk::ImageUsageFlagBits::eColorAttachment
| vk::ImageUsageFlagBits::eStorage); | vk::ImageUsageFlagBits::eSampled
m_offscreenColor = m_alloc.createImage(colorCreateInfo); | vk::ImageUsageFlagBits::eStorage);
m_offscreenColor.descriptor =
nvvkpp::image::create2DDescriptor(m_device, m_offscreenColor.image, vk::SamplerCreateInfo{}, nvvk::ImageDedicated image = m_alloc.createImage(colorCreateInfo);
m_offscreenColorFormat, vk::ImageLayout::eGeneral); vk::ImageViewCreateInfo ivInfo = nvvk::makeImageViewCreateInfo(image.image, colorCreateInfo);
m_offscreenColor = m_alloc.createTexture(image, ivInfo, vk::SamplerCreateInfo());
m_offscreenColor.descriptor.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
}
// Creating the depth buffer // Creating the depth buffer
auto depthCreateInfo = auto depthCreateInfo =
nvvkpp::image::create2DInfo(m_size, m_offscreenDepthFormat, nvvk::makeImage2DCreateInfo(m_size, m_offscreenDepthFormat,
vk::ImageUsageFlagBits::eDepthStencilAttachment); vk::ImageUsageFlagBits::eDepthStencilAttachment);
m_offscreenDepth = m_alloc.createImage(depthCreateInfo); {
nvvk::Image image = m_alloc.createImage(depthCreateInfo);
vk::ImageViewCreateInfo depthStencilView; vk::ImageViewCreateInfo depthStencilView;
depthStencilView.setViewType(vk::ImageViewType::e2D); depthStencilView.setViewType(vk::ImageViewType::e2D);
depthStencilView.setFormat(m_offscreenDepthFormat); depthStencilView.setFormat(m_offscreenDepthFormat);
depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1}); depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1});
depthStencilView.setImage(m_offscreenDepth.image); depthStencilView.setImage(image.image);
m_offscreenDepth.descriptor.imageView = m_device.createImageView(depthStencilView);
m_offscreenDepth = m_alloc.createTexture(image, depthStencilView);
}
// Setting the image layout for both color and depth // Setting the image layout for both color and depth
{ {
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex); nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
auto cmdBuf = genCmdBuf.createCommandBuffer(); auto cmdBuf = genCmdBuf.createCommandBuffer();
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined, nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eGeneral); vk::ImageLayout::eGeneral);
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageAspectFlagBits::eDepth, nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eUndefined, vk::ImageLayout::eDepthStencilAttachmentOptimal,
vk::ImageLayout::eDepthStencilAttachmentOptimal); vk::ImageAspectFlagBits::eDepth);
genCmdBuf.flushCommandBuffer(cmdBuf); genCmdBuf.submitAndWait(cmdBuf);
} }
// Creating a renderpass for the offscreen // Creating a renderpass for the offscreen
if(!m_offscreenRenderPass) if(!m_offscreenRenderPass)
{ {
m_offscreenRenderPass = m_offscreenRenderPass =
nvvkpp::util::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat, nvvk::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat, 1, true,
1, true, true, vk::ImageLayout::eGeneral, true, vk::ImageLayout::eGeneral, vk::ImageLayout::eGeneral);
vk::ImageLayout::eGeneral);
} }
// Creating the frame buffer for offscreen // Creating the frame buffer for offscreen
@ -550,13 +555,14 @@ void HelloVulkan::createPostPipeline()
// Pipeline: completely generic, no vertices // Pipeline: completely generic, no vertices
std::vector<std::string> paths = defaultSearchPaths; std::vector<std::string> paths = defaultSearchPaths;
nvvkpp::GraphicsPipelineGenerator pipelineGenerator(m_device, m_postPipelineLayout, m_renderPass); nvvk::GraphicsPipelineGeneratorCombined pipelineGenerator(m_device, m_postPipelineLayout,
m_renderPass);
pipelineGenerator.addShader(nvh::loadFile("shaders/passthrough.vert.spv", true, paths), pipelineGenerator.addShader(nvh::loadFile("shaders/passthrough.vert.spv", true, paths),
vk::ShaderStageFlagBits::eVertex); vk::ShaderStageFlagBits::eVertex);
pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths), pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths),
vk::ShaderStageFlagBits::eFragment); vk::ShaderStageFlagBits::eFragment);
pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone); pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone);
m_postPipeline = pipelineGenerator.create(); m_postPipeline = pipelineGenerator.createPipeline();
m_debug.setObjectName(m_postPipeline, "post"); m_debug.setObjectName(m_postPipeline, "post");
} }
@ -570,10 +576,10 @@ void HelloVulkan::createPostDescriptor()
using vkDT = vk::DescriptorType; using vkDT = vk::DescriptorType;
using vkSS = vk::ShaderStageFlagBits; using vkSS = vk::ShaderStageFlagBits;
m_postDescSetLayoutBind.emplace_back(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment)); m_postDescSetLayoutBind.addBinding(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
m_postDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_postDescSetLayoutBind); m_postDescSetLayout = m_postDescSetLayoutBind.createLayout(m_device);
m_postDescPool = nvvkpp::util::createDescriptorPool(m_device, m_postDescSetLayoutBind); m_postDescPool = m_postDescSetLayoutBind.createPool(m_device);
m_postDescSet = nvvkpp::util::createDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout); m_postDescSet = nvvk::allocateDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -582,8 +588,7 @@ void HelloVulkan::createPostDescriptor()
void HelloVulkan::updatePostDescriptorSet() void HelloVulkan::updatePostDescriptorSet()
{ {
vk::WriteDescriptorSet writeDescriptorSets = vk::WriteDescriptorSet writeDescriptorSets =
nvvkpp::util::createWrite(m_postDescSet, m_postDescSetLayoutBind[0], m_postDescSetLayoutBind.makeWrite(m_postDescSet, 0, &m_offscreenColor.descriptor);
&m_offscreenColor.descriptor);
m_device.updateDescriptorSets(writeDescriptorSets, nullptr); m_device.updateDescriptorSets(writeDescriptorSets, nullptr);
} }
@ -621,13 +626,13 @@ void HelloVulkan::initRayTracing()
auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2, auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2,
vk::PhysicalDeviceRayTracingPropertiesKHR>(); vk::PhysicalDeviceRayTracingPropertiesKHR>();
m_rtProperties = properties.get<vk::PhysicalDeviceRayTracingPropertiesKHR>(); m_rtProperties = properties.get<vk::PhysicalDeviceRayTracingPropertiesKHR>();
m_rtBuilder.setup(m_device, m_physicalDevice, m_graphicsQueueIndex); m_rtBuilder.setup(m_device, &m_alloc, m_graphicsQueueIndex);
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Converting a OBJ primitive to the ray tracing geometry used for the BLAS // Converting a OBJ primitive to the ray tracing geometry used for the BLAS
// //
nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model) nvvk::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model)
{ {
vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate; vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate;
asCreate.setGeometryType(vk::GeometryTypeKHR::eTriangles); asCreate.setGeometryType(vk::GeometryTypeKHR::eTriangles);
@ -658,7 +663,7 @@ nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjM
offset.setPrimitiveOffset(0); offset.setPrimitiveOffset(0);
offset.setTransformOffset(0); offset.setTransformOffset(0);
nvvkpp::RaytracingBuilderKHR::Blas blas; nvvk::RaytracingBuilderKHR::Blas blas;
blas.asGeometry.emplace_back(asGeom); blas.asGeometry.emplace_back(asGeom);
blas.asCreateGeometryInfo.emplace_back(asCreate); blas.asCreateGeometryInfo.emplace_back(asCreate);
blas.asBuildOffsetInfo.emplace_back(offset); blas.asBuildOffsetInfo.emplace_back(offset);
@ -685,12 +690,12 @@ void HelloVulkan::createTopLevelAS()
m_tlas.reserve(m_objInstance.size()); m_tlas.reserve(m_objInstance.size());
for(int i = 0; i < static_cast<int>(m_objInstance.size()); i++) for(int i = 0; i < static_cast<int>(m_objInstance.size()); i++)
{ {
nvvkpp::RaytracingBuilderKHR::Instance rayInst; nvvk::RaytracingBuilderKHR::Instance rayInst;
rayInst.transform = m_objInstance[i].transform; // Position of the instance rayInst.transform = m_objInstance[i].transform; // Position of the instance
rayInst.instanceId = i; // gl_InstanceID rayInst.instanceId = i; // gl_InstanceID
rayInst.blasId = m_objInstance[i].objIndex; rayInst.blasId = m_objInstance[i].objIndex;
rayInst.hitGroupId = 0; rayInst.hitGroupId = 0;
rayInst.flags = vk::GeometryInstanceFlagBitsKHR::eTriangleCullDisable; rayInst.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
m_tlas.emplace_back(rayInst); m_tlas.emplace_back(rayInst);
} }
m_rtBuilder.buildTlas(m_tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace m_rtBuilder.buildTlas(m_tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace
@ -706,25 +711,25 @@ void HelloVulkan::createRtDescriptorSet()
using vkSS = vk::ShaderStageFlagBits; using vkSS = vk::ShaderStageFlagBits;
using vkDSLB = vk::DescriptorSetLayoutBinding; using vkDSLB = vk::DescriptorSetLayoutBinding;
m_rtDescSetLayoutBind.emplace_back(vkDSLB(0, vkDT::eAccelerationStructureKHR, 1, m_rtDescSetLayoutBind.addBinding(vkDSLB(0, vkDT::eAccelerationStructureKHR, 1,
vkSS::eRaygenKHR | vkSS::eClosestHitKHR)); // TLAS vkSS::eRaygenKHR | vkSS::eClosestHitKHR)); // TLAS
m_rtDescSetLayoutBind.emplace_back( m_rtDescSetLayoutBind.addBinding(
vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image
m_rtDescPool = nvvkpp::util::createDescriptorPool(m_device, m_rtDescSetLayoutBind); m_rtDescPool = m_rtDescSetLayoutBind.createPool(m_device);
m_rtDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_rtDescSetLayoutBind); m_rtDescSetLayout = m_rtDescSetLayoutBind.createLayout(m_device);
m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0]; m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0];
vk::AccelerationStructureKHR tlas = m_rtBuilder.getAccelerationStructure();
vk::WriteDescriptorSetAccelerationStructureKHR descASInfo; vk::WriteDescriptorSetAccelerationStructureKHR descASInfo;
descASInfo.setAccelerationStructureCount(1); descASInfo.setAccelerationStructureCount(1);
descASInfo.setPAccelerationStructures(&m_rtBuilder.getAccelerationStructure()); descASInfo.setPAccelerationStructures(&tlas);
vk::DescriptorImageInfo imageInfo{ vk::DescriptorImageInfo imageInfo{
{}, m_offscreenColor.descriptor.imageView, vk::ImageLayout::eGeneral}; {}, m_offscreenColor.descriptor.imageView, vk::ImageLayout::eGeneral};
std::vector<vk::WriteDescriptorSet> writes; std::vector<vk::WriteDescriptorSet> writes;
writes.emplace_back( writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 0, &descASInfo));
nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[0], &descASInfo)); writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 1, &imageInfo));
writes.emplace_back(nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[1], &imageInfo));
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr); m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
} }
@ -753,16 +758,17 @@ void HelloVulkan::createRtPipeline()
std::vector<std::string> paths = defaultSearchPaths; std::vector<std::string> paths = defaultSearchPaths;
vk::ShaderModule raygenSM = vk::ShaderModule raygenSM =
nvvkpp::util::createShaderModule(m_device, // nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rgen.spv", true, paths)); nvh::loadFile("shaders/raytrace.rgen.spv", true, paths));
vk::ShaderModule missSM = vk::ShaderModule missSM =
nvvkpp::util::createShaderModule(m_device, // nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths)); nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths));
// The second miss shader is invoked when a shadow ray misses the geometry. It // The second miss shader is invoked when a shadow ray misses the geometry. It
// simply indicates that no occlusion has been found // simply indicates that no occlusion has been found
vk::ShaderModule shadowmissSM = nvvkpp::util::createShaderModule( vk::ShaderModule shadowmissSM =
m_device, nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths)); nvvk::createShaderModule(m_device,
nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
std::vector<vk::PipelineShaderStageCreateInfo> stages; std::vector<vk::PipelineShaderStageCreateInfo> stages;
@ -788,8 +794,8 @@ void HelloVulkan::createRtPipeline()
// Hit Group - Closest Hit + AnyHit // Hit Group - Closest Hit + AnyHit
vk::ShaderModule chitSM = vk::ShaderModule chitSM =
nvvkpp::util::createShaderModule(m_device, // nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rchit.spv", true, paths)); nvh::loadFile("shaders/raytrace.rchit.spv", true, paths));
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup, vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup,
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR,
@ -853,17 +859,17 @@ void HelloVulkan::createRtShaderBindingTable()
m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize, m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize,
shaderHandleStorage.data()); shaderHandleStorage.data());
// Write the handles in the SBT // Write the handles in the SBT
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex); nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer(); vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
m_rtSBTBuffer = m_rtSBTBuffer =
m_alloc.createBuffer(cmdBuf, shaderHandleStorage, vk::BufferUsageFlagBits::eRayTracingKHR); m_alloc.createBuffer(cmdBuf, shaderHandleStorage, vk::BufferUsageFlagBits::eRayTracingKHR);
m_debug.setObjectName(m_rtSBTBuffer.buffer, "SBT"); m_debug.setObjectName(m_rtSBTBuffer.buffer, "SBT");
genCmdBuf.flushCommandBuffer(cmdBuf); genCmdBuf.submitAndWait(cmdBuf);
m_alloc.flushStaging(); m_alloc.finalizeAndReleaseStaging();
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -927,24 +933,24 @@ void HelloVulkan::animationInstances(float time)
* nvmath::translation_mat4(radius, 0.f, 0.f); * nvmath::translation_mat4(radius, 0.f, 0.f);
inst.transformIT = nvmath::transpose(nvmath::invert(inst.transform)); inst.transformIT = nvmath::transpose(nvmath::invert(inst.transform));
nvvkpp::RaytracingBuilderKHR::Instance& tinst = m_tlas[wusonIdx]; nvvk::RaytracingBuilderKHR::Instance& tinst = m_tlas[wusonIdx];
tinst.transform = inst.transform; tinst.transform = inst.transform;
} }
// Update the buffer // Update the buffer
vk::DeviceSize bufferSize = m_objInstance.size() * sizeof(ObjInstance); vk::DeviceSize bufferSize = m_objInstance.size() * sizeof(ObjInstance);
nvvkBuffer stagingBuffer = m_alloc.createBuffer(bufferSize, vk::BufferUsageFlagBits::eTransferSrc, nvvk::Buffer stagingBuffer = m_alloc.createBuffer(bufferSize, vk::BufferUsageFlagBits::eTransferSrc,
vk::MemoryPropertyFlagBits::eHostVisible); vk::MemoryPropertyFlagBits::eHostVisible);
// Copy data to staging buffer // Copy data to staging buffer
auto* gInst = m_alloc.map(stagingBuffer); auto* gInst = m_alloc.map(stagingBuffer);
memcpy(gInst, m_objInstance.data(), bufferSize); memcpy(gInst, m_objInstance.data(), bufferSize);
m_alloc.unmap(stagingBuffer); m_alloc.unmap(stagingBuffer);
// Copy staging buffer to the Scene Description buffer // Copy staging buffer to the Scene Description buffer
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex); nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer(); vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
cmdBuf.copyBuffer(stagingBuffer.buffer, m_sceneDesc.buffer, vk::BufferCopy(0, 0, bufferSize)); cmdBuf.copyBuffer(stagingBuffer.buffer, m_sceneDesc.buffer, vk::BufferCopy(0, 0, bufferSize));
m_debug.endLabel(cmdBuf); m_debug.endLabel(cmdBuf);
genCmdBuf.flushCommandBuffer(cmdBuf); genCmdBuf.submitAndWait(cmdBuf);
m_alloc.destroy(stagingBuffer); m_alloc.destroy(stagingBuffer);
m_rtBuilder.updateTlasMatrices(m_tlas); m_rtBuilder.updateTlasMatrices(m_tlas);
@ -957,8 +963,8 @@ void HelloVulkan::animationObject(float time)
updateCompDescriptors(model.vertexBuffer); updateCompDescriptors(model.vertexBuffer);
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex); nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer(); vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
cmdBuf.bindPipeline(vk::PipelineBindPoint::eCompute, m_compPipeline); cmdBuf.bindPipeline(vk::PipelineBindPoint::eCompute, m_compPipeline);
cmdBuf.bindDescriptorSets(vk::PipelineBindPoint::eCompute, m_compPipelineLayout, 0, cmdBuf.bindDescriptorSets(vk::PipelineBindPoint::eCompute, m_compPipelineLayout, 0,
@ -966,27 +972,26 @@ void HelloVulkan::animationObject(float time)
cmdBuf.pushConstants(m_compPipelineLayout, vk::ShaderStageFlagBits::eCompute, 0, sizeof(float), cmdBuf.pushConstants(m_compPipelineLayout, vk::ShaderStageFlagBits::eCompute, 0, sizeof(float),
&time); &time);
cmdBuf.dispatch(model.nbVertices, 1, 1); cmdBuf.dispatch(model.nbVertices, 1, 1);
genCmdBuf.flushCommandBuffer(cmdBuf); genCmdBuf.submitAndWait(cmdBuf);
} }
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// #VK_compute // #VK_compute
void HelloVulkan::createCompDescriptors() void HelloVulkan::createCompDescriptors()
{ {
m_compDescSetLayoutBind.emplace_back(vk::DescriptorSetLayoutBinding( m_compDescSetLayoutBind.addBinding(vk::DescriptorSetLayoutBinding(
0, vk::DescriptorType::eStorageBuffer, 1, vk::ShaderStageFlagBits::eCompute)); 0, vk::DescriptorType::eStorageBuffer, 1, vk::ShaderStageFlagBits::eCompute));
m_compDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_compDescSetLayoutBind); m_compDescSetLayout = m_compDescSetLayoutBind.createLayout(m_device);
m_compDescPool = nvvkpp::util::createDescriptorPool(m_device, m_compDescSetLayoutBind, 1); m_compDescPool = m_compDescSetLayoutBind.createPool(m_device, 1);
m_compDescSet = nvvkpp::util::createDescriptorSet(m_device, m_compDescPool, m_compDescSetLayout); m_compDescSet = nvvk::allocateDescriptorSet(m_device, m_compDescPool, m_compDescSetLayout);
} }
void HelloVulkan::updateCompDescriptors(nvvkBuffer& vertex) void HelloVulkan::updateCompDescriptors(nvvk::Buffer& vertex)
{ {
std::vector<vk::WriteDescriptorSet> writes; std::vector<vk::WriteDescriptorSet> writes;
vk::DescriptorBufferInfo dbiUnif{vertex.buffer, 0, VK_WHOLE_SIZE}; vk::DescriptorBufferInfo dbiUnif{vertex.buffer, 0, VK_WHOLE_SIZE};
writes.emplace_back( writes.emplace_back(m_compDescSetLayoutBind.makeWrite(m_compDescSet, 0, &dbiUnif));
nvvkpp::util::createWrite(m_compDescSet, m_compDescSetLayoutBind[0], &dbiUnif));
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr); m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
} }
@ -999,9 +1004,9 @@ void HelloVulkan::createCompPipelines()
vk::ComputePipelineCreateInfo computePipelineCreateInfo{{}, {}, m_compPipelineLayout}; vk::ComputePipelineCreateInfo computePipelineCreateInfo{{}, {}, m_compPipelineLayout};
computePipelineCreateInfo.stage = computePipelineCreateInfo.stage =
nvvkpp::util::loadShader(m_device, nvvk::createShaderStageInfo(m_device,
nvh::loadFile("shaders/anim.comp.spv", true, defaultSearchPaths), nvh::loadFile("shaders/anim.comp.spv", true, defaultSearchPaths),
vk::ShaderStageFlagBits::eCompute); VK_SHADER_STAGE_COMPUTE_BIT);
m_compPipeline = m_device.createComputePipeline({}, computePipelineCreateInfo, nullptr); m_compPipeline = m_device.createComputePipeline({}, computePipelineCreateInfo, nullptr);
m_device.destroy(computePipelineCreateInfo.stage.module); m_device.destroy(computePipelineCreateInfo.stage.module);
} }

View file

@ -26,16 +26,14 @@
*/ */
#pragma once #pragma once
#include "nvvkpp/allocator_dedicated_vkpp.hpp" #define NVVK_ALLOC_DEDICATED
#include "nvvkpp/appbase_vkpp.hpp" #include "nvvk/allocator_vk.hpp"
#include "nvvkpp/debug_util_vkpp.hpp" #include "nvvk/appbase_vkpp.hpp"
#include "nvvk/debug_util_vk.hpp"
#include "nvvk/descriptorsets_vk.hpp"
// #VKRay // #VKRay
#define ALLOC_DEDICATED #include "nvvk/raytraceKHR_vk.hpp"
#include "nvvkpp/raytraceKHR_vkpp.hpp"
using nvvkBuffer = nvvkpp::BufferDedicated;
using nvvkTexture = nvvkpp::TextureDedicated;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Simple rasterizer of OBJ objects // Simple rasterizer of OBJ objects
@ -44,10 +42,11 @@ using nvvkTexture = nvvkpp::TextureDedicated;
// - Rendering is done in an offscreen framebuffer // - Rendering is done in an offscreen framebuffer
// - The image of the framebuffer is displayed in post-process in a full-screen quad // - The image of the framebuffer is displayed in post-process in a full-screen quad
// //
class HelloVulkan : public nvvkpp::AppBase class HelloVulkan : public nvvk::AppBase
{ {
public: public:
void setup(const vk::Device& device, void setup(const vk::Instance& instance,
const vk::Device& device,
const vk::PhysicalDevice& physicalDevice, const vk::PhysicalDevice& physicalDevice,
uint32_t queueFamily) override; uint32_t queueFamily) override;
void createDescriptorSetLayout(); void createDescriptorSetLayout();
@ -66,12 +65,12 @@ public:
// The OBJ model // The OBJ model
struct ObjModel struct ObjModel
{ {
uint32_t nbIndices{0}; uint32_t nbIndices{0};
uint32_t nbVertices{0}; uint32_t nbVertices{0};
nvvkBuffer vertexBuffer; // Device buffer of all 'Vertex' nvvk::Buffer vertexBuffer; // Device buffer of all 'Vertex'
nvvkBuffer indexBuffer; // Device buffer of the indices forming triangles nvvk::Buffer indexBuffer; // Device buffer of the indices forming triangles
nvvkBuffer matColorBuffer; // Device buffer of array of 'Wavefront material' nvvk::Buffer matColorBuffer; // Device buffer of array of 'Wavefront material'
nvvkBuffer matIndexBuffer; // Device buffer of array of 'Wavefront material' nvvk::Buffer matIndexBuffer; // Device buffer of array of 'Wavefront material'
}; };
// Instance of the OBJ // Instance of the OBJ
@ -98,19 +97,19 @@ public:
std::vector<ObjInstance> m_objInstance; std::vector<ObjInstance> m_objInstance;
// Graphic pipeline // Graphic pipeline
vk::PipelineLayout m_pipelineLayout; vk::PipelineLayout m_pipelineLayout;
vk::Pipeline m_graphicsPipeline; vk::Pipeline m_graphicsPipeline;
std::vector<vk::DescriptorSetLayoutBinding> m_descSetLayoutBind; nvvk::DescriptorSetBindings m_descSetLayoutBind;
vk::DescriptorPool m_descPool; vk::DescriptorPool m_descPool;
vk::DescriptorSetLayout m_descSetLayout; vk::DescriptorSetLayout m_descSetLayout;
vk::DescriptorSet m_descSet; vk::DescriptorSet m_descSet;
nvvkBuffer m_cameraMat; // Device-Host of the camera matrices nvvk::Buffer m_cameraMat; // Device-Host of the camera matrices
nvvkBuffer m_sceneDesc; // Device buffer of the OBJ instances nvvk::Buffer m_sceneDesc; // Device buffer of the OBJ instances
std::vector<nvvkTexture> m_textures; // vector of all textures of the scene std::vector<nvvk::Texture> m_textures; // vector of all textures of the scene
nvvkpp::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures nvvk::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures
nvvkpp::DebugUtil m_debug; // Utility to name objects nvvk::DebugUtil m_debug; // Utility to name objects
// #Post // #Post
void createOffscreenRender(); void createOffscreenRender();
@ -119,44 +118,44 @@ public:
void updatePostDescriptorSet(); void updatePostDescriptorSet();
void drawPost(vk::CommandBuffer cmdBuf); void drawPost(vk::CommandBuffer cmdBuf);
std::vector<vk::DescriptorSetLayoutBinding> m_postDescSetLayoutBind; nvvk::DescriptorSetBindings m_postDescSetLayoutBind;
vk::DescriptorPool m_postDescPool; vk::DescriptorPool m_postDescPool;
vk::DescriptorSetLayout m_postDescSetLayout; vk::DescriptorSetLayout m_postDescSetLayout;
vk::DescriptorSet m_postDescSet; vk::DescriptorSet m_postDescSet;
vk::Pipeline m_postPipeline; vk::Pipeline m_postPipeline;
vk::PipelineLayout m_postPipelineLayout; vk::PipelineLayout m_postPipelineLayout;
vk::RenderPass m_offscreenRenderPass; vk::RenderPass m_offscreenRenderPass;
vk::Framebuffer m_offscreenFramebuffer; vk::Framebuffer m_offscreenFramebuffer;
nvvkTexture m_offscreenColor; nvvk::Texture m_offscreenColor;
vk::Format m_offscreenColorFormat{vk::Format::eR32G32B32A32Sfloat}; vk::Format m_offscreenColorFormat{vk::Format::eR32G32B32A32Sfloat};
nvvkTexture m_offscreenDepth; nvvk::Texture m_offscreenDepth;
vk::Format m_offscreenDepthFormat{vk::Format::eD32Sfloat}; vk::Format m_offscreenDepthFormat{vk::Format::eD32Sfloat};
// #VKRay // #VKRay
void initRayTracing(); void initRayTracing();
nvvkpp::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model); nvvk::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
void createBottomLevelAS(); void createBottomLevelAS();
void createTopLevelAS(); void createTopLevelAS();
void createRtDescriptorSet(); void createRtDescriptorSet();
void updateRtDescriptorSet(); void updateRtDescriptorSet();
void createRtPipeline(); void createRtPipeline();
void createRtShaderBindingTable(); void createRtShaderBindingTable();
void raytrace(const vk::CommandBuffer& cmdBuf, const nvmath::vec4f& clearColor); void raytrace(const vk::CommandBuffer& cmdBuf, const nvmath::vec4f& clearColor);
vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties; vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties;
nvvkpp::RaytracingBuilderKHR m_rtBuilder; nvvk::RaytracingBuilderKHR m_rtBuilder;
std::vector<vk::DescriptorSetLayoutBinding> m_rtDescSetLayoutBind; nvvk::DescriptorSetBindings m_rtDescSetLayoutBind;
vk::DescriptorPool m_rtDescPool; vk::DescriptorPool m_rtDescPool;
vk::DescriptorSetLayout m_rtDescSetLayout; vk::DescriptorSetLayout m_rtDescSetLayout;
vk::DescriptorSet m_rtDescSet; vk::DescriptorSet m_rtDescSet;
std::vector<vk::RayTracingShaderGroupCreateInfoKHR> m_rtShaderGroups; std::vector<vk::RayTracingShaderGroupCreateInfoKHR> m_rtShaderGroups;
vk::PipelineLayout m_rtPipelineLayout; vk::PipelineLayout m_rtPipelineLayout;
vk::Pipeline m_rtPipeline; vk::Pipeline m_rtPipeline;
nvvkBuffer m_rtSBTBuffer; nvvk::Buffer m_rtSBTBuffer;
std::vector<nvvkpp::RaytracingBuilderKHR::Instance> m_tlas; std::vector<nvvk::RaytracingBuilderKHR::Instance> m_tlas;
std::vector<nvvkpp::RaytracingBuilderKHR::Blas> m_blas; std::vector<nvvk::RaytracingBuilderKHR::Blas> m_blas;
struct RtPushConstant struct RtPushConstant
{ {
@ -172,13 +171,13 @@ public:
// #VK_compute // #VK_compute
void createCompDescriptors(); void createCompDescriptors();
void updateCompDescriptors(nvvkBuffer& vertex); void updateCompDescriptors(nvvk::Buffer& vertex);
void createCompPipelines(); void createCompPipelines();
std::vector<vk::DescriptorSetLayoutBinding> m_compDescSetLayoutBind; nvvk::DescriptorSetBindings m_compDescSetLayoutBind;
vk::DescriptorPool m_compDescPool; vk::DescriptorPool m_compDescPool;
vk::DescriptorSetLayout m_compDescSetLayout; vk::DescriptorSetLayout m_compDescSetLayout;
vk::DescriptorSet m_compDescSet; vk::DescriptorSet m_compDescSet;
vk::Pipeline m_compPipeline; vk::Pipeline m_compPipeline;
vk::PipelineLayout m_compPipelineLayout; vk::PipelineLayout m_compPipelineLayout;
}; };

View file

@ -39,10 +39,12 @@
#include "nvh/cameramanipulator.hpp" #include "nvh/cameramanipulator.hpp"
#include "nvh/fileoperations.hpp" #include "nvh/fileoperations.hpp"
#include "nvpsystem.hpp" #include "nvpsystem.hpp"
#include "nvvkpp/appbase_vkpp.hpp" #include "nvvk/appbase_vkpp.hpp"
#include "nvvkpp/commands_vkpp.hpp" #include "nvvk/commands_vk.hpp"
#include "nvvkpp/context_vkpp.hpp" #include "nvvk/context_vk.hpp"
#include "nvvkpp/utilities_vkpp.hpp"
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
#define UNUSED(x) (void)(x) #define UNUSED(x) (void)(x)
@ -124,7 +126,7 @@ int main(int argc, char** argv)
vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature; vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature;
// Requesting Vulkan extensions and layers // Requesting Vulkan extensions and layers
nvvkpp::ContextCreateInfo contextInfo(true); nvvk::ContextCreateInfo contextInfo(true);
contextInfo.setVersion(1, 2); contextInfo.setVersion(1, 2);
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true); contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME); contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME);
@ -148,7 +150,7 @@ int main(int argc, char** argv)
contextInfo.addDeviceExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME); contextInfo.addDeviceExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
// Creating Vulkan base application // Creating Vulkan base application
nvvkpp::Context vkctx{}; nvvk::Context vkctx{};
vkctx.initInstance(contextInfo); vkctx.initInstance(contextInfo);
// Find all compatible devices // Find all compatible devices
auto compatibleDevices = vkctx.getCompatibleDevices(contextInfo); auto compatibleDevices = vkctx.getCompatibleDevices(contextInfo);
@ -163,7 +165,8 @@ int main(int argc, char** argv)
const vk::SurfaceKHR surface = helloVk.getVkSurface(vkctx.m_instance, window); const vk::SurfaceKHR surface = helloVk.getVkSurface(vkctx.m_instance, window);
vkctx.setGCTQueueWithPresent(surface); vkctx.setGCTQueueWithPresent(surface);
helloVk.setup(vkctx.m_device, vkctx.m_physicalDevice, vkctx.m_queueGCT.familyIndex); helloVk.setup(vkctx.m_instance, vkctx.m_device, vkctx.m_physicalDevice,
vkctx.m_queueGCT.familyIndex);
helloVk.createSurface(surface, SAMPLE_WIDTH, SAMPLE_HEIGHT); helloVk.createSurface(surface, SAMPLE_WIDTH, SAMPLE_HEIGHT);
helloVk.createDepthBuffer(); helloVk.createDepthBuffer();
helloVk.createRenderPass(); helloVk.createRenderPass();
@ -256,7 +259,8 @@ int main(int argc, char** argv)
// Clearing screen // Clearing screen
vk::ClearValue clearValues[2]; vk::ClearValue clearValues[2];
clearValues[0].setColor(nvvkpp::util::clearColor(clearColor)); clearValues[0].setColor(
std::array<float, 4>({clearColor[0], clearColor[1], clearColor[2], clearColor[3]}));
clearValues[1].setDepthStencil({1.0f, 0}); clearValues[1].setDepthStencil({1.0f, 0});
// Offscreen render pass // Offscreen render pass
@ -308,7 +312,6 @@ int main(int argc, char** argv)
helloVk.destroyResources(); helloVk.destroyResources();
helloVk.destroy(); helloVk.destroy();
vkctx.m_instance.destroySurfaceKHR(surface);
vkctx.deinit(); vkctx.deinit();
glfwDestroyWindow(window); glfwDestroyWindow(window);

View file

@ -6,7 +6,7 @@
#include "raycommon.glsl" #include "raycommon.glsl"
#include "wavefront.glsl" #include "wavefront.glsl"
hitAttributeEXT vec3 attribs; hitAttributeEXT vec2 attribs;
// clang-format off // clang-format off
layout(location = 0) rayPayloadInEXT hitPayload prd; layout(location = 0) rayPayloadInEXT hitPayload prd;

View file

@ -36,13 +36,14 @@ extern std::vector<std::string> defaultSearchPaths;
#include "hello_vulkan.h" #include "hello_vulkan.h"
#include "nvh//cameramanipulator.hpp" #include "nvh//cameramanipulator.hpp"
#include "nvvkpp/descriptorsets_vkpp.hpp" #include "nvvk/descriptorsets_vk.hpp"
#include "nvvkpp/pipeline_vkpp.hpp" #include "nvvk/pipeline_vk.hpp"
#include "nvh/fileoperations.hpp" #include "nvh/fileoperations.hpp"
#include "nvvkpp/commands_vkpp.hpp" #include "nvvk/commands_vk.hpp"
#include "nvvkpp/renderpass_vkpp.hpp" #include "nvvk/renderpasses_vk.hpp"
#include "nvvkpp/utilities_vkpp.hpp" #include "nvvk/shaders_vk.hpp"
// Holding the camera matrices // Holding the camera matrices
struct CameraMatrices struct CameraMatrices
@ -58,11 +59,12 @@ struct CameraMatrices
// Keep the handle on the device // Keep the handle on the device
// Initialize the tool to do all our allocations: buffers, images // Initialize the tool to do all our allocations: buffers, images
// //
void HelloVulkan::setup(const vk::Device& device, void HelloVulkan::setup(const vk::Instance& instance,
const vk::Device& device,
const vk::PhysicalDevice& physicalDevice, const vk::PhysicalDevice& physicalDevice,
uint32_t queueFamily) uint32_t queueFamily)
{ {
AppBase::setup(device, physicalDevice, queueFamily); AppBase::setup(instance, device, physicalDevice, queueFamily);
m_alloc.init(device, physicalDevice); m_alloc.init(device, physicalDevice);
m_debug.setup(m_device); m_debug.setup(m_device);
} }
@ -99,34 +101,34 @@ void HelloVulkan::createDescriptorSetLayout()
uint32_t nbObj = static_cast<uint32_t>(m_objModel.size()); uint32_t nbObj = static_cast<uint32_t>(m_objModel.size());
// Camera matrices (binding = 0) // Camera matrices (binding = 0)
m_descSetLayoutBind.emplace_back( m_descSetLayoutBind.addBinding(
vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR)); vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR));
// Materials (binding = 1) // Materials (binding = 1)
m_descSetLayoutBind.emplace_back( m_descSetLayoutBind.addBinding(
vkDS(1, vkDT::eStorageBuffer, nbObj, vkDS(1, vkDT::eStorageBuffer, nbObj,
vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR | vkSS::eAnyHitKHR)); vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR | vkSS::eAnyHitKHR));
// Scene description (binding = 2) // Scene description (binding = 2)
m_descSetLayoutBind.emplace_back( // m_descSetLayoutBind.addBinding( //
vkDS(2, vkDT::eStorageBuffer, 1, vkDS(2, vkDT::eStorageBuffer, 1,
vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR | vkSS::eAnyHitKHR)); vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR | vkSS::eAnyHitKHR));
// Textures (binding = 3) // Textures (binding = 3)
m_descSetLayoutBind.emplace_back( m_descSetLayoutBind.addBinding(
vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR)); vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR));
// Materials (binding = 4) // Materials (binding = 4)
m_descSetLayoutBind.emplace_back( // m_descSetLayoutBind.addBinding( //
vkDS(4, vkDT::eStorageBuffer, nbObj, vkDS(4, vkDT::eStorageBuffer, nbObj,
vkSS::eFragment | vkSS::eClosestHitKHR | vkSS::eAnyHitKHR)); vkSS::eFragment | vkSS::eClosestHitKHR | vkSS::eAnyHitKHR));
// Storing vertices (binding = 5) // Storing vertices (binding = 5)
m_descSetLayoutBind.emplace_back( // m_descSetLayoutBind.addBinding( //
vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR | vkSS::eAnyHitKHR)); vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR | vkSS::eAnyHitKHR));
// Storing indices (binding = 6) // Storing indices (binding = 6)
m_descSetLayoutBind.emplace_back( // m_descSetLayoutBind.addBinding( //
vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR | vkSS::eAnyHitKHR)); vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR | vkSS::eAnyHitKHR));
m_descSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_descSetLayoutBind); m_descSetLayout = m_descSetLayoutBind.createLayout(m_device);
m_descPool = nvvkpp::util::createDescriptorPool(m_device, m_descSetLayoutBind, 1); m_descPool = m_descSetLayoutBind.createPool(m_device, 1);
m_descSet = nvvkpp::util::createDescriptorSet(m_device, m_descPool, m_descSetLayout); m_descSet = nvvk::allocateDescriptorSet(m_device, m_descPool, m_descSetLayout);
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -138,9 +140,9 @@ void HelloVulkan::updateDescriptorSet()
// Camera matrices and scene description // Camera matrices and scene description
vk::DescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE}; vk::DescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE};
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[0], &dbiUnif)); writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 0, &dbiUnif));
vk::DescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE}; vk::DescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[2], &dbiSceneDesc)); writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 2, &dbiSceneDesc));
// All material buffers, 1 buffer per OBJ // All material buffers, 1 buffer per OBJ
std::vector<vk::DescriptorBufferInfo> dbiMat; std::vector<vk::DescriptorBufferInfo> dbiMat;
@ -154,11 +156,10 @@ void HelloVulkan::updateDescriptorSet()
dbiVert.emplace_back(obj.vertexBuffer.buffer, 0, VK_WHOLE_SIZE); dbiVert.emplace_back(obj.vertexBuffer.buffer, 0, VK_WHOLE_SIZE);
dbiIdx.emplace_back(obj.indexBuffer.buffer, 0, VK_WHOLE_SIZE); dbiIdx.emplace_back(obj.indexBuffer.buffer, 0, VK_WHOLE_SIZE);
} }
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[1], dbiMat.data())); writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 1, dbiMat.data()));
writes.emplace_back( writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 4, dbiMatIdx.data()));
nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[4], dbiMatIdx.data())); writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 5, dbiVert.data()));
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[5], dbiVert.data())); writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 6, dbiIdx.data()));
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[6], dbiIdx.data()));
// All texture samplers // All texture samplers
std::vector<vk::DescriptorImageInfo> diit; std::vector<vk::DescriptorImageInfo> diit;
@ -166,7 +167,7 @@ void HelloVulkan::updateDescriptorSet()
{ {
diit.push_back(texture.descriptor); diit.push_back(texture.descriptor);
} }
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[3], diit.data())); writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 3, diit.data()));
// Writing the information // Writing the information
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr); m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
@ -192,19 +193,18 @@ void HelloVulkan::createGraphicsPipeline()
m_pipelineLayout = m_device.createPipelineLayout(pipelineLayoutCreateInfo); m_pipelineLayout = m_device.createPipelineLayout(pipelineLayoutCreateInfo);
// Creating the Pipeline // Creating the Pipeline
std::vector<std::string> paths = defaultSearchPaths; std::vector<std::string> paths = defaultSearchPaths;
nvvkpp::GraphicsPipelineGenerator gpb(m_device, m_pipelineLayout, m_offscreenRenderPass); nvvk::GraphicsPipelineGeneratorCombined gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
gpb.depthStencilState = {true}; gpb.depthStencilState.depthTestEnable = true;
gpb.addShader(nvh::loadFile("shaders/vert_shader.vert.spv", true, paths), vkSS::eVertex); gpb.addShader(nvh::loadFile("shaders/vert_shader.vert.spv", true, paths), vkSS::eVertex);
gpb.addShader(nvh::loadFile("shaders/frag_shader.frag.spv", true, paths), vkSS::eFragment); gpb.addShader(nvh::loadFile("shaders/frag_shader.frag.spv", true, paths), vkSS::eFragment);
gpb.vertexInputState.bindingDescriptions = {{0, sizeof(VertexObj)}}; gpb.addBindingDescription({0, sizeof(VertexObj)});
gpb.vertexInputState.attributeDescriptions = { gpb.addAttributeDescriptions({{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)}, {1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)},
{1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)}, {2, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, color)},
{2, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, color)}, {3, 0, vk::Format::eR32G32Sfloat, offsetof(VertexObj, texCoord)}});
{3, 0, vk::Format::eR32G32Sfloat, offsetof(VertexObj, texCoord)}};
m_graphicsPipeline = gpb.create(); m_graphicsPipeline = gpb.createPipeline();
m_debug.setObjectName(m_graphicsPipeline, "Graphics"); m_debug.setObjectName(m_graphicsPipeline, "Graphics");
} }
@ -237,8 +237,8 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size()); model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
// Create the buffers on Device and copy vertices, indices and materials // Create the buffers on Device and copy vertices, indices and materials
nvvkpp::SingleCommandBuffer cmdBufGet(m_device, m_graphicsQueueIndex); nvvk::CommandPool cmdBufGet(m_device, m_graphicsQueueIndex);
vk::CommandBuffer cmdBuf = cmdBufGet.createCommandBuffer(); vk::CommandBuffer cmdBuf = cmdBufGet.createCommandBuffer();
model.vertexBuffer = model.vertexBuffer =
m_alloc.createBuffer(cmdBuf, loader.m_vertices, m_alloc.createBuffer(cmdBuf, loader.m_vertices,
vkBU::eVertexBuffer | vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress); vkBU::eVertexBuffer | vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress);
@ -249,8 +249,8 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, vkBU::eStorageBuffer); model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, vkBU::eStorageBuffer);
// Creates all textures found // Creates all textures found
createTextureImages(cmdBuf, loader.m_textures); createTextureImages(cmdBuf, loader.m_textures);
cmdBufGet.flushCommandBuffer(cmdBuf); cmdBufGet.submitAndWait(cmdBuf);
m_alloc.flushStaging(); m_alloc.finalizeAndReleaseStaging();
std::string objNb = std::to_string(instance.objIndex); std::string objNb = std::to_string(instance.objIndex);
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str())); m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
@ -285,12 +285,12 @@ void HelloVulkan::createUniformBuffer()
void HelloVulkan::createSceneDescriptionBuffer() void HelloVulkan::createSceneDescriptionBuffer()
{ {
using vkBU = vk::BufferUsageFlagBits; using vkBU = vk::BufferUsageFlagBits;
nvvkpp::SingleCommandBuffer cmdGen(m_device, m_graphicsQueueIndex); nvvk::CommandPool cmdGen(m_device, m_graphicsQueueIndex);
auto cmdBuf = cmdGen.createCommandBuffer(); auto cmdBuf = cmdGen.createCommandBuffer();
m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer); m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer);
cmdGen.flushCommandBuffer(cmdBuf); cmdGen.submitAndWait(cmdBuf);
m_alloc.flushStaging(); m_alloc.finalizeAndReleaseStaging();
m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc"); m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc");
} }
@ -310,21 +310,21 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
// If no textures are present, create a dummy one to accommodate the pipeline layout // If no textures are present, create a dummy one to accommodate the pipeline layout
if(textures.empty() && m_textures.empty()) if(textures.empty() && m_textures.empty())
{ {
nvvkTexture texture; nvvk::Texture texture;
std::array<uint8_t, 4> color{255u, 255u, 255u, 255u}; std::array<uint8_t, 4> color{255u, 255u, 255u, 255u};
vk::DeviceSize bufferSize = sizeof(color); vk::DeviceSize bufferSize = sizeof(color);
auto imgSize = vk::Extent2D(1, 1); auto imgSize = vk::Extent2D(1, 1);
auto imageCreateInfo = nvvkpp::image::create2DInfo(imgSize, format); auto imageCreateInfo = nvvk::makeImage2DCreateInfo(imgSize, format);
// Creating the dummy texure
nvvk::Image image = m_alloc.createImage(cmdBuf, bufferSize, color.data(), imageCreateInfo);
vk::ImageViewCreateInfo ivInfo = nvvk::makeImageViewCreateInfo(image.image, imageCreateInfo);
texture = m_alloc.createTexture(image, ivInfo, samplerCreateInfo);
// Creating the VKImage
texture = m_alloc.createImage(cmdBuf, bufferSize, color.data(), imageCreateInfo);
// Setting up the descriptor used by the shader
texture.descriptor =
nvvkpp::image::create2DDescriptor(m_device, texture.image, samplerCreateInfo, format);
// The image format must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL // The image format must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
nvvkpp::image::setImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined, nvvk::cmdBarrierImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eShaderReadOnlyOptimal); vk::ImageLayout::eShaderReadOnlyOptimal);
m_textures.push_back(texture); m_textures.push_back(texture);
} }
else else
@ -351,16 +351,16 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4; vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4;
auto imgSize = vk::Extent2D(texWidth, texHeight); auto imgSize = vk::Extent2D(texWidth, texHeight);
auto imageCreateInfo = nvvkpp::image::create2DInfo(imgSize, format, vkIU::eSampled, true); auto imageCreateInfo = nvvk::makeImage2DCreateInfo(imgSize, format, vkIU::eSampled, true);
{ {
nvvkTexture texture; nvvk::ImageDedicated image =
texture = m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo); m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo);
nvvk::cmdGenerateMipmaps(cmdBuf, image.image, format, imgSize, imageCreateInfo.mipLevels);
vk::ImageViewCreateInfo ivInfo =
nvvk::makeImageViewCreateInfo(image.image, imageCreateInfo);
nvvk::Texture texture = m_alloc.createTexture(image, ivInfo, samplerCreateInfo);
nvvkpp::image::generateMipmaps(cmdBuf, texture.image, format, imgSize,
imageCreateInfo.mipLevels);
texture.descriptor =
nvvkpp::image::create2DDescriptor(m_device, texture.image, samplerCreateInfo, format);
m_textures.push_back(texture); m_textures.push_back(texture);
} }
} }
@ -437,7 +437,7 @@ void HelloVulkan::rasterize(const vk::CommandBuffer& cmdBuf)
cmdBuf.pushConstants<ObjPushConstant>(m_pipelineLayout, vkSS::eVertex | vkSS::eFragment, 0, cmdBuf.pushConstants<ObjPushConstant>(m_pipelineLayout, vkSS::eVertex | vkSS::eFragment, 0,
m_pushConstant); m_pushConstant);
cmdBuf.bindVertexBuffers(0, 1, &model.vertexBuffer.buffer, &offset); cmdBuf.bindVertexBuffers(0, {model.vertexBuffer.buffer}, {offset});
cmdBuf.bindIndexBuffer(model.indexBuffer.buffer, 0, vk::IndexType::eUint32); cmdBuf.bindIndexBuffer(model.indexBuffer.buffer, 0, vk::IndexType::eUint32);
cmdBuf.drawIndexed(model.nbIndices, 1, 0, 0, 0); cmdBuf.drawIndexed(model.nbIndices, 1, 0, 0, 0);
} }
@ -467,49 +467,54 @@ void HelloVulkan::createOffscreenRender()
m_alloc.destroy(m_offscreenDepth); m_alloc.destroy(m_offscreenDepth);
// Creating the color image // Creating the color image
auto colorCreateInfo = nvvkpp::image::create2DInfo(m_size, m_offscreenColorFormat, {
vk::ImageUsageFlagBits::eColorAttachment auto colorCreateInfo = nvvk::makeImage2DCreateInfo(m_size, m_offscreenColorFormat,
| vk::ImageUsageFlagBits::eSampled vk::ImageUsageFlagBits::eColorAttachment
| vk::ImageUsageFlagBits::eStorage); | vk::ImageUsageFlagBits::eSampled
m_offscreenColor = m_alloc.createImage(colorCreateInfo); | vk::ImageUsageFlagBits::eStorage);
m_offscreenColor.descriptor =
nvvkpp::image::create2DDescriptor(m_device, m_offscreenColor.image, vk::SamplerCreateInfo{}, nvvk::ImageDedicated image = m_alloc.createImage(colorCreateInfo);
m_offscreenColorFormat, vk::ImageLayout::eGeneral); vk::ImageViewCreateInfo ivInfo = nvvk::makeImageViewCreateInfo(image.image, colorCreateInfo);
m_offscreenColor = m_alloc.createTexture(image, ivInfo, vk::SamplerCreateInfo());
m_offscreenColor.descriptor.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
}
// Creating the depth buffer // Creating the depth buffer
auto depthCreateInfo = auto depthCreateInfo =
nvvkpp::image::create2DInfo(m_size, m_offscreenDepthFormat, nvvk::makeImage2DCreateInfo(m_size, m_offscreenDepthFormat,
vk::ImageUsageFlagBits::eDepthStencilAttachment); vk::ImageUsageFlagBits::eDepthStencilAttachment);
m_offscreenDepth = m_alloc.createImage(depthCreateInfo); {
nvvk::Image image = m_alloc.createImage(depthCreateInfo);
vk::ImageViewCreateInfo depthStencilView; vk::ImageViewCreateInfo depthStencilView;
depthStencilView.setViewType(vk::ImageViewType::e2D); depthStencilView.setViewType(vk::ImageViewType::e2D);
depthStencilView.setFormat(m_offscreenDepthFormat); depthStencilView.setFormat(m_offscreenDepthFormat);
depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1}); depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1});
depthStencilView.setImage(m_offscreenDepth.image); depthStencilView.setImage(image.image);
m_offscreenDepth.descriptor.imageView = m_device.createImageView(depthStencilView);
m_offscreenDepth = m_alloc.createTexture(image, depthStencilView);
}
// Setting the image layout for both color and depth // Setting the image layout for both color and depth
{ {
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex); nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
auto cmdBuf = genCmdBuf.createCommandBuffer(); auto cmdBuf = genCmdBuf.createCommandBuffer();
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined, nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eGeneral); vk::ImageLayout::eGeneral);
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageAspectFlagBits::eDepth, nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eUndefined, vk::ImageLayout::eDepthStencilAttachmentOptimal,
vk::ImageLayout::eDepthStencilAttachmentOptimal); vk::ImageAspectFlagBits::eDepth);
genCmdBuf.flushCommandBuffer(cmdBuf); genCmdBuf.submitAndWait(cmdBuf);
} }
// Creating a renderpass for the offscreen // Creating a renderpass for the offscreen
if(!m_offscreenRenderPass) if(!m_offscreenRenderPass)
{ {
m_offscreenRenderPass = m_offscreenRenderPass =
nvvkpp::util::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat, nvvk::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat, 1, true,
1, true, true, vk::ImageLayout::eGeneral, true, vk::ImageLayout::eGeneral, vk::ImageLayout::eGeneral);
vk::ImageLayout::eGeneral);
} }
// Creating the frame buffer for offscreen // Creating the frame buffer for offscreen
@ -546,13 +551,14 @@ void HelloVulkan::createPostPipeline()
// Pipeline: completely generic, no vertices // Pipeline: completely generic, no vertices
std::vector<std::string> paths = defaultSearchPaths; std::vector<std::string> paths = defaultSearchPaths;
nvvkpp::GraphicsPipelineGenerator pipelineGenerator(m_device, m_postPipelineLayout, m_renderPass); nvvk::GraphicsPipelineGeneratorCombined pipelineGenerator(m_device, m_postPipelineLayout,
m_renderPass);
pipelineGenerator.addShader(nvh::loadFile("shaders/passthrough.vert.spv", true, paths), pipelineGenerator.addShader(nvh::loadFile("shaders/passthrough.vert.spv", true, paths),
vk::ShaderStageFlagBits::eVertex); vk::ShaderStageFlagBits::eVertex);
pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths), pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths),
vk::ShaderStageFlagBits::eFragment); vk::ShaderStageFlagBits::eFragment);
pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone); pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone);
m_postPipeline = pipelineGenerator.create(); m_postPipeline = pipelineGenerator.createPipeline();
m_debug.setObjectName(m_postPipeline, "post"); m_debug.setObjectName(m_postPipeline, "post");
} }
@ -566,10 +572,10 @@ void HelloVulkan::createPostDescriptor()
using vkDT = vk::DescriptorType; using vkDT = vk::DescriptorType;
using vkSS = vk::ShaderStageFlagBits; using vkSS = vk::ShaderStageFlagBits;
m_postDescSetLayoutBind.emplace_back(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment)); m_postDescSetLayoutBind.addBinding(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
m_postDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_postDescSetLayoutBind); m_postDescSetLayout = m_postDescSetLayoutBind.createLayout(m_device);
m_postDescPool = nvvkpp::util::createDescriptorPool(m_device, m_postDescSetLayoutBind); m_postDescPool = m_postDescSetLayoutBind.createPool(m_device);
m_postDescSet = nvvkpp::util::createDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout); m_postDescSet = nvvk::allocateDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -578,8 +584,7 @@ void HelloVulkan::createPostDescriptor()
void HelloVulkan::updatePostDescriptorSet() void HelloVulkan::updatePostDescriptorSet()
{ {
vk::WriteDescriptorSet writeDescriptorSets = vk::WriteDescriptorSet writeDescriptorSets =
nvvkpp::util::createWrite(m_postDescSet, m_postDescSetLayoutBind[0], m_postDescSetLayoutBind.makeWrite(m_postDescSet, 0, &m_offscreenColor.descriptor);
&m_offscreenColor.descriptor);
m_device.updateDescriptorSets(writeDescriptorSets, nullptr); m_device.updateDescriptorSets(writeDescriptorSets, nullptr);
} }
@ -617,13 +622,13 @@ void HelloVulkan::initRayTracing()
auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2, auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2,
vk::PhysicalDeviceRayTracingPropertiesKHR>(); vk::PhysicalDeviceRayTracingPropertiesKHR>();
m_rtProperties = properties.get<vk::PhysicalDeviceRayTracingPropertiesKHR>(); m_rtProperties = properties.get<vk::PhysicalDeviceRayTracingPropertiesKHR>();
m_rtBuilder.setup(m_device, m_physicalDevice, m_graphicsQueueIndex); m_rtBuilder.setup(m_device, &m_alloc, m_graphicsQueueIndex);
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Converting a OBJ primitive to the ray tracing geometry used for the BLAS // Converting a OBJ primitive to the ray tracing geometry used for the BLAS
// //
nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model) nvvk::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model)
{ {
vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate; vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate;
asCreate.setGeometryType(vk::GeometryTypeKHR::eTriangles); asCreate.setGeometryType(vk::GeometryTypeKHR::eTriangles);
@ -655,7 +660,7 @@ nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjM
offset.setPrimitiveOffset(0); offset.setPrimitiveOffset(0);
offset.setTransformOffset(0); offset.setTransformOffset(0);
nvvkpp::RaytracingBuilderKHR::Blas blas; nvvk::RaytracingBuilderKHR::Blas blas;
blas.asGeometry.emplace_back(asGeom); blas.asGeometry.emplace_back(asGeom);
blas.asCreateGeometryInfo.emplace_back(asCreate); blas.asCreateGeometryInfo.emplace_back(asCreate);
blas.asBuildOffsetInfo.emplace_back(offset); blas.asBuildOffsetInfo.emplace_back(offset);
@ -665,7 +670,7 @@ nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjM
void HelloVulkan::createBottomLevelAS() void HelloVulkan::createBottomLevelAS()
{ {
// BLAS - Storing each primitive in a geometry // BLAS - Storing each primitive in a geometry
std::vector<nvvkpp::RaytracingBuilderKHR::Blas> allBlas; std::vector<nvvk::RaytracingBuilderKHR::Blas> allBlas;
allBlas.reserve(m_objModel.size()); allBlas.reserve(m_objModel.size());
for(const auto& obj : m_objModel) for(const auto& obj : m_objModel)
{ {
@ -679,16 +684,16 @@ void HelloVulkan::createBottomLevelAS()
void HelloVulkan::createTopLevelAS() void HelloVulkan::createTopLevelAS()
{ {
std::vector<nvvkpp::RaytracingBuilderKHR::Instance> tlas; std::vector<nvvk::RaytracingBuilderKHR::Instance> tlas;
tlas.reserve(m_objInstance.size()); tlas.reserve(m_objInstance.size());
for(int i = 0; i < static_cast<int>(m_objInstance.size()); i++) for(int i = 0; i < static_cast<int>(m_objInstance.size()); i++)
{ {
nvvkpp::RaytracingBuilderKHR::Instance rayInst; nvvk::RaytracingBuilderKHR::Instance rayInst;
rayInst.transform = m_objInstance[i].transform; // Position of the instance rayInst.transform = m_objInstance[i].transform; // Position of the instance
rayInst.instanceId = i; // gl_InstanceID rayInst.instanceId = i; // gl_InstanceID
rayInst.blasId = m_objInstance[i].objIndex; rayInst.blasId = m_objInstance[i].objIndex;
rayInst.hitGroupId = 0; // We will use the same hit group for all objects rayInst.hitGroupId = 0; // We will use the same hit group for all objects
rayInst.flags = vk::GeometryInstanceFlagBitsKHR::eTriangleCullDisable; rayInst.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
tlas.emplace_back(rayInst); tlas.emplace_back(rayInst);
} }
m_rtBuilder.buildTlas(tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace); m_rtBuilder.buildTlas(tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace);
@ -703,25 +708,25 @@ void HelloVulkan::createRtDescriptorSet()
using vkSS = vk::ShaderStageFlagBits; using vkSS = vk::ShaderStageFlagBits;
using vkDSLB = vk::DescriptorSetLayoutBinding; using vkDSLB = vk::DescriptorSetLayoutBinding;
m_rtDescSetLayoutBind.emplace_back(vkDSLB(0, vkDT::eAccelerationStructureKHR, 1, m_rtDescSetLayoutBind.addBinding(vkDSLB(0, vkDT::eAccelerationStructureKHR, 1,
vkSS::eRaygenKHR | vkSS::eClosestHitKHR)); // TLAS vkSS::eRaygenKHR | vkSS::eClosestHitKHR)); // TLAS
m_rtDescSetLayoutBind.emplace_back( m_rtDescSetLayoutBind.addBinding(
vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image
m_rtDescPool = nvvkpp::util::createDescriptorPool(m_device, m_rtDescSetLayoutBind); m_rtDescPool = m_rtDescSetLayoutBind.createPool(m_device);
m_rtDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_rtDescSetLayoutBind); m_rtDescSetLayout = m_rtDescSetLayoutBind.createLayout(m_device);
m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0]; m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0];
vk::AccelerationStructureKHR tlas = m_rtBuilder.getAccelerationStructure();
vk::WriteDescriptorSetAccelerationStructureKHR descASInfo; vk::WriteDescriptorSetAccelerationStructureKHR descASInfo;
descASInfo.setAccelerationStructureCount(1); descASInfo.setAccelerationStructureCount(1);
descASInfo.setPAccelerationStructures(&m_rtBuilder.getAccelerationStructure()); descASInfo.setPAccelerationStructures(&tlas);
vk::DescriptorImageInfo imageInfo{ vk::DescriptorImageInfo imageInfo{
{}, m_offscreenColor.descriptor.imageView, vk::ImageLayout::eGeneral}; {}, m_offscreenColor.descriptor.imageView, vk::ImageLayout::eGeneral};
std::vector<vk::WriteDescriptorSet> writes; std::vector<vk::WriteDescriptorSet> writes;
writes.emplace_back( writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 0, &descASInfo));
nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[0], &descASInfo)); writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 1, &imageInfo));
writes.emplace_back(nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[1], &imageInfo));
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr); m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
} }
@ -750,16 +755,17 @@ void HelloVulkan::createRtPipeline()
std::vector<std::string> paths = defaultSearchPaths; std::vector<std::string> paths = defaultSearchPaths;
vk::ShaderModule raygenSM = vk::ShaderModule raygenSM =
nvvkpp::util::createShaderModule(m_device, // nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rgen.spv", true, paths)); nvh::loadFile("shaders/raytrace.rgen.spv", true, paths));
vk::ShaderModule missSM = vk::ShaderModule missSM =
nvvkpp::util::createShaderModule(m_device, // nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths)); nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths));
// The second miss shader is invoked when a shadow ray misses the geometry. It // The second miss shader is invoked when a shadow ray misses the geometry. It
// simply indicates that no occlusion has been found // simply indicates that no occlusion has been found
vk::ShaderModule shadowmissSM = nvvkpp::util::createShaderModule( vk::ShaderModule shadowmissSM =
m_device, nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths)); nvvk::createShaderModule(m_device,
nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
std::vector<vk::PipelineShaderStageCreateInfo> stages; std::vector<vk::PipelineShaderStageCreateInfo> stages;
@ -785,11 +791,11 @@ void HelloVulkan::createRtPipeline()
// Hit Group - Closest Hit + AnyHit // Hit Group - Closest Hit + AnyHit
vk::ShaderModule chitSM = vk::ShaderModule chitSM =
nvvkpp::util::createShaderModule(m_device, // nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rchit.spv", true, paths)); nvh::loadFile("shaders/raytrace.rchit.spv", true, paths));
vk::ShaderModule ahitSM = vk::ShaderModule ahitSM =
nvvkpp::util::createShaderModule(m_device, // nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rahit.spv", true, paths)); nvh::loadFile("shaders/raytrace.rahit.spv", true, paths));
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup, vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup,
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR,
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR}; VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR};
@ -855,17 +861,17 @@ void HelloVulkan::createRtShaderBindingTable()
m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize, m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize,
shaderHandleStorage.data()); shaderHandleStorage.data());
// Write the handles in the SBT // Write the handles in the SBT
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex); nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer(); vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
m_rtSBTBuffer = m_rtSBTBuffer =
m_alloc.createBuffer(cmdBuf, shaderHandleStorage, vk::BufferUsageFlagBits::eRayTracingKHR); m_alloc.createBuffer(cmdBuf, shaderHandleStorage, vk::BufferUsageFlagBits::eRayTracingKHR);
m_debug.setObjectName(m_rtSBTBuffer.buffer, "SBT"); m_debug.setObjectName(m_rtSBTBuffer.buffer, "SBT");
genCmdBuf.flushCommandBuffer(cmdBuf); genCmdBuf.submitAndWait(cmdBuf);
m_alloc.flushStaging(); m_alloc.finalizeAndReleaseStaging();
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------

View file

@ -26,16 +26,14 @@
*/ */
#pragma once #pragma once
#include "nvvkpp/allocator_dedicated_vkpp.hpp" #define NVVK_ALLOC_DEDICATED
#include "nvvkpp/appbase_vkpp.hpp" #include "nvvk/allocator_vk.hpp"
#include "nvvkpp/debug_util_vkpp.hpp" #include "nvvk/appbase_vkpp.hpp"
#include "nvvk/debug_util_vk.hpp"
#include "nvvk/descriptorsets_vk.hpp"
// #VKRay // #VKRay
#define ALLOC_DEDICATED #include "nvvk/raytraceKHR_vk.hpp"
#include "nvvkpp/raytraceKHR_vkpp.hpp"
using nvvkBuffer = nvvkpp::BufferDedicated;
using nvvkTexture = nvvkpp::TextureDedicated;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Simple rasterizer of OBJ objects // Simple rasterizer of OBJ objects
@ -44,10 +42,11 @@ using nvvkTexture = nvvkpp::TextureDedicated;
// - Rendering is done in an offscreen framebuffer // - Rendering is done in an offscreen framebuffer
// - The image of the framebuffer is displayed in post-process in a full-screen quad // - The image of the framebuffer is displayed in post-process in a full-screen quad
// //
class HelloVulkan : public nvvkpp::AppBase class HelloVulkan : public nvvk::AppBase
{ {
public: public:
void setup(const vk::Device& device, void setup(const vk::Instance& instance,
const vk::Device& device,
const vk::PhysicalDevice& physicalDevice, const vk::PhysicalDevice& physicalDevice,
uint32_t queueFamily) override; uint32_t queueFamily) override;
void createDescriptorSetLayout(); void createDescriptorSetLayout();
@ -66,12 +65,12 @@ public:
// The OBJ model // The OBJ model
struct ObjModel struct ObjModel
{ {
uint32_t nbIndices{0}; uint32_t nbIndices{0};
uint32_t nbVertices{0}; uint32_t nbVertices{0};
nvvkBuffer vertexBuffer; // Device buffer of all 'Vertex' nvvk::Buffer vertexBuffer; // Device buffer of all 'Vertex'
nvvkBuffer indexBuffer; // Device buffer of the indices forming triangles nvvk::Buffer indexBuffer; // Device buffer of the indices forming triangles
nvvkBuffer matColorBuffer; // Device buffer of array of 'Wavefront material' nvvk::Buffer matColorBuffer; // Device buffer of array of 'Wavefront material'
nvvkBuffer matIndexBuffer; // Device buffer of array of 'Wavefront material' nvvk::Buffer matIndexBuffer; // Device buffer of array of 'Wavefront material'
}; };
// Instance of the OBJ // Instance of the OBJ
@ -98,19 +97,19 @@ public:
std::vector<ObjInstance> m_objInstance; std::vector<ObjInstance> m_objInstance;
// Graphic pipeline // Graphic pipeline
vk::PipelineLayout m_pipelineLayout; vk::PipelineLayout m_pipelineLayout;
vk::Pipeline m_graphicsPipeline; vk::Pipeline m_graphicsPipeline;
std::vector<vk::DescriptorSetLayoutBinding> m_descSetLayoutBind; nvvk::DescriptorSetBindings m_descSetLayoutBind;
vk::DescriptorPool m_descPool; vk::DescriptorPool m_descPool;
vk::DescriptorSetLayout m_descSetLayout; vk::DescriptorSetLayout m_descSetLayout;
vk::DescriptorSet m_descSet; vk::DescriptorSet m_descSet;
nvvkBuffer m_cameraMat; // Device-Host of the camera matrices nvvk::Buffer m_cameraMat; // Device-Host of the camera matrices
nvvkBuffer m_sceneDesc; // Device buffer of the OBJ instances nvvk::Buffer m_sceneDesc; // Device buffer of the OBJ instances
std::vector<nvvkTexture> m_textures; // vector of all textures of the scene std::vector<nvvk::Texture> m_textures; // vector of all textures of the scene
nvvkpp::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures nvvk::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures
nvvkpp::DebugUtil m_debug; // Utility to name objects nvvk::DebugUtil m_debug; // Utility to name objects
// #Post // #Post
void createOffscreenRender(); void createOffscreenRender();
@ -119,42 +118,42 @@ public:
void updatePostDescriptorSet(); void updatePostDescriptorSet();
void drawPost(vk::CommandBuffer cmdBuf); void drawPost(vk::CommandBuffer cmdBuf);
std::vector<vk::DescriptorSetLayoutBinding> m_postDescSetLayoutBind; nvvk::DescriptorSetBindings m_postDescSetLayoutBind;
vk::DescriptorPool m_postDescPool; vk::DescriptorPool m_postDescPool;
vk::DescriptorSetLayout m_postDescSetLayout; vk::DescriptorSetLayout m_postDescSetLayout;
vk::DescriptorSet m_postDescSet; vk::DescriptorSet m_postDescSet;
vk::Pipeline m_postPipeline; vk::Pipeline m_postPipeline;
vk::PipelineLayout m_postPipelineLayout; vk::PipelineLayout m_postPipelineLayout;
vk::RenderPass m_offscreenRenderPass; vk::RenderPass m_offscreenRenderPass;
vk::Framebuffer m_offscreenFramebuffer; vk::Framebuffer m_offscreenFramebuffer;
nvvkTexture m_offscreenColor; nvvk::Texture m_offscreenColor;
vk::Format m_offscreenColorFormat{vk::Format::eR32G32B32A32Sfloat}; vk::Format m_offscreenColorFormat{vk::Format::eR32G32B32A32Sfloat};
nvvkTexture m_offscreenDepth; nvvk::Texture m_offscreenDepth;
vk::Format m_offscreenDepthFormat{vk::Format::eD32Sfloat}; vk::Format m_offscreenDepthFormat{vk::Format::eD32Sfloat};
// #VKRay // #VKRay
void initRayTracing(); void initRayTracing();
nvvkpp::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model); nvvk::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
void createBottomLevelAS(); void createBottomLevelAS();
void createTopLevelAS(); void createTopLevelAS();
void createRtDescriptorSet(); void createRtDescriptorSet();
void updateRtDescriptorSet(); void updateRtDescriptorSet();
void createRtPipeline(); void createRtPipeline();
void createRtShaderBindingTable(); void createRtShaderBindingTable();
void raytrace(const vk::CommandBuffer& cmdBuf, const nvmath::vec4f& clearColor); void raytrace(const vk::CommandBuffer& cmdBuf, const nvmath::vec4f& clearColor);
void resetFrame(); void resetFrame();
void updateFrame(); void updateFrame();
vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties; vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties;
nvvkpp::RaytracingBuilderKHR m_rtBuilder; nvvk::RaytracingBuilderKHR m_rtBuilder;
std::vector<vk::DescriptorSetLayoutBinding> m_rtDescSetLayoutBind; nvvk::DescriptorSetBindings m_rtDescSetLayoutBind;
vk::DescriptorPool m_rtDescPool; vk::DescriptorPool m_rtDescPool;
vk::DescriptorSetLayout m_rtDescSetLayout; vk::DescriptorSetLayout m_rtDescSetLayout;
vk::DescriptorSet m_rtDescSet; vk::DescriptorSet m_rtDescSet;
std::vector<vk::RayTracingShaderGroupCreateInfoKHR> m_rtShaderGroups; std::vector<vk::RayTracingShaderGroupCreateInfoKHR> m_rtShaderGroups;
vk::PipelineLayout m_rtPipelineLayout; vk::PipelineLayout m_rtPipelineLayout;
vk::Pipeline m_rtPipeline; vk::Pipeline m_rtPipeline;
nvvkBuffer m_rtSBTBuffer; nvvk::Buffer m_rtSBTBuffer;
int m_maxFrames{10000}; int m_maxFrames{10000};
struct RtPushConstant struct RtPushConstant

View file

@ -39,10 +39,11 @@
#include "nvh/cameramanipulator.hpp" #include "nvh/cameramanipulator.hpp"
#include "nvh/fileoperations.hpp" #include "nvh/fileoperations.hpp"
#include "nvpsystem.hpp" #include "nvpsystem.hpp"
#include "nvvkpp/appbase_vkpp.hpp" #include "nvvk/appbase_vkpp.hpp"
#include "nvvkpp/commands_vkpp.hpp" #include "nvvk/commands_vk.hpp"
#include "nvvkpp/context_vkpp.hpp" #include "nvvk/context_vk.hpp"
#include "nvvkpp/utilities_vkpp.hpp"
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
#define UNUSED(x) (void)(x) #define UNUSED(x) (void)(x)
@ -124,7 +125,7 @@ int main(int argc, char** argv)
vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature; vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature;
// Requesting Vulkan extensions and layers // Requesting Vulkan extensions and layers
nvvkpp::ContextCreateInfo contextInfo(true); nvvk::ContextCreateInfo contextInfo(true);
contextInfo.setVersion(1, 2); contextInfo.setVersion(1, 2);
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true); contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME); contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME);
@ -148,7 +149,7 @@ int main(int argc, char** argv)
contextInfo.addDeviceExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME); contextInfo.addDeviceExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
// Creating Vulkan base application // Creating Vulkan base application
nvvkpp::Context vkctx{}; nvvk::Context vkctx{};
vkctx.initInstance(contextInfo); vkctx.initInstance(contextInfo);
// Find all compatible devices // Find all compatible devices
auto compatibleDevices = vkctx.getCompatibleDevices(contextInfo); auto compatibleDevices = vkctx.getCompatibleDevices(contextInfo);
@ -163,7 +164,8 @@ int main(int argc, char** argv)
const vk::SurfaceKHR surface = helloVk.getVkSurface(vkctx.m_instance, window); const vk::SurfaceKHR surface = helloVk.getVkSurface(vkctx.m_instance, window);
vkctx.setGCTQueueWithPresent(surface); vkctx.setGCTQueueWithPresent(surface);
helloVk.setup(vkctx.m_device, vkctx.m_physicalDevice, vkctx.m_queueGCT.familyIndex); helloVk.setup(vkctx.m_instance, vkctx.m_device, vkctx.m_physicalDevice,
vkctx.m_queueGCT.familyIndex);
helloVk.createSurface(surface, SAMPLE_WIDTH, SAMPLE_HEIGHT); helloVk.createSurface(surface, SAMPLE_WIDTH, SAMPLE_HEIGHT);
helloVk.createDepthBuffer(); helloVk.createDepthBuffer();
helloVk.createRenderPass(); helloVk.createRenderPass();
@ -244,7 +246,8 @@ int main(int argc, char** argv)
// Clearing screen // Clearing screen
vk::ClearValue clearValues[2]; vk::ClearValue clearValues[2];
clearValues[0].setColor(nvvkpp::util::clearColor(clearColor)); clearValues[0].setColor(
std::array<float, 4>({clearColor[0], clearColor[1], clearColor[2], clearColor[3]}));
clearValues[1].setDepthStencil({1.0f, 0}); clearValues[1].setDepthStencil({1.0f, 0});
// Offscreen render pass // Offscreen render pass
@ -296,7 +299,6 @@ int main(int argc, char** argv)
helloVk.destroyResources(); helloVk.destroyResources();
helloVk.destroy(); helloVk.destroy();
vkctx.m_instance.destroySurfaceKHR(surface);
vkctx.deinit(); vkctx.deinit();
glfwDestroyWindow(window); glfwDestroyWindow(window);

View file

@ -6,7 +6,7 @@
#include "raycommon.glsl" #include "raycommon.glsl"
#include "wavefront.glsl" #include "wavefront.glsl"
hitAttributeEXT vec3 attribs; hitAttributeEXT vec2 attribs;
// clang-format off // clang-format off
layout(location = 0) rayPayloadInEXT hitPayload prd; layout(location = 0) rayPayloadInEXT hitPayload prd;

View file

@ -36,13 +36,14 @@ extern std::vector<std::string> defaultSearchPaths;
#include "hello_vulkan.h" #include "hello_vulkan.h"
#include "nvh//cameramanipulator.hpp" #include "nvh//cameramanipulator.hpp"
#include "nvvkpp/descriptorsets_vkpp.hpp" #include "nvvk/descriptorsets_vk.hpp"
#include "nvvkpp/pipeline_vkpp.hpp" #include "nvvk/pipeline_vk.hpp"
#include "nvh/fileoperations.hpp" #include "nvh/fileoperations.hpp"
#include "nvvkpp/commands_vkpp.hpp" #include "nvvk/commands_vk.hpp"
#include "nvvkpp/renderpass_vkpp.hpp" #include "nvvk/renderpasses_vk.hpp"
#include "nvvkpp/utilities_vkpp.hpp" #include "nvvk/shaders_vk.hpp"
// Holding the camera matrices // Holding the camera matrices
struct CameraMatrices struct CameraMatrices
@ -58,11 +59,12 @@ struct CameraMatrices
// Keep the handle on the device // Keep the handle on the device
// Initialize the tool to do all our allocations: buffers, images // Initialize the tool to do all our allocations: buffers, images
// //
void HelloVulkan::setup(const vk::Device& device, void HelloVulkan::setup(const vk::Instance& instance,
const vk::Device& device,
const vk::PhysicalDevice& physicalDevice, const vk::PhysicalDevice& physicalDevice,
uint32_t queueFamily) uint32_t queueFamily)
{ {
AppBase::setup(device, physicalDevice, queueFamily); AppBase::setup(instance, device, physicalDevice, queueFamily);
m_alloc.init(device, physicalDevice); m_alloc.init(device, physicalDevice);
m_debug.setup(m_device); m_debug.setup(m_device);
} }
@ -99,31 +101,31 @@ void HelloVulkan::createDescriptorSetLayout()
uint32_t nbObj = static_cast<uint32_t>(m_objModel.size()); uint32_t nbObj = static_cast<uint32_t>(m_objModel.size());
// Camera matrices (binding = 0) // Camera matrices (binding = 0)
m_descSetLayoutBind.emplace_back( m_descSetLayoutBind.addBinding(
vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR)); vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR));
// Materials (binding = 1) // Materials (binding = 1)
m_descSetLayoutBind.emplace_back( m_descSetLayoutBind.addBinding(
vkDS(1, vkDT::eStorageBuffer, nbObj, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR)); vkDS(1, vkDT::eStorageBuffer, nbObj, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
// Scene description (binding = 2) // Scene description (binding = 2)
m_descSetLayoutBind.emplace_back( // m_descSetLayoutBind.addBinding( //
vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR)); vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
// Textures (binding = 3) // Textures (binding = 3)
m_descSetLayoutBind.emplace_back( m_descSetLayoutBind.addBinding(
vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR)); vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR));
// Materials (binding = 4) // Materials (binding = 4)
m_descSetLayoutBind.emplace_back( m_descSetLayoutBind.addBinding(
vkDS(4, vkDT::eStorageBuffer, nbObj, vkSS::eFragment | vkSS::eClosestHitKHR)); vkDS(4, vkDT::eStorageBuffer, nbObj, vkSS::eFragment | vkSS::eClosestHitKHR));
// Storing vertices (binding = 5) // Storing vertices (binding = 5)
m_descSetLayoutBind.emplace_back( // m_descSetLayoutBind.addBinding( //
vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR)); vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
// Storing indices (binding = 6) // Storing indices (binding = 6)
m_descSetLayoutBind.emplace_back( // m_descSetLayoutBind.addBinding( //
vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR)); vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
m_descSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_descSetLayoutBind); m_descSetLayout = m_descSetLayoutBind.createLayout(m_device);
m_descPool = nvvkpp::util::createDescriptorPool(m_device, m_descSetLayoutBind, 1); m_descPool = m_descSetLayoutBind.createPool(m_device, 1);
m_descSet = nvvkpp::util::createDescriptorSet(m_device, m_descPool, m_descSetLayout); m_descSet = nvvk::allocateDescriptorSet(m_device, m_descPool, m_descSetLayout);
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -135,9 +137,9 @@ void HelloVulkan::updateDescriptorSet()
// Camera matrices and scene description // Camera matrices and scene description
vk::DescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE}; vk::DescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE};
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[0], &dbiUnif)); writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 0, &dbiUnif));
vk::DescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE}; vk::DescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[2], &dbiSceneDesc)); writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 2, &dbiSceneDesc));
// All material buffers, 1 buffer per OBJ // All material buffers, 1 buffer per OBJ
std::vector<vk::DescriptorBufferInfo> dbiMat; std::vector<vk::DescriptorBufferInfo> dbiMat;
@ -151,11 +153,10 @@ void HelloVulkan::updateDescriptorSet()
dbiVert.emplace_back(obj.vertexBuffer.buffer, 0, VK_WHOLE_SIZE); dbiVert.emplace_back(obj.vertexBuffer.buffer, 0, VK_WHOLE_SIZE);
dbiIdx.emplace_back(obj.indexBuffer.buffer, 0, VK_WHOLE_SIZE); dbiIdx.emplace_back(obj.indexBuffer.buffer, 0, VK_WHOLE_SIZE);
} }
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[1], dbiMat.data())); writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 1, dbiMat.data()));
writes.emplace_back( writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 4, dbiMatIdx.data()));
nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[4], dbiMatIdx.data())); writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 5, dbiVert.data()));
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[5], dbiVert.data())); writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 6, dbiIdx.data()));
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[6], dbiIdx.data()));
// All texture samplers // All texture samplers
std::vector<vk::DescriptorImageInfo> diit; std::vector<vk::DescriptorImageInfo> diit;
@ -163,7 +164,7 @@ void HelloVulkan::updateDescriptorSet()
{ {
diit.push_back(texture.descriptor); diit.push_back(texture.descriptor);
} }
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[3], diit.data())); writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 3, diit.data()));
// Writing the information // Writing the information
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr); m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
@ -189,19 +190,18 @@ void HelloVulkan::createGraphicsPipeline()
m_pipelineLayout = m_device.createPipelineLayout(pipelineLayoutCreateInfo); m_pipelineLayout = m_device.createPipelineLayout(pipelineLayoutCreateInfo);
// Creating the Pipeline // Creating the Pipeline
std::vector<std::string> paths = defaultSearchPaths; std::vector<std::string> paths = defaultSearchPaths;
nvvkpp::GraphicsPipelineGenerator gpb(m_device, m_pipelineLayout, m_offscreenRenderPass); nvvk::GraphicsPipelineGeneratorCombined gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
gpb.depthStencilState = {true}; gpb.depthStencilState.depthTestEnable = true;
gpb.addShader(nvh::loadFile("shaders/vert_shader.vert.spv", true, paths), vkSS::eVertex); gpb.addShader(nvh::loadFile("shaders/vert_shader.vert.spv", true, paths), vkSS::eVertex);
gpb.addShader(nvh::loadFile("shaders/frag_shader.frag.spv", true, paths), vkSS::eFragment); gpb.addShader(nvh::loadFile("shaders/frag_shader.frag.spv", true, paths), vkSS::eFragment);
gpb.vertexInputState.bindingDescriptions = {{0, sizeof(VertexObj)}}; gpb.addBindingDescription({0, sizeof(VertexObj)});
gpb.vertexInputState.attributeDescriptions = { gpb.addAttributeDescriptions({{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)}, {1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)},
{1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)}, {2, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, color)},
{2, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, color)}, {3, 0, vk::Format::eR32G32Sfloat, offsetof(VertexObj, texCoord)}});
{3, 0, vk::Format::eR32G32Sfloat, offsetof(VertexObj, texCoord)}};
m_graphicsPipeline = gpb.create(); m_graphicsPipeline = gpb.createPipeline();
m_debug.setObjectName(m_graphicsPipeline, "Graphics"); m_debug.setObjectName(m_graphicsPipeline, "Graphics");
} }
@ -234,8 +234,8 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size()); model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
// Create the buffers on Device and copy vertices, indices and materials // Create the buffers on Device and copy vertices, indices and materials
nvvkpp::SingleCommandBuffer cmdBufGet(m_device, m_graphicsQueueIndex); nvvk::CommandPool cmdBufGet(m_device, m_graphicsQueueIndex);
vk::CommandBuffer cmdBuf = cmdBufGet.createCommandBuffer(); vk::CommandBuffer cmdBuf = cmdBufGet.createCommandBuffer();
model.vertexBuffer = model.vertexBuffer =
m_alloc.createBuffer(cmdBuf, loader.m_vertices, m_alloc.createBuffer(cmdBuf, loader.m_vertices,
vkBU::eVertexBuffer | vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress); vkBU::eVertexBuffer | vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress);
@ -246,8 +246,8 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, vkBU::eStorageBuffer); model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, vkBU::eStorageBuffer);
// Creates all textures found // Creates all textures found
createTextureImages(cmdBuf, loader.m_textures); createTextureImages(cmdBuf, loader.m_textures);
cmdBufGet.flushCommandBuffer(cmdBuf); cmdBufGet.submitAndWait(cmdBuf);
m_alloc.flushStaging(); m_alloc.finalizeAndReleaseStaging();
std::string objNb = std::to_string(instance.objIndex); std::string objNb = std::to_string(instance.objIndex);
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str())); m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
@ -282,12 +282,12 @@ void HelloVulkan::createUniformBuffer()
void HelloVulkan::createSceneDescriptionBuffer() void HelloVulkan::createSceneDescriptionBuffer()
{ {
using vkBU = vk::BufferUsageFlagBits; using vkBU = vk::BufferUsageFlagBits;
nvvkpp::SingleCommandBuffer cmdGen(m_device, m_graphicsQueueIndex); nvvk::CommandPool cmdGen(m_device, m_graphicsQueueIndex);
auto cmdBuf = cmdGen.createCommandBuffer(); auto cmdBuf = cmdGen.createCommandBuffer();
m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer); m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer);
cmdGen.flushCommandBuffer(cmdBuf); cmdGen.submitAndWait(cmdBuf);
m_alloc.flushStaging(); m_alloc.finalizeAndReleaseStaging();
m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc"); m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc");
} }
@ -307,21 +307,21 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
// If no textures are present, create a dummy one to accommodate the pipeline layout // If no textures are present, create a dummy one to accommodate the pipeline layout
if(textures.empty() && m_textures.empty()) if(textures.empty() && m_textures.empty())
{ {
nvvkTexture texture; nvvk::Texture texture;
std::array<uint8_t, 4> color{255u, 255u, 255u, 255u}; std::array<uint8_t, 4> color{255u, 255u, 255u, 255u};
vk::DeviceSize bufferSize = sizeof(color); vk::DeviceSize bufferSize = sizeof(color);
auto imgSize = vk::Extent2D(1, 1); auto imgSize = vk::Extent2D(1, 1);
auto imageCreateInfo = nvvkpp::image::create2DInfo(imgSize, format); auto imageCreateInfo = nvvk::makeImage2DCreateInfo(imgSize, format);
// Creating the dummy texure
nvvk::Image image = m_alloc.createImage(cmdBuf, bufferSize, color.data(), imageCreateInfo);
vk::ImageViewCreateInfo ivInfo = nvvk::makeImageViewCreateInfo(image.image, imageCreateInfo);
texture = m_alloc.createTexture(image, ivInfo, samplerCreateInfo);
// Creating the VKImage
texture = m_alloc.createImage(cmdBuf, bufferSize, color.data(), imageCreateInfo);
// Setting up the descriptor used by the shader
texture.descriptor =
nvvkpp::image::create2DDescriptor(m_device, texture.image, samplerCreateInfo, format);
// The image format must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL // The image format must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
nvvkpp::image::setImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined, nvvk::cmdBarrierImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eShaderReadOnlyOptimal); vk::ImageLayout::eShaderReadOnlyOptimal);
m_textures.push_back(texture); m_textures.push_back(texture);
} }
else else
@ -348,16 +348,16 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4; vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4;
auto imgSize = vk::Extent2D(texWidth, texHeight); auto imgSize = vk::Extent2D(texWidth, texHeight);
auto imageCreateInfo = nvvkpp::image::create2DInfo(imgSize, format, vkIU::eSampled, true); auto imageCreateInfo = nvvk::makeImage2DCreateInfo(imgSize, format, vkIU::eSampled, true);
{ {
nvvkTexture texture; nvvk::ImageDedicated image =
texture = m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo); m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo);
nvvk::cmdGenerateMipmaps(cmdBuf, image.image, format, imgSize, imageCreateInfo.mipLevels);
vk::ImageViewCreateInfo ivInfo =
nvvk::makeImageViewCreateInfo(image.image, imageCreateInfo);
nvvk::Texture texture = m_alloc.createTexture(image, ivInfo, samplerCreateInfo);
nvvkpp::image::generateMipmaps(cmdBuf, texture.image, format, imgSize,
imageCreateInfo.mipLevels);
texture.descriptor =
nvvkpp::image::create2DDescriptor(m_device, texture.image, samplerCreateInfo, format);
m_textures.push_back(texture); m_textures.push_back(texture);
} }
} }
@ -434,7 +434,7 @@ void HelloVulkan::rasterize(const vk::CommandBuffer& cmdBuf)
cmdBuf.pushConstants<ObjPushConstant>(m_pipelineLayout, vkSS::eVertex | vkSS::eFragment, 0, cmdBuf.pushConstants<ObjPushConstant>(m_pipelineLayout, vkSS::eVertex | vkSS::eFragment, 0,
m_pushConstant); m_pushConstant);
cmdBuf.bindVertexBuffers(0, 1, &model.vertexBuffer.buffer, &offset); cmdBuf.bindVertexBuffers(0, {model.vertexBuffer.buffer}, {offset});
cmdBuf.bindIndexBuffer(model.indexBuffer.buffer, 0, vk::IndexType::eUint32); cmdBuf.bindIndexBuffer(model.indexBuffer.buffer, 0, vk::IndexType::eUint32);
cmdBuf.drawIndexed(model.nbIndices, 1, 0, 0, 0); cmdBuf.drawIndexed(model.nbIndices, 1, 0, 0, 0);
} }
@ -464,49 +464,54 @@ void HelloVulkan::createOffscreenRender()
m_alloc.destroy(m_offscreenDepth); m_alloc.destroy(m_offscreenDepth);
// Creating the color image // Creating the color image
auto colorCreateInfo = nvvkpp::image::create2DInfo(m_size, m_offscreenColorFormat, {
vk::ImageUsageFlagBits::eColorAttachment auto colorCreateInfo = nvvk::makeImage2DCreateInfo(m_size, m_offscreenColorFormat,
| vk::ImageUsageFlagBits::eSampled vk::ImageUsageFlagBits::eColorAttachment
| vk::ImageUsageFlagBits::eStorage); | vk::ImageUsageFlagBits::eSampled
m_offscreenColor = m_alloc.createImage(colorCreateInfo); | vk::ImageUsageFlagBits::eStorage);
m_offscreenColor.descriptor =
nvvkpp::image::create2DDescriptor(m_device, m_offscreenColor.image, vk::SamplerCreateInfo{}, nvvk::ImageDedicated image = m_alloc.createImage(colorCreateInfo);
m_offscreenColorFormat, vk::ImageLayout::eGeneral); vk::ImageViewCreateInfo ivInfo = nvvk::makeImageViewCreateInfo(image.image, colorCreateInfo);
m_offscreenColor = m_alloc.createTexture(image, ivInfo, vk::SamplerCreateInfo());
m_offscreenColor.descriptor.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
}
// Creating the depth buffer // Creating the depth buffer
auto depthCreateInfo = auto depthCreateInfo =
nvvkpp::image::create2DInfo(m_size, m_offscreenDepthFormat, nvvk::makeImage2DCreateInfo(m_size, m_offscreenDepthFormat,
vk::ImageUsageFlagBits::eDepthStencilAttachment); vk::ImageUsageFlagBits::eDepthStencilAttachment);
m_offscreenDepth = m_alloc.createImage(depthCreateInfo); {
nvvk::Image image = m_alloc.createImage(depthCreateInfo);
vk::ImageViewCreateInfo depthStencilView; vk::ImageViewCreateInfo depthStencilView;
depthStencilView.setViewType(vk::ImageViewType::e2D); depthStencilView.setViewType(vk::ImageViewType::e2D);
depthStencilView.setFormat(m_offscreenDepthFormat); depthStencilView.setFormat(m_offscreenDepthFormat);
depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1}); depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1});
depthStencilView.setImage(m_offscreenDepth.image); depthStencilView.setImage(image.image);
m_offscreenDepth.descriptor.imageView = m_device.createImageView(depthStencilView);
m_offscreenDepth = m_alloc.createTexture(image, depthStencilView);
}
// Setting the image layout for both color and depth // Setting the image layout for both color and depth
{ {
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex); nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
auto cmdBuf = genCmdBuf.createCommandBuffer(); auto cmdBuf = genCmdBuf.createCommandBuffer();
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined, nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eGeneral); vk::ImageLayout::eGeneral);
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageAspectFlagBits::eDepth, nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eUndefined, vk::ImageLayout::eDepthStencilAttachmentOptimal,
vk::ImageLayout::eDepthStencilAttachmentOptimal); vk::ImageAspectFlagBits::eDepth);
genCmdBuf.flushCommandBuffer(cmdBuf); genCmdBuf.submitAndWait(cmdBuf);
} }
// Creating a renderpass for the offscreen // Creating a renderpass for the offscreen
if(!m_offscreenRenderPass) if(!m_offscreenRenderPass)
{ {
m_offscreenRenderPass = m_offscreenRenderPass =
nvvkpp::util::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat, nvvk::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat, 1, true,
1, true, true, vk::ImageLayout::eGeneral, true, vk::ImageLayout::eGeneral, vk::ImageLayout::eGeneral);
vk::ImageLayout::eGeneral);
} }
// Creating the frame buffer for offscreen // Creating the frame buffer for offscreen
@ -543,13 +548,14 @@ void HelloVulkan::createPostPipeline()
// Pipeline: completely generic, no vertices // Pipeline: completely generic, no vertices
std::vector<std::string> paths = defaultSearchPaths; std::vector<std::string> paths = defaultSearchPaths;
nvvkpp::GraphicsPipelineGenerator pipelineGenerator(m_device, m_postPipelineLayout, m_renderPass); nvvk::GraphicsPipelineGeneratorCombined pipelineGenerator(m_device, m_postPipelineLayout,
m_renderPass);
pipelineGenerator.addShader(nvh::loadFile("shaders/passthrough.vert.spv", true, paths), pipelineGenerator.addShader(nvh::loadFile("shaders/passthrough.vert.spv", true, paths),
vk::ShaderStageFlagBits::eVertex); vk::ShaderStageFlagBits::eVertex);
pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths), pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths),
vk::ShaderStageFlagBits::eFragment); vk::ShaderStageFlagBits::eFragment);
pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone); pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone);
m_postPipeline = pipelineGenerator.create(); m_postPipeline = pipelineGenerator.createPipeline();
m_debug.setObjectName(m_postPipeline, "post"); m_debug.setObjectName(m_postPipeline, "post");
} }
@ -563,10 +569,10 @@ void HelloVulkan::createPostDescriptor()
using vkDT = vk::DescriptorType; using vkDT = vk::DescriptorType;
using vkSS = vk::ShaderStageFlagBits; using vkSS = vk::ShaderStageFlagBits;
m_postDescSetLayoutBind.emplace_back(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment)); m_postDescSetLayoutBind.addBinding(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
m_postDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_postDescSetLayoutBind); m_postDescSetLayout = m_postDescSetLayoutBind.createLayout(m_device);
m_postDescPool = nvvkpp::util::createDescriptorPool(m_device, m_postDescSetLayoutBind); m_postDescPool = m_postDescSetLayoutBind.createPool(m_device);
m_postDescSet = nvvkpp::util::createDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout); m_postDescSet = nvvk::allocateDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -575,8 +581,7 @@ void HelloVulkan::createPostDescriptor()
void HelloVulkan::updatePostDescriptorSet() void HelloVulkan::updatePostDescriptorSet()
{ {
vk::WriteDescriptorSet writeDescriptorSets = vk::WriteDescriptorSet writeDescriptorSets =
nvvkpp::util::createWrite(m_postDescSet, m_postDescSetLayoutBind[0], m_postDescSetLayoutBind.makeWrite(m_postDescSet, 0, &m_offscreenColor.descriptor);
&m_offscreenColor.descriptor);
m_device.updateDescriptorSets(writeDescriptorSets, nullptr); m_device.updateDescriptorSets(writeDescriptorSets, nullptr);
} }
@ -614,15 +619,15 @@ void HelloVulkan::initRayTracing()
auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2, auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2,
vk::PhysicalDeviceRayTracingPropertiesKHR>(); vk::PhysicalDeviceRayTracingPropertiesKHR>();
m_rtProperties = properties.get<vk::PhysicalDeviceRayTracingPropertiesKHR>(); m_rtProperties = properties.get<vk::PhysicalDeviceRayTracingPropertiesKHR>();
m_rtBuilder.setup(m_device, m_physicalDevice, m_graphicsQueueIndex); m_rtBuilder.setup(m_device, &m_alloc, m_graphicsQueueIndex);
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Converting a OBJ primitive to the ray tracing geometry used for the BLAS // Converting a OBJ primitive to the ray tracing geometry used for the BLAS
// //
nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model) nvvk::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model)
{ {
nvvkpp::RaytracingBuilderKHR::Blas blas; nvvk::RaytracingBuilderKHR::Blas blas;
vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate; vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate;
asCreate.setGeometryType(vk::GeometryTypeKHR::eTriangles); asCreate.setGeometryType(vk::GeometryTypeKHR::eTriangles);
asCreate.setIndexType(vk::IndexType::eUint32); asCreate.setIndexType(vk::IndexType::eUint32);
@ -659,7 +664,7 @@ nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjM
void HelloVulkan::createBottomLevelAS() void HelloVulkan::createBottomLevelAS()
{ {
// BLAS - Storing each primitive in a geometry // BLAS - Storing each primitive in a geometry
std::vector<nvvkpp::RaytracingBuilderKHR::Blas> allBlas; std::vector<nvvk::RaytracingBuilderKHR::Blas> allBlas;
allBlas.reserve(m_objModel.size()); allBlas.reserve(m_objModel.size());
for(const auto& obj : m_objModel) for(const auto& obj : m_objModel)
{ {
@ -673,16 +678,16 @@ void HelloVulkan::createBottomLevelAS()
void HelloVulkan::createTopLevelAS() void HelloVulkan::createTopLevelAS()
{ {
std::vector<nvvkpp::RaytracingBuilderKHR::Instance> tlas; std::vector<nvvk::RaytracingBuilderKHR::Instance> tlas;
tlas.reserve(m_objInstance.size()); tlas.reserve(m_objInstance.size());
for(int i = 0; i < static_cast<int>(m_objInstance.size()); i++) for(int i = 0; i < static_cast<int>(m_objInstance.size()); i++)
{ {
nvvkpp::RaytracingBuilderKHR::Instance rayInst; nvvk::RaytracingBuilderKHR::Instance rayInst;
rayInst.transform = m_objInstance[i].transform; // Position of the instance rayInst.transform = m_objInstance[i].transform; // Position of the instance
rayInst.instanceId = i; // gl_InstanceID rayInst.instanceId = i; // gl_InstanceID
rayInst.blasId = m_objInstance[i].objIndex; rayInst.blasId = m_objInstance[i].objIndex;
rayInst.hitGroupId = 0; // We will use the same hit group for all objects rayInst.hitGroupId = 0; // We will use the same hit group for all objects
rayInst.flags = vk::GeometryInstanceFlagBitsKHR::eTriangleCullDisable; rayInst.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
tlas.emplace_back(rayInst); tlas.emplace_back(rayInst);
} }
m_rtBuilder.buildTlas(tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace); m_rtBuilder.buildTlas(tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace);
@ -697,25 +702,25 @@ void HelloVulkan::createRtDescriptorSet()
using vkSS = vk::ShaderStageFlagBits; using vkSS = vk::ShaderStageFlagBits;
using vkDSLB = vk::DescriptorSetLayoutBinding; using vkDSLB = vk::DescriptorSetLayoutBinding;
m_rtDescSetLayoutBind.emplace_back(vkDSLB(0, vkDT::eAccelerationStructureKHR, 1, m_rtDescSetLayoutBind.addBinding(vkDSLB(0, vkDT::eAccelerationStructureKHR, 1,
vkSS::eRaygenKHR | vkSS::eClosestHitKHR)); // TLAS vkSS::eRaygenKHR | vkSS::eClosestHitKHR)); // TLAS
m_rtDescSetLayoutBind.emplace_back( m_rtDescSetLayoutBind.addBinding(
vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image
m_rtDescPool = nvvkpp::util::createDescriptorPool(m_device, m_rtDescSetLayoutBind); m_rtDescPool = m_rtDescSetLayoutBind.createPool(m_device);
m_rtDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_rtDescSetLayoutBind); m_rtDescSetLayout = m_rtDescSetLayoutBind.createLayout(m_device);
m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0]; m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0];
vk::AccelerationStructureKHR tlas = m_rtBuilder.getAccelerationStructure();
vk::WriteDescriptorSetAccelerationStructureKHR descASInfo; vk::WriteDescriptorSetAccelerationStructureKHR descASInfo;
descASInfo.setAccelerationStructureCount(1); descASInfo.setAccelerationStructureCount(1);
descASInfo.setPAccelerationStructures(&m_rtBuilder.getAccelerationStructure()); descASInfo.setPAccelerationStructures(&tlas);
vk::DescriptorImageInfo imageInfo{ vk::DescriptorImageInfo imageInfo{
{}, m_offscreenColor.descriptor.imageView, vk::ImageLayout::eGeneral}; {}, m_offscreenColor.descriptor.imageView, vk::ImageLayout::eGeneral};
std::vector<vk::WriteDescriptorSet> writes; std::vector<vk::WriteDescriptorSet> writes;
writes.emplace_back( writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 0, &descASInfo));
nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[0], &descASInfo)); writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 1, &imageInfo));
writes.emplace_back(nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[1], &imageInfo));
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr); m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
} }
@ -744,16 +749,17 @@ void HelloVulkan::createRtPipeline()
std::vector<std::string> paths = defaultSearchPaths; std::vector<std::string> paths = defaultSearchPaths;
vk::ShaderModule raygenSM = vk::ShaderModule raygenSM =
nvvkpp::util::createShaderModule(m_device, // nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rgen.spv", true, paths)); nvh::loadFile("shaders/raytrace.rgen.spv", true, paths));
vk::ShaderModule missSM = vk::ShaderModule missSM =
nvvkpp::util::createShaderModule(m_device, // nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths)); nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths));
// The second miss shader is invoked when a shadow ray misses the geometry. It // The second miss shader is invoked when a shadow ray misses the geometry. It
// simply indicates that no occlusion has been found // simply indicates that no occlusion has been found
vk::ShaderModule shadowmissSM = nvvkpp::util::createShaderModule( vk::ShaderModule shadowmissSM =
m_device, nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths)); nvvk::createShaderModule(m_device,
nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
std::vector<vk::PipelineShaderStageCreateInfo> stages; std::vector<vk::PipelineShaderStageCreateInfo> stages;
@ -779,8 +785,8 @@ void HelloVulkan::createRtPipeline()
// Hit Group - Closest Hit + AnyHit // Hit Group - Closest Hit + AnyHit
vk::ShaderModule chitSM = vk::ShaderModule chitSM =
nvvkpp::util::createShaderModule(m_device, // nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rchit.spv", true, paths)); nvh::loadFile("shaders/raytrace.rchit.spv", true, paths));
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup, vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup,
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR,
@ -795,14 +801,13 @@ void HelloVulkan::createRtPipeline()
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR}; VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR};
vk::ShaderModule call0 = vk::ShaderModule call0 =
nvvkpp::util::createShaderModule(m_device, nvvk::createShaderModule(m_device,
nvh::loadFile("shaders/light_point.rcall.spv", true, paths)); nvh::loadFile("shaders/light_point.rcall.spv", true, paths));
vk::ShaderModule call1 = vk::ShaderModule call1 =
nvvkpp::util::createShaderModule(m_device, nvvk::createShaderModule(m_device,
nvh::loadFile("shaders/light_spot.rcall.spv", true, paths)); nvh::loadFile("shaders/light_spot.rcall.spv", true, paths));
vk::ShaderModule call2 = vk::ShaderModule call2 =
nvvkpp::util::createShaderModule(m_device, nvvk::createShaderModule(m_device, nvh::loadFile("shaders/light_inf.rcall.spv", true, paths));
nvh::loadFile("shaders/light_inf.rcall.spv", true, paths));
stages.push_back({{}, vk::ShaderStageFlagBits::eCallableKHR, call0, "main"}); stages.push_back({{}, vk::ShaderStageFlagBits::eCallableKHR, call0, "main"});
callGroup.setGeneralShader(static_cast<uint32_t>(stages.size() - 1)); callGroup.setGeneralShader(static_cast<uint32_t>(stages.size() - 1));
@ -874,17 +879,17 @@ void HelloVulkan::createRtShaderBindingTable()
m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize, m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize,
shaderHandleStorage.data()); shaderHandleStorage.data());
// Write the handles in the SBT // Write the handles in the SBT
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex); nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer(); vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
m_rtSBTBuffer = m_rtSBTBuffer =
m_alloc.createBuffer(cmdBuf, shaderHandleStorage, vk::BufferUsageFlagBits::eRayTracingKHR); m_alloc.createBuffer(cmdBuf, shaderHandleStorage, vk::BufferUsageFlagBits::eRayTracingKHR);
m_debug.setObjectName(m_rtSBTBuffer.buffer, "SBT"); m_debug.setObjectName(m_rtSBTBuffer.buffer, "SBT");
genCmdBuf.flushCommandBuffer(cmdBuf); genCmdBuf.submitAndWait(cmdBuf);
m_alloc.flushStaging(); m_alloc.finalizeAndReleaseStaging();
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------

View file

@ -26,16 +26,15 @@
*/ */
#pragma once #pragma once
#include "nvvkpp/allocator_dedicated_vkpp.hpp" #define NVVK_ALLOC_DEDICATED
#include "nvvkpp/appbase_vkpp.hpp" #include "nvvk/allocator_vk.hpp"
#include "nvvkpp/debug_util_vkpp.hpp" #include "nvvk/appbase_vkpp.hpp"
#include "nvvk/debug_util_vk.hpp"
#include "nvvk/descriptorsets_vk.hpp"
// #VKRay // #VKRay
#define ALLOC_DEDICATED #include "nvvk/raytraceKHR_vk.hpp"
#include "nvvkpp/raytraceKHR_vkpp.hpp"
using nvvkBuffer = nvvkpp::BufferDedicated;
using nvvkTexture = nvvkpp::TextureDedicated;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Simple rasterizer of OBJ objects // Simple rasterizer of OBJ objects
@ -44,10 +43,11 @@ using nvvkTexture = nvvkpp::TextureDedicated;
// - Rendering is done in an offscreen framebuffer // - Rendering is done in an offscreen framebuffer
// - The image of the framebuffer is displayed in post-process in a full-screen quad // - The image of the framebuffer is displayed in post-process in a full-screen quad
// //
class HelloVulkan : public nvvkpp::AppBase class HelloVulkan : public nvvk::AppBase
{ {
public: public:
void setup(const vk::Device& device, void setup(const vk::Instance& instance,
const vk::Device& device,
const vk::PhysicalDevice& physicalDevice, const vk::PhysicalDevice& physicalDevice,
uint32_t queueFamily) override; uint32_t queueFamily) override;
void createDescriptorSetLayout(); void createDescriptorSetLayout();
@ -66,12 +66,12 @@ public:
// The OBJ model // The OBJ model
struct ObjModel struct ObjModel
{ {
uint32_t nbIndices{0}; uint32_t nbIndices{0};
uint32_t nbVertices{0}; uint32_t nbVertices{0};
nvvkBuffer vertexBuffer; // Device buffer of all 'Vertex' nvvk::Buffer vertexBuffer; // Device buffer of all 'Vertex'
nvvkBuffer indexBuffer; // Device buffer of the indices forming triangles nvvk::Buffer indexBuffer; // Device buffer of the indices forming triangles
nvvkBuffer matColorBuffer; // Device buffer of array of 'Wavefront material' nvvk::Buffer matColorBuffer; // Device buffer of array of 'Wavefront material'
nvvkBuffer matIndexBuffer; // Device buffer of array of 'Wavefront material' nvvk::Buffer matIndexBuffer; // Device buffer of array of 'Wavefront material'
}; };
// Instance of the OBJ // Instance of the OBJ
@ -101,19 +101,19 @@ public:
std::vector<ObjInstance> m_objInstance; std::vector<ObjInstance> m_objInstance;
// Graphic pipeline // Graphic pipeline
vk::PipelineLayout m_pipelineLayout; vk::PipelineLayout m_pipelineLayout;
vk::Pipeline m_graphicsPipeline; vk::Pipeline m_graphicsPipeline;
std::vector<vk::DescriptorSetLayoutBinding> m_descSetLayoutBind; nvvk::DescriptorSetBindings m_descSetLayoutBind;
vk::DescriptorPool m_descPool; vk::DescriptorPool m_descPool;
vk::DescriptorSetLayout m_descSetLayout; vk::DescriptorSetLayout m_descSetLayout;
vk::DescriptorSet m_descSet; vk::DescriptorSet m_descSet;
nvvkBuffer m_cameraMat; // Device-Host of the camera matrices nvvk::Buffer m_cameraMat; // Device-Host of the camera matrices
nvvkBuffer m_sceneDesc; // Device buffer of the OBJ instances nvvk::Buffer m_sceneDesc; // Device buffer of the OBJ instances
std::vector<nvvkTexture> m_textures; // vector of all textures of the scene std::vector<nvvk::Texture> m_textures; // vector of all textures of the scene
nvvkpp::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures nvvk::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures
nvvkpp::DebugUtil m_debug; // Utility to name objects nvvk::DebugUtil m_debug; // Utility to name objects
// #Post // #Post
void createOffscreenRender(); void createOffscreenRender();
@ -122,41 +122,41 @@ public:
void updatePostDescriptorSet(); void updatePostDescriptorSet();
void drawPost(vk::CommandBuffer cmdBuf); void drawPost(vk::CommandBuffer cmdBuf);
std::vector<vk::DescriptorSetLayoutBinding> m_postDescSetLayoutBind; nvvk::DescriptorSetBindings m_postDescSetLayoutBind;
vk::DescriptorPool m_postDescPool; vk::DescriptorPool m_postDescPool;
vk::DescriptorSetLayout m_postDescSetLayout; vk::DescriptorSetLayout m_postDescSetLayout;
vk::DescriptorSet m_postDescSet; vk::DescriptorSet m_postDescSet;
vk::Pipeline m_postPipeline; vk::Pipeline m_postPipeline;
vk::PipelineLayout m_postPipelineLayout; vk::PipelineLayout m_postPipelineLayout;
vk::RenderPass m_offscreenRenderPass; vk::RenderPass m_offscreenRenderPass;
vk::Framebuffer m_offscreenFramebuffer; vk::Framebuffer m_offscreenFramebuffer;
nvvkTexture m_offscreenColor; nvvk::Texture m_offscreenColor;
vk::Format m_offscreenColorFormat{vk::Format::eR32G32B32A32Sfloat}; vk::Format m_offscreenColorFormat{vk::Format::eR32G32B32A32Sfloat};
nvvkTexture m_offscreenDepth; nvvk::Texture m_offscreenDepth;
vk::Format m_offscreenDepthFormat{vk::Format::eD32Sfloat}; vk::Format m_offscreenDepthFormat{vk::Format::eD32Sfloat};
// #VKRay // #VKRay
void initRayTracing(); void initRayTracing();
nvvkpp::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model); nvvk::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
void createBottomLevelAS(); void createBottomLevelAS();
void createTopLevelAS(); void createTopLevelAS();
void createRtDescriptorSet(); void createRtDescriptorSet();
void updateRtDescriptorSet(); void updateRtDescriptorSet();
void createRtPipeline(); void createRtPipeline();
void createRtShaderBindingTable(); void createRtShaderBindingTable();
void raytrace(const vk::CommandBuffer& cmdBuf, const nvmath::vec4f& clearColor); void raytrace(const vk::CommandBuffer& cmdBuf, const nvmath::vec4f& clearColor);
vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties; vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties;
nvvkpp::RaytracingBuilderKHR m_rtBuilder; nvvk::RaytracingBuilderKHR m_rtBuilder;
std::vector<vk::DescriptorSetLayoutBinding> m_rtDescSetLayoutBind; nvvk::DescriptorSetBindings m_rtDescSetLayoutBind;
vk::DescriptorPool m_rtDescPool; vk::DescriptorPool m_rtDescPool;
vk::DescriptorSetLayout m_rtDescSetLayout; vk::DescriptorSetLayout m_rtDescSetLayout;
vk::DescriptorSet m_rtDescSet; vk::DescriptorSet m_rtDescSet;
std::vector<vk::RayTracingShaderGroupCreateInfoKHR> m_rtShaderGroups; std::vector<vk::RayTracingShaderGroupCreateInfoKHR> m_rtShaderGroups;
vk::PipelineLayout m_rtPipelineLayout; vk::PipelineLayout m_rtPipelineLayout;
vk::Pipeline m_rtPipeline; vk::Pipeline m_rtPipeline;
nvvkBuffer m_rtSBTBuffer; nvvk::Buffer m_rtSBTBuffer;
struct RtPushConstant struct RtPushConstant
{ {

View file

@ -31,6 +31,7 @@
#include <array> #include <array>
#include <vulkan/vulkan.hpp> #include <vulkan/vulkan.hpp>
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
#include "imgui.h" #include "imgui.h"
#include "imgui_impl_glfw.h" #include "imgui_impl_glfw.h"
@ -39,10 +40,10 @@
#include "nvh/cameramanipulator.hpp" #include "nvh/cameramanipulator.hpp"
#include "nvh/fileoperations.hpp" #include "nvh/fileoperations.hpp"
#include "nvpsystem.hpp" #include "nvpsystem.hpp"
#include "nvvkpp/appbase_vkpp.hpp" #include "nvvk/appbase_vkpp.hpp"
#include "nvvkpp/commands_vkpp.hpp" #include "nvvk/commands_vk.hpp"
#include "nvvkpp/context_vkpp.hpp" #include "nvvk/context_vk.hpp"
#include "nvvkpp/utilities_vkpp.hpp"
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
#define UNUSED(x) (void)(x) #define UNUSED(x) (void)(x)
@ -141,7 +142,7 @@ int main(int argc, char** argv)
vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature; vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature;
// Requesting Vulkan extensions and layers // Requesting Vulkan extensions and layers
nvvkpp::ContextCreateInfo contextInfo(true); nvvk::ContextCreateInfo contextInfo(true);
contextInfo.setVersion(1, 2); contextInfo.setVersion(1, 2);
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true); contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME); contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME);
@ -165,7 +166,7 @@ int main(int argc, char** argv)
contextInfo.addDeviceExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME); contextInfo.addDeviceExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
// Creating Vulkan base application // Creating Vulkan base application
nvvkpp::Context vkctx{}; nvvk::Context vkctx{};
vkctx.initInstance(contextInfo); vkctx.initInstance(contextInfo);
// Find all compatible devices // Find all compatible devices
auto compatibleDevices = vkctx.getCompatibleDevices(contextInfo); auto compatibleDevices = vkctx.getCompatibleDevices(contextInfo);
@ -180,7 +181,8 @@ int main(int argc, char** argv)
const vk::SurfaceKHR surface = helloVk.getVkSurface(vkctx.m_instance, window); const vk::SurfaceKHR surface = helloVk.getVkSurface(vkctx.m_instance, window);
vkctx.setGCTQueueWithPresent(surface); vkctx.setGCTQueueWithPresent(surface);
helloVk.setup(vkctx.m_device, vkctx.m_physicalDevice, vkctx.m_queueGCT.familyIndex); helloVk.setup(vkctx.m_instance, vkctx.m_device, vkctx.m_physicalDevice,
vkctx.m_queueGCT.familyIndex);
helloVk.createSurface(surface, SAMPLE_WIDTH, SAMPLE_HEIGHT); helloVk.createSurface(surface, SAMPLE_WIDTH, SAMPLE_HEIGHT);
helloVk.createDepthBuffer(); helloVk.createDepthBuffer();
helloVk.createRenderPass(); helloVk.createRenderPass();
@ -258,7 +260,8 @@ int main(int argc, char** argv)
// Clearing screen // Clearing screen
vk::ClearValue clearValues[2]; vk::ClearValue clearValues[2];
clearValues[0].setColor(nvvkpp::util::clearColor(clearColor)); clearValues[0].setColor(
std::array<float, 4>({clearColor[0], clearColor[1], clearColor[2], clearColor[3]}));
clearValues[1].setDepthStencil({1.0f, 0}); clearValues[1].setDepthStencil({1.0f, 0});
// Offscreen render pass // Offscreen render pass
@ -310,7 +313,6 @@ int main(int argc, char** argv)
helloVk.destroyResources(); helloVk.destroyResources();
helloVk.destroy(); helloVk.destroy();
vkctx.m_instance.destroySurfaceKHR(surface);
vkctx.deinit(); vkctx.deinit();
glfwDestroyWindow(window); glfwDestroyWindow(window);

View file

@ -6,7 +6,7 @@
#include "raycommon.glsl" #include "raycommon.glsl"
#include "wavefront.glsl" #include "wavefront.glsl"
hitAttributeEXT vec3 attribs; hitAttributeEXT vec2 attribs;
// clang-format off // clang-format off
layout(location = 0) rayPayloadInEXT hitPayload prd; layout(location = 0) rayPayloadInEXT hitPayload prd;

View file

@ -38,13 +38,14 @@ extern std::vector<std::string> defaultSearchPaths;
#include "hello_vulkan.h" #include "hello_vulkan.h"
#include "nvh//cameramanipulator.hpp" #include "nvh//cameramanipulator.hpp"
#include "nvvkpp/descriptorsets_vkpp.hpp" #include "nvvk/descriptorsets_vk.hpp"
#include "nvvkpp/pipeline_vkpp.hpp" #include "nvvk/pipeline_vk.hpp"
#include "nvh/fileoperations.hpp" #include "nvh/fileoperations.hpp"
#include "nvvkpp/commands_vkpp.hpp" #include "nvvk/commands_vk.hpp"
#include "nvvkpp/renderpass_vkpp.hpp" #include "nvvk/renderpasses_vk.hpp"
#include "nvvkpp/utilities_vkpp.hpp" #include "nvvk/shaders_vk.hpp"
// Holding the camera matrices // Holding the camera matrices
struct CameraMatrices struct CameraMatrices
@ -60,25 +61,26 @@ struct CameraMatrices
// Keep the handle on the device // Keep the handle on the device
// Initialize the tool to do all our allocations: buffers, images // Initialize the tool to do all our allocations: buffers, images
// //
void HelloVulkan::setup(const vk::Device& device, void HelloVulkan::setup(const vk::Instance& instance,
const vk::Device& device,
const vk::PhysicalDevice& physicalDevice, const vk::PhysicalDevice& physicalDevice,
uint32_t queueFamily) uint32_t queueFamily)
{ {
AppBase::setup(device, physicalDevice, queueFamily); AppBase::setup(instance, device, physicalDevice, queueFamily);
#if defined(ALLOC_DEDICATED) #if defined(NVVK_ALLOC_DEDICATED)
m_alloc.init(device, physicalDevice); m_alloc.init(device, physicalDevice);
#elif defined(ALLOC_DMA) #elif defined(NVVK_ALLOC_DMA)
m_memAllocator.init(device, physicalDevice); m_memAllocator.init(device, physicalDevice);
m_memAllocator.setAllocateFlags(VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR, true); m_memAllocator.setAllocateFlags(VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT, true);
m_alloc.init(device, &m_memAllocator); m_alloc.init(device, physicalDevice, &m_memAllocator);
#elif defined(ALLOC_VMA) #elif defined(NVVK_ALLOC_VMA)
VmaAllocatorCreateInfo allocatorInfo = {}; VmaAllocatorCreateInfo allocatorInfo = {};
allocatorInfo.instance = instance;
allocatorInfo.physicalDevice = physicalDevice; allocatorInfo.physicalDevice = physicalDevice;
allocatorInfo.device = device; allocatorInfo.device = device;
allocatorInfo.flags |= allocatorInfo.flags = VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT;
VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT | VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT;
vmaCreateAllocator(&allocatorInfo, &m_memAllocator); vmaCreateAllocator(&allocatorInfo, &m_memAllocator);
m_alloc.init(device, m_memAllocator); m_alloc.init(device, physicalDevice, m_memAllocator);
#endif #endif
m_debug.setup(m_device); m_debug.setup(m_device);
} }
@ -98,20 +100,9 @@ void HelloVulkan::updateUniformBuffer()
// #VKRay // #VKRay
ubo.projInverse = nvmath::invert(ubo.proj); ubo.projInverse = nvmath::invert(ubo.proj);
#if defined(ALLOC_DEDICATED) void* data = m_alloc.map(m_cameraMat);
void* data = m_device.mapMemory(m_cameraMat.allocation, 0, sizeof(CameraMatrices));
memcpy(data, &ubo, sizeof(ubo)); memcpy(data, &ubo, sizeof(ubo));
m_device.unmapMemory(m_cameraMat.allocation); m_alloc.unmap(m_cameraMat);
#elif defined(ALLOC_DMA)
void* data = m_memAllocator.map(m_cameraMat.allocation);
memcpy(data, &ubo, sizeof(ubo));
m_memAllocator.unmap(m_cameraMat.allocation);
#elif defined(ALLOC_VMA)
void* data;
vmaMapMemory(m_memAllocator, m_cameraMat.allocation, &data);
memcpy(data, &ubo, sizeof(ubo));
vmaUnmapMemory(m_memAllocator, m_cameraMat.allocation);
#endif
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -126,31 +117,31 @@ void HelloVulkan::createDescriptorSetLayout()
uint32_t nbObj = static_cast<uint32_t>(m_objModel.size()); uint32_t nbObj = static_cast<uint32_t>(m_objModel.size());
// Camera matrices (binding = 0) // Camera matrices (binding = 0)
m_descSetLayoutBind.emplace_back( m_descSetLayoutBind.addBinding(
vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR)); vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR));
// Materials (binding = 1) // Materials (binding = 1)
m_descSetLayoutBind.emplace_back( m_descSetLayoutBind.addBinding(
vkDS(1, vkDT::eStorageBuffer, nbObj, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR)); vkDS(1, vkDT::eStorageBuffer, nbObj, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
// Scene description (binding = 2) // Scene description (binding = 2)
m_descSetLayoutBind.emplace_back( // m_descSetLayoutBind.addBinding( //
vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR)); vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
// Textures (binding = 3) // Textures (binding = 3)
m_descSetLayoutBind.emplace_back( m_descSetLayoutBind.addBinding(
vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR)); vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR));
// Materials (binding = 4) // Materials (binding = 4)
m_descSetLayoutBind.emplace_back( m_descSetLayoutBind.addBinding(
vkDS(4, vkDT::eStorageBuffer, nbObj, vkSS::eFragment | vkSS::eClosestHitKHR)); vkDS(4, vkDT::eStorageBuffer, nbObj, vkSS::eFragment | vkSS::eClosestHitKHR));
// Storing vertices (binding = 5) // Storing vertices (binding = 5)
m_descSetLayoutBind.emplace_back( // m_descSetLayoutBind.addBinding( //
vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR)); vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
// Storing indices (binding = 6) // Storing indices (binding = 6)
m_descSetLayoutBind.emplace_back( // m_descSetLayoutBind.addBinding( //
vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR)); vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
m_descSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_descSetLayoutBind); m_descSetLayout = m_descSetLayoutBind.createLayout(m_device);
m_descPool = nvvkpp::util::createDescriptorPool(m_device, m_descSetLayoutBind, 1); m_descPool = m_descSetLayoutBind.createPool(m_device, 1);
m_descSet = nvvkpp::util::createDescriptorSet(m_device, m_descPool, m_descSetLayout); m_descSet = nvvk::allocateDescriptorSet(m_device, m_descPool, m_descSetLayout);
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -162,9 +153,9 @@ void HelloVulkan::updateDescriptorSet()
// Camera matrices and scene description // Camera matrices and scene description
vk::DescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE}; vk::DescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE};
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[0], &dbiUnif)); writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 0, &dbiUnif));
vk::DescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE}; vk::DescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[2], &dbiSceneDesc)); writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 2, &dbiSceneDesc));
// All material buffers, 1 buffer per OBJ // All material buffers, 1 buffer per OBJ
std::vector<vk::DescriptorBufferInfo> dbiMat; std::vector<vk::DescriptorBufferInfo> dbiMat;
@ -178,11 +169,10 @@ void HelloVulkan::updateDescriptorSet()
dbiVert.emplace_back(obj.vertexBuffer.buffer, 0, VK_WHOLE_SIZE); dbiVert.emplace_back(obj.vertexBuffer.buffer, 0, VK_WHOLE_SIZE);
dbiIdx.emplace_back(obj.indexBuffer.buffer, 0, VK_WHOLE_SIZE); dbiIdx.emplace_back(obj.indexBuffer.buffer, 0, VK_WHOLE_SIZE);
} }
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[1], dbiMat.data())); writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 1, dbiMat.data()));
writes.emplace_back( writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 4, dbiMatIdx.data()));
nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[4], dbiMatIdx.data())); writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 5, dbiVert.data()));
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[5], dbiVert.data())); writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 6, dbiIdx.data()));
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[6], dbiIdx.data()));
// All texture samplers // All texture samplers
std::vector<vk::DescriptorImageInfo> diit; std::vector<vk::DescriptorImageInfo> diit;
@ -190,7 +180,7 @@ void HelloVulkan::updateDescriptorSet()
{ {
diit.push_back(texture.descriptor); diit.push_back(texture.descriptor);
} }
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[3], diit.data())); writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 3, diit.data()));
// Writing the information // Writing the information
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr); m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
@ -216,19 +206,18 @@ void HelloVulkan::createGraphicsPipeline()
m_pipelineLayout = m_device.createPipelineLayout(pipelineLayoutCreateInfo); m_pipelineLayout = m_device.createPipelineLayout(pipelineLayoutCreateInfo);
// Creating the Pipeline // Creating the Pipeline
std::vector<std::string> paths = defaultSearchPaths; std::vector<std::string> paths = defaultSearchPaths;
nvvkpp::GraphicsPipelineGenerator gpb(m_device, m_pipelineLayout, m_offscreenRenderPass); nvvk::GraphicsPipelineGeneratorCombined gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
gpb.depthStencilState = {true}; gpb.depthStencilState.depthTestEnable = true;
gpb.addShader(nvh::loadFile("shaders/vert_shader.vert.spv", true, paths), vkSS::eVertex); gpb.addShader(nvh::loadFile("shaders/vert_shader.vert.spv", true, paths), vkSS::eVertex);
gpb.addShader(nvh::loadFile("shaders/frag_shader.frag.spv", true, paths), vkSS::eFragment); gpb.addShader(nvh::loadFile("shaders/frag_shader.frag.spv", true, paths), vkSS::eFragment);
gpb.vertexInputState.bindingDescriptions = {{0, sizeof(VertexObj)}}; gpb.addBindingDescription({0, sizeof(VertexObj)});
gpb.vertexInputState.attributeDescriptions = { gpb.addAttributeDescriptions({{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)}, {1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)},
{1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)}, {2, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, color)},
{2, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, color)}, {3, 0, vk::Format::eR32G32Sfloat, offsetof(VertexObj, texCoord)}});
{3, 0, vk::Format::eR32G32Sfloat, offsetof(VertexObj, texCoord)}};
m_graphicsPipeline = gpb.create(); m_graphicsPipeline = gpb.createPipeline();
m_debug.setObjectName(m_graphicsPipeline, "Graphics"); m_debug.setObjectName(m_graphicsPipeline, "Graphics");
} }
@ -261,8 +250,8 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size()); model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
// Create the buffers on Device and copy vertices, indices and materials // Create the buffers on Device and copy vertices, indices and materials
nvvkpp::SingleCommandBuffer cmdBufGet(m_device, m_graphicsQueueIndex); nvvk::CommandPool cmdBufGet(m_device, m_graphicsQueueIndex);
vk::CommandBuffer cmdBuf = cmdBufGet.createCommandBuffer(); vk::CommandBuffer cmdBuf = cmdBufGet.createCommandBuffer();
model.vertexBuffer = model.vertexBuffer =
m_alloc.createBuffer(cmdBuf, loader.m_vertices, m_alloc.createBuffer(cmdBuf, loader.m_vertices,
vkBU::eVertexBuffer | vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress); vkBU::eVertexBuffer | vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress);
@ -273,8 +262,8 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, vkBU::eStorageBuffer); model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, vkBU::eStorageBuffer);
// Creates all textures found // Creates all textures found
createTextureImages(cmdBuf, loader.m_textures); createTextureImages(cmdBuf, loader.m_textures);
cmdBufGet.flushCommandBuffer(cmdBuf); cmdBufGet.submitAndWait(cmdBuf);
m_alloc.flushStaging(); m_alloc.finalizeAndReleaseStaging();
std::string objNb = std::to_string(instance.objIndex); std::string objNb = std::to_string(instance.objIndex);
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str())); m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
@ -296,12 +285,7 @@ void HelloVulkan::createUniformBuffer()
using vkMP = vk::MemoryPropertyFlagBits; using vkMP = vk::MemoryPropertyFlagBits;
m_cameraMat = m_alloc.createBuffer(sizeof(CameraMatrices), vkBU::eUniformBuffer, m_cameraMat = m_alloc.createBuffer(sizeof(CameraMatrices), vkBU::eUniformBuffer,
#if defined(ALLOC_DEDICATED) || defined(ALLOC_DMA) vkMP::eHostVisible | vkMP::eHostCoherent);
vkMP::eHostVisible | vkMP::eHostCoherent
#elif defined(ALLOC_VMA)
VMA_MEMORY_USAGE_CPU_TO_GPU
#endif
);
m_debug.setObjectName(m_cameraMat.buffer, "cameraMat"); m_debug.setObjectName(m_cameraMat.buffer, "cameraMat");
} }
@ -314,12 +298,12 @@ void HelloVulkan::createUniformBuffer()
void HelloVulkan::createSceneDescriptionBuffer() void HelloVulkan::createSceneDescriptionBuffer()
{ {
using vkBU = vk::BufferUsageFlagBits; using vkBU = vk::BufferUsageFlagBits;
nvvkpp::SingleCommandBuffer cmdGen(m_device, m_graphicsQueueIndex); nvvk::CommandPool cmdGen(m_device, m_graphicsQueueIndex);
auto cmdBuf = cmdGen.createCommandBuffer(); auto cmdBuf = cmdGen.createCommandBuffer();
m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer); m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer);
cmdGen.flushCommandBuffer(cmdBuf); cmdGen.submitAndWait(cmdBuf);
m_alloc.flushStaging(); m_alloc.finalizeAndReleaseStaging();
m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc"); m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc");
} }
@ -339,21 +323,21 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
// If no textures are present, create a dummy one to accommodate the pipeline layout // If no textures are present, create a dummy one to accommodate the pipeline layout
if(textures.empty() && m_textures.empty()) if(textures.empty() && m_textures.empty())
{ {
nvvkTexture texture; nvvk::Texture texture;
std::array<uint8_t, 4> color{255u, 255u, 255u, 255u}; std::array<uint8_t, 4> color{255u, 255u, 255u, 255u};
vk::DeviceSize bufferSize = sizeof(color); vk::DeviceSize bufferSize = sizeof(color);
auto imgSize = vk::Extent2D(1, 1); auto imgSize = vk::Extent2D(1, 1);
auto imageCreateInfo = nvvkpp::image::create2DInfo(imgSize, format); auto imageCreateInfo = nvvk::makeImage2DCreateInfo(imgSize, format);
// Creating the dummy texure
nvvk::Image image = m_alloc.createImage(cmdBuf, bufferSize, color.data(), imageCreateInfo);
vk::ImageViewCreateInfo ivInfo = nvvk::makeImageViewCreateInfo(image.image, imageCreateInfo);
texture = m_alloc.createTexture(image, ivInfo, samplerCreateInfo);
// Creating the VKImage
texture = m_alloc.createImage(cmdBuf, bufferSize, color.data(), imageCreateInfo);
// Setting up the descriptor used by the shader
texture.descriptor =
nvvkpp::image::create2DDescriptor(m_device, texture.image, samplerCreateInfo, format);
// The image format must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL // The image format must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
nvvkpp::image::setImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined, nvvk::cmdBarrierImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eShaderReadOnlyOptimal); vk::ImageLayout::eShaderReadOnlyOptimal);
m_textures.push_back(texture); m_textures.push_back(texture);
} }
else else
@ -380,16 +364,15 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4; vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4;
auto imgSize = vk::Extent2D(texWidth, texHeight); auto imgSize = vk::Extent2D(texWidth, texHeight);
auto imageCreateInfo = nvvkpp::image::create2DInfo(imgSize, format, vkIU::eSampled, true); auto imageCreateInfo = nvvk::makeImage2DCreateInfo(imgSize, format, vkIU::eSampled, true);
{ {
nvvkTexture texture; nvvk::Image image = m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo);
texture = m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo); nvvk::cmdGenerateMipmaps(cmdBuf, image.image, format, imgSize, imageCreateInfo.mipLevels);
vk::ImageViewCreateInfo ivInfo =
nvvk::makeImageViewCreateInfo(image.image, imageCreateInfo);
nvvk::Texture texture = m_alloc.createTexture(image, ivInfo, samplerCreateInfo);
nvvkpp::image::generateMipmaps(cmdBuf, texture.image, format, imgSize,
imageCreateInfo.mipLevels);
texture.descriptor =
nvvkpp::image::create2DDescriptor(m_device, texture.image, samplerCreateInfo, format);
m_textures.push_back(texture); m_textures.push_back(texture);
} }
} }
@ -439,9 +422,10 @@ void HelloVulkan::destroyResources()
m_device.destroy(m_rtPipelineLayout); m_device.destroy(m_rtPipelineLayout);
m_alloc.destroy(m_rtSBTBuffer); m_alloc.destroy(m_rtSBTBuffer);
#if defined(ALLOC_DMA) m_alloc.deinit();
#if defined(NVVK_ALLOC_DMA)
m_memAllocator.deinit(); m_memAllocator.deinit();
#elif defined(ALLOC_VMA) #elif defined(NVVK_ALLOC_VMA)
vmaDestroyAllocator(m_memAllocator); vmaDestroyAllocator(m_memAllocator);
#endif #endif
} }
@ -472,7 +456,7 @@ void HelloVulkan::rasterize(const vk::CommandBuffer& cmdBuf)
cmdBuf.pushConstants<ObjPushConstant>(m_pipelineLayout, vkSS::eVertex | vkSS::eFragment, 0, cmdBuf.pushConstants<ObjPushConstant>(m_pipelineLayout, vkSS::eVertex | vkSS::eFragment, 0,
m_pushConstant); m_pushConstant);
cmdBuf.bindVertexBuffers(0, 1, &model.vertexBuffer.buffer, &offset); cmdBuf.bindVertexBuffers(0, {model.vertexBuffer.buffer}, {offset});
cmdBuf.bindIndexBuffer(model.indexBuffer.buffer, 0, vk::IndexType::eUint32); cmdBuf.bindIndexBuffer(model.indexBuffer.buffer, 0, vk::IndexType::eUint32);
cmdBuf.drawIndexed(model.nbIndices, 1, 0, 0, 0); cmdBuf.drawIndexed(model.nbIndices, 1, 0, 0, 0);
} }
@ -502,49 +486,54 @@ void HelloVulkan::createOffscreenRender()
m_alloc.destroy(m_offscreenDepth); m_alloc.destroy(m_offscreenDepth);
// Creating the color image // Creating the color image
auto colorCreateInfo = nvvkpp::image::create2DInfo(m_size, m_offscreenColorFormat, {
vk::ImageUsageFlagBits::eColorAttachment auto colorCreateInfo = nvvk::makeImage2DCreateInfo(m_size, m_offscreenColorFormat,
| vk::ImageUsageFlagBits::eSampled vk::ImageUsageFlagBits::eColorAttachment
| vk::ImageUsageFlagBits::eStorage); | vk::ImageUsageFlagBits::eSampled
m_offscreenColor = m_alloc.createImage(colorCreateInfo); | vk::ImageUsageFlagBits::eStorage);
m_offscreenColor.descriptor =
nvvkpp::image::create2DDescriptor(m_device, m_offscreenColor.image, vk::SamplerCreateInfo{}, nvvk::Image image = m_alloc.createImage(colorCreateInfo);
m_offscreenColorFormat, vk::ImageLayout::eGeneral); vk::ImageViewCreateInfo ivInfo = nvvk::makeImageViewCreateInfo(image.image, colorCreateInfo);
m_offscreenColor = m_alloc.createTexture(image, ivInfo, vk::SamplerCreateInfo());
m_offscreenColor.descriptor.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
}
// Creating the depth buffer // Creating the depth buffer
auto depthCreateInfo = auto depthCreateInfo =
nvvkpp::image::create2DInfo(m_size, m_offscreenDepthFormat, nvvk::makeImage2DCreateInfo(m_size, m_offscreenDepthFormat,
vk::ImageUsageFlagBits::eDepthStencilAttachment); vk::ImageUsageFlagBits::eDepthStencilAttachment);
m_offscreenDepth = m_alloc.createImage(depthCreateInfo); {
nvvk::Image image = m_alloc.createImage(depthCreateInfo);
vk::ImageViewCreateInfo depthStencilView; vk::ImageViewCreateInfo depthStencilView;
depthStencilView.setViewType(vk::ImageViewType::e2D); depthStencilView.setViewType(vk::ImageViewType::e2D);
depthStencilView.setFormat(m_offscreenDepthFormat); depthStencilView.setFormat(m_offscreenDepthFormat);
depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1}); depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1});
depthStencilView.setImage(m_offscreenDepth.image); depthStencilView.setImage(image.image);
m_offscreenDepth.descriptor.imageView = m_device.createImageView(depthStencilView);
m_offscreenDepth = m_alloc.createTexture(image, depthStencilView);
}
// Setting the image layout for both color and depth // Setting the image layout for both color and depth
{ {
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex); nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
auto cmdBuf = genCmdBuf.createCommandBuffer(); auto cmdBuf = genCmdBuf.createCommandBuffer();
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined, nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eGeneral); vk::ImageLayout::eGeneral);
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageAspectFlagBits::eDepth, nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eUndefined, vk::ImageLayout::eDepthStencilAttachmentOptimal,
vk::ImageLayout::eDepthStencilAttachmentOptimal); vk::ImageAspectFlagBits::eDepth);
genCmdBuf.flushCommandBuffer(cmdBuf); genCmdBuf.submitAndWait(cmdBuf);
} }
// Creating a renderpass for the offscreen // Creating a renderpass for the offscreen
if(!m_offscreenRenderPass) if(!m_offscreenRenderPass)
{ {
m_offscreenRenderPass = m_offscreenRenderPass =
nvvkpp::util::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat, nvvk::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat, 1, true,
1, true, true, vk::ImageLayout::eGeneral, true, vk::ImageLayout::eGeneral, vk::ImageLayout::eGeneral);
vk::ImageLayout::eGeneral);
} }
// Creating the frame buffer for offscreen // Creating the frame buffer for offscreen
@ -581,13 +570,14 @@ void HelloVulkan::createPostPipeline()
// Pipeline: completely generic, no vertices // Pipeline: completely generic, no vertices
std::vector<std::string> paths = defaultSearchPaths; std::vector<std::string> paths = defaultSearchPaths;
nvvkpp::GraphicsPipelineGenerator pipelineGenerator(m_device, m_postPipelineLayout, m_renderPass); nvvk::GraphicsPipelineGeneratorCombined pipelineGenerator(m_device, m_postPipelineLayout,
m_renderPass);
pipelineGenerator.addShader(nvh::loadFile("shaders/passthrough.vert.spv", true, paths), pipelineGenerator.addShader(nvh::loadFile("shaders/passthrough.vert.spv", true, paths),
vk::ShaderStageFlagBits::eVertex); vk::ShaderStageFlagBits::eVertex);
pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths), pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths),
vk::ShaderStageFlagBits::eFragment); vk::ShaderStageFlagBits::eFragment);
pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone); pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone);
m_postPipeline = pipelineGenerator.create(); m_postPipeline = pipelineGenerator.createPipeline();
m_debug.setObjectName(m_postPipeline, "post"); m_debug.setObjectName(m_postPipeline, "post");
} }
@ -601,10 +591,10 @@ void HelloVulkan::createPostDescriptor()
using vkDT = vk::DescriptorType; using vkDT = vk::DescriptorType;
using vkSS = vk::ShaderStageFlagBits; using vkSS = vk::ShaderStageFlagBits;
m_postDescSetLayoutBind.emplace_back(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment)); m_postDescSetLayoutBind.addBinding(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
m_postDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_postDescSetLayoutBind); m_postDescSetLayout = m_postDescSetLayoutBind.createLayout(m_device);
m_postDescPool = nvvkpp::util::createDescriptorPool(m_device, m_postDescSetLayoutBind); m_postDescPool = m_postDescSetLayoutBind.createPool(m_device);
m_postDescSet = nvvkpp::util::createDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout); m_postDescSet = nvvk::allocateDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -613,8 +603,7 @@ void HelloVulkan::createPostDescriptor()
void HelloVulkan::updatePostDescriptorSet() void HelloVulkan::updatePostDescriptorSet()
{ {
vk::WriteDescriptorSet writeDescriptorSets = vk::WriteDescriptorSet writeDescriptorSets =
nvvkpp::util::createWrite(m_postDescSet, m_postDescSetLayoutBind[0], m_postDescSetLayoutBind.makeWrite(m_postDescSet, 0, &m_offscreenColor.descriptor);
&m_offscreenColor.descriptor);
m_device.updateDescriptorSets(writeDescriptorSets, nullptr); m_device.updateDescriptorSets(writeDescriptorSets, nullptr);
} }
@ -652,21 +641,15 @@ void HelloVulkan::initRayTracing()
auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2, auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2,
vk::PhysicalDeviceRayTracingPropertiesKHR>(); vk::PhysicalDeviceRayTracingPropertiesKHR>();
m_rtProperties = properties.get<vk::PhysicalDeviceRayTracingPropertiesKHR>(); m_rtProperties = properties.get<vk::PhysicalDeviceRayTracingPropertiesKHR>();
#if defined(ALLOC_DEDICATED) m_rtBuilder.setup(m_device, &m_alloc, m_graphicsQueueIndex);
m_rtBuilder.setup(m_device, m_physicalDevice, m_graphicsQueueIndex);
#elif defined(ALLOC_DMA)
m_rtBuilder.setup(m_device, m_memAllocator, m_graphicsQueueIndex);
#elif defined(ALLOC_VMA)
m_rtBuilder.setup(m_device, m_memAllocator, m_graphicsQueueIndex);
#endif
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Converting a OBJ primitive to the ray tracing geometry used for the BLAS // Converting a OBJ primitive to the ray tracing geometry used for the BLAS
// //
nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model) nvvk::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model)
{ {
nvvkpp::RaytracingBuilderKHR::Blas blas; nvvk::RaytracingBuilderKHR::Blas blas;
vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate; vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate;
asCreate.setGeometryType(vk::GeometryTypeKHR::eTriangles); asCreate.setGeometryType(vk::GeometryTypeKHR::eTriangles);
asCreate.setIndexType(vk::IndexType::eUint32); asCreate.setIndexType(vk::IndexType::eUint32);
@ -703,7 +686,7 @@ nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjM
void HelloVulkan::createBottomLevelAS() void HelloVulkan::createBottomLevelAS()
{ {
// BLAS - Storing each primitive in a geometry // BLAS - Storing each primitive in a geometry
std::vector<nvvkpp::RaytracingBuilderKHR::Blas> allBlas; std::vector<nvvk::RaytracingBuilderKHR::Blas> allBlas;
allBlas.reserve(m_objModel.size()); allBlas.reserve(m_objModel.size());
for(const auto& obj : m_objModel) for(const auto& obj : m_objModel)
{ {
@ -717,16 +700,16 @@ void HelloVulkan::createBottomLevelAS()
void HelloVulkan::createTopLevelAS() void HelloVulkan::createTopLevelAS()
{ {
std::vector<nvvkpp::RaytracingBuilderKHR::Instance> tlas; std::vector<nvvk::RaytracingBuilderKHR::Instance> tlas;
tlas.reserve(m_objInstance.size()); tlas.reserve(m_objInstance.size());
for(int i = 0; i < static_cast<int>(m_objInstance.size()); i++) for(int i = 0; i < static_cast<int>(m_objInstance.size()); i++)
{ {
nvvkpp::RaytracingBuilderKHR::Instance rayInst; nvvk::RaytracingBuilderKHR::Instance rayInst;
rayInst.transform = m_objInstance[i].transform; // Position of the instance rayInst.transform = m_objInstance[i].transform; // Position of the instance
rayInst.instanceId = i; // gl_InstanceID rayInst.instanceId = i; // gl_InstanceID
rayInst.blasId = m_objInstance[i].objIndex; rayInst.blasId = m_objInstance[i].objIndex;
rayInst.hitGroupId = 0; // We will use the same hit group for all objects rayInst.hitGroupId = 0; // We will use the same hit group for all objects
rayInst.flags = vk::GeometryInstanceFlagBitsKHR::eTriangleCullDisable; rayInst.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
tlas.emplace_back(rayInst); tlas.emplace_back(rayInst);
} }
m_rtBuilder.buildTlas(tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace); m_rtBuilder.buildTlas(tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace);
@ -741,25 +724,25 @@ void HelloVulkan::createRtDescriptorSet()
using vkSS = vk::ShaderStageFlagBits; using vkSS = vk::ShaderStageFlagBits;
using vkDSLB = vk::DescriptorSetLayoutBinding; using vkDSLB = vk::DescriptorSetLayoutBinding;
m_rtDescSetLayoutBind.emplace_back(vkDSLB(0, vkDT::eAccelerationStructureKHR, 1, m_rtDescSetLayoutBind.addBinding(vkDSLB(0, vkDT::eAccelerationStructureKHR, 1,
vkSS::eRaygenKHR | vkSS::eClosestHitKHR)); // TLAS vkSS::eRaygenKHR | vkSS::eClosestHitKHR)); // TLAS
m_rtDescSetLayoutBind.emplace_back( m_rtDescSetLayoutBind.addBinding(
vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image
m_rtDescPool = nvvkpp::util::createDescriptorPool(m_device, m_rtDescSetLayoutBind); m_rtDescPool = m_rtDescSetLayoutBind.createPool(m_device);
m_rtDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_rtDescSetLayoutBind); m_rtDescSetLayout = m_rtDescSetLayoutBind.createLayout(m_device);
m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0]; m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0];
vk::AccelerationStructureKHR tlas = m_rtBuilder.getAccelerationStructure();
vk::WriteDescriptorSetAccelerationStructureKHR descASInfo; vk::WriteDescriptorSetAccelerationStructureKHR descASInfo;
descASInfo.setAccelerationStructureCount(1); descASInfo.setAccelerationStructureCount(1);
descASInfo.setPAccelerationStructures(&m_rtBuilder.getAccelerationStructure()); descASInfo.setPAccelerationStructures(&tlas);
vk::DescriptorImageInfo imageInfo{ vk::DescriptorImageInfo imageInfo{
{}, m_offscreenColor.descriptor.imageView, vk::ImageLayout::eGeneral}; {}, m_offscreenColor.descriptor.imageView, vk::ImageLayout::eGeneral};
std::vector<vk::WriteDescriptorSet> writes; std::vector<vk::WriteDescriptorSet> writes;
writes.emplace_back( writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 0, &descASInfo));
nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[0], &descASInfo)); writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 1, &imageInfo));
writes.emplace_back(nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[1], &imageInfo));
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr); m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
} }
@ -788,16 +771,17 @@ void HelloVulkan::createRtPipeline()
std::vector<std::string> paths = defaultSearchPaths; std::vector<std::string> paths = defaultSearchPaths;
vk::ShaderModule raygenSM = vk::ShaderModule raygenSM =
nvvkpp::util::createShaderModule(m_device, // nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rgen.spv", true, paths)); nvh::loadFile("shaders/raytrace.rgen.spv", true, paths));
vk::ShaderModule missSM = vk::ShaderModule missSM =
nvvkpp::util::createShaderModule(m_device, // nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths)); nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths));
// The second miss shader is invoked when a shadow ray misses the geometry. It // The second miss shader is invoked when a shadow ray misses the geometry. It
// simply indicates that no occlusion has been found // simply indicates that no occlusion has been found
vk::ShaderModule shadowmissSM = nvvkpp::util::createShaderModule( vk::ShaderModule shadowmissSM =
m_device, nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths)); nvvk::createShaderModule(m_device,
nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
std::vector<vk::PipelineShaderStageCreateInfo> stages; std::vector<vk::PipelineShaderStageCreateInfo> stages;
@ -823,8 +807,8 @@ void HelloVulkan::createRtPipeline()
// Hit Group - Closest Hit + AnyHit // Hit Group - Closest Hit + AnyHit
vk::ShaderModule chitSM = vk::ShaderModule chitSM =
nvvkpp::util::createShaderModule(m_device, // nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rchit.spv", true, paths)); nvh::loadFile("shaders/raytrace.rchit.spv", true, paths));
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup, vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup,
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR,
@ -888,17 +872,17 @@ void HelloVulkan::createRtShaderBindingTable()
m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize, m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize,
shaderHandleStorage.data()); shaderHandleStorage.data());
// Write the handles in the SBT // Write the handles in the SBT
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex); nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer(); vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
m_rtSBTBuffer = m_rtSBTBuffer =
m_alloc.createBuffer(cmdBuf, shaderHandleStorage, vk::BufferUsageFlagBits::eRayTracingKHR); m_alloc.createBuffer(cmdBuf, shaderHandleStorage, vk::BufferUsageFlagBits::eRayTracingKHR);
m_debug.setObjectName(m_rtSBTBuffer.buffer, "SBT"); m_debug.setObjectName(m_rtSBTBuffer.buffer, "SBT");
genCmdBuf.flushCommandBuffer(cmdBuf); genCmdBuf.submitAndWait(cmdBuf);
m_alloc.flushStaging(); m_alloc.finalizeAndReleaseStaging();
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------

View file

@ -27,29 +27,17 @@
#pragma once #pragma once
// #VKRay // #VKRay
//#define ALLOC_DEDICATED //#define NVVK_ALLOC_DEDICATED
#define ALLOC_DMA #define NVVK_ALLOC_DMA
//#define ALLOC_VMA //#define NVVK_ALLOC_VMA
#include "nvvkpp/appbase_vkpp.hpp" #include "nvvk/allocator_vk.hpp"
#include "nvvkpp/debug_util_vkpp.hpp" #include "nvvk/appbase_vkpp.hpp"
#include "nvvk/debug_util_vk.hpp"
#include "nvvk/descriptorsets_vk.hpp"
// #VKRay // #VKRay
#include "nvvkpp/raytraceKHR_vkpp.hpp" #include "nvvk/raytraceKHR_vk.hpp"
#if defined(ALLOC_DEDICATED)
#include "nvvkpp/allocator_dedicated_vkpp.hpp"
using nvvkBuffer = nvvkpp::BufferDedicated;
using nvvkTexture = nvvkpp::TextureDedicated;
#elif defined(ALLOC_DMA)
#include "nvvkpp/allocator_dma_vkpp.hpp"
using nvvkBuffer = nvvkpp::BufferDma;
using nvvkTexture = nvvkpp::TextureDma;
#elif defined(ALLOC_VMA)
#include "nvvkpp/allocator_vma_vkpp.hpp"
using nvvkBuffer = nvvkpp::BufferVma;
using nvvkTexture = nvvkpp::TextureVma;
#endif
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Simple rasterizer of OBJ objects // Simple rasterizer of OBJ objects
@ -58,10 +46,11 @@ using nvvkTexture = nvvkpp::TextureVma;
// - Rendering is done in an offscreen framebuffer // - Rendering is done in an offscreen framebuffer
// - The image of the framebuffer is displayed in post-process in a full-screen quad // - The image of the framebuffer is displayed in post-process in a full-screen quad
// //
class HelloVulkan : public nvvkpp::AppBase class HelloVulkan : public nvvk::AppBase
{ {
public: public:
void setup(const vk::Device& device, void setup(const vk::Instance& instance,
const vk::Device& device,
const vk::PhysicalDevice& physicalDevice, const vk::PhysicalDevice& physicalDevice,
uint32_t queueFamily) override; uint32_t queueFamily) override;
void createDescriptorSetLayout(); void createDescriptorSetLayout();
@ -80,12 +69,12 @@ public:
// The OBJ model // The OBJ model
struct ObjModel struct ObjModel
{ {
uint32_t nbIndices{0}; uint32_t nbIndices{0};
uint32_t nbVertices{0}; uint32_t nbVertices{0};
nvvkBuffer vertexBuffer; // Device buffer of all 'Vertex' nvvk::Buffer vertexBuffer; // Device buffer of all 'Vertex'
nvvkBuffer indexBuffer; // Device buffer of the indices forming triangles nvvk::Buffer indexBuffer; // Device buffer of the indices forming triangles
nvvkBuffer matColorBuffer; // Device buffer of array of 'Wavefront material' nvvk::Buffer matColorBuffer; // Device buffer of array of 'Wavefront material'
nvvkBuffer matIndexBuffer; // Device buffer of array of 'Wavefront material' nvvk::Buffer matIndexBuffer; // Device buffer of array of 'Wavefront material'
}; };
// Instance of the OBJ // Instance of the OBJ
@ -112,28 +101,28 @@ public:
std::vector<ObjInstance> m_objInstance; std::vector<ObjInstance> m_objInstance;
// Graphic pipeline // Graphic pipeline
vk::PipelineLayout m_pipelineLayout; vk::PipelineLayout m_pipelineLayout;
vk::Pipeline m_graphicsPipeline; vk::Pipeline m_graphicsPipeline;
std::vector<vk::DescriptorSetLayoutBinding> m_descSetLayoutBind; nvvk::DescriptorSetBindings m_descSetLayoutBind;
vk::DescriptorPool m_descPool; vk::DescriptorPool m_descPool;
vk::DescriptorSetLayout m_descSetLayout; vk::DescriptorSetLayout m_descSetLayout;
vk::DescriptorSet m_descSet; vk::DescriptorSet m_descSet;
nvvkBuffer m_cameraMat; // Device-Host of the camera matrices nvvk::Buffer m_cameraMat; // Device-Host of the camera matrices
nvvkBuffer m_sceneDesc; // Device buffer of the OBJ instances nvvk::Buffer m_sceneDesc; // Device buffer of the OBJ instances
std::vector<nvvkTexture> m_textures; // vector of all textures of the scene std::vector<nvvk::Texture> m_textures; // vector of all textures of the scene
#if defined(ALLOC_DEDICATED) #if defined(NVVK_ALLOC_DEDICATED)
nvvkpp::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures nvvk::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures
#elif defined(ALLOC_DMA) #elif defined(NVVK_ALLOC_DMA)
nvvkpp::AllocatorDma m_alloc; // Allocator for buffer, images, acceleration structures nvvk::AllocatorDma m_alloc; // Allocator for buffer, images, acceleration structures
nvvk::DeviceMemoryAllocator m_memAllocator; nvvk::DeviceMemoryAllocator m_memAllocator;
#elif defined(ALLOC_VMA) #elif defined(NVVK_ALLOC_VMA)
nvvkpp::AllocatorVma m_alloc; // Allocator for buffer, images, acceleration structures nvvk::AllocatorVma m_alloc; // Allocator for buffer, images, acceleration structures
VmaAllocator m_memAllocator; VmaAllocator m_memAllocator;
#endif #endif
nvvkpp::DebugUtil m_debug; // Utility to name objects nvvk::DebugUtil m_debug; // Utility to name objects
// #Post // #Post
void createOffscreenRender(); void createOffscreenRender();
@ -142,41 +131,41 @@ public:
void updatePostDescriptorSet(); void updatePostDescriptorSet();
void drawPost(vk::CommandBuffer cmdBuf); void drawPost(vk::CommandBuffer cmdBuf);
std::vector<vk::DescriptorSetLayoutBinding> m_postDescSetLayoutBind; nvvk::DescriptorSetBindings m_postDescSetLayoutBind;
vk::DescriptorPool m_postDescPool; vk::DescriptorPool m_postDescPool;
vk::DescriptorSetLayout m_postDescSetLayout; vk::DescriptorSetLayout m_postDescSetLayout;
vk::DescriptorSet m_postDescSet; vk::DescriptorSet m_postDescSet;
vk::Pipeline m_postPipeline; vk::Pipeline m_postPipeline;
vk::PipelineLayout m_postPipelineLayout; vk::PipelineLayout m_postPipelineLayout;
vk::RenderPass m_offscreenRenderPass; vk::RenderPass m_offscreenRenderPass;
vk::Framebuffer m_offscreenFramebuffer; vk::Framebuffer m_offscreenFramebuffer;
nvvkTexture m_offscreenColor; nvvk::Texture m_offscreenColor;
vk::Format m_offscreenColorFormat{vk::Format::eR32G32B32A32Sfloat}; vk::Format m_offscreenColorFormat{vk::Format::eR32G32B32A32Sfloat};
nvvkTexture m_offscreenDepth; nvvk::Texture m_offscreenDepth;
vk::Format m_offscreenDepthFormat{vk::Format::eD32Sfloat}; vk::Format m_offscreenDepthFormat{vk::Format::eD32Sfloat};
// #VKRay // #VKRay
void initRayTracing(); void initRayTracing();
nvvkpp::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model); nvvk::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
void createBottomLevelAS(); void createBottomLevelAS();
void createTopLevelAS(); void createTopLevelAS();
void createRtDescriptorSet(); void createRtDescriptorSet();
void updateRtDescriptorSet(); void updateRtDescriptorSet();
void createRtPipeline(); void createRtPipeline();
void createRtShaderBindingTable(); void createRtShaderBindingTable();
void raytrace(const vk::CommandBuffer& cmdBuf, const nvmath::vec4f& clearColor); void raytrace(const vk::CommandBuffer& cmdBuf, const nvmath::vec4f& clearColor);
vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties; vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties;
nvvkpp::RaytracingBuilderKHR m_rtBuilder; nvvk::RaytracingBuilderKHR m_rtBuilder;
std::vector<vk::DescriptorSetLayoutBinding> m_rtDescSetLayoutBind; nvvk::DescriptorSetBindings m_rtDescSetLayoutBind;
vk::DescriptorPool m_rtDescPool; vk::DescriptorPool m_rtDescPool;
vk::DescriptorSetLayout m_rtDescSetLayout; vk::DescriptorSetLayout m_rtDescSetLayout;
vk::DescriptorSet m_rtDescSet; vk::DescriptorSet m_rtDescSet;
std::vector<vk::RayTracingShaderGroupCreateInfoKHR> m_rtShaderGroups; std::vector<vk::RayTracingShaderGroupCreateInfoKHR> m_rtShaderGroups;
vk::PipelineLayout m_rtPipelineLayout; vk::PipelineLayout m_rtPipelineLayout;
vk::Pipeline m_rtPipeline; vk::Pipeline m_rtPipeline;
nvvkBuffer m_rtSBTBuffer; nvvk::Buffer m_rtSBTBuffer;
struct RtPushConstant struct RtPushConstant
{ {

View file

@ -32,6 +32,7 @@
#include <array> #include <array>
#include <random> #include <random>
#include <vulkan/vulkan.hpp> #include <vulkan/vulkan.hpp>
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
#include "imgui.h" #include "imgui.h"
#include "imgui_impl_glfw.h" #include "imgui_impl_glfw.h"
@ -40,10 +41,10 @@
#include "nvh/cameramanipulator.hpp" #include "nvh/cameramanipulator.hpp"
#include "nvh/fileoperations.hpp" #include "nvh/fileoperations.hpp"
#include "nvpsystem.hpp" #include "nvpsystem.hpp"
#include "nvvkpp/appbase_vkpp.hpp" #include "nvvk/appbase_vkpp.hpp"
#include "nvvkpp/commands_vkpp.hpp" #include "nvvk/commands_vk.hpp"
#include "nvvkpp/context_vkpp.hpp" #include "nvvk/context_vk.hpp"
#include "nvvkpp/utilities_vkpp.hpp"
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
#define UNUSED(x) (void)(x) #define UNUSED(x) (void)(x)
@ -125,7 +126,7 @@ int main(int argc, char** argv)
vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature; vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature;
// Requesting Vulkan extensions and layers // Requesting Vulkan extensions and layers
nvvkpp::ContextCreateInfo contextInfo(true); nvvk::ContextCreateInfo contextInfo(true);
contextInfo.setVersion(1, 2); contextInfo.setVersion(1, 2);
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true); contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME); contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME);
@ -149,7 +150,7 @@ int main(int argc, char** argv)
contextInfo.addDeviceExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME); contextInfo.addDeviceExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
// Creating Vulkan base application // Creating Vulkan base application
nvvkpp::Context vkctx{}; nvvk::Context vkctx{};
vkctx.initInstance(contextInfo); vkctx.initInstance(contextInfo);
// Find all compatible devices // Find all compatible devices
auto compatibleDevices = vkctx.getCompatibleDevices(contextInfo); auto compatibleDevices = vkctx.getCompatibleDevices(contextInfo);
@ -164,7 +165,8 @@ int main(int argc, char** argv)
const vk::SurfaceKHR surface = helloVk.getVkSurface(vkctx.m_instance, window); const vk::SurfaceKHR surface = helloVk.getVkSurface(vkctx.m_instance, window);
vkctx.setGCTQueueWithPresent(surface); vkctx.setGCTQueueWithPresent(surface);
helloVk.setup(vkctx.m_device, vkctx.m_physicalDevice, vkctx.m_queueGCT.familyIndex); helloVk.setup(vkctx.m_instance, vkctx.m_device, vkctx.m_physicalDevice,
vkctx.m_queueGCT.familyIndex);
helloVk.createSurface(surface, SAMPLE_WIDTH, SAMPLE_HEIGHT); helloVk.createSurface(surface, SAMPLE_WIDTH, SAMPLE_HEIGHT);
helloVk.createDepthBuffer(); helloVk.createDepthBuffer();
helloVk.createRenderPass(); helloVk.createRenderPass();
@ -258,7 +260,8 @@ int main(int argc, char** argv)
// Clearing screen // Clearing screen
vk::ClearValue clearValues[2]; vk::ClearValue clearValues[2];
clearValues[0].setColor(nvvkpp::util::clearColor(clearColor)); clearValues[0].setColor(
std::array<float, 4>({clearColor[0], clearColor[1], clearColor[2], clearColor[3]}));
clearValues[1].setDepthStencil({1.0f, 0}); clearValues[1].setDepthStencil({1.0f, 0});
// Offscreen render pass // Offscreen render pass
@ -310,7 +313,6 @@ int main(int argc, char** argv)
helloVk.destroyResources(); helloVk.destroyResources();
helloVk.destroy(); helloVk.destroy();
vkctx.m_instance.destroySurfaceKHR(surface);
vkctx.deinit(); vkctx.deinit();
glfwDestroyWindow(window); glfwDestroyWindow(window);

View file

@ -6,7 +6,7 @@
#include "raycommon.glsl" #include "raycommon.glsl"
#include "wavefront.glsl" #include "wavefront.glsl"
hitAttributeEXT vec3 attribs; hitAttributeEXT vec2 attribs;
// clang-format off // clang-format off
layout(location = 0) rayPayloadInEXT hitPayload prd; layout(location = 0) rayPayloadInEXT hitPayload prd;

View file

@ -36,13 +36,14 @@ extern std::vector<std::string> defaultSearchPaths;
#include "hello_vulkan.h" #include "hello_vulkan.h"
#include "nvh//cameramanipulator.hpp" #include "nvh//cameramanipulator.hpp"
#include "nvvkpp/descriptorsets_vkpp.hpp" #include "nvvk/descriptorsets_vk.hpp"
#include "nvvkpp/pipeline_vkpp.hpp" #include "nvvk/pipeline_vk.hpp"
#include "nvh/fileoperations.hpp" #include "nvh/fileoperations.hpp"
#include "nvvkpp/commands_vkpp.hpp" #include "nvvk/commands_vk.hpp"
#include "nvvkpp/renderpass_vkpp.hpp" #include "nvvk/renderpasses_vk.hpp"
#include "nvvkpp/utilities_vkpp.hpp"
#include "nvvk/shaders_vk.hpp"
#include <random> #include <random>
// Holding the camera matrices // Holding the camera matrices
@ -59,11 +60,12 @@ struct CameraMatrices
// Keep the handle on the device // Keep the handle on the device
// Initialize the tool to do all our allocations: buffers, images // Initialize the tool to do all our allocations: buffers, images
// //
void HelloVulkan::setup(const vk::Device& device, void HelloVulkan::setup(const vk::Instance& instance,
const vk::Device& device,
const vk::PhysicalDevice& physicalDevice, const vk::PhysicalDevice& physicalDevice,
uint32_t queueFamily) uint32_t queueFamily)
{ {
AppBase::setup(device, physicalDevice, queueFamily); AppBase::setup(instance, device, physicalDevice, queueFamily);
m_alloc.init(device, physicalDevice); m_alloc.init(device, physicalDevice);
m_debug.setup(m_device); m_debug.setup(m_device);
} }
@ -100,34 +102,34 @@ void HelloVulkan::createDescriptorSetLayout()
uint32_t nbObj = static_cast<uint32_t>(m_objModel.size()); uint32_t nbObj = static_cast<uint32_t>(m_objModel.size());
// Camera matrices (binding = 0) // Camera matrices (binding = 0)
m_descSetLayoutBind.emplace_back( m_descSetLayoutBind.addBinding(
vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR)); vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR));
// Materials (binding = 1) // Materials (binding = 1)
m_descSetLayoutBind.emplace_back(vkDS(1, vkDT::eStorageBuffer, nbObj + 1, m_descSetLayoutBind.addBinding(vkDS(1, vkDT::eStorageBuffer, nbObj + 1,
vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR)); vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
// Scene description (binding = 2) // Scene description (binding = 2)
m_descSetLayoutBind.emplace_back( // m_descSetLayoutBind.addBinding( //
vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR)); vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
// Textures (binding = 3) // Textures (binding = 3)
m_descSetLayoutBind.emplace_back( m_descSetLayoutBind.addBinding(
vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR)); vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR));
// Materials Index (binding = 4) // Materials Index (binding = 4)
m_descSetLayoutBind.emplace_back( m_descSetLayoutBind.addBinding(
vkDS(4, vkDT::eStorageBuffer, nbObj + 1, vkSS::eFragment | vkSS::eClosestHitKHR)); vkDS(4, vkDT::eStorageBuffer, nbObj + 1, vkSS::eFragment | vkSS::eClosestHitKHR));
// Storing vertices (binding = 5) // Storing vertices (binding = 5)
m_descSetLayoutBind.emplace_back( // m_descSetLayoutBind.addBinding( //
vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR)); vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
// Storing indices (binding = 6) // Storing indices (binding = 6)
m_descSetLayoutBind.emplace_back( // m_descSetLayoutBind.addBinding( //
vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR)); vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
// Storing spheres (binding = 7) // Storing spheres (binding = 7)
m_descSetLayoutBind.emplace_back( // m_descSetLayoutBind.addBinding( //
vkDS(7, vkDT::eStorageBuffer, 1, vkSS::eClosestHitKHR | vkSS::eIntersectionKHR)); vkDS(7, vkDT::eStorageBuffer, 1, vkSS::eClosestHitKHR | vkSS::eIntersectionKHR));
m_descSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_descSetLayoutBind); m_descSetLayout = m_descSetLayoutBind.createLayout(m_device);
m_descPool = nvvkpp::util::createDescriptorPool(m_device, m_descSetLayoutBind, 1); m_descPool = m_descSetLayoutBind.createPool(m_device, 1);
m_descSet = nvvkpp::util::createDescriptorSet(m_device, m_descPool, m_descSetLayout); m_descSet = nvvk::allocateDescriptorSet(m_device, m_descPool, m_descSetLayout);
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -139,9 +141,9 @@ void HelloVulkan::updateDescriptorSet()
// Camera matrices and scene description // Camera matrices and scene description
vk::DescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE}; vk::DescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE};
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[0], &dbiUnif)); writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 0, &dbiUnif));
vk::DescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE}; vk::DescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[2], &dbiSceneDesc)); writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 2, &dbiSceneDesc));
// All material buffers, 1 buffer per OBJ // All material buffers, 1 buffer per OBJ
std::vector<vk::DescriptorBufferInfo> dbiMat; std::vector<vk::DescriptorBufferInfo> dbiMat;
@ -158,14 +160,13 @@ void HelloVulkan::updateDescriptorSet()
dbiMat.emplace_back(m_spheresMatColorBuffer.buffer, 0, VK_WHOLE_SIZE); dbiMat.emplace_back(m_spheresMatColorBuffer.buffer, 0, VK_WHOLE_SIZE);
dbiMatIdx.emplace_back(m_spheresMatIndexBuffer.buffer, 0, VK_WHOLE_SIZE); dbiMatIdx.emplace_back(m_spheresMatIndexBuffer.buffer, 0, VK_WHOLE_SIZE);
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[1], dbiMat.data())); writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 1, dbiMat.data()));
writes.emplace_back( writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 4, dbiMatIdx.data()));
nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[4], dbiMatIdx.data())); writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 5, dbiVert.data()));
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[5], dbiVert.data())); writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 6, dbiIdx.data()));
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[6], dbiIdx.data()));
vk::DescriptorBufferInfo dbiSpheres{m_spheresBuffer.buffer, 0, VK_WHOLE_SIZE}; vk::DescriptorBufferInfo dbiSpheres{m_spheresBuffer.buffer, 0, VK_WHOLE_SIZE};
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[7], &dbiSpheres)); writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 7, &dbiSpheres));
// All texture samplers // All texture samplers
std::vector<vk::DescriptorImageInfo> diit; std::vector<vk::DescriptorImageInfo> diit;
@ -173,7 +174,7 @@ void HelloVulkan::updateDescriptorSet()
{ {
diit.push_back(texture.descriptor); diit.push_back(texture.descriptor);
} }
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[3], diit.data())); writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 3, diit.data()));
// Writing the information // Writing the information
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr); m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
@ -199,19 +200,18 @@ void HelloVulkan::createGraphicsPipeline()
m_pipelineLayout = m_device.createPipelineLayout(pipelineLayoutCreateInfo); m_pipelineLayout = m_device.createPipelineLayout(pipelineLayoutCreateInfo);
// Creating the Pipeline // Creating the Pipeline
std::vector<std::string> paths = defaultSearchPaths; std::vector<std::string> paths = defaultSearchPaths;
nvvkpp::GraphicsPipelineGenerator gpb(m_device, m_pipelineLayout, m_offscreenRenderPass); nvvk::GraphicsPipelineGeneratorCombined gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
gpb.depthStencilState = {true}; gpb.depthStencilState.depthTestEnable = true;
gpb.addShader(nvh::loadFile("shaders/vert_shader.vert.spv", true, paths), vkSS::eVertex); gpb.addShader(nvh::loadFile("shaders/vert_shader.vert.spv", true, paths), vkSS::eVertex);
gpb.addShader(nvh::loadFile("shaders/frag_shader.frag.spv", true, paths), vkSS::eFragment); gpb.addShader(nvh::loadFile("shaders/frag_shader.frag.spv", true, paths), vkSS::eFragment);
gpb.vertexInputState.bindingDescriptions = {{0, sizeof(VertexObj)}}; gpb.addBindingDescription({0, sizeof(VertexObj)});
gpb.vertexInputState.attributeDescriptions = { gpb.addAttributeDescriptions({{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)}, {1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)},
{1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)}, {2, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, color)},
{2, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, color)}, {3, 0, vk::Format::eR32G32Sfloat, offsetof(VertexObj, texCoord)}});
{3, 0, vk::Format::eR32G32Sfloat, offsetof(VertexObj, texCoord)}};
m_graphicsPipeline = gpb.create(); m_graphicsPipeline = gpb.createPipeline();
m_debug.setObjectName(m_graphicsPipeline, "Graphics"); m_debug.setObjectName(m_graphicsPipeline, "Graphics");
} }
@ -244,8 +244,8 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size()); model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
// Create the buffers on Device and copy vertices, indices and materials // Create the buffers on Device and copy vertices, indices and materials
nvvkpp::SingleCommandBuffer cmdBufGet(m_device, m_graphicsQueueIndex); nvvk::CommandPool cmdBufGet(m_device, m_graphicsQueueIndex);
vk::CommandBuffer cmdBuf = cmdBufGet.createCommandBuffer(); vk::CommandBuffer cmdBuf = cmdBufGet.createCommandBuffer();
model.vertexBuffer = model.vertexBuffer =
m_alloc.createBuffer(cmdBuf, loader.m_vertices, m_alloc.createBuffer(cmdBuf, loader.m_vertices,
vkBU::eVertexBuffer | vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress); vkBU::eVertexBuffer | vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress);
@ -256,8 +256,8 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, vkBU::eStorageBuffer); model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, vkBU::eStorageBuffer);
// Creates all textures found // Creates all textures found
createTextureImages(cmdBuf, loader.m_textures); createTextureImages(cmdBuf, loader.m_textures);
cmdBufGet.flushCommandBuffer(cmdBuf); cmdBufGet.submitAndWait(cmdBuf);
m_alloc.flushStaging(); m_alloc.finalizeAndReleaseStaging();
std::string objNb = std::to_string(instance.objIndex); std::string objNb = std::to_string(instance.objIndex);
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str())); m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
@ -292,12 +292,12 @@ void HelloVulkan::createUniformBuffer()
void HelloVulkan::createSceneDescriptionBuffer() void HelloVulkan::createSceneDescriptionBuffer()
{ {
using vkBU = vk::BufferUsageFlagBits; using vkBU = vk::BufferUsageFlagBits;
nvvkpp::SingleCommandBuffer cmdGen(m_device, m_graphicsQueueIndex); nvvk::CommandPool cmdGen(m_device, m_graphicsQueueIndex);
auto cmdBuf = cmdGen.createCommandBuffer(); auto cmdBuf = cmdGen.createCommandBuffer();
m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer); m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer);
cmdGen.flushCommandBuffer(cmdBuf); cmdGen.submitAndWait(cmdBuf);
m_alloc.flushStaging(); m_alloc.finalizeAndReleaseStaging();
m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc"); m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc");
} }
@ -317,21 +317,21 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
// If no textures are present, create a dummy one to accommodate the pipeline layout // If no textures are present, create a dummy one to accommodate the pipeline layout
if(textures.empty() && m_textures.empty()) if(textures.empty() && m_textures.empty())
{ {
nvvkTexture texture; nvvk::Texture texture;
std::array<uint8_t, 4> color{255u, 255u, 255u, 255u}; std::array<uint8_t, 4> color{255u, 255u, 255u, 255u};
vk::DeviceSize bufferSize = sizeof(color); vk::DeviceSize bufferSize = sizeof(color);
auto imgSize = vk::Extent2D(1, 1); auto imgSize = vk::Extent2D(1, 1);
auto imageCreateInfo = nvvkpp::image::create2DInfo(imgSize, format); auto imageCreateInfo = nvvk::makeImage2DCreateInfo(imgSize, format);
// Creating the dummy texure
nvvk::Image image = m_alloc.createImage(cmdBuf, bufferSize, color.data(), imageCreateInfo);
vk::ImageViewCreateInfo ivInfo = nvvk::makeImageViewCreateInfo(image.image, imageCreateInfo);
texture = m_alloc.createTexture(image, ivInfo, samplerCreateInfo);
// Creating the VKImage
texture = m_alloc.createImage(cmdBuf, bufferSize, color.data(), imageCreateInfo);
// Setting up the descriptor used by the shader
texture.descriptor =
nvvkpp::image::create2DDescriptor(m_device, texture.image, samplerCreateInfo, format);
// The image format must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL // The image format must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
nvvkpp::image::setImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined, nvvk::cmdBarrierImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eShaderReadOnlyOptimal); vk::ImageLayout::eShaderReadOnlyOptimal);
m_textures.push_back(texture); m_textures.push_back(texture);
} }
else else
@ -358,16 +358,16 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4; vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4;
auto imgSize = vk::Extent2D(texWidth, texHeight); auto imgSize = vk::Extent2D(texWidth, texHeight);
auto imageCreateInfo = nvvkpp::image::create2DInfo(imgSize, format, vkIU::eSampled, true); auto imageCreateInfo = nvvk::makeImage2DCreateInfo(imgSize, format, vkIU::eSampled, true);
{ {
nvvkTexture texture; nvvk::ImageDedicated image =
texture = m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo); m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo);
nvvk::cmdGenerateMipmaps(cmdBuf, image.image, format, imgSize, imageCreateInfo.mipLevels);
vk::ImageViewCreateInfo ivInfo =
nvvk::makeImageViewCreateInfo(image.image, imageCreateInfo);
nvvk::Texture texture = m_alloc.createTexture(image, ivInfo, samplerCreateInfo);
nvvkpp::image::generateMipmaps(cmdBuf, texture.image, format, imgSize,
imageCreateInfo.mipLevels);
texture.descriptor =
nvvkpp::image::create2DDescriptor(m_device, texture.image, samplerCreateInfo, format);
m_textures.push_back(texture); m_textures.push_back(texture);
} }
} }
@ -449,7 +449,7 @@ void HelloVulkan::rasterize(const vk::CommandBuffer& cmdBuf)
cmdBuf.pushConstants<ObjPushConstant>(m_pipelineLayout, vkSS::eVertex | vkSS::eFragment, 0, cmdBuf.pushConstants<ObjPushConstant>(m_pipelineLayout, vkSS::eVertex | vkSS::eFragment, 0,
m_pushConstant); m_pushConstant);
cmdBuf.bindVertexBuffers(0, 1, &model.vertexBuffer.buffer, &offset); cmdBuf.bindVertexBuffers(0, {model.vertexBuffer.buffer}, {offset});
cmdBuf.bindIndexBuffer(model.indexBuffer.buffer, 0, vk::IndexType::eUint32); cmdBuf.bindIndexBuffer(model.indexBuffer.buffer, 0, vk::IndexType::eUint32);
cmdBuf.drawIndexed(model.nbIndices, 1, 0, 0, 0); cmdBuf.drawIndexed(model.nbIndices, 1, 0, 0, 0);
} }
@ -479,49 +479,54 @@ void HelloVulkan::createOffscreenRender()
m_alloc.destroy(m_offscreenDepth); m_alloc.destroy(m_offscreenDepth);
// Creating the color image // Creating the color image
auto colorCreateInfo = nvvkpp::image::create2DInfo(m_size, m_offscreenColorFormat, {
vk::ImageUsageFlagBits::eColorAttachment auto colorCreateInfo = nvvk::makeImage2DCreateInfo(m_size, m_offscreenColorFormat,
| vk::ImageUsageFlagBits::eSampled vk::ImageUsageFlagBits::eColorAttachment
| vk::ImageUsageFlagBits::eStorage); | vk::ImageUsageFlagBits::eSampled
m_offscreenColor = m_alloc.createImage(colorCreateInfo); | vk::ImageUsageFlagBits::eStorage);
m_offscreenColor.descriptor =
nvvkpp::image::create2DDescriptor(m_device, m_offscreenColor.image, vk::SamplerCreateInfo{}, nvvk::Image image = m_alloc.createImage(colorCreateInfo);
m_offscreenColorFormat, vk::ImageLayout::eGeneral); vk::ImageViewCreateInfo ivInfo = nvvk::makeImageViewCreateInfo(image.image, colorCreateInfo);
m_offscreenColor = m_alloc.createTexture(image, ivInfo, vk::SamplerCreateInfo());
m_offscreenColor.descriptor.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
}
// Creating the depth buffer // Creating the depth buffer
auto depthCreateInfo = auto depthCreateInfo =
nvvkpp::image::create2DInfo(m_size, m_offscreenDepthFormat, nvvk::makeImage2DCreateInfo(m_size, m_offscreenDepthFormat,
vk::ImageUsageFlagBits::eDepthStencilAttachment); vk::ImageUsageFlagBits::eDepthStencilAttachment);
m_offscreenDepth = m_alloc.createImage(depthCreateInfo); {
nvvk::Image image = m_alloc.createImage(depthCreateInfo);
vk::ImageViewCreateInfo depthStencilView; vk::ImageViewCreateInfo depthStencilView;
depthStencilView.setViewType(vk::ImageViewType::e2D); depthStencilView.setViewType(vk::ImageViewType::e2D);
depthStencilView.setFormat(m_offscreenDepthFormat); depthStencilView.setFormat(m_offscreenDepthFormat);
depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1}); depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1});
depthStencilView.setImage(m_offscreenDepth.image); depthStencilView.setImage(image.image);
m_offscreenDepth.descriptor.imageView = m_device.createImageView(depthStencilView);
m_offscreenDepth = m_alloc.createTexture(image, depthStencilView);
}
// Setting the image layout for both color and depth // Setting the image layout for both color and depth
{ {
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex); nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
auto cmdBuf = genCmdBuf.createCommandBuffer(); auto cmdBuf = genCmdBuf.createCommandBuffer();
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined, nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eGeneral); vk::ImageLayout::eGeneral);
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageAspectFlagBits::eDepth, nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eUndefined, vk::ImageLayout::eDepthStencilAttachmentOptimal,
vk::ImageLayout::eDepthStencilAttachmentOptimal); vk::ImageAspectFlagBits::eDepth);
genCmdBuf.flushCommandBuffer(cmdBuf); genCmdBuf.submitAndWait(cmdBuf);
} }
// Creating a renderpass for the offscreen // Creating a renderpass for the offscreen
if(!m_offscreenRenderPass) if(!m_offscreenRenderPass)
{ {
m_offscreenRenderPass = m_offscreenRenderPass =
nvvkpp::util::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat, nvvk::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat, 1, true,
1, true, true, vk::ImageLayout::eGeneral, true, vk::ImageLayout::eGeneral, vk::ImageLayout::eGeneral);
vk::ImageLayout::eGeneral);
} }
// Creating the frame buffer for offscreen // Creating the frame buffer for offscreen
@ -558,13 +563,14 @@ void HelloVulkan::createPostPipeline()
// Pipeline: completely generic, no vertices // Pipeline: completely generic, no vertices
std::vector<std::string> paths = defaultSearchPaths; std::vector<std::string> paths = defaultSearchPaths;
nvvkpp::GraphicsPipelineGenerator pipelineGenerator(m_device, m_postPipelineLayout, m_renderPass); nvvk::GraphicsPipelineGeneratorCombined pipelineGenerator(m_device, m_postPipelineLayout,
m_renderPass);
pipelineGenerator.addShader(nvh::loadFile("shaders/passthrough.vert.spv", true, paths), pipelineGenerator.addShader(nvh::loadFile("shaders/passthrough.vert.spv", true, paths),
vk::ShaderStageFlagBits::eVertex); vk::ShaderStageFlagBits::eVertex);
pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths), pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths),
vk::ShaderStageFlagBits::eFragment); vk::ShaderStageFlagBits::eFragment);
pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone); pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone);
m_postPipeline = pipelineGenerator.create(); m_postPipeline = pipelineGenerator.createPipeline();
m_debug.setObjectName(m_postPipeline, "post"); m_debug.setObjectName(m_postPipeline, "post");
} }
@ -578,10 +584,10 @@ void HelloVulkan::createPostDescriptor()
using vkDT = vk::DescriptorType; using vkDT = vk::DescriptorType;
using vkSS = vk::ShaderStageFlagBits; using vkSS = vk::ShaderStageFlagBits;
m_postDescSetLayoutBind.emplace_back(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment)); m_postDescSetLayoutBind.addBinding(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
m_postDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_postDescSetLayoutBind); m_postDescSetLayout = m_postDescSetLayoutBind.createLayout(m_device);
m_postDescPool = nvvkpp::util::createDescriptorPool(m_device, m_postDescSetLayoutBind); m_postDescPool = m_postDescSetLayoutBind.createPool(m_device);
m_postDescSet = nvvkpp::util::createDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout); m_postDescSet = nvvk::allocateDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -590,8 +596,7 @@ void HelloVulkan::createPostDescriptor()
void HelloVulkan::updatePostDescriptorSet() void HelloVulkan::updatePostDescriptorSet()
{ {
vk::WriteDescriptorSet writeDescriptorSets = vk::WriteDescriptorSet writeDescriptorSets =
nvvkpp::util::createWrite(m_postDescSet, m_postDescSetLayoutBind[0], m_postDescSetLayoutBind.makeWrite(m_postDescSet, 0, &m_offscreenColor.descriptor);
&m_offscreenColor.descriptor);
m_device.updateDescriptorSets(writeDescriptorSets, nullptr); m_device.updateDescriptorSets(writeDescriptorSets, nullptr);
} }
@ -629,13 +634,13 @@ void HelloVulkan::initRayTracing()
auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2, auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2,
vk::PhysicalDeviceRayTracingPropertiesKHR>(); vk::PhysicalDeviceRayTracingPropertiesKHR>();
m_rtProperties = properties.get<vk::PhysicalDeviceRayTracingPropertiesKHR>(); m_rtProperties = properties.get<vk::PhysicalDeviceRayTracingPropertiesKHR>();
m_rtBuilder.setup(m_device, m_physicalDevice, m_graphicsQueueIndex); m_rtBuilder.setup(m_device, &m_alloc, m_graphicsQueueIndex);
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Converting a OBJ primitive to the ray tracing geometry used for the BLAS // Converting a OBJ primitive to the ray tracing geometry used for the BLAS
// //
nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model) nvvk::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model)
{ {
vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate; vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate;
asCreate.setGeometryType(vk::GeometryTypeKHR::eTriangles); asCreate.setGeometryType(vk::GeometryTypeKHR::eTriangles);
@ -667,7 +672,7 @@ nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjM
offset.setPrimitiveOffset(0); offset.setPrimitiveOffset(0);
offset.setTransformOffset(0); offset.setTransformOffset(0);
nvvkpp::RaytracingBuilderKHR::Blas blas; nvvk::RaytracingBuilderKHR::Blas blas;
blas.asGeometry.emplace_back(asGeom); blas.asGeometry.emplace_back(asGeom);
blas.asCreateGeometryInfo.emplace_back(asCreate); blas.asCreateGeometryInfo.emplace_back(asCreate);
blas.asBuildOffsetInfo.emplace_back(offset); blas.asBuildOffsetInfo.emplace_back(offset);
@ -677,7 +682,7 @@ nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjM
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Returning the ray tracing geometry used for the BLAS, containing all spheres // Returning the ray tracing geometry used for the BLAS, containing all spheres
// //
nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::sphereToVkGeometryKHR() nvvk::RaytracingBuilderKHR::Blas HelloVulkan::sphereToVkGeometryKHR()
{ {
vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate; vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate;
asCreate.setGeometryType(vk::GeometryTypeKHR::eAabbs); asCreate.setGeometryType(vk::GeometryTypeKHR::eAabbs);
@ -705,7 +710,7 @@ nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::sphereToVkGeometryKHR()
offset.setPrimitiveOffset(0); offset.setPrimitiveOffset(0);
offset.setTransformOffset(0); offset.setTransformOffset(0);
nvvkpp::RaytracingBuilderKHR::Blas blas; nvvk::RaytracingBuilderKHR::Blas blas;
blas.asGeometry.emplace_back(asGeom); blas.asGeometry.emplace_back(asGeom);
blas.asCreateGeometryInfo.emplace_back(asCreate); blas.asCreateGeometryInfo.emplace_back(asCreate);
blas.asBuildOffsetInfo.emplace_back(offset); blas.asBuildOffsetInfo.emplace_back(offset);
@ -759,13 +764,13 @@ void HelloVulkan::createSpheres()
// Creating all buffers // Creating all buffers
using vkBU = vk::BufferUsageFlagBits; using vkBU = vk::BufferUsageFlagBits;
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex); nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
auto cmdBuf = genCmdBuf.createCommandBuffer(); auto cmdBuf = genCmdBuf.createCommandBuffer();
m_spheresBuffer = m_alloc.createBuffer(cmdBuf, m_spheres, vkBU::eStorageBuffer); m_spheresBuffer = m_alloc.createBuffer(cmdBuf, m_spheres, vkBU::eStorageBuffer);
m_spheresAabbBuffer = m_alloc.createBuffer(cmdBuf, aabbs, vkBU::eShaderDeviceAddress); m_spheresAabbBuffer = m_alloc.createBuffer(cmdBuf, aabbs, vkBU::eShaderDeviceAddress);
m_spheresMatIndexBuffer = m_alloc.createBuffer(cmdBuf, matIdx, vkBU::eStorageBuffer); m_spheresMatIndexBuffer = m_alloc.createBuffer(cmdBuf, matIdx, vkBU::eStorageBuffer);
m_spheresMatColorBuffer = m_alloc.createBuffer(cmdBuf, materials, vkBU::eStorageBuffer); m_spheresMatColorBuffer = m_alloc.createBuffer(cmdBuf, materials, vkBU::eStorageBuffer);
genCmdBuf.flushCommandBuffer(cmdBuf); genCmdBuf.submitAndWait(cmdBuf);
// Debug information // Debug information
m_debug.setObjectName(m_spheresBuffer.buffer, "spheres"); m_debug.setObjectName(m_spheresBuffer.buffer, "spheres");
@ -777,7 +782,7 @@ void HelloVulkan::createSpheres()
void HelloVulkan::createBottomLevelAS() void HelloVulkan::createBottomLevelAS()
{ {
// BLAS - Storing each primitive in a geometry // BLAS - Storing each primitive in a geometry
std::vector<nvvkpp::RaytracingBuilderKHR::Blas> allBlas; std::vector<nvvk::RaytracingBuilderKHR::Blas> allBlas;
allBlas.reserve(m_objModel.size()); allBlas.reserve(m_objModel.size());
for(const auto& obj : m_objModel) for(const auto& obj : m_objModel)
{ {
@ -798,27 +803,27 @@ void HelloVulkan::createBottomLevelAS()
void HelloVulkan::createTopLevelAS() void HelloVulkan::createTopLevelAS()
{ {
std::vector<nvvkpp::RaytracingBuilderKHR::Instance> tlas; std::vector<nvvk::RaytracingBuilderKHR::Instance> tlas;
tlas.reserve(m_objInstance.size()); tlas.reserve(m_objInstance.size());
for(int i = 0; i < static_cast<int>(m_objInstance.size()); i++) for(int i = 0; i < static_cast<int>(m_objInstance.size()); i++)
{ {
nvvkpp::RaytracingBuilderKHR::Instance rayInst; nvvk::RaytracingBuilderKHR::Instance rayInst;
rayInst.transform = m_objInstance[i].transform; // Position of the instance rayInst.transform = m_objInstance[i].transform; // Position of the instance
rayInst.instanceId = i; // gl_InstanceID rayInst.instanceId = i; // gl_InstanceID
rayInst.blasId = m_objInstance[i].objIndex; rayInst.blasId = m_objInstance[i].objIndex;
rayInst.hitGroupId = 0; // We will use the same hit group for all objects rayInst.hitGroupId = 0; // We will use the same hit group for all objects
rayInst.flags = vk::GeometryInstanceFlagBitsKHR::eTriangleCullDisable; rayInst.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
tlas.emplace_back(rayInst); tlas.emplace_back(rayInst);
} }
// Add the blas containing all spheres // Add the blas containing all spheres
{ {
nvvkpp::RaytracingBuilderKHR::Instance rayInst; nvvk::RaytracingBuilderKHR::Instance rayInst;
rayInst.transform = m_objInstance[0].transform; // Position of the instance rayInst.transform = m_objInstance[0].transform; // Position of the instance
rayInst.instanceId = static_cast<uint32_t>(tlas.size()); // gl_InstanceID rayInst.instanceId = static_cast<uint32_t>(tlas.size()); // gl_InstanceID
rayInst.blasId = static_cast<uint32_t>(m_objModel.size()); rayInst.blasId = static_cast<uint32_t>(m_objModel.size());
rayInst.hitGroupId = 1; // We will use the same hit group for all objects rayInst.hitGroupId = 1; // We will use the same hit group for all objects
rayInst.flags = vk::GeometryInstanceFlagBitsKHR::eTriangleCullDisable; rayInst.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
tlas.emplace_back(rayInst); tlas.emplace_back(rayInst);
} }
@ -834,25 +839,25 @@ void HelloVulkan::createRtDescriptorSet()
using vkSS = vk::ShaderStageFlagBits; using vkSS = vk::ShaderStageFlagBits;
using vkDSLB = vk::DescriptorSetLayoutBinding; using vkDSLB = vk::DescriptorSetLayoutBinding;
m_rtDescSetLayoutBind.emplace_back(vkDSLB(0, vkDT::eAccelerationStructureKHR, 1, m_rtDescSetLayoutBind.addBinding(vkDSLB(0, vkDT::eAccelerationStructureKHR, 1,
vkSS::eRaygenKHR | vkSS::eClosestHitKHR)); // TLAS vkSS::eRaygenKHR | vkSS::eClosestHitKHR)); // TLAS
m_rtDescSetLayoutBind.emplace_back( m_rtDescSetLayoutBind.addBinding(
vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image
m_rtDescPool = nvvkpp::util::createDescriptorPool(m_device, m_rtDescSetLayoutBind); m_rtDescPool = m_rtDescSetLayoutBind.createPool(m_device);
m_rtDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_rtDescSetLayoutBind); m_rtDescSetLayout = m_rtDescSetLayoutBind.createLayout(m_device);
m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0]; m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0];
vk::AccelerationStructureKHR tlas = m_rtBuilder.getAccelerationStructure();
vk::WriteDescriptorSetAccelerationStructureKHR descASInfo; vk::WriteDescriptorSetAccelerationStructureKHR descASInfo;
descASInfo.setAccelerationStructureCount(1); descASInfo.setAccelerationStructureCount(1);
descASInfo.setPAccelerationStructures(&m_rtBuilder.getAccelerationStructure()); descASInfo.setPAccelerationStructures(&tlas);
vk::DescriptorImageInfo imageInfo{ vk::DescriptorImageInfo imageInfo{
{}, m_offscreenColor.descriptor.imageView, vk::ImageLayout::eGeneral}; {}, m_offscreenColor.descriptor.imageView, vk::ImageLayout::eGeneral};
std::vector<vk::WriteDescriptorSet> writes; std::vector<vk::WriteDescriptorSet> writes;
writes.emplace_back( writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 0, &descASInfo));
nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[0], &descASInfo)); writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 1, &imageInfo));
writes.emplace_back(nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[1], &imageInfo));
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr); m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
} }
@ -881,16 +886,17 @@ void HelloVulkan::createRtPipeline()
std::vector<std::string> paths = defaultSearchPaths; std::vector<std::string> paths = defaultSearchPaths;
vk::ShaderModule raygenSM = vk::ShaderModule raygenSM =
nvvkpp::util::createShaderModule(m_device, // nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rgen.spv", true, paths)); nvh::loadFile("shaders/raytrace.rgen.spv", true, paths));
vk::ShaderModule missSM = vk::ShaderModule missSM =
nvvkpp::util::createShaderModule(m_device, // nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths)); nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths));
// The second miss shader is invoked when a shadow ray misses the geometry. It // The second miss shader is invoked when a shadow ray misses the geometry. It
// simply indicates that no occlusion has been found // simply indicates that no occlusion has been found
vk::ShaderModule shadowmissSM = nvvkpp::util::createShaderModule( vk::ShaderModule shadowmissSM =
m_device, nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths)); nvvk::createShaderModule(m_device,
nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
std::vector<vk::PipelineShaderStageCreateInfo> stages; std::vector<vk::PipelineShaderStageCreateInfo> stages;
@ -916,8 +922,8 @@ void HelloVulkan::createRtPipeline()
// Hit Group0 - Closest Hit // Hit Group0 - Closest Hit
vk::ShaderModule chitSM = vk::ShaderModule chitSM =
nvvkpp::util::createShaderModule(m_device, // nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rchit.spv", true, paths)); nvh::loadFile("shaders/raytrace.rchit.spv", true, paths));
{ {
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup, vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup,
@ -930,11 +936,11 @@ void HelloVulkan::createRtPipeline()
// Hit Group1 - Closest Hit + Intersection (procedural) // Hit Group1 - Closest Hit + Intersection (procedural)
vk::ShaderModule chit2SM = vk::ShaderModule chit2SM =
nvvkpp::util::createShaderModule(m_device, // nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace2.rchit.spv", true, paths)); nvh::loadFile("shaders/raytrace2.rchit.spv", true, paths));
vk::ShaderModule rintSM = vk::ShaderModule rintSM =
nvvkpp::util::createShaderModule(m_device, // nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rint.spv", true, paths)); nvh::loadFile("shaders/raytrace.rint.spv", true, paths));
{ {
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eProceduralHitGroup, vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eProceduralHitGroup,
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR,
@ -1003,17 +1009,17 @@ void HelloVulkan::createRtShaderBindingTable()
m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize, m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize,
shaderHandleStorage.data()); shaderHandleStorage.data());
// Write the handles in the SBT // Write the handles in the SBT
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex); nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer(); vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
m_rtSBTBuffer = m_rtSBTBuffer =
m_alloc.createBuffer(cmdBuf, shaderHandleStorage, vk::BufferUsageFlagBits::eRayTracingKHR); m_alloc.createBuffer(cmdBuf, shaderHandleStorage, vk::BufferUsageFlagBits::eRayTracingKHR);
m_debug.setObjectName(m_rtSBTBuffer.buffer, "SBT"); m_debug.setObjectName(m_rtSBTBuffer.buffer, "SBT");
genCmdBuf.flushCommandBuffer(cmdBuf); genCmdBuf.submitAndWait(cmdBuf);
m_alloc.flushStaging(); m_alloc.finalizeAndReleaseStaging();
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------

View file

@ -26,16 +26,14 @@
*/ */
#pragma once #pragma once
#include "nvvkpp/allocator_dedicated_vkpp.hpp" #define NVVK_ALLOC_DEDICATED
#include "nvvkpp/appbase_vkpp.hpp" #include "nvvk/allocator_vk.hpp"
#include "nvvkpp/debug_util_vkpp.hpp" #include "nvvk/appbase_vkpp.hpp"
#include "nvvk/debug_util_vk.hpp"
#include "nvvk/descriptorsets_vk.hpp"
// #VKRay // #VKRay
#define ALLOC_DEDICATED #include "nvvk/raytraceKHR_vk.hpp"
#include "nvvkpp/raytraceKHR_vkpp.hpp"
using nvvkBuffer = nvvkpp::BufferDedicated;
using nvvkTexture = nvvkpp::TextureDedicated;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Simple rasterizer of OBJ objects // Simple rasterizer of OBJ objects
@ -44,10 +42,11 @@ using nvvkTexture = nvvkpp::TextureDedicated;
// - Rendering is done in an offscreen framebuffer // - Rendering is done in an offscreen framebuffer
// - The image of the framebuffer is displayed in post-process in a full-screen quad // - The image of the framebuffer is displayed in post-process in a full-screen quad
// //
class HelloVulkan : public nvvkpp::AppBase class HelloVulkan : public nvvk::AppBase
{ {
public: public:
void setup(const vk::Device& device, void setup(const vk::Instance& instance,
const vk::Device& device,
const vk::PhysicalDevice& physicalDevice, const vk::PhysicalDevice& physicalDevice,
uint32_t queueFamily) override; uint32_t queueFamily) override;
void createDescriptorSetLayout(); void createDescriptorSetLayout();
@ -66,12 +65,12 @@ public:
// The OBJ model // The OBJ model
struct ObjModel struct ObjModel
{ {
uint32_t nbIndices{0}; uint32_t nbIndices{0};
uint32_t nbVertices{0}; uint32_t nbVertices{0};
nvvkBuffer vertexBuffer; // Device buffer of all 'Vertex' nvvk::Buffer vertexBuffer; // Device buffer of all 'Vertex'
nvvkBuffer indexBuffer; // Device buffer of the indices forming triangles nvvk::Buffer indexBuffer; // Device buffer of the indices forming triangles
nvvkBuffer matColorBuffer; // Device buffer of array of 'Wavefront material' nvvk::Buffer matColorBuffer; // Device buffer of array of 'Wavefront material'
nvvkBuffer matIndexBuffer; // Device buffer of array of 'Wavefront material' nvvk::Buffer matIndexBuffer; // Device buffer of array of 'Wavefront material'
}; };
// Instance of the OBJ // Instance of the OBJ
@ -98,19 +97,19 @@ public:
std::vector<ObjInstance> m_objInstance; std::vector<ObjInstance> m_objInstance;
// Graphic pipeline // Graphic pipeline
vk::PipelineLayout m_pipelineLayout; vk::PipelineLayout m_pipelineLayout;
vk::Pipeline m_graphicsPipeline; vk::Pipeline m_graphicsPipeline;
std::vector<vk::DescriptorSetLayoutBinding> m_descSetLayoutBind; nvvk::DescriptorSetBindings m_descSetLayoutBind;
vk::DescriptorPool m_descPool; vk::DescriptorPool m_descPool;
vk::DescriptorSetLayout m_descSetLayout; vk::DescriptorSetLayout m_descSetLayout;
vk::DescriptorSet m_descSet; vk::DescriptorSet m_descSet;
nvvkBuffer m_cameraMat; // Device-Host of the camera matrices nvvk::Buffer m_cameraMat; // Device-Host of the camera matrices
nvvkBuffer m_sceneDesc; // Device buffer of the OBJ instances nvvk::Buffer m_sceneDesc; // Device buffer of the OBJ instances
std::vector<nvvkTexture> m_textures; // vector of all textures of the scene std::vector<nvvk::Texture> m_textures; // vector of all textures of the scene
nvvkpp::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures nvvk::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures
nvvkpp::DebugUtil m_debug; // Utility to name objects nvvk::DebugUtil m_debug; // Utility to name objects
// #Post // #Post
void createOffscreenRender(); void createOffscreenRender();
@ -119,41 +118,41 @@ public:
void updatePostDescriptorSet(); void updatePostDescriptorSet();
void drawPost(vk::CommandBuffer cmdBuf); void drawPost(vk::CommandBuffer cmdBuf);
std::vector<vk::DescriptorSetLayoutBinding> m_postDescSetLayoutBind; nvvk::DescriptorSetBindings m_postDescSetLayoutBind;
vk::DescriptorPool m_postDescPool; vk::DescriptorPool m_postDescPool;
vk::DescriptorSetLayout m_postDescSetLayout; vk::DescriptorSetLayout m_postDescSetLayout;
vk::DescriptorSet m_postDescSet; vk::DescriptorSet m_postDescSet;
vk::Pipeline m_postPipeline; vk::Pipeline m_postPipeline;
vk::PipelineLayout m_postPipelineLayout; vk::PipelineLayout m_postPipelineLayout;
vk::RenderPass m_offscreenRenderPass; vk::RenderPass m_offscreenRenderPass;
vk::Framebuffer m_offscreenFramebuffer; vk::Framebuffer m_offscreenFramebuffer;
nvvkTexture m_offscreenColor; nvvk::Texture m_offscreenColor;
vk::Format m_offscreenColorFormat{vk::Format::eR32G32B32A32Sfloat}; vk::Format m_offscreenColorFormat{vk::Format::eR32G32B32A32Sfloat};
nvvkTexture m_offscreenDepth; nvvk::Texture m_offscreenDepth;
vk::Format m_offscreenDepthFormat{vk::Format::eD32Sfloat}; vk::Format m_offscreenDepthFormat{vk::Format::eD32Sfloat};
// #VKRay // #VKRay
void initRayTracing(); void initRayTracing();
nvvkpp::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model); nvvk::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
void createBottomLevelAS(); void createBottomLevelAS();
void createTopLevelAS(); void createTopLevelAS();
void createRtDescriptorSet(); void createRtDescriptorSet();
void updateRtDescriptorSet(); void updateRtDescriptorSet();
void createRtPipeline(); void createRtPipeline();
void createRtShaderBindingTable(); void createRtShaderBindingTable();
void raytrace(const vk::CommandBuffer& cmdBuf, const nvmath::vec4f& clearColor); void raytrace(const vk::CommandBuffer& cmdBuf, const nvmath::vec4f& clearColor);
vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties; vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties;
nvvkpp::RaytracingBuilderKHR m_rtBuilder; nvvk::RaytracingBuilderKHR m_rtBuilder;
std::vector<vk::DescriptorSetLayoutBinding> m_rtDescSetLayoutBind; nvvk::DescriptorSetBindings m_rtDescSetLayoutBind;
vk::DescriptorPool m_rtDescPool; vk::DescriptorPool m_rtDescPool;
vk::DescriptorSetLayout m_rtDescSetLayout; vk::DescriptorSetLayout m_rtDescSetLayout;
vk::DescriptorSet m_rtDescSet; vk::DescriptorSet m_rtDescSet;
std::vector<vk::RayTracingShaderGroupCreateInfoKHR> m_rtShaderGroups; std::vector<vk::RayTracingShaderGroupCreateInfoKHR> m_rtShaderGroups;
vk::PipelineLayout m_rtPipelineLayout; vk::PipelineLayout m_rtPipelineLayout;
vk::Pipeline m_rtPipeline; vk::Pipeline m_rtPipeline;
nvvkBuffer m_rtSBTBuffer; nvvk::Buffer m_rtSBTBuffer;
struct RtPushConstant struct RtPushConstant
{ {
@ -176,12 +175,12 @@ public:
nvmath::vec3f maximum; nvmath::vec3f maximum;
}; };
nvvkpp::RaytracingBuilderKHR::Blas sphereToVkGeometryKHR(); nvvk::RaytracingBuilderKHR::Blas sphereToVkGeometryKHR();
std::vector<Sphere> m_spheres; // All spheres std::vector<Sphere> m_spheres; // All spheres
nvvkBuffer m_spheresBuffer; // Buffer holding the spheres nvvk::Buffer m_spheresBuffer; // Buffer holding the spheres
nvvkBuffer m_spheresAabbBuffer; // Buffer of all Aabb nvvk::Buffer m_spheresAabbBuffer; // Buffer of all Aabb
nvvkBuffer m_spheresMatColorBuffer; // Multiple materials nvvk::Buffer m_spheresMatColorBuffer; // Multiple materials
nvvkBuffer m_spheresMatIndexBuffer; // Define which sphere uses which material nvvk::Buffer m_spheresMatIndexBuffer; // Define which sphere uses which material
void createSpheres(); void createSpheres();
}; };

View file

@ -31,6 +31,7 @@
#include <array> #include <array>
#include <vulkan/vulkan.hpp> #include <vulkan/vulkan.hpp>
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
#include "imgui.h" #include "imgui.h"
#include "imgui_impl_glfw.h" #include "imgui_impl_glfw.h"
@ -39,10 +40,10 @@
#include "nvh/cameramanipulator.hpp" #include "nvh/cameramanipulator.hpp"
#include "nvh/fileoperations.hpp" #include "nvh/fileoperations.hpp"
#include "nvpsystem.hpp" #include "nvpsystem.hpp"
#include "nvvkpp/appbase_vkpp.hpp" #include "nvvk/appbase_vkpp.hpp"
#include "nvvkpp/commands_vkpp.hpp" #include "nvvk/commands_vk.hpp"
#include "nvvkpp/context_vkpp.hpp" #include "nvvk/context_vk.hpp"
#include "nvvkpp/utilities_vkpp.hpp"
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
#define UNUSED(x) (void)(x) #define UNUSED(x) (void)(x)
@ -124,7 +125,7 @@ int main(int argc, char** argv)
vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature; vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature;
// Requesting Vulkan extensions and layers // Requesting Vulkan extensions and layers
nvvkpp::ContextCreateInfo contextInfo(true); nvvk::ContextCreateInfo contextInfo(true);
contextInfo.setVersion(1, 2); contextInfo.setVersion(1, 2);
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true); contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME); contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME);
@ -148,7 +149,7 @@ int main(int argc, char** argv)
contextInfo.addDeviceExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME); contextInfo.addDeviceExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
// Creating Vulkan base application // Creating Vulkan base application
nvvkpp::Context vkctx{}; nvvk::Context vkctx{};
vkctx.initInstance(contextInfo); vkctx.initInstance(contextInfo);
// Find all compatible devices // Find all compatible devices
auto compatibleDevices = vkctx.getCompatibleDevices(contextInfo); auto compatibleDevices = vkctx.getCompatibleDevices(contextInfo);
@ -163,7 +164,8 @@ int main(int argc, char** argv)
const vk::SurfaceKHR surface = helloVk.getVkSurface(vkctx.m_instance, window); const vk::SurfaceKHR surface = helloVk.getVkSurface(vkctx.m_instance, window);
vkctx.setGCTQueueWithPresent(surface); vkctx.setGCTQueueWithPresent(surface);
helloVk.setup(vkctx.m_device, vkctx.m_physicalDevice, vkctx.m_queueGCT.familyIndex); helloVk.setup(vkctx.m_instance, vkctx.m_device, vkctx.m_physicalDevice,
vkctx.m_queueGCT.familyIndex);
helloVk.createSurface(surface, SAMPLE_WIDTH, SAMPLE_HEIGHT); helloVk.createSurface(surface, SAMPLE_WIDTH, SAMPLE_HEIGHT);
helloVk.createDepthBuffer(); helloVk.createDepthBuffer();
helloVk.createRenderPass(); helloVk.createRenderPass();
@ -241,7 +243,8 @@ int main(int argc, char** argv)
// Clearing screen // Clearing screen
vk::ClearValue clearValues[2]; vk::ClearValue clearValues[2];
clearValues[0].setColor(nvvkpp::util::clearColor(clearColor)); clearValues[0].setColor(
std::array<float, 4>({clearColor[0], clearColor[1], clearColor[2], clearColor[3]}));
clearValues[1].setDepthStencil({1.0f, 0}); clearValues[1].setDepthStencil({1.0f, 0});
// Offscreen render pass // Offscreen render pass
@ -293,7 +296,6 @@ int main(int argc, char** argv)
helloVk.destroyResources(); helloVk.destroyResources();
helloVk.destroy(); helloVk.destroy();
vkctx.m_instance.destroySurfaceKHR(surface);
vkctx.deinit(); vkctx.deinit();
glfwDestroyWindow(window); glfwDestroyWindow(window);

View file

@ -6,7 +6,7 @@
#include "raycommon.glsl" #include "raycommon.glsl"
#include "wavefront.glsl" #include "wavefront.glsl"
hitAttributeEXT vec3 attribs; hitAttributeEXT vec2 attribs;
// clang-format off // clang-format off
layout(location = 0) rayPayloadInEXT hitPayload prd; layout(location = 0) rayPayloadInEXT hitPayload prd;

View file

@ -6,7 +6,7 @@
#include "raycommon.glsl" #include "raycommon.glsl"
#include "wavefront.glsl" #include "wavefront.glsl"
hitAttributeEXT vec3 attribs; hitAttributeEXT vec2 attribs;
// clang-format off // clang-format off
layout(location = 0) rayPayloadInEXT hitPayload prd; layout(location = 0) rayPayloadInEXT hitPayload prd;

View file

@ -36,13 +36,14 @@ extern std::vector<std::string> defaultSearchPaths;
#include "hello_vulkan.h" #include "hello_vulkan.h"
#include "nvh//cameramanipulator.hpp" #include "nvh//cameramanipulator.hpp"
#include "nvvkpp/descriptorsets_vkpp.hpp" #include "nvvk/descriptorsets_vk.hpp"
#include "nvvkpp/pipeline_vkpp.hpp" #include "nvvk/pipeline_vk.hpp"
#include "nvh/fileoperations.hpp" #include "nvh/fileoperations.hpp"
#include "nvvkpp/commands_vkpp.hpp" #include "nvvk/commands_vk.hpp"
#include "nvvkpp/renderpass_vkpp.hpp" #include "nvvk/renderpasses_vk.hpp"
#include "nvvkpp/utilities_vkpp.hpp" #include "nvvk/shaders_vk.hpp"
// Holding the camera matrices // Holding the camera matrices
struct CameraMatrices struct CameraMatrices
@ -58,11 +59,12 @@ struct CameraMatrices
// Keep the handle on the device // Keep the handle on the device
// Initialize the tool to do all our allocations: buffers, images // Initialize the tool to do all our allocations: buffers, images
// //
void HelloVulkan::setup(const vk::Device& device, void HelloVulkan::setup(const vk::Instance& instance,
const vk::Device& device,
const vk::PhysicalDevice& physicalDevice, const vk::PhysicalDevice& physicalDevice,
uint32_t queueFamily) uint32_t queueFamily)
{ {
AppBase::setup(device, physicalDevice, queueFamily); AppBase::setup(instance, device, physicalDevice, queueFamily);
m_alloc.init(device, physicalDevice); m_alloc.init(device, physicalDevice);
m_debug.setup(m_device); m_debug.setup(m_device);
} }
@ -99,31 +101,31 @@ void HelloVulkan::createDescriptorSetLayout()
uint32_t nbObj = static_cast<uint32_t>(m_objModel.size()); uint32_t nbObj = static_cast<uint32_t>(m_objModel.size());
// Camera matrices (binding = 0) // Camera matrices (binding = 0)
m_descSetLayoutBind.emplace_back( m_descSetLayoutBind.addBinding(
vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR)); vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR));
// Materials (binding = 1) // Materials (binding = 1)
m_descSetLayoutBind.emplace_back( m_descSetLayoutBind.addBinding(
vkDS(1, vkDT::eStorageBuffer, nbObj, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR)); vkDS(1, vkDT::eStorageBuffer, nbObj, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
// Scene description (binding = 2) // Scene description (binding = 2)
m_descSetLayoutBind.emplace_back( // m_descSetLayoutBind.addBinding( //
vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR)); vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
// Textures (binding = 3) // Textures (binding = 3)
m_descSetLayoutBind.emplace_back( m_descSetLayoutBind.addBinding(
vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR)); vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR));
// Materials (binding = 4) // Materials (binding = 4)
m_descSetLayoutBind.emplace_back( m_descSetLayoutBind.addBinding(
vkDS(4, vkDT::eStorageBuffer, nbObj, vkSS::eFragment | vkSS::eClosestHitKHR)); vkDS(4, vkDT::eStorageBuffer, nbObj, vkSS::eFragment | vkSS::eClosestHitKHR));
// Storing vertices (binding = 5) // Storing vertices (binding = 5)
m_descSetLayoutBind.emplace_back( // m_descSetLayoutBind.addBinding( //
vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR)); vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
// Storing indices (binding = 6) // Storing indices (binding = 6)
m_descSetLayoutBind.emplace_back( // m_descSetLayoutBind.addBinding( //
vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR)); vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
m_descSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_descSetLayoutBind); m_descSetLayout = m_descSetLayoutBind.createLayout(m_device);
m_descPool = nvvkpp::util::createDescriptorPool(m_device, m_descSetLayoutBind, 1); m_descPool = m_descSetLayoutBind.createPool(m_device, 1);
m_descSet = nvvkpp::util::createDescriptorSet(m_device, m_descPool, m_descSetLayout); m_descSet = nvvk::allocateDescriptorSet(m_device, m_descPool, m_descSetLayout);
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -135,9 +137,9 @@ void HelloVulkan::updateDescriptorSet()
// Camera matrices and scene description // Camera matrices and scene description
vk::DescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE}; vk::DescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE};
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[0], &dbiUnif)); writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 0, &dbiUnif));
vk::DescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE}; vk::DescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[2], &dbiSceneDesc)); writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 2, &dbiSceneDesc));
// All material buffers, 1 buffer per OBJ // All material buffers, 1 buffer per OBJ
std::vector<vk::DescriptorBufferInfo> dbiMat; std::vector<vk::DescriptorBufferInfo> dbiMat;
@ -151,11 +153,10 @@ void HelloVulkan::updateDescriptorSet()
dbiVert.emplace_back(obj.vertexBuffer.buffer, 0, VK_WHOLE_SIZE); dbiVert.emplace_back(obj.vertexBuffer.buffer, 0, VK_WHOLE_SIZE);
dbiIdx.emplace_back(obj.indexBuffer.buffer, 0, VK_WHOLE_SIZE); dbiIdx.emplace_back(obj.indexBuffer.buffer, 0, VK_WHOLE_SIZE);
} }
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[1], dbiMat.data())); writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 1, dbiMat.data()));
writes.emplace_back( writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 4, dbiMatIdx.data()));
nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[4], dbiMatIdx.data())); writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 5, dbiVert.data()));
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[5], dbiVert.data())); writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 6, dbiIdx.data()));
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[6], dbiIdx.data()));
// All texture samplers // All texture samplers
std::vector<vk::DescriptorImageInfo> diit; std::vector<vk::DescriptorImageInfo> diit;
@ -163,7 +164,7 @@ void HelloVulkan::updateDescriptorSet()
{ {
diit.push_back(texture.descriptor); diit.push_back(texture.descriptor);
} }
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[3], diit.data())); writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 3, diit.data()));
// Writing the information // Writing the information
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr); m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
@ -189,19 +190,18 @@ void HelloVulkan::createGraphicsPipeline()
m_pipelineLayout = m_device.createPipelineLayout(pipelineLayoutCreateInfo); m_pipelineLayout = m_device.createPipelineLayout(pipelineLayoutCreateInfo);
// Creating the Pipeline // Creating the Pipeline
std::vector<std::string> paths = defaultSearchPaths; std::vector<std::string> paths = defaultSearchPaths;
nvvkpp::GraphicsPipelineGenerator gpb(m_device, m_pipelineLayout, m_offscreenRenderPass); nvvk::GraphicsPipelineGeneratorCombined gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
gpb.depthStencilState = {true}; gpb.depthStencilState.depthTestEnable = true;
gpb.addShader(nvh::loadFile("shaders/vert_shader.vert.spv", true, paths), vkSS::eVertex); gpb.addShader(nvh::loadFile("shaders/vert_shader.vert.spv", true, paths), vkSS::eVertex);
gpb.addShader(nvh::loadFile("shaders/frag_shader.frag.spv", true, paths), vkSS::eFragment); gpb.addShader(nvh::loadFile("shaders/frag_shader.frag.spv", true, paths), vkSS::eFragment);
gpb.vertexInputState.bindingDescriptions = {{0, sizeof(VertexObj)}}; gpb.addBindingDescription({0, sizeof(VertexObj)});
gpb.vertexInputState.attributeDescriptions = { gpb.addAttributeDescriptions({{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)}, {1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)},
{1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)}, {2, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, color)},
{2, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, color)}, {3, 0, vk::Format::eR32G32Sfloat, offsetof(VertexObj, texCoord)}});
{3, 0, vk::Format::eR32G32Sfloat, offsetof(VertexObj, texCoord)}};
m_graphicsPipeline = gpb.create(); m_graphicsPipeline = gpb.createPipeline();
m_debug.setObjectName(m_graphicsPipeline, "Graphics"); m_debug.setObjectName(m_graphicsPipeline, "Graphics");
} }
@ -234,8 +234,8 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size()); model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
// Create the buffers on Device and copy vertices, indices and materials // Create the buffers on Device and copy vertices, indices and materials
nvvkpp::SingleCommandBuffer cmdBufGet(m_device, m_graphicsQueueIndex); nvvk::CommandPool cmdBufGet(m_device, m_graphicsQueueIndex);
vk::CommandBuffer cmdBuf = cmdBufGet.createCommandBuffer(); vk::CommandBuffer cmdBuf = cmdBufGet.createCommandBuffer();
model.vertexBuffer = model.vertexBuffer =
m_alloc.createBuffer(cmdBuf, loader.m_vertices, m_alloc.createBuffer(cmdBuf, loader.m_vertices,
vkBU::eVertexBuffer | vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress); vkBU::eVertexBuffer | vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress);
@ -246,8 +246,8 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, vkBU::eStorageBuffer); model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, vkBU::eStorageBuffer);
// Creates all textures found // Creates all textures found
createTextureImages(cmdBuf, loader.m_textures); createTextureImages(cmdBuf, loader.m_textures);
cmdBufGet.flushCommandBuffer(cmdBuf); cmdBufGet.submitAndWait(cmdBuf);
m_alloc.flushStaging(); m_alloc.finalizeAndReleaseStaging();
std::string objNb = std::to_string(instance.objIndex); std::string objNb = std::to_string(instance.objIndex);
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str())); m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
@ -282,12 +282,12 @@ void HelloVulkan::createUniformBuffer()
void HelloVulkan::createSceneDescriptionBuffer() void HelloVulkan::createSceneDescriptionBuffer()
{ {
using vkBU = vk::BufferUsageFlagBits; using vkBU = vk::BufferUsageFlagBits;
nvvkpp::SingleCommandBuffer cmdGen(m_device, m_graphicsQueueIndex); nvvk::CommandPool cmdGen(m_device, m_graphicsQueueIndex);
auto cmdBuf = cmdGen.createCommandBuffer(); auto cmdBuf = cmdGen.createCommandBuffer();
m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer); m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer);
cmdGen.flushCommandBuffer(cmdBuf); cmdGen.submitAndWait(cmdBuf);
m_alloc.flushStaging(); m_alloc.finalizeAndReleaseStaging();
m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc"); m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc");
} }
@ -307,21 +307,21 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
// If no textures are present, create a dummy one to accommodate the pipeline layout // If no textures are present, create a dummy one to accommodate the pipeline layout
if(textures.empty() && m_textures.empty()) if(textures.empty() && m_textures.empty())
{ {
nvvkTexture texture; nvvk::Texture texture;
std::array<uint8_t, 4> color{255u, 255u, 255u, 255u}; std::array<uint8_t, 4> color{255u, 255u, 255u, 255u};
vk::DeviceSize bufferSize = sizeof(color); vk::DeviceSize bufferSize = sizeof(color);
auto imgSize = vk::Extent2D(1, 1); auto imgSize = vk::Extent2D(1, 1);
auto imageCreateInfo = nvvkpp::image::create2DInfo(imgSize, format); auto imageCreateInfo = nvvk::makeImage2DCreateInfo(imgSize, format);
// Creating the dummy texure
nvvk::Image image = m_alloc.createImage(cmdBuf, bufferSize, color.data(), imageCreateInfo);
vk::ImageViewCreateInfo ivInfo = nvvk::makeImageViewCreateInfo(image.image, imageCreateInfo);
texture = m_alloc.createTexture(image, ivInfo, samplerCreateInfo);
// Creating the VKImage
texture = m_alloc.createImage(cmdBuf, bufferSize, color.data(), imageCreateInfo);
// Setting up the descriptor used by the shader
texture.descriptor =
nvvkpp::image::create2DDescriptor(m_device, texture.image, samplerCreateInfo, format);
// The image format must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL // The image format must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
nvvkpp::image::setImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined, nvvk::cmdBarrierImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eShaderReadOnlyOptimal); vk::ImageLayout::eShaderReadOnlyOptimal);
m_textures.push_back(texture); m_textures.push_back(texture);
} }
else else
@ -348,16 +348,16 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4; vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4;
auto imgSize = vk::Extent2D(texWidth, texHeight); auto imgSize = vk::Extent2D(texWidth, texHeight);
auto imageCreateInfo = nvvkpp::image::create2DInfo(imgSize, format, vkIU::eSampled, true); auto imageCreateInfo = nvvk::makeImage2DCreateInfo(imgSize, format, vkIU::eSampled, true);
{ {
nvvkTexture texture; nvvk::ImageDedicated image =
texture = m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo); m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo);
nvvk::cmdGenerateMipmaps(cmdBuf, image.image, format, imgSize, imageCreateInfo.mipLevels);
vk::ImageViewCreateInfo ivInfo =
nvvk::makeImageViewCreateInfo(image.image, imageCreateInfo);
nvvk::Texture texture = m_alloc.createTexture(image, ivInfo, samplerCreateInfo);
nvvkpp::image::generateMipmaps(cmdBuf, texture.image, format, imgSize,
imageCreateInfo.mipLevels);
texture.descriptor =
nvvkpp::image::create2DDescriptor(m_device, texture.image, samplerCreateInfo, format);
m_textures.push_back(texture); m_textures.push_back(texture);
} }
} }
@ -434,7 +434,7 @@ void HelloVulkan::rasterize(const vk::CommandBuffer& cmdBuf)
cmdBuf.pushConstants<ObjPushConstant>(m_pipelineLayout, vkSS::eVertex | vkSS::eFragment, 0, cmdBuf.pushConstants<ObjPushConstant>(m_pipelineLayout, vkSS::eVertex | vkSS::eFragment, 0,
m_pushConstant); m_pushConstant);
cmdBuf.bindVertexBuffers(0, 1, &model.vertexBuffer.buffer, &offset); cmdBuf.bindVertexBuffers(0, {model.vertexBuffer.buffer}, {offset});
cmdBuf.bindIndexBuffer(model.indexBuffer.buffer, 0, vk::IndexType::eUint32); cmdBuf.bindIndexBuffer(model.indexBuffer.buffer, 0, vk::IndexType::eUint32);
cmdBuf.drawIndexed(model.nbIndices, 1, 0, 0, 0); cmdBuf.drawIndexed(model.nbIndices, 1, 0, 0, 0);
} }
@ -464,49 +464,54 @@ void HelloVulkan::createOffscreenRender()
m_alloc.destroy(m_offscreenDepth); m_alloc.destroy(m_offscreenDepth);
// Creating the color image // Creating the color image
auto colorCreateInfo = nvvkpp::image::create2DInfo(m_size, m_offscreenColorFormat, {
vk::ImageUsageFlagBits::eColorAttachment auto colorCreateInfo = nvvk::makeImage2DCreateInfo(m_size, m_offscreenColorFormat,
| vk::ImageUsageFlagBits::eSampled vk::ImageUsageFlagBits::eColorAttachment
| vk::ImageUsageFlagBits::eStorage); | vk::ImageUsageFlagBits::eSampled
m_offscreenColor = m_alloc.createImage(colorCreateInfo); | vk::ImageUsageFlagBits::eStorage);
m_offscreenColor.descriptor =
nvvkpp::image::create2DDescriptor(m_device, m_offscreenColor.image, vk::SamplerCreateInfo{}, nvvk::Image image = m_alloc.createImage(colorCreateInfo);
m_offscreenColorFormat, vk::ImageLayout::eGeneral); vk::ImageViewCreateInfo ivInfo = nvvk::makeImageViewCreateInfo(image.image, colorCreateInfo);
m_offscreenColor = m_alloc.createTexture(image, ivInfo, vk::SamplerCreateInfo());
m_offscreenColor.descriptor.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
}
// Creating the depth buffer // Creating the depth buffer
auto depthCreateInfo = auto depthCreateInfo =
nvvkpp::image::create2DInfo(m_size, m_offscreenDepthFormat, nvvk::makeImage2DCreateInfo(m_size, m_offscreenDepthFormat,
vk::ImageUsageFlagBits::eDepthStencilAttachment); vk::ImageUsageFlagBits::eDepthStencilAttachment);
m_offscreenDepth = m_alloc.createImage(depthCreateInfo); {
nvvk::Image image = m_alloc.createImage(depthCreateInfo);
vk::ImageViewCreateInfo depthStencilView; vk::ImageViewCreateInfo depthStencilView;
depthStencilView.setViewType(vk::ImageViewType::e2D); depthStencilView.setViewType(vk::ImageViewType::e2D);
depthStencilView.setFormat(m_offscreenDepthFormat); depthStencilView.setFormat(m_offscreenDepthFormat);
depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1}); depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1});
depthStencilView.setImage(m_offscreenDepth.image); depthStencilView.setImage(image.image);
m_offscreenDepth.descriptor.imageView = m_device.createImageView(depthStencilView);
m_offscreenDepth = m_alloc.createTexture(image, depthStencilView);
}
// Setting the image layout for both color and depth // Setting the image layout for both color and depth
{ {
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex); nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
auto cmdBuf = genCmdBuf.createCommandBuffer(); auto cmdBuf = genCmdBuf.createCommandBuffer();
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined, nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eGeneral); vk::ImageLayout::eGeneral);
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageAspectFlagBits::eDepth, nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eUndefined, vk::ImageLayout::eDepthStencilAttachmentOptimal,
vk::ImageLayout::eDepthStencilAttachmentOptimal); vk::ImageAspectFlagBits::eDepth);
genCmdBuf.flushCommandBuffer(cmdBuf); genCmdBuf.submitAndWait(cmdBuf);
} }
// Creating a renderpass for the offscreen // Creating a renderpass for the offscreen
if(!m_offscreenRenderPass) if(!m_offscreenRenderPass)
{ {
m_offscreenRenderPass = m_offscreenRenderPass =
nvvkpp::util::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat, nvvk::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat, 1, true,
1, true, true, vk::ImageLayout::eGeneral, true, vk::ImageLayout::eGeneral, vk::ImageLayout::eGeneral);
vk::ImageLayout::eGeneral);
} }
// Creating the frame buffer for offscreen // Creating the frame buffer for offscreen
@ -543,13 +548,14 @@ void HelloVulkan::createPostPipeline()
// Pipeline: completely generic, no vertices // Pipeline: completely generic, no vertices
std::vector<std::string> paths = defaultSearchPaths; std::vector<std::string> paths = defaultSearchPaths;
nvvkpp::GraphicsPipelineGenerator pipelineGenerator(m_device, m_postPipelineLayout, m_renderPass); nvvk::GraphicsPipelineGeneratorCombined pipelineGenerator(m_device, m_postPipelineLayout,
m_renderPass);
pipelineGenerator.addShader(nvh::loadFile("shaders/passthrough.vert.spv", true, paths), pipelineGenerator.addShader(nvh::loadFile("shaders/passthrough.vert.spv", true, paths),
vk::ShaderStageFlagBits::eVertex); vk::ShaderStageFlagBits::eVertex);
pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths), pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths),
vk::ShaderStageFlagBits::eFragment); vk::ShaderStageFlagBits::eFragment);
pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone); pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone);
m_postPipeline = pipelineGenerator.create(); m_postPipeline = pipelineGenerator.createPipeline();
m_debug.setObjectName(m_postPipeline, "post"); m_debug.setObjectName(m_postPipeline, "post");
} }
@ -563,10 +569,10 @@ void HelloVulkan::createPostDescriptor()
using vkDT = vk::DescriptorType; using vkDT = vk::DescriptorType;
using vkSS = vk::ShaderStageFlagBits; using vkSS = vk::ShaderStageFlagBits;
m_postDescSetLayoutBind.emplace_back(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment)); m_postDescSetLayoutBind.addBinding(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
m_postDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_postDescSetLayoutBind); m_postDescSetLayout = m_postDescSetLayoutBind.createLayout(m_device);
m_postDescPool = nvvkpp::util::createDescriptorPool(m_device, m_postDescSetLayoutBind); m_postDescPool = m_postDescSetLayoutBind.createPool(m_device);
m_postDescSet = nvvkpp::util::createDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout); m_postDescSet = nvvk::allocateDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -575,8 +581,7 @@ void HelloVulkan::createPostDescriptor()
void HelloVulkan::updatePostDescriptorSet() void HelloVulkan::updatePostDescriptorSet()
{ {
vk::WriteDescriptorSet writeDescriptorSets = vk::WriteDescriptorSet writeDescriptorSets =
nvvkpp::util::createWrite(m_postDescSet, m_postDescSetLayoutBind[0], m_postDescSetLayoutBind.makeWrite(m_postDescSet, 0, &m_offscreenColor.descriptor);
&m_offscreenColor.descriptor);
m_device.updateDescriptorSets(writeDescriptorSets, nullptr); m_device.updateDescriptorSets(writeDescriptorSets, nullptr);
} }
@ -614,15 +619,15 @@ void HelloVulkan::initRayTracing()
auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2, auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2,
vk::PhysicalDeviceRayTracingPropertiesKHR>(); vk::PhysicalDeviceRayTracingPropertiesKHR>();
m_rtProperties = properties.get<vk::PhysicalDeviceRayTracingPropertiesKHR>(); m_rtProperties = properties.get<vk::PhysicalDeviceRayTracingPropertiesKHR>();
m_rtBuilder.setup(m_device, m_physicalDevice, m_graphicsQueueIndex); m_rtBuilder.setup(m_device, &m_alloc, m_graphicsQueueIndex);
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Converting a OBJ primitive to the ray tracing geometry used for the BLAS // Converting a OBJ primitive to the ray tracing geometry used for the BLAS
// //
nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model) nvvk::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model)
{ {
nvvkpp::RaytracingBuilderKHR::Blas blas; nvvk::RaytracingBuilderKHR::Blas blas;
vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate; vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate;
asCreate.setGeometryType(vk::GeometryTypeKHR::eTriangles); asCreate.setGeometryType(vk::GeometryTypeKHR::eTriangles);
asCreate.setIndexType(vk::IndexType::eUint32); asCreate.setIndexType(vk::IndexType::eUint32);
@ -659,7 +664,7 @@ nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjM
void HelloVulkan::createBottomLevelAS() void HelloVulkan::createBottomLevelAS()
{ {
// BLAS - Storing each primitive in a geometry // BLAS - Storing each primitive in a geometry
std::vector<nvvkpp::RaytracingBuilderKHR::Blas> allBlas; std::vector<nvvk::RaytracingBuilderKHR::Blas> allBlas;
allBlas.reserve(m_objModel.size()); allBlas.reserve(m_objModel.size());
for(const auto& obj : m_objModel) for(const auto& obj : m_objModel)
{ {
@ -673,16 +678,16 @@ void HelloVulkan::createBottomLevelAS()
void HelloVulkan::createTopLevelAS() void HelloVulkan::createTopLevelAS()
{ {
std::vector<nvvkpp::RaytracingBuilderKHR::Instance> tlas; std::vector<nvvk::RaytracingBuilderKHR::Instance> tlas;
tlas.reserve(m_objInstance.size()); tlas.reserve(m_objInstance.size());
for(int i = 0; i < static_cast<int>(m_objInstance.size()); i++) for(int i = 0; i < static_cast<int>(m_objInstance.size()); i++)
{ {
nvvkpp::RaytracingBuilderKHR::Instance rayInst; nvvk::RaytracingBuilderKHR::Instance rayInst;
rayInst.transform = m_objInstance[i].transform; // Position of the instance rayInst.transform = m_objInstance[i].transform; // Position of the instance
rayInst.instanceId = i; // gl_InstanceID rayInst.instanceId = i; // gl_InstanceID
rayInst.blasId = m_objInstance[i].objIndex; rayInst.blasId = m_objInstance[i].objIndex;
rayInst.hitGroupId = 0; // We will use the same hit group for all objects rayInst.hitGroupId = 0; // We will use the same hit group for all objects
rayInst.flags = vk::GeometryInstanceFlagBitsKHR::eTriangleCullDisable; rayInst.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
tlas.emplace_back(rayInst); tlas.emplace_back(rayInst);
} }
m_rtBuilder.buildTlas(tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace); m_rtBuilder.buildTlas(tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace);
@ -697,25 +702,25 @@ void HelloVulkan::createRtDescriptorSet()
using vkSS = vk::ShaderStageFlagBits; using vkSS = vk::ShaderStageFlagBits;
using vkDSLB = vk::DescriptorSetLayoutBinding; using vkDSLB = vk::DescriptorSetLayoutBinding;
m_rtDescSetLayoutBind.emplace_back(vkDSLB(0, vkDT::eAccelerationStructureKHR, 1, m_rtDescSetLayoutBind.addBinding(vkDSLB(0, vkDT::eAccelerationStructureKHR, 1,
vkSS::eRaygenKHR | vkSS::eClosestHitKHR)); // TLAS vkSS::eRaygenKHR | vkSS::eClosestHitKHR)); // TLAS
m_rtDescSetLayoutBind.emplace_back( m_rtDescSetLayoutBind.addBinding(
vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image
m_rtDescPool = nvvkpp::util::createDescriptorPool(m_device, m_rtDescSetLayoutBind); m_rtDescPool = m_rtDescSetLayoutBind.createPool(m_device);
m_rtDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_rtDescSetLayoutBind); m_rtDescSetLayout = m_rtDescSetLayoutBind.createLayout(m_device);
m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0]; m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0];
vk::AccelerationStructureKHR tlas = m_rtBuilder.getAccelerationStructure();
vk::WriteDescriptorSetAccelerationStructureKHR descASInfo; vk::WriteDescriptorSetAccelerationStructureKHR descASInfo;
descASInfo.setAccelerationStructureCount(1); descASInfo.setAccelerationStructureCount(1);
descASInfo.setPAccelerationStructures(&m_rtBuilder.getAccelerationStructure()); descASInfo.setPAccelerationStructures(&tlas);
vk::DescriptorImageInfo imageInfo{ vk::DescriptorImageInfo imageInfo{
{}, m_offscreenColor.descriptor.imageView, vk::ImageLayout::eGeneral}; {}, m_offscreenColor.descriptor.imageView, vk::ImageLayout::eGeneral};
std::vector<vk::WriteDescriptorSet> writes; std::vector<vk::WriteDescriptorSet> writes;
writes.emplace_back( writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 0, &descASInfo));
nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[0], &descASInfo)); writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 1, &imageInfo));
writes.emplace_back(nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[1], &imageInfo));
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr); m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
} }
@ -744,16 +749,17 @@ void HelloVulkan::createRtPipeline()
std::vector<std::string> paths = defaultSearchPaths; std::vector<std::string> paths = defaultSearchPaths;
vk::ShaderModule raygenSM = vk::ShaderModule raygenSM =
nvvkpp::util::createShaderModule(m_device, // nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rgen.spv", true, paths)); nvh::loadFile("shaders/raytrace.rgen.spv", true, paths));
vk::ShaderModule missSM = vk::ShaderModule missSM =
nvvkpp::util::createShaderModule(m_device, // nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths)); nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths));
// The second miss shader is invoked when a shadow ray misses the geometry. It // The second miss shader is invoked when a shadow ray misses the geometry. It
// simply indicates that no occlusion has been found // simply indicates that no occlusion has been found
vk::ShaderModule shadowmissSM = nvvkpp::util::createShaderModule( vk::ShaderModule shadowmissSM =
m_device, nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths)); nvvk::createShaderModule(m_device,
nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
std::vector<vk::PipelineShaderStageCreateInfo> stages; std::vector<vk::PipelineShaderStageCreateInfo> stages;
@ -779,8 +785,8 @@ void HelloVulkan::createRtPipeline()
// Hit Group - Closest Hit + AnyHit // Hit Group - Closest Hit + AnyHit
vk::ShaderModule chitSM = vk::ShaderModule chitSM =
nvvkpp::util::createShaderModule(m_device, // nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rchit.spv", true, paths)); nvh::loadFile("shaders/raytrace.rchit.spv", true, paths));
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup, vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup,
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR,
@ -844,17 +850,17 @@ void HelloVulkan::createRtShaderBindingTable()
m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize, m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize,
shaderHandleStorage.data()); shaderHandleStorage.data());
// Write the handles in the SBT // Write the handles in the SBT
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex); nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer(); vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
m_rtSBTBuffer = m_rtSBTBuffer =
m_alloc.createBuffer(cmdBuf, shaderHandleStorage, vk::BufferUsageFlagBits::eRayTracingKHR); m_alloc.createBuffer(cmdBuf, shaderHandleStorage, vk::BufferUsageFlagBits::eRayTracingKHR);
m_debug.setObjectName(m_rtSBTBuffer.buffer, "SBT"); m_debug.setObjectName(m_rtSBTBuffer.buffer, "SBT");
genCmdBuf.flushCommandBuffer(cmdBuf); genCmdBuf.submitAndWait(cmdBuf);
m_alloc.flushStaging(); m_alloc.finalizeAndReleaseStaging();
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------

View file

@ -26,16 +26,14 @@
*/ */
#pragma once #pragma once
#include "nvvkpp/allocator_dedicated_vkpp.hpp" #define NVVK_ALLOC_DEDICATED
#include "nvvkpp/appbase_vkpp.hpp" #include "nvvk/allocator_vk.hpp"
#include "nvvkpp/debug_util_vkpp.hpp" #include "nvvk/appbase_vkpp.hpp"
#include "nvvk/debug_util_vk.hpp"
#include "nvvk/descriptorsets_vk.hpp"
// #VKRay // #VKRay
#define ALLOC_DEDICATED #include "nvvk/raytraceKHR_vk.hpp"
#include "nvvkpp/raytraceKHR_vkpp.hpp"
using nvvkBuffer = nvvkpp::BufferDedicated;
using nvvkTexture = nvvkpp::TextureDedicated;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Simple rasterizer of OBJ objects // Simple rasterizer of OBJ objects
@ -44,10 +42,11 @@ using nvvkTexture = nvvkpp::TextureDedicated;
// - Rendering is done in an offscreen framebuffer // - Rendering is done in an offscreen framebuffer
// - The image of the framebuffer is displayed in post-process in a full-screen quad // - The image of the framebuffer is displayed in post-process in a full-screen quad
// //
class HelloVulkan : public nvvkpp::AppBase class HelloVulkan : public nvvk::AppBase
{ {
public: public:
void setup(const vk::Device& device, void setup(const vk::Instance& instance,
const vk::Device& device,
const vk::PhysicalDevice& physicalDevice, const vk::PhysicalDevice& physicalDevice,
uint32_t queueFamily) override; uint32_t queueFamily) override;
void createDescriptorSetLayout(); void createDescriptorSetLayout();
@ -66,12 +65,12 @@ public:
// The OBJ model // The OBJ model
struct ObjModel struct ObjModel
{ {
uint32_t nbIndices{0}; uint32_t nbIndices{0};
uint32_t nbVertices{0}; uint32_t nbVertices{0};
nvvkBuffer vertexBuffer; // Device buffer of all 'Vertex' nvvk::Buffer vertexBuffer; // Device buffer of all 'Vertex'
nvvkBuffer indexBuffer; // Device buffer of the indices forming triangles nvvk::Buffer indexBuffer; // Device buffer of the indices forming triangles
nvvkBuffer matColorBuffer; // Device buffer of array of 'Wavefront material' nvvk::Buffer matColorBuffer; // Device buffer of array of 'Wavefront material'
nvvkBuffer matIndexBuffer; // Device buffer of array of 'Wavefront material' nvvk::Buffer matIndexBuffer; // Device buffer of array of 'Wavefront material'
}; };
// Instance of the OBJ // Instance of the OBJ
@ -98,19 +97,19 @@ public:
std::vector<ObjInstance> m_objInstance; std::vector<ObjInstance> m_objInstance;
// Graphic pipeline // Graphic pipeline
vk::PipelineLayout m_pipelineLayout; vk::PipelineLayout m_pipelineLayout;
vk::Pipeline m_graphicsPipeline; vk::Pipeline m_graphicsPipeline;
std::vector<vk::DescriptorSetLayoutBinding> m_descSetLayoutBind; nvvk::DescriptorSetBindings m_descSetLayoutBind;
vk::DescriptorPool m_descPool; vk::DescriptorPool m_descPool;
vk::DescriptorSetLayout m_descSetLayout; vk::DescriptorSetLayout m_descSetLayout;
vk::DescriptorSet m_descSet; vk::DescriptorSet m_descSet;
nvvkBuffer m_cameraMat; // Device-Host of the camera matrices nvvk::Buffer m_cameraMat; // Device-Host of the camera matrices
nvvkBuffer m_sceneDesc; // Device buffer of the OBJ instances nvvk::Buffer m_sceneDesc; // Device buffer of the OBJ instances
std::vector<nvvkTexture> m_textures; // vector of all textures of the scene std::vector<nvvk::Texture> m_textures; // vector of all textures of the scene
nvvkpp::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures nvvk::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures
nvvkpp::DebugUtil m_debug; // Utility to name objects nvvk::DebugUtil m_debug; // Utility to name objects
// #Post // #Post
void createOffscreenRender(); void createOffscreenRender();
@ -119,42 +118,42 @@ public:
void updatePostDescriptorSet(); void updatePostDescriptorSet();
void drawPost(vk::CommandBuffer cmdBuf); void drawPost(vk::CommandBuffer cmdBuf);
std::vector<vk::DescriptorSetLayoutBinding> m_postDescSetLayoutBind; nvvk::DescriptorSetBindings m_postDescSetLayoutBind;
vk::DescriptorPool m_postDescPool; vk::DescriptorPool m_postDescPool;
vk::DescriptorSetLayout m_postDescSetLayout; vk::DescriptorSetLayout m_postDescSetLayout;
vk::DescriptorSet m_postDescSet; vk::DescriptorSet m_postDescSet;
vk::Pipeline m_postPipeline; vk::Pipeline m_postPipeline;
vk::PipelineLayout m_postPipelineLayout; vk::PipelineLayout m_postPipelineLayout;
vk::RenderPass m_offscreenRenderPass; vk::RenderPass m_offscreenRenderPass;
vk::Framebuffer m_offscreenFramebuffer; vk::Framebuffer m_offscreenFramebuffer;
nvvkTexture m_offscreenColor; nvvk::Texture m_offscreenColor;
vk::Format m_offscreenColorFormat{vk::Format::eR32G32B32A32Sfloat}; vk::Format m_offscreenColorFormat{vk::Format::eR32G32B32A32Sfloat};
nvvkTexture m_offscreenDepth; nvvk::Texture m_offscreenDepth;
vk::Format m_offscreenDepthFormat{vk::Format::eD32Sfloat}; vk::Format m_offscreenDepthFormat{vk::Format::eD32Sfloat};
// #VKRay // #VKRay
void initRayTracing(); void initRayTracing();
nvvkpp::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model); nvvk::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
void createBottomLevelAS(); void createBottomLevelAS();
void createTopLevelAS(); void createTopLevelAS();
void createRtDescriptorSet(); void createRtDescriptorSet();
void updateRtDescriptorSet(); void updateRtDescriptorSet();
void createRtPipeline(); void createRtPipeline();
void createRtShaderBindingTable(); void createRtShaderBindingTable();
void raytrace(const vk::CommandBuffer& cmdBuf, const nvmath::vec4f& clearColor); void raytrace(const vk::CommandBuffer& cmdBuf, const nvmath::vec4f& clearColor);
void resetFrame(); void resetFrame();
void updateFrame(); void updateFrame();
vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties; vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties;
nvvkpp::RaytracingBuilderKHR m_rtBuilder; nvvk::RaytracingBuilderKHR m_rtBuilder;
std::vector<vk::DescriptorSetLayoutBinding> m_rtDescSetLayoutBind; nvvk::DescriptorSetBindings m_rtDescSetLayoutBind;
vk::DescriptorPool m_rtDescPool; vk::DescriptorPool m_rtDescPool;
vk::DescriptorSetLayout m_rtDescSetLayout; vk::DescriptorSetLayout m_rtDescSetLayout;
vk::DescriptorSet m_rtDescSet; vk::DescriptorSet m_rtDescSet;
std::vector<vk::RayTracingShaderGroupCreateInfoKHR> m_rtShaderGroups; std::vector<vk::RayTracingShaderGroupCreateInfoKHR> m_rtShaderGroups;
vk::PipelineLayout m_rtPipelineLayout; vk::PipelineLayout m_rtPipelineLayout;
vk::Pipeline m_rtPipeline; vk::Pipeline m_rtPipeline;
nvvkBuffer m_rtSBTBuffer; nvvk::Buffer m_rtSBTBuffer;
int m_maxFrames{100}; int m_maxFrames{100};
struct RtPushConstant struct RtPushConstant

View file

@ -31,6 +31,7 @@
#include <array> #include <array>
#include <vulkan/vulkan.hpp> #include <vulkan/vulkan.hpp>
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
#include "imgui.h" #include "imgui.h"
#include "imgui_impl_glfw.h" #include "imgui_impl_glfw.h"
@ -39,10 +40,10 @@
#include "nvh/cameramanipulator.hpp" #include "nvh/cameramanipulator.hpp"
#include "nvh/fileoperations.hpp" #include "nvh/fileoperations.hpp"
#include "nvpsystem.hpp" #include "nvpsystem.hpp"
#include "nvvkpp/appbase_vkpp.hpp" #include "nvvk/appbase_vkpp.hpp"
#include "nvvkpp/commands_vkpp.hpp" #include "nvvk/commands_vk.hpp"
#include "nvvkpp/context_vkpp.hpp" #include "nvvk/context_vk.hpp"
#include "nvvkpp/utilities_vkpp.hpp"
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
#define UNUSED(x) (void)(x) #define UNUSED(x) (void)(x)
@ -132,7 +133,7 @@ int main(int argc, char** argv)
vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature; vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature;
// Requesting Vulkan extensions and layers // Requesting Vulkan extensions and layers
nvvkpp::ContextCreateInfo contextInfo(true); nvvk::ContextCreateInfo contextInfo(true);
contextInfo.setVersion(1, 2); contextInfo.setVersion(1, 2);
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true); contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME); contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME);
@ -156,7 +157,7 @@ int main(int argc, char** argv)
contextInfo.addDeviceExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME); contextInfo.addDeviceExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
// Creating Vulkan base application // Creating Vulkan base application
nvvkpp::Context vkctx{}; nvvk::Context vkctx{};
vkctx.initInstance(contextInfo); vkctx.initInstance(contextInfo);
// Find all compatible devices // Find all compatible devices
auto compatibleDevices = vkctx.getCompatibleDevices(contextInfo); auto compatibleDevices = vkctx.getCompatibleDevices(contextInfo);
@ -171,7 +172,8 @@ int main(int argc, char** argv)
const vk::SurfaceKHR surface = helloVk.getVkSurface(vkctx.m_instance, window); const vk::SurfaceKHR surface = helloVk.getVkSurface(vkctx.m_instance, window);
vkctx.setGCTQueueWithPresent(surface); vkctx.setGCTQueueWithPresent(surface);
helloVk.setup(vkctx.m_device, vkctx.m_physicalDevice, vkctx.m_queueGCT.familyIndex); helloVk.setup(vkctx.m_instance, vkctx.m_device, vkctx.m_physicalDevice,
vkctx.m_queueGCT.familyIndex);
helloVk.createSurface(surface, SAMPLE_WIDTH, SAMPLE_HEIGHT); helloVk.createSurface(surface, SAMPLE_WIDTH, SAMPLE_HEIGHT);
helloVk.createDepthBuffer(); helloVk.createDepthBuffer();
helloVk.createRenderPass(); helloVk.createRenderPass();
@ -254,7 +256,8 @@ int main(int argc, char** argv)
// Clearing screen // Clearing screen
vk::ClearValue clearValues[2]; vk::ClearValue clearValues[2];
clearValues[0].setColor(nvvkpp::util::clearColor(clearColor)); clearValues[0].setColor(
std::array<float, 4>({clearColor[0], clearColor[1], clearColor[2], clearColor[3]}));
clearValues[1].setDepthStencil({1.0f, 0}); clearValues[1].setDepthStencil({1.0f, 0});
// Offscreen render pass // Offscreen render pass
@ -306,7 +309,6 @@ int main(int argc, char** argv)
helloVk.destroyResources(); helloVk.destroyResources();
helloVk.destroy(); helloVk.destroy();
vkctx.m_instance.destroySurfaceKHR(surface);
vkctx.deinit(); vkctx.deinit();
glfwDestroyWindow(window); glfwDestroyWindow(window);

View file

@ -6,7 +6,7 @@
#include "raycommon.glsl" #include "raycommon.glsl"
#include "wavefront.glsl" #include "wavefront.glsl"
hitAttributeEXT vec3 attribs; hitAttributeEXT vec2 attribs;
// clang-format off // clang-format off
layout(location = 0) rayPayloadInEXT hitPayload prd; layout(location = 0) rayPayloadInEXT hitPayload prd;

View file

@ -36,13 +36,14 @@ extern std::vector<std::string> defaultSearchPaths;
#include "hello_vulkan.h" #include "hello_vulkan.h"
#include "nvh//cameramanipulator.hpp" #include "nvh//cameramanipulator.hpp"
#include "nvvkpp/descriptorsets_vkpp.hpp" #include "nvvk/descriptorsets_vk.hpp"
#include "nvvkpp/pipeline_vkpp.hpp" #include "nvvk/pipeline_vk.hpp"
#include "nvh/fileoperations.hpp" #include "nvh/fileoperations.hpp"
#include "nvvkpp/commands_vkpp.hpp" #include "nvvk/commands_vk.hpp"
#include "nvvkpp/renderpass_vkpp.hpp" #include "nvvk/renderpasses_vk.hpp"
#include "nvvkpp/utilities_vkpp.hpp" #include "nvvk/shaders_vk.hpp"
// Holding the camera matrices // Holding the camera matrices
struct CameraMatrices struct CameraMatrices
@ -58,11 +59,12 @@ struct CameraMatrices
// Keep the handle on the device // Keep the handle on the device
// Initialize the tool to do all our allocations: buffers, images // Initialize the tool to do all our allocations: buffers, images
// //
void HelloVulkan::setup(const vk::Device& device, void HelloVulkan::setup(const vk::Instance& instance,
const vk::Device& device,
const vk::PhysicalDevice& physicalDevice, const vk::PhysicalDevice& physicalDevice,
uint32_t queueFamily) uint32_t queueFamily)
{ {
AppBase::setup(device, physicalDevice, queueFamily); AppBase::setup(instance, device, physicalDevice, queueFamily);
m_alloc.init(device, physicalDevice); m_alloc.init(device, physicalDevice);
m_debug.setup(m_device); m_debug.setup(m_device);
} }
@ -99,31 +101,31 @@ void HelloVulkan::createDescriptorSetLayout()
uint32_t nbObj = static_cast<uint32_t>(m_objModel.size()); uint32_t nbObj = static_cast<uint32_t>(m_objModel.size());
// Camera matrices (binding = 0) // Camera matrices (binding = 0)
m_descSetLayoutBind.emplace_back( m_descSetLayoutBind.addBinding(
vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR)); vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR));
// Materials (binding = 1) // Materials (binding = 1)
m_descSetLayoutBind.emplace_back( m_descSetLayoutBind.addBinding(
vkDS(1, vkDT::eStorageBuffer, nbObj, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR)); vkDS(1, vkDT::eStorageBuffer, nbObj, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
// Scene description (binding = 2) // Scene description (binding = 2)
m_descSetLayoutBind.emplace_back( // m_descSetLayoutBind.addBinding( //
vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR)); vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
// Textures (binding = 3) // Textures (binding = 3)
m_descSetLayoutBind.emplace_back( m_descSetLayoutBind.addBinding(
vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR)); vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR));
// Materials (binding = 4) // Materials (binding = 4)
m_descSetLayoutBind.emplace_back( m_descSetLayoutBind.addBinding(
vkDS(4, vkDT::eStorageBuffer, nbObj, vkSS::eFragment | vkSS::eClosestHitKHR)); vkDS(4, vkDT::eStorageBuffer, nbObj, vkSS::eFragment | vkSS::eClosestHitKHR));
// Storing vertices (binding = 5) // Storing vertices (binding = 5)
m_descSetLayoutBind.emplace_back( // m_descSetLayoutBind.addBinding( //
vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR)); vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
// Storing indices (binding = 6) // Storing indices (binding = 6)
m_descSetLayoutBind.emplace_back( // m_descSetLayoutBind.addBinding( //
vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR)); vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
m_descSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_descSetLayoutBind); m_descSetLayout = m_descSetLayoutBind.createLayout(m_device);
m_descPool = nvvkpp::util::createDescriptorPool(m_device, m_descSetLayoutBind, 1); m_descPool = m_descSetLayoutBind.createPool(m_device, 1);
m_descSet = nvvkpp::util::createDescriptorSet(m_device, m_descPool, m_descSetLayout); m_descSet = nvvk::allocateDescriptorSet(m_device, m_descPool, m_descSetLayout);
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -135,9 +137,9 @@ void HelloVulkan::updateDescriptorSet()
// Camera matrices and scene description // Camera matrices and scene description
vk::DescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE}; vk::DescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE};
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[0], &dbiUnif)); writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 0, &dbiUnif));
vk::DescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE}; vk::DescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[2], &dbiSceneDesc)); writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 2, &dbiSceneDesc));
// All material buffers, 1 buffer per OBJ // All material buffers, 1 buffer per OBJ
std::vector<vk::DescriptorBufferInfo> dbiMat; std::vector<vk::DescriptorBufferInfo> dbiMat;
@ -151,11 +153,10 @@ void HelloVulkan::updateDescriptorSet()
dbiVert.push_back({m_objModel[i].vertexBuffer.buffer, 0, VK_WHOLE_SIZE}); dbiVert.push_back({m_objModel[i].vertexBuffer.buffer, 0, VK_WHOLE_SIZE});
dbiIdx.push_back({m_objModel[i].indexBuffer.buffer, 0, VK_WHOLE_SIZE}); dbiIdx.push_back({m_objModel[i].indexBuffer.buffer, 0, VK_WHOLE_SIZE});
} }
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[1], dbiMat.data())); writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 1, dbiMat.data()));
writes.emplace_back( writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 4, dbiMatIdx.data()));
nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[4], dbiMatIdx.data())); writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 5, dbiVert.data()));
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[5], dbiVert.data())); writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 6, dbiIdx.data()));
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[6], dbiIdx.data()));
// All texture samplers // All texture samplers
std::vector<vk::DescriptorImageInfo> diit; std::vector<vk::DescriptorImageInfo> diit;
@ -163,7 +164,7 @@ void HelloVulkan::updateDescriptorSet()
{ {
diit.push_back(m_textures[i].descriptor); diit.push_back(m_textures[i].descriptor);
} }
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[3], diit.data())); writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 3, diit.data()));
// Writing the information // Writing the information
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr); m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
@ -189,19 +190,18 @@ void HelloVulkan::createGraphicsPipeline()
m_pipelineLayout = m_device.createPipelineLayout(pipelineLayoutCreateInfo); m_pipelineLayout = m_device.createPipelineLayout(pipelineLayoutCreateInfo);
// Creating the Pipeline // Creating the Pipeline
std::vector<std::string> paths = defaultSearchPaths; std::vector<std::string> paths = defaultSearchPaths;
nvvkpp::GraphicsPipelineGenerator gpb(m_device, m_pipelineLayout, m_offscreenRenderPass); nvvk::GraphicsPipelineGeneratorCombined gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
gpb.depthStencilState = {true}; gpb.depthStencilState.depthTestEnable = true;
gpb.addShader(nvh::loadFile("shaders/vert_shader.vert.spv", true, paths), vkSS::eVertex); gpb.addShader(nvh::loadFile("shaders/vert_shader.vert.spv", true, paths), vkSS::eVertex);
gpb.addShader(nvh::loadFile("shaders/frag_shader.frag.spv", true, paths), vkSS::eFragment); gpb.addShader(nvh::loadFile("shaders/frag_shader.frag.spv", true, paths), vkSS::eFragment);
gpb.vertexInputState.bindingDescriptions = {{0, sizeof(VertexObj)}}; gpb.addBindingDescription({0, sizeof(VertexObj)});
gpb.vertexInputState.attributeDescriptions = { gpb.addAttributeDescriptions({{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)}, {1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)},
{1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)}, {2, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, color)},
{2, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, color)}, {3, 0, vk::Format::eR32G32Sfloat, offsetof(VertexObj, texCoord)}});
{3, 0, vk::Format::eR32G32Sfloat, offsetof(VertexObj, texCoord)}};
m_graphicsPipeline = gpb.create(); m_graphicsPipeline = gpb.createPipeline();
m_debug.setObjectName(m_graphicsPipeline, "Graphics"); m_debug.setObjectName(m_graphicsPipeline, "Graphics");
} }
@ -234,8 +234,8 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size()); model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
// Create the buffers on Device and copy vertices, indices and materials // Create the buffers on Device and copy vertices, indices and materials
nvvkpp::SingleCommandBuffer cmdBufGet(m_device, m_graphicsQueueIndex); nvvk::CommandPool cmdBufGet(m_device, m_graphicsQueueIndex);
vk::CommandBuffer cmdBuf = cmdBufGet.createCommandBuffer(); vk::CommandBuffer cmdBuf = cmdBufGet.createCommandBuffer();
model.vertexBuffer = model.vertexBuffer =
m_alloc.createBuffer(cmdBuf, loader.m_vertices, m_alloc.createBuffer(cmdBuf, loader.m_vertices,
vkBU::eVertexBuffer | vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress); vkBU::eVertexBuffer | vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress);
@ -246,8 +246,8 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, vkBU::eStorageBuffer); model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, vkBU::eStorageBuffer);
// Creates all textures found // Creates all textures found
createTextureImages(cmdBuf, loader.m_textures); createTextureImages(cmdBuf, loader.m_textures);
cmdBufGet.flushCommandBuffer(cmdBuf); cmdBufGet.submitAndWait(cmdBuf);
m_alloc.flushStaging(); m_alloc.finalizeAndReleaseStaging();
std::string objNb = std::to_string(instance.objIndex); std::string objNb = std::to_string(instance.objIndex);
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str())); m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
@ -282,12 +282,12 @@ void HelloVulkan::createUniformBuffer()
void HelloVulkan::createSceneDescriptionBuffer() void HelloVulkan::createSceneDescriptionBuffer()
{ {
using vkBU = vk::BufferUsageFlagBits; using vkBU = vk::BufferUsageFlagBits;
nvvkpp::SingleCommandBuffer cmdGen(m_device, m_graphicsQueueIndex); nvvk::CommandPool cmdGen(m_device, m_graphicsQueueIndex);
auto cmdBuf = cmdGen.createCommandBuffer(); auto cmdBuf = cmdGen.createCommandBuffer();
m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer); m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer);
cmdGen.flushCommandBuffer(cmdBuf); cmdGen.submitAndWait(cmdBuf);
m_alloc.flushStaging(); m_alloc.finalizeAndReleaseStaging();
m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc"); m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc");
} }
@ -307,21 +307,21 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
// If no textures are present, create a dummy one to accommodate the pipeline layout // If no textures are present, create a dummy one to accommodate the pipeline layout
if(textures.empty() && m_textures.empty()) if(textures.empty() && m_textures.empty())
{ {
nvvkTexture texture; nvvk::Texture texture;
std::array<uint8_t, 4> color{255u, 255u, 255u, 255u}; std::array<uint8_t, 4> color{255u, 255u, 255u, 255u};
vk::DeviceSize bufferSize = sizeof(color); vk::DeviceSize bufferSize = sizeof(color);
auto imgSize = vk::Extent2D(1, 1); auto imgSize = vk::Extent2D(1, 1);
auto imageCreateInfo = nvvkpp::image::create2DInfo(imgSize, format); auto imageCreateInfo = nvvk::makeImage2DCreateInfo(imgSize, format);
// Creating the dummy texure
nvvk::Image image = m_alloc.createImage(cmdBuf, bufferSize, color.data(), imageCreateInfo);
vk::ImageViewCreateInfo ivInfo = nvvk::makeImageViewCreateInfo(image.image, imageCreateInfo);
texture = m_alloc.createTexture(image, ivInfo, samplerCreateInfo);
// Creating the VKImage
texture = m_alloc.createImage(cmdBuf, bufferSize, color.data(), imageCreateInfo);
// Setting up the descriptor used by the shader
texture.descriptor =
nvvkpp::image::create2DDescriptor(m_device, texture.image, samplerCreateInfo, format);
// The image format must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL // The image format must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
nvvkpp::image::setImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined, nvvk::cmdBarrierImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eShaderReadOnlyOptimal); vk::ImageLayout::eShaderReadOnlyOptimal);
m_textures.push_back(texture); m_textures.push_back(texture);
} }
else else
@ -348,16 +348,16 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4; vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4;
auto imgSize = vk::Extent2D(texWidth, texHeight); auto imgSize = vk::Extent2D(texWidth, texHeight);
auto imageCreateInfo = nvvkpp::image::create2DInfo(imgSize, format, vkIU::eSampled, true); auto imageCreateInfo = nvvk::makeImage2DCreateInfo(imgSize, format, vkIU::eSampled, true);
{ {
nvvkTexture texture; nvvk::ImageDedicated image =
texture = m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo); m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo);
nvvk::cmdGenerateMipmaps(cmdBuf, image.image, format, imgSize, imageCreateInfo.mipLevels);
vk::ImageViewCreateInfo ivInfo =
nvvk::makeImageViewCreateInfo(image.image, imageCreateInfo);
nvvk::Texture texture = m_alloc.createTexture(image, ivInfo, samplerCreateInfo);
nvvkpp::image::generateMipmaps(cmdBuf, texture.image, format, imgSize,
imageCreateInfo.mipLevels);
texture.descriptor =
nvvkpp::image::create2DDescriptor(m_device, texture.image, samplerCreateInfo, format);
m_textures.push_back(texture); m_textures.push_back(texture);
} }
} }
@ -434,7 +434,7 @@ void HelloVulkan::rasterize(const vk::CommandBuffer& cmdBuf)
cmdBuf.pushConstants<ObjPushConstant>(m_pipelineLayout, vkSS::eVertex | vkSS::eFragment, 0, cmdBuf.pushConstants<ObjPushConstant>(m_pipelineLayout, vkSS::eVertex | vkSS::eFragment, 0,
m_pushConstant); m_pushConstant);
cmdBuf.bindVertexBuffers(0, 1, &model.vertexBuffer.buffer, &offset); cmdBuf.bindVertexBuffers(0, {model.vertexBuffer.buffer}, {offset});
cmdBuf.bindIndexBuffer(model.indexBuffer.buffer, 0, vk::IndexType::eUint32); cmdBuf.bindIndexBuffer(model.indexBuffer.buffer, 0, vk::IndexType::eUint32);
cmdBuf.drawIndexed(model.nbIndices, 1, 0, 0, 0); cmdBuf.drawIndexed(model.nbIndices, 1, 0, 0, 0);
} }
@ -464,49 +464,54 @@ void HelloVulkan::createOffscreenRender()
m_alloc.destroy(m_offscreenDepth); m_alloc.destroy(m_offscreenDepth);
// Creating the color image // Creating the color image
auto colorCreateInfo = nvvkpp::image::create2DInfo(m_size, m_offscreenColorFormat, {
vk::ImageUsageFlagBits::eColorAttachment auto colorCreateInfo = nvvk::makeImage2DCreateInfo(m_size, m_offscreenColorFormat,
| vk::ImageUsageFlagBits::eSampled vk::ImageUsageFlagBits::eColorAttachment
| vk::ImageUsageFlagBits::eStorage); | vk::ImageUsageFlagBits::eSampled
m_offscreenColor = m_alloc.createImage(colorCreateInfo); | vk::ImageUsageFlagBits::eStorage);
m_offscreenColor.descriptor =
nvvkpp::image::create2DDescriptor(m_device, m_offscreenColor.image, vk::SamplerCreateInfo{}, nvvk::Image image = m_alloc.createImage(colorCreateInfo);
m_offscreenColorFormat, vk::ImageLayout::eGeneral); vk::ImageViewCreateInfo ivInfo = nvvk::makeImageViewCreateInfo(image.image, colorCreateInfo);
m_offscreenColor = m_alloc.createTexture(image, ivInfo, vk::SamplerCreateInfo());
m_offscreenColor.descriptor.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
}
// Creating the depth buffer // Creating the depth buffer
auto depthCreateInfo = auto depthCreateInfo =
nvvkpp::image::create2DInfo(m_size, m_offscreenDepthFormat, nvvk::makeImage2DCreateInfo(m_size, m_offscreenDepthFormat,
vk::ImageUsageFlagBits::eDepthStencilAttachment); vk::ImageUsageFlagBits::eDepthStencilAttachment);
m_offscreenDepth = m_alloc.createImage(depthCreateInfo); {
nvvk::Image image = m_alloc.createImage(depthCreateInfo);
vk::ImageViewCreateInfo depthStencilView; vk::ImageViewCreateInfo depthStencilView;
depthStencilView.setViewType(vk::ImageViewType::e2D); depthStencilView.setViewType(vk::ImageViewType::e2D);
depthStencilView.setFormat(m_offscreenDepthFormat); depthStencilView.setFormat(m_offscreenDepthFormat);
depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1}); depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1});
depthStencilView.setImage(m_offscreenDepth.image); depthStencilView.setImage(image.image);
m_offscreenDepth.descriptor.imageView = m_device.createImageView(depthStencilView);
m_offscreenDepth = m_alloc.createTexture(image, depthStencilView);
}
// Setting the image layout for both color and depth // Setting the image layout for both color and depth
{ {
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex); nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
auto cmdBuf = genCmdBuf.createCommandBuffer(); auto cmdBuf = genCmdBuf.createCommandBuffer();
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined, nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eGeneral); vk::ImageLayout::eGeneral);
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageAspectFlagBits::eDepth, nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eUndefined, vk::ImageLayout::eDepthStencilAttachmentOptimal,
vk::ImageLayout::eDepthStencilAttachmentOptimal); vk::ImageAspectFlagBits::eDepth);
genCmdBuf.flushCommandBuffer(cmdBuf); genCmdBuf.submitAndWait(cmdBuf);
} }
// Creating a renderpass for the offscreen // Creating a renderpass for the offscreen
if(!m_offscreenRenderPass) if(!m_offscreenRenderPass)
{ {
m_offscreenRenderPass = m_offscreenRenderPass =
nvvkpp::util::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat, nvvk::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat, 1, true,
1, true, true, vk::ImageLayout::eGeneral, true, vk::ImageLayout::eGeneral, vk::ImageLayout::eGeneral);
vk::ImageLayout::eGeneral);
} }
// Creating the frame buffer for offscreen // Creating the frame buffer for offscreen
@ -543,13 +548,14 @@ void HelloVulkan::createPostPipeline()
// Pipeline: completely generic, no vertices // Pipeline: completely generic, no vertices
std::vector<std::string> paths = defaultSearchPaths; std::vector<std::string> paths = defaultSearchPaths;
nvvkpp::GraphicsPipelineGenerator pipelineGenerator(m_device, m_postPipelineLayout, m_renderPass); nvvk::GraphicsPipelineGeneratorCombined pipelineGenerator(m_device, m_postPipelineLayout,
m_renderPass);
pipelineGenerator.addShader(nvh::loadFile("shaders/passthrough.vert.spv", true, paths), pipelineGenerator.addShader(nvh::loadFile("shaders/passthrough.vert.spv", true, paths),
vk::ShaderStageFlagBits::eVertex); vk::ShaderStageFlagBits::eVertex);
pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths), pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths),
vk::ShaderStageFlagBits::eFragment); vk::ShaderStageFlagBits::eFragment);
pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone); pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone);
m_postPipeline = pipelineGenerator.create(); m_postPipeline = pipelineGenerator.createPipeline();
m_debug.setObjectName(m_postPipeline, "post"); m_debug.setObjectName(m_postPipeline, "post");
} }
@ -563,10 +569,10 @@ void HelloVulkan::createPostDescriptor()
using vkDT = vk::DescriptorType; using vkDT = vk::DescriptorType;
using vkSS = vk::ShaderStageFlagBits; using vkSS = vk::ShaderStageFlagBits;
m_postDescSetLayoutBind.emplace_back(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment)); m_postDescSetLayoutBind.addBinding(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
m_postDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_postDescSetLayoutBind); m_postDescSetLayout = m_postDescSetLayoutBind.createLayout(m_device);
m_postDescPool = nvvkpp::util::createDescriptorPool(m_device, m_postDescSetLayoutBind); m_postDescPool = m_postDescSetLayoutBind.createPool(m_device);
m_postDescSet = nvvkpp::util::createDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout); m_postDescSet = nvvk::allocateDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -575,8 +581,7 @@ void HelloVulkan::createPostDescriptor()
void HelloVulkan::updatePostDescriptorSet() void HelloVulkan::updatePostDescriptorSet()
{ {
vk::WriteDescriptorSet writeDescriptorSets = vk::WriteDescriptorSet writeDescriptorSets =
nvvkpp::util::createWrite(m_postDescSet, m_postDescSetLayoutBind[0], m_postDescSetLayoutBind.makeWrite(m_postDescSet, 0, &m_offscreenColor.descriptor);
&m_offscreenColor.descriptor);
m_device.updateDescriptorSets(writeDescriptorSets, nullptr); m_device.updateDescriptorSets(writeDescriptorSets, nullptr);
} }
@ -614,15 +619,15 @@ void HelloVulkan::initRayTracing()
auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2, auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2,
vk::PhysicalDeviceRayTracingPropertiesKHR>(); vk::PhysicalDeviceRayTracingPropertiesKHR>();
m_rtProperties = properties.get<vk::PhysicalDeviceRayTracingPropertiesKHR>(); m_rtProperties = properties.get<vk::PhysicalDeviceRayTracingPropertiesKHR>();
m_rtBuilder.setup(m_device, m_physicalDevice, m_graphicsQueueIndex); m_rtBuilder.setup(m_device, &m_alloc, m_graphicsQueueIndex);
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Converting a OBJ primitive to the ray tracing geometry used for the BLAS // Converting a OBJ primitive to the ray tracing geometry used for the BLAS
// //
nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model) nvvk::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model)
{ {
nvvkpp::RaytracingBuilderKHR::Blas blas; nvvk::RaytracingBuilderKHR::Blas blas;
vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate; vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate;
asCreate.setGeometryType(vk::GeometryTypeKHR::eTriangles); asCreate.setGeometryType(vk::GeometryTypeKHR::eTriangles);
asCreate.setIndexType(vk::IndexType::eUint32); asCreate.setIndexType(vk::IndexType::eUint32);
@ -659,7 +664,7 @@ nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjM
void HelloVulkan::createBottomLevelAS() void HelloVulkan::createBottomLevelAS()
{ {
// BLAS - Storing each primitive in a geometry // BLAS - Storing each primitive in a geometry
std::vector<nvvkpp::RaytracingBuilderKHR::Blas> allBlas; std::vector<nvvk::RaytracingBuilderKHR::Blas> allBlas;
allBlas.reserve(m_objModel.size()); allBlas.reserve(m_objModel.size());
for(const auto& obj : m_objModel) for(const auto& obj : m_objModel)
{ {
@ -673,17 +678,16 @@ void HelloVulkan::createBottomLevelAS()
void HelloVulkan::createTopLevelAS() void HelloVulkan::createTopLevelAS()
{ {
std::vector<nvvkpp::RaytracingBuilderKHR::Instance> tlas; std::vector<nvvk::RaytracingBuilderKHR::Instance> tlas;
tlas.reserve(m_objInstance.size()); tlas.reserve(m_objInstance.size());
for(int i = 0; i < static_cast<int>(m_objInstance.size()); i++) for(int i = 0; i < static_cast<int>(m_objInstance.size()); i++)
{ {
nvvkpp::RaytracingBuilderKHR::Instance rayInst; nvvk::RaytracingBuilderKHR::Instance rayInst;
rayInst.transform = m_objInstance[i].transform; // Position of the instance rayInst.transform = m_objInstance[i].transform; // Position of the instance
rayInst.instanceId = i; // gl_InstanceID rayInst.instanceId = i; // gl_InstanceID
rayInst.blasId = m_objInstance[i].objIndex; rayInst.blasId = m_objInstance[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;
rayInst.flags = vk::GeometryInstanceFlagBitsKHR::eTriangleCullDisable; rayInst.hitGroupId = m_objInstance[i].hitgroup; // Using the hit group set in main
rayInst.hitGroupId = m_objInstance[i].hitgroup;
tlas.emplace_back(rayInst); tlas.emplace_back(rayInst);
} }
m_rtBuilder.buildTlas(tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace); m_rtBuilder.buildTlas(tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace);
@ -698,25 +702,25 @@ void HelloVulkan::createRtDescriptorSet()
using vkSS = vk::ShaderStageFlagBits; using vkSS = vk::ShaderStageFlagBits;
using vkDSLB = vk::DescriptorSetLayoutBinding; using vkDSLB = vk::DescriptorSetLayoutBinding;
m_rtDescSetLayoutBind.emplace_back(vkDSLB(0, vkDT::eAccelerationStructureKHR, 1, m_rtDescSetLayoutBind.addBinding(vkDSLB(0, vkDT::eAccelerationStructureKHR, 1,
vkSS::eRaygenKHR | vkSS::eClosestHitKHR)); // TLAS vkSS::eRaygenKHR | vkSS::eClosestHitKHR)); // TLAS
m_rtDescSetLayoutBind.emplace_back( m_rtDescSetLayoutBind.addBinding(
vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image
m_rtDescPool = nvvkpp::util::createDescriptorPool(m_device, m_rtDescSetLayoutBind); m_rtDescPool = m_rtDescSetLayoutBind.createPool(m_device);
m_rtDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_rtDescSetLayoutBind); m_rtDescSetLayout = m_rtDescSetLayoutBind.createLayout(m_device);
m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0]; m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0];
vk::AccelerationStructureKHR tlas = m_rtBuilder.getAccelerationStructure();
vk::WriteDescriptorSetAccelerationStructureKHR descASInfo; vk::WriteDescriptorSetAccelerationStructureKHR descASInfo;
descASInfo.setAccelerationStructureCount(1); descASInfo.setAccelerationStructureCount(1);
descASInfo.setPAccelerationStructures(&m_rtBuilder.getAccelerationStructure()); descASInfo.setPAccelerationStructures(&tlas);
vk::DescriptorImageInfo imageInfo{ vk::DescriptorImageInfo imageInfo{
{}, m_offscreenColor.descriptor.imageView, vk::ImageLayout::eGeneral}; {}, m_offscreenColor.descriptor.imageView, vk::ImageLayout::eGeneral};
std::vector<vk::WriteDescriptorSet> writes; std::vector<vk::WriteDescriptorSet> writes;
writes.emplace_back( writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 0, &descASInfo));
nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[0], &descASInfo)); writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 1, &imageInfo));
writes.emplace_back(nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[1], &imageInfo));
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr); m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
} }
@ -745,16 +749,17 @@ void HelloVulkan::createRtPipeline()
std::vector<std::string> paths = defaultSearchPaths; std::vector<std::string> paths = defaultSearchPaths;
vk::ShaderModule raygenSM = vk::ShaderModule raygenSM =
nvvkpp::util::createShaderModule(m_device, // nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rgen.spv", true, paths)); nvh::loadFile("shaders/raytrace.rgen.spv", true, paths));
vk::ShaderModule missSM = vk::ShaderModule missSM =
nvvkpp::util::createShaderModule(m_device, // nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths)); nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths));
// The second miss shader is invoked when a shadow ray misses the geometry. It // The second miss shader is invoked when a shadow ray misses the geometry. It
// simply indicates that no occlusion has been found // simply indicates that no occlusion has been found
vk::ShaderModule shadowmissSM = nvvkpp::util::createShaderModule( vk::ShaderModule shadowmissSM =
m_device, nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths)); nvvk::createShaderModule(m_device,
nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
std::vector<vk::PipelineShaderStageCreateInfo> stages; std::vector<vk::PipelineShaderStageCreateInfo> stages;
@ -780,11 +785,11 @@ void HelloVulkan::createRtPipeline()
// Hit Group - Closest Hit + AnyHit // Hit Group - Closest Hit + AnyHit
vk::ShaderModule chitSM = vk::ShaderModule chitSM =
nvvkpp::util::createShaderModule(m_device, // nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rchit.spv", true, paths)); nvh::loadFile("shaders/raytrace.rchit.spv", true, paths));
vk::ShaderModule chit2SM = vk::ShaderModule chit2SM =
nvvkpp::util::createShaderModule(m_device, // nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace2.rchit.spv", true, paths)); nvh::loadFile("shaders/raytrace2.rchit.spv", true, paths));
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup, vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup,
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR,
@ -893,17 +898,17 @@ void HelloVulkan::createRtShaderBindingTable()
} }
// Write the handles in the SBT // Write the handles in the SBT
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex); nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer(); vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
m_rtSBTBuffer = m_alloc.createBuffer(cmdBuf, sbtBuffer, vk::BufferUsageFlagBits::eRayTracingKHR); m_rtSBTBuffer = m_alloc.createBuffer(cmdBuf, sbtBuffer, vk::BufferUsageFlagBits::eRayTracingKHR);
m_debug.setObjectName(m_rtSBTBuffer.buffer, "SBT"); m_debug.setObjectName(m_rtSBTBuffer.buffer, "SBT");
genCmdBuf.flushCommandBuffer(cmdBuf); genCmdBuf.submitAndWait(cmdBuf);
m_alloc.flushStaging(); m_alloc.finalizeAndReleaseStaging();
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------

View file

@ -26,16 +26,14 @@
*/ */
#pragma once #pragma once
#include "nvvkpp/allocator_dedicated_vkpp.hpp" #define NVVK_ALLOC_DEDICATED
#include "nvvkpp/appbase_vkpp.hpp" #include "nvvk/allocator_vk.hpp"
#include "nvvkpp/debug_util_vkpp.hpp" #include "nvvk/appbase_vkpp.hpp"
#include "nvvk/debug_util_vk.hpp"
#include "nvvk/descriptorsets_vk.hpp"
// #VKRay // #VKRay
#define ALLOC_DEDICATED #include "nvvk/raytraceKHR_vk.hpp"
#include "nvvkpp/raytraceKHR_vkpp.hpp"
using nvvkBuffer = nvvkpp::BufferDedicated;
using nvvkTexture = nvvkpp::TextureDedicated;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Simple rasterizer of OBJ objects // Simple rasterizer of OBJ objects
@ -44,10 +42,11 @@ using nvvkTexture = nvvkpp::TextureDedicated;
// - Rendering is done in an offscreen framebuffer // - Rendering is done in an offscreen framebuffer
// - The image of the framebuffer is displayed in post-process in a full-screen quad // - The image of the framebuffer is displayed in post-process in a full-screen quad
// //
class HelloVulkan : public nvvkpp::AppBase class HelloVulkan : public nvvk::AppBase
{ {
public: public:
void setup(const vk::Device& device, void setup(const vk::Instance& instance,
const vk::Device& device,
const vk::PhysicalDevice& physicalDevice, const vk::PhysicalDevice& physicalDevice,
uint32_t queueFamily) override; uint32_t queueFamily) override;
void createDescriptorSetLayout(); void createDescriptorSetLayout();
@ -66,12 +65,12 @@ public:
// The OBJ model // The OBJ model
struct ObjModel struct ObjModel
{ {
uint32_t nbIndices{0}; uint32_t nbIndices{0};
uint32_t nbVertices{0}; uint32_t nbVertices{0};
nvvkBuffer vertexBuffer; // Device buffer of all 'Vertex' nvvk::Buffer vertexBuffer; // Device buffer of all 'Vertex'
nvvkBuffer indexBuffer; // Device buffer of the indices forming triangles nvvk::Buffer indexBuffer; // Device buffer of the indices forming triangles
nvvkBuffer matColorBuffer; // Device buffer of array of 'Wavefront material' nvvk::Buffer matColorBuffer; // Device buffer of array of 'Wavefront material'
nvvkBuffer matIndexBuffer; // Device buffer of array of 'Wavefront material' nvvk::Buffer matIndexBuffer; // Device buffer of array of 'Wavefront material'
}; };
// Instance of the OBJ // Instance of the OBJ
@ -99,19 +98,19 @@ public:
std::vector<ObjInstance> m_objInstance; std::vector<ObjInstance> m_objInstance;
// Graphic pipeline // Graphic pipeline
vk::PipelineLayout m_pipelineLayout; vk::PipelineLayout m_pipelineLayout;
vk::Pipeline m_graphicsPipeline; vk::Pipeline m_graphicsPipeline;
std::vector<vk::DescriptorSetLayoutBinding> m_descSetLayoutBind; nvvk::DescriptorSetBindings m_descSetLayoutBind;
vk::DescriptorPool m_descPool; vk::DescriptorPool m_descPool;
vk::DescriptorSetLayout m_descSetLayout; vk::DescriptorSetLayout m_descSetLayout;
vk::DescriptorSet m_descSet; vk::DescriptorSet m_descSet;
nvvkBuffer m_cameraMat; // Device-Host of the camera matrices nvvk::Buffer m_cameraMat; // Device-Host of the camera matrices
nvvkBuffer m_sceneDesc; // Device buffer of the OBJ instances nvvk::Buffer m_sceneDesc; // Device buffer of the OBJ instances
std::vector<nvvkTexture> m_textures; // vector of all textures of the scene std::vector<nvvk::Texture> m_textures; // vector of all textures of the scene
nvvkpp::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures nvvk::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures
nvvkpp::DebugUtil m_debug; // Utility to name objects nvvk::DebugUtil m_debug; // Utility to name objects
// #Post // #Post
void createOffscreenRender(); void createOffscreenRender();
@ -120,41 +119,41 @@ public:
void updatePostDescriptorSet(); void updatePostDescriptorSet();
void drawPost(vk::CommandBuffer cmdBuf); void drawPost(vk::CommandBuffer cmdBuf);
std::vector<vk::DescriptorSetLayoutBinding> m_postDescSetLayoutBind; nvvk::DescriptorSetBindings m_postDescSetLayoutBind;
vk::DescriptorPool m_postDescPool; vk::DescriptorPool m_postDescPool;
vk::DescriptorSetLayout m_postDescSetLayout; vk::DescriptorSetLayout m_postDescSetLayout;
vk::DescriptorSet m_postDescSet; vk::DescriptorSet m_postDescSet;
vk::Pipeline m_postPipeline; vk::Pipeline m_postPipeline;
vk::PipelineLayout m_postPipelineLayout; vk::PipelineLayout m_postPipelineLayout;
vk::RenderPass m_offscreenRenderPass; vk::RenderPass m_offscreenRenderPass;
vk::Framebuffer m_offscreenFramebuffer; vk::Framebuffer m_offscreenFramebuffer;
nvvkTexture m_offscreenColor; nvvk::Texture m_offscreenColor;
vk::Format m_offscreenColorFormat{vk::Format::eR32G32B32A32Sfloat}; vk::Format m_offscreenColorFormat{vk::Format::eR32G32B32A32Sfloat};
nvvkTexture m_offscreenDepth; nvvk::Texture m_offscreenDepth;
vk::Format m_offscreenDepthFormat{vk::Format::eD32Sfloat}; vk::Format m_offscreenDepthFormat{vk::Format::eD32Sfloat};
// #VKRay // #VKRay
void initRayTracing(); void initRayTracing();
nvvkpp::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model); nvvk::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
void createBottomLevelAS(); void createBottomLevelAS();
void createTopLevelAS(); void createTopLevelAS();
void createRtDescriptorSet(); void createRtDescriptorSet();
void updateRtDescriptorSet(); void updateRtDescriptorSet();
void createRtPipeline(); void createRtPipeline();
void createRtShaderBindingTable(); void createRtShaderBindingTable();
void raytrace(const vk::CommandBuffer& cmdBuf, const nvmath::vec4f& clearColor); void raytrace(const vk::CommandBuffer& cmdBuf, const nvmath::vec4f& clearColor);
vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties; vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties;
nvvkpp::RaytracingBuilderKHR m_rtBuilder; nvvk::RaytracingBuilderKHR m_rtBuilder;
std::vector<vk::DescriptorSetLayoutBinding> m_rtDescSetLayoutBind; nvvk::DescriptorSetBindings m_rtDescSetLayoutBind;
vk::DescriptorPool m_rtDescPool; vk::DescriptorPool m_rtDescPool;
vk::DescriptorSetLayout m_rtDescSetLayout; vk::DescriptorSetLayout m_rtDescSetLayout;
vk::DescriptorSet m_rtDescSet; vk::DescriptorSet m_rtDescSet;
std::vector<vk::RayTracingShaderGroupCreateInfoKHR> m_rtShaderGroups; std::vector<vk::RayTracingShaderGroupCreateInfoKHR> m_rtShaderGroups;
vk::PipelineLayout m_rtPipelineLayout; vk::PipelineLayout m_rtPipelineLayout;
vk::Pipeline m_rtPipeline; vk::Pipeline m_rtPipeline;
nvvkBuffer m_rtSBTBuffer; nvvk::Buffer m_rtSBTBuffer;
struct RtPushConstant struct RtPushConstant
{ {

View file

@ -31,6 +31,7 @@
#include <array> #include <array>
#include <vulkan/vulkan.hpp> #include <vulkan/vulkan.hpp>
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
#include "imgui.h" #include "imgui.h"
#include "imgui_impl_glfw.h" #include "imgui_impl_glfw.h"
@ -39,10 +40,9 @@
#include "nvh/cameramanipulator.hpp" #include "nvh/cameramanipulator.hpp"
#include "nvh/fileoperations.hpp" #include "nvh/fileoperations.hpp"
#include "nvpsystem.hpp" #include "nvpsystem.hpp"
#include "nvvkpp/appbase_vkpp.hpp" #include "nvvk/appbase_vkpp.hpp"
#include "nvvkpp/commands_vkpp.hpp" #include "nvvk/commands_vk.hpp"
#include "nvvkpp/context_vkpp.hpp" #include "nvvk/context_vk.hpp"
#include "nvvkpp/utilities_vkpp.hpp"
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
#define UNUSED(x) (void)(x) #define UNUSED(x) (void)(x)
@ -124,7 +124,7 @@ int main(int argc, char** argv)
vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature; vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature;
// Requesting Vulkan extensions and layers // Requesting Vulkan extensions and layers
nvvkpp::ContextCreateInfo contextInfo(true); nvvk::ContextCreateInfo contextInfo(true);
contextInfo.setVersion(1, 2); contextInfo.setVersion(1, 2);
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true); contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME); contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME);
@ -148,7 +148,7 @@ int main(int argc, char** argv)
contextInfo.addDeviceExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME); contextInfo.addDeviceExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
// Creating Vulkan base application // Creating Vulkan base application
nvvkpp::Context vkctx{}; nvvk::Context vkctx{};
vkctx.initInstance(contextInfo); vkctx.initInstance(contextInfo);
// Find all compatible devices // Find all compatible devices
auto compatibleDevices = vkctx.getCompatibleDevices(contextInfo); auto compatibleDevices = vkctx.getCompatibleDevices(contextInfo);
@ -163,7 +163,8 @@ int main(int argc, char** argv)
const vk::SurfaceKHR surface = helloVk.getVkSurface(vkctx.m_instance, window); const vk::SurfaceKHR surface = helloVk.getVkSurface(vkctx.m_instance, window);
vkctx.setGCTQueueWithPresent(surface); vkctx.setGCTQueueWithPresent(surface);
helloVk.setup(vkctx.m_device, vkctx.m_physicalDevice, vkctx.m_queueGCT.familyIndex); helloVk.setup(vkctx.m_instance, vkctx.m_device, vkctx.m_physicalDevice,
vkctx.m_queueGCT.familyIndex);
helloVk.createSurface(surface, SAMPLE_WIDTH, SAMPLE_HEIGHT); helloVk.createSurface(surface, SAMPLE_WIDTH, SAMPLE_HEIGHT);
helloVk.createDepthBuffer(); helloVk.createDepthBuffer();
helloVk.createRenderPass(); helloVk.createRenderPass();
@ -251,7 +252,8 @@ int main(int argc, char** argv)
// Clearing screen // Clearing screen
vk::ClearValue clearValues[2]; vk::ClearValue clearValues[2];
clearValues[0].setColor(nvvkpp::util::clearColor(clearColor)); clearValues[0].setColor(
std::array<float, 4>({clearColor[0], clearColor[1], clearColor[2], clearColor[3]}));
clearValues[1].setDepthStencil({1.0f, 0}); clearValues[1].setDepthStencil({1.0f, 0});
// Offscreen render pass // Offscreen render pass
@ -303,7 +305,6 @@ int main(int argc, char** argv)
helloVk.destroyResources(); helloVk.destroyResources();
helloVk.destroy(); helloVk.destroy();
vkctx.m_instance.destroySurfaceKHR(surface);
vkctx.deinit(); vkctx.deinit();
glfwDestroyWindow(window); glfwDestroyWindow(window);

View file

@ -6,7 +6,7 @@
#include "raycommon.glsl" #include "raycommon.glsl"
#include "wavefront.glsl" #include "wavefront.glsl"
hitAttributeEXT vec3 attribs; hitAttributeEXT vec2 attribs;
// clang-format off // clang-format off
layout(location = 0) rayPayloadInEXT hitPayload prd; layout(location = 0) rayPayloadInEXT hitPayload prd;

View file

@ -36,13 +36,13 @@ extern std::vector<std::string> defaultSearchPaths;
#include "hello_vulkan.h" #include "hello_vulkan.h"
#include "nvh//cameramanipulator.hpp" #include "nvh//cameramanipulator.hpp"
#include "nvvkpp/descriptorsets_vkpp.hpp" #include "nvvk/descriptorsets_vk.hpp"
#include "nvvkpp/pipeline_vkpp.hpp" #include "nvvk/pipeline_vk.hpp"
#include "nvh/fileoperations.hpp" #include "nvh/fileoperations.hpp"
#include "nvvkpp/commands_vkpp.hpp" #include "nvvk/commands_vk.hpp"
#include "nvvkpp/renderpass_vkpp.hpp" #include "nvvk/renderpasses_vk.hpp"
#include "nvvkpp/utilities_vkpp.hpp"
// Holding the camera matrices // Holding the camera matrices
struct CameraMatrices struct CameraMatrices
@ -58,11 +58,12 @@ struct CameraMatrices
// Keep the handle on the device // Keep the handle on the device
// Initialize the tool to do all our allocations: buffers, images // Initialize the tool to do all our allocations: buffers, images
// //
void HelloVulkan::setup(const vk::Device& device, void HelloVulkan::setup(const vk::Instance& instance,
const vk::Device& device,
const vk::PhysicalDevice& physicalDevice, const vk::PhysicalDevice& physicalDevice,
uint32_t queueFamily) uint32_t queueFamily)
{ {
AppBase::setup(device, physicalDevice, queueFamily); AppBase::setup(instance, device, physicalDevice, queueFamily);
m_alloc.init(device, physicalDevice); m_alloc.init(device, physicalDevice);
m_debug.setup(m_device); m_debug.setup(m_device);
} }
@ -99,33 +100,33 @@ void HelloVulkan::createDescriptorSetLayout()
uint32_t nbObj = static_cast<uint32_t>(m_objModel.size()); uint32_t nbObj = static_cast<uint32_t>(m_objModel.size());
// Camera matrices (binding = 0) // Camera matrices (binding = 0)
m_descSetLayoutBind.emplace_back( m_descSetLayoutBind.addBinding(
vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR)); vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR));
// Materials (binding = 1) // Materials (binding = 1)
m_descSetLayoutBind.emplace_back( m_descSetLayoutBind.addBinding(
vkDS(1, vkDT::eStorageBuffer, nbObj, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR)); vkDS(1, vkDT::eStorageBuffer, nbObj, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
// Scene description (binding = 2) // Scene description (binding = 2)
m_descSetLayoutBind.emplace_back( // m_descSetLayoutBind.addBinding( //
vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR)); vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
// Textures (binding = 3) // Textures (binding = 3)
m_descSetLayoutBind.emplace_back( m_descSetLayoutBind.addBinding(
vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR)); vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR));
// Materials (binding = 4) // Materials (binding = 4)
m_descSetLayoutBind.emplace_back( m_descSetLayoutBind.addBinding(
vkDS(4, vkDT::eStorageBuffer, nbObj, vkSS::eFragment | vkSS::eClosestHitKHR)); vkDS(4, vkDT::eStorageBuffer, nbObj, vkSS::eFragment | vkSS::eClosestHitKHR));
// Storing vertices (binding = 5) // Storing vertices (binding = 5)
m_descSetLayoutBind.emplace_back( // m_descSetLayoutBind.addBinding( //
vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR)); vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
// Storing indices (binding = 6) // Storing indices (binding = 6)
m_descSetLayoutBind.emplace_back( // m_descSetLayoutBind.addBinding( //
vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR)); vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
// The top level acceleration structure // The top level acceleration structure
m_descSetLayoutBind.emplace_back( // m_descSetLayoutBind.addBinding( //
vkDS(7, vkDT::eAccelerationStructureKHR, 1, vkSS::eFragment)); vkDS(7, vkDT::eAccelerationStructureKHR, 1, vkSS::eFragment));
m_descSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_descSetLayoutBind); m_descSetLayout = m_descSetLayoutBind.createLayout(m_device);
m_descPool = nvvkpp::util::createDescriptorPool(m_device, m_descSetLayoutBind, 1); m_descPool = m_descSetLayoutBind.createPool(m_device, 1);
m_descSet = nvvkpp::util::createDescriptorSet(m_device, m_descPool, m_descSetLayout); m_descSet = nvvk::allocateDescriptorSet(m_device, m_descPool, m_descSetLayout);
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -137,9 +138,9 @@ void HelloVulkan::updateDescriptorSet()
// Camera matrices and scene description // Camera matrices and scene description
vk::DescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE}; vk::DescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE};
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[0], &dbiUnif)); writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 0, &dbiUnif));
vk::DescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE}; vk::DescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[2], &dbiSceneDesc)); writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 2, &dbiSceneDesc));
// All material buffers, 1 buffer per OBJ // All material buffers, 1 buffer per OBJ
std::vector<vk::DescriptorBufferInfo> dbiMat; std::vector<vk::DescriptorBufferInfo> dbiMat;
@ -153,11 +154,10 @@ void HelloVulkan::updateDescriptorSet()
dbiVert.emplace_back(obj.vertexBuffer.buffer, 0, VK_WHOLE_SIZE); dbiVert.emplace_back(obj.vertexBuffer.buffer, 0, VK_WHOLE_SIZE);
dbiIdx.emplace_back(obj.indexBuffer.buffer, 0, VK_WHOLE_SIZE); dbiIdx.emplace_back(obj.indexBuffer.buffer, 0, VK_WHOLE_SIZE);
} }
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[1], dbiMat.data())); writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 1, dbiMat.data()));
writes.emplace_back( writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 4, dbiMatIdx.data()));
nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[4], dbiMatIdx.data())); writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 5, dbiVert.data()));
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[5], dbiVert.data())); writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 6, dbiIdx.data()));
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[6], dbiIdx.data()));
// All texture samplers // All texture samplers
std::vector<vk::DescriptorImageInfo> diit; std::vector<vk::DescriptorImageInfo> diit;
@ -165,13 +165,13 @@ void HelloVulkan::updateDescriptorSet()
{ {
diit.push_back(texture.descriptor); diit.push_back(texture.descriptor);
} }
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[3], diit.data())); writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 3, diit.data()));
vk::AccelerationStructureKHR tlas = m_rtBuilder.getAccelerationStructure();
vk::WriteDescriptorSetAccelerationStructureKHR descASInfo; vk::WriteDescriptorSetAccelerationStructureKHR descASInfo;
descASInfo.setAccelerationStructureCount(1); descASInfo.setAccelerationStructureCount(1);
descASInfo.setPAccelerationStructures(&m_rtBuilder.getAccelerationStructure()); descASInfo.setPAccelerationStructures(&tlas);
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[7], &descASInfo)); writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 7, &descASInfo));
// Writing the information // Writing the information
@ -198,19 +198,18 @@ void HelloVulkan::createGraphicsPipeline()
m_pipelineLayout = m_device.createPipelineLayout(pipelineLayoutCreateInfo); m_pipelineLayout = m_device.createPipelineLayout(pipelineLayoutCreateInfo);
// Creating the Pipeline // Creating the Pipeline
std::vector<std::string> paths = defaultSearchPaths; std::vector<std::string> paths = defaultSearchPaths;
nvvkpp::GraphicsPipelineGenerator gpb(m_device, m_pipelineLayout, m_offscreenRenderPass); nvvk::GraphicsPipelineGeneratorCombined gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
gpb.depthStencilState = {true}; gpb.depthStencilState.depthTestEnable = true;
gpb.addShader(nvh::loadFile("shaders/vert_shader.vert.spv", true, paths), vkSS::eVertex); gpb.addShader(nvh::loadFile("shaders/vert_shader.vert.spv", true, paths), vkSS::eVertex);
gpb.addShader(nvh::loadFile("shaders/frag_shader.frag.spv", true, paths), vkSS::eFragment); gpb.addShader(nvh::loadFile("shaders/frag_shader.frag.spv", true, paths), vkSS::eFragment);
gpb.vertexInputState.bindingDescriptions = {{0, sizeof(VertexObj)}}; gpb.addBindingDescription({0, sizeof(VertexObj)});
gpb.vertexInputState.attributeDescriptions = { gpb.addAttributeDescriptions({{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)}, {1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)},
{1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)}, {2, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, color)},
{2, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, color)}, {3, 0, vk::Format::eR32G32Sfloat, offsetof(VertexObj, texCoord)}});
{3, 0, vk::Format::eR32G32Sfloat, offsetof(VertexObj, texCoord)}};
m_graphicsPipeline = gpb.create(); m_graphicsPipeline = gpb.createPipeline();
m_debug.setObjectName(m_graphicsPipeline, "Graphics"); m_debug.setObjectName(m_graphicsPipeline, "Graphics");
} }
@ -243,8 +242,8 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size()); model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
// Create the buffers on Device and copy vertices, indices and materials // Create the buffers on Device and copy vertices, indices and materials
nvvkpp::SingleCommandBuffer cmdBufGet(m_device, m_graphicsQueueIndex); nvvk::CommandPool cmdBufGet(m_device, m_graphicsQueueIndex);
vk::CommandBuffer cmdBuf = cmdBufGet.createCommandBuffer(); vk::CommandBuffer cmdBuf = cmdBufGet.createCommandBuffer();
model.vertexBuffer = model.vertexBuffer =
m_alloc.createBuffer(cmdBuf, loader.m_vertices, m_alloc.createBuffer(cmdBuf, loader.m_vertices,
vkBU::eVertexBuffer | vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress); vkBU::eVertexBuffer | vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress);
@ -255,8 +254,8 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, vkBU::eStorageBuffer); model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, vkBU::eStorageBuffer);
// Creates all textures found // Creates all textures found
createTextureImages(cmdBuf, loader.m_textures); createTextureImages(cmdBuf, loader.m_textures);
cmdBufGet.flushCommandBuffer(cmdBuf); cmdBufGet.submitAndWait(cmdBuf);
m_alloc.flushStaging(); m_alloc.finalizeAndReleaseStaging();
std::string objNb = std::to_string(instance.objIndex); std::string objNb = std::to_string(instance.objIndex);
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str())); m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
@ -291,12 +290,12 @@ void HelloVulkan::createUniformBuffer()
void HelloVulkan::createSceneDescriptionBuffer() void HelloVulkan::createSceneDescriptionBuffer()
{ {
using vkBU = vk::BufferUsageFlagBits; using vkBU = vk::BufferUsageFlagBits;
nvvkpp::SingleCommandBuffer cmdGen(m_device, m_graphicsQueueIndex); nvvk::CommandPool cmdGen(m_device, m_graphicsQueueIndex);
auto cmdBuf = cmdGen.createCommandBuffer(); auto cmdBuf = cmdGen.createCommandBuffer();
m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer); m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer);
cmdGen.flushCommandBuffer(cmdBuf); cmdGen.submitAndWait(cmdBuf);
m_alloc.flushStaging(); m_alloc.finalizeAndReleaseStaging();
m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc"); m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc");
} }
@ -316,21 +315,21 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
// If no textures are present, create a dummy one to accommodate the pipeline layout // If no textures are present, create a dummy one to accommodate the pipeline layout
if(textures.empty() && m_textures.empty()) if(textures.empty() && m_textures.empty())
{ {
nvvkTexture texture; nvvk::Texture texture;
std::array<uint8_t, 4> color{255u, 255u, 255u, 255u}; std::array<uint8_t, 4> color{255u, 255u, 255u, 255u};
vk::DeviceSize bufferSize = sizeof(color); vk::DeviceSize bufferSize = sizeof(color);
auto imgSize = vk::Extent2D(1, 1); auto imgSize = vk::Extent2D(1, 1);
auto imageCreateInfo = nvvkpp::image::create2DInfo(imgSize, format); auto imageCreateInfo = nvvk::makeImage2DCreateInfo(imgSize, format);
// Creating the VKImage // Creating the VKImage
texture = m_alloc.createImage(cmdBuf, bufferSize, color.data(), imageCreateInfo); nvvk::Image image = m_alloc.createImage(cmdBuf, bufferSize, color.data(), imageCreateInfo);
// Setting up the descriptor used by the shader vk::ImageViewCreateInfo ivInfo = nvvk::makeImageViewCreateInfo(image.image, imageCreateInfo);
texture.descriptor = texture = m_alloc.createTexture(image, ivInfo, samplerCreateInfo);
nvvkpp::image::create2DDescriptor(m_device, texture.image, samplerCreateInfo, format);
// The image format must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL // The image format must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
nvvkpp::image::setImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined, nvvk::cmdBarrierImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eShaderReadOnlyOptimal); vk::ImageLayout::eShaderReadOnlyOptimal);
m_textures.push_back(texture); m_textures.push_back(texture);
} }
else else
@ -357,16 +356,15 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4; vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4;
auto imgSize = vk::Extent2D(texWidth, texHeight); auto imgSize = vk::Extent2D(texWidth, texHeight);
auto imageCreateInfo = nvvkpp::image::create2DInfo(imgSize, format, vkIU::eSampled, true); auto imageCreateInfo = nvvk::makeImage2DCreateInfo(imgSize, format, vkIU::eSampled, true);
{ {
nvvkTexture texture; nvvk::Image image = m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo);
texture = m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo); nvvk::cmdGenerateMipmaps(cmdBuf, image.image, format, imgSize, imageCreateInfo.mipLevels);
vk::ImageViewCreateInfo ivInfo =
nvvk::makeImageViewCreateInfo(image.image, imageCreateInfo);
nvvk::Texture texture = m_alloc.createTexture(image, ivInfo, samplerCreateInfo);
nvvkpp::image::generateMipmaps(cmdBuf, texture.image, format, imgSize,
imageCreateInfo.mipLevels);
texture.descriptor =
nvvkpp::image::create2DDescriptor(m_device, texture.image, samplerCreateInfo, format);
m_textures.push_back(texture); m_textures.push_back(texture);
} }
} }
@ -438,7 +436,7 @@ void HelloVulkan::rasterize(const vk::CommandBuffer& cmdBuf)
cmdBuf.pushConstants<ObjPushConstant>(m_pipelineLayout, vkSS::eVertex | vkSS::eFragment, 0, cmdBuf.pushConstants<ObjPushConstant>(m_pipelineLayout, vkSS::eVertex | vkSS::eFragment, 0,
m_pushConstant); m_pushConstant);
cmdBuf.bindVertexBuffers(0, 1, &model.vertexBuffer.buffer, &offset); cmdBuf.bindVertexBuffers(0, {model.vertexBuffer.buffer}, {offset});
cmdBuf.bindIndexBuffer(model.indexBuffer.buffer, 0, vk::IndexType::eUint32); cmdBuf.bindIndexBuffer(model.indexBuffer.buffer, 0, vk::IndexType::eUint32);
cmdBuf.drawIndexed(model.nbIndices, 1, 0, 0, 0); cmdBuf.drawIndexed(model.nbIndices, 1, 0, 0, 0);
} }
@ -467,49 +465,54 @@ void HelloVulkan::createOffscreenRender()
m_alloc.destroy(m_offscreenDepth); m_alloc.destroy(m_offscreenDepth);
// Creating the color image // Creating the color image
auto colorCreateInfo = nvvkpp::image::create2DInfo(m_size, m_offscreenColorFormat, {
vk::ImageUsageFlagBits::eColorAttachment auto colorCreateInfo = nvvk::makeImage2DCreateInfo(m_size, m_offscreenColorFormat,
| vk::ImageUsageFlagBits::eSampled vk::ImageUsageFlagBits::eColorAttachment
| vk::ImageUsageFlagBits::eStorage); | vk::ImageUsageFlagBits::eSampled
m_offscreenColor = m_alloc.createImage(colorCreateInfo); | vk::ImageUsageFlagBits::eStorage);
m_offscreenColor.descriptor =
nvvkpp::image::create2DDescriptor(m_device, m_offscreenColor.image, vk::SamplerCreateInfo{}, nvvk::Image image = m_alloc.createImage(colorCreateInfo);
m_offscreenColorFormat, vk::ImageLayout::eGeneral); vk::ImageViewCreateInfo ivInfo = nvvk::makeImageViewCreateInfo(image.image, colorCreateInfo);
m_offscreenColor = m_alloc.createTexture(image, ivInfo, vk::SamplerCreateInfo());
m_offscreenColor.descriptor.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
}
// Creating the depth buffer // Creating the depth buffer
auto depthCreateInfo = auto depthCreateInfo =
nvvkpp::image::create2DInfo(m_size, m_offscreenDepthFormat, nvvk::makeImage2DCreateInfo(m_size, m_offscreenDepthFormat,
vk::ImageUsageFlagBits::eDepthStencilAttachment); vk::ImageUsageFlagBits::eDepthStencilAttachment);
m_offscreenDepth = m_alloc.createImage(depthCreateInfo); {
nvvk::Image image = m_alloc.createImage(depthCreateInfo);
vk::ImageViewCreateInfo depthStencilView; vk::ImageViewCreateInfo depthStencilView;
depthStencilView.setViewType(vk::ImageViewType::e2D); depthStencilView.setViewType(vk::ImageViewType::e2D);
depthStencilView.setFormat(m_offscreenDepthFormat); depthStencilView.setFormat(m_offscreenDepthFormat);
depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1}); depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1});
depthStencilView.setImage(m_offscreenDepth.image); depthStencilView.setImage(image.image);
m_offscreenDepth.descriptor.imageView = m_device.createImageView(depthStencilView);
m_offscreenDepth = m_alloc.createTexture(image, depthStencilView);
}
// Setting the image layout for both color and depth // Setting the image layout for both color and depth
{ {
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex); nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
auto cmdBuf = genCmdBuf.createCommandBuffer(); auto cmdBuf = genCmdBuf.createCommandBuffer();
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined, nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eGeneral); vk::ImageLayout::eGeneral);
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageAspectFlagBits::eDepth, nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eUndefined, vk::ImageLayout::eDepthStencilAttachmentOptimal,
vk::ImageLayout::eDepthStencilAttachmentOptimal); vk::ImageAspectFlagBits::eDepth);
genCmdBuf.flushCommandBuffer(cmdBuf); genCmdBuf.submitAndWait(cmdBuf);
} }
// Creating a renderpass for the offscreen // Creating a renderpass for the offscreen
if(!m_offscreenRenderPass) if(!m_offscreenRenderPass)
{ {
m_offscreenRenderPass = m_offscreenRenderPass =
nvvkpp::util::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat, nvvk::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat, 1, true,
1, true, true, vk::ImageLayout::eGeneral, true, vk::ImageLayout::eGeneral, vk::ImageLayout::eGeneral);
vk::ImageLayout::eGeneral);
} }
// Creating the frame buffer for offscreen // Creating the frame buffer for offscreen
@ -546,13 +549,14 @@ void HelloVulkan::createPostPipeline()
// Pipeline: completely generic, no vertices // Pipeline: completely generic, no vertices
std::vector<std::string> paths = defaultSearchPaths; std::vector<std::string> paths = defaultSearchPaths;
nvvkpp::GraphicsPipelineGenerator pipelineGenerator(m_device, m_postPipelineLayout, m_renderPass); nvvk::GraphicsPipelineGeneratorCombined pipelineGenerator(m_device, m_postPipelineLayout,
m_renderPass);
pipelineGenerator.addShader(nvh::loadFile("shaders/passthrough.vert.spv", true, paths), pipelineGenerator.addShader(nvh::loadFile("shaders/passthrough.vert.spv", true, paths),
vk::ShaderStageFlagBits::eVertex); vk::ShaderStageFlagBits::eVertex);
pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths), pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths),
vk::ShaderStageFlagBits::eFragment); vk::ShaderStageFlagBits::eFragment);
pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone); pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone);
m_postPipeline = pipelineGenerator.create(); m_postPipeline = pipelineGenerator.createPipeline();
m_debug.setObjectName(m_postPipeline, "post"); m_debug.setObjectName(m_postPipeline, "post");
} }
@ -566,10 +570,10 @@ void HelloVulkan::createPostDescriptor()
using vkDT = vk::DescriptorType; using vkDT = vk::DescriptorType;
using vkSS = vk::ShaderStageFlagBits; using vkSS = vk::ShaderStageFlagBits;
m_postDescSetLayoutBind.emplace_back(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment)); m_postDescSetLayoutBind.addBinding(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
m_postDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_postDescSetLayoutBind); m_postDescSetLayout = m_postDescSetLayoutBind.createLayout(m_device);
m_postDescPool = nvvkpp::util::createDescriptorPool(m_device, m_postDescSetLayoutBind); m_postDescPool = m_postDescSetLayoutBind.createPool(m_device);
m_postDescSet = nvvkpp::util::createDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout); m_postDescSet = nvvk::allocateDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -578,8 +582,7 @@ void HelloVulkan::createPostDescriptor()
void HelloVulkan::updatePostDescriptorSet() void HelloVulkan::updatePostDescriptorSet()
{ {
vk::WriteDescriptorSet writeDescriptorSets = vk::WriteDescriptorSet writeDescriptorSets =
nvvkpp::util::createWrite(m_postDescSet, m_postDescSetLayoutBind[0], m_postDescSetLayoutBind.makeWrite(m_postDescSet, 0, &m_offscreenColor.descriptor);
&m_offscreenColor.descriptor);
m_device.updateDescriptorSets(writeDescriptorSets, nullptr); m_device.updateDescriptorSets(writeDescriptorSets, nullptr);
} }
@ -617,13 +620,13 @@ void HelloVulkan::initRayTracing()
auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2, auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2,
vk::PhysicalDeviceRayTracingPropertiesKHR>(); vk::PhysicalDeviceRayTracingPropertiesKHR>();
m_rtProperties = properties.get<vk::PhysicalDeviceRayTracingPropertiesKHR>(); m_rtProperties = properties.get<vk::PhysicalDeviceRayTracingPropertiesKHR>();
m_rtBuilder.setup(m_device, m_physicalDevice, m_graphicsQueueIndex); m_rtBuilder.setup(m_device, &m_alloc, m_graphicsQueueIndex);
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Converting a OBJ primitive to the ray tracing geometry used for the BLAS // Converting a OBJ primitive to the ray tracing geometry used for the BLAS
// //
nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model) nvvk::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model)
{ {
// Setting up the creation info of acceleration structure // Setting up the creation info of acceleration structure
vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate; vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate;
@ -660,7 +663,7 @@ nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjM
offset.setTransformOffset(0); offset.setTransformOffset(0);
// Our blas is only one geometry, but could be made of many geometries // Our blas is only one geometry, but could be made of many geometries
nvvkpp::RaytracingBuilderKHR::Blas blas; nvvk::RaytracingBuilderKHR::Blas blas;
blas.asGeometry.emplace_back(asGeom); blas.asGeometry.emplace_back(asGeom);
blas.asCreateGeometryInfo.emplace_back(asCreate); blas.asCreateGeometryInfo.emplace_back(asCreate);
blas.asBuildOffsetInfo.emplace_back(offset); blas.asBuildOffsetInfo.emplace_back(offset);
@ -674,7 +677,7 @@ nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjM
void HelloVulkan::createBottomLevelAS() void HelloVulkan::createBottomLevelAS()
{ {
// BLAS - Storing each primitive in a geometry // BLAS - Storing each primitive in a geometry
std::vector<nvvkpp::RaytracingBuilderKHR::Blas> allBlas; std::vector<nvvk::RaytracingBuilderKHR::Blas> allBlas;
allBlas.reserve(m_objModel.size()); allBlas.reserve(m_objModel.size());
for(const auto& obj : m_objModel) for(const auto& obj : m_objModel)
{ {
@ -688,16 +691,16 @@ void HelloVulkan::createBottomLevelAS()
void HelloVulkan::createTopLevelAS() void HelloVulkan::createTopLevelAS()
{ {
std::vector<nvvkpp::RaytracingBuilderKHR::Instance> tlas; std::vector<nvvk::RaytracingBuilderKHR::Instance> tlas;
tlas.reserve(m_objInstance.size()); tlas.reserve(m_objInstance.size());
for(int i = 0; i < static_cast<int>(m_objInstance.size()); i++) for(int i = 0; i < static_cast<int>(m_objInstance.size()); i++)
{ {
nvvkpp::RaytracingBuilderKHR::Instance rayInst; nvvk::RaytracingBuilderKHR::Instance rayInst;
rayInst.transform = m_objInstance[i].transform; // Position of the instance rayInst.transform = m_objInstance[i].transform; // Position of the instance
rayInst.instanceId = i; // gl_InstanceID rayInst.instanceId = i; // gl_InstanceID
rayInst.blasId = m_objInstance[i].objIndex; rayInst.blasId = m_objInstance[i].objIndex;
rayInst.hitGroupId = 0; // We will use the same hit group for all objects rayInst.hitGroupId = 0; // We will use the same hit group for all objects
rayInst.flags = vk::GeometryInstanceFlagBitsKHR::eTriangleCullDisable; rayInst.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
tlas.emplace_back(rayInst); tlas.emplace_back(rayInst);
} }
m_rtBuilder.buildTlas(tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace); m_rtBuilder.buildTlas(tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace);

View file

@ -26,16 +26,14 @@
*/ */
#pragma once #pragma once
#include "nvvkpp/allocator_dedicated_vkpp.hpp" #define NVVK_ALLOC_DEDICATED
#include "nvvkpp/appbase_vkpp.hpp" #include "nvvk/allocator_vk.hpp"
#include "nvvkpp/debug_util_vkpp.hpp" #include "nvvk/appbase_vkpp.hpp"
#include "nvvk/debug_util_vk.hpp"
#include "nvvk/descriptorsets_vk.hpp"
// #VKRay // #VKRay
#define ALLOC_DEDICATED #include "nvvk/raytraceKHR_vk.hpp"
#include "nvvkpp/raytraceKHR_vkpp.hpp"
using nvvkBuffer = nvvkpp::BufferDedicated;
using nvvkTexture = nvvkpp::TextureDedicated;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Simple rasterizer of OBJ objects // Simple rasterizer of OBJ objects
@ -44,10 +42,11 @@ using nvvkTexture = nvvkpp::TextureDedicated;
// - Rendering is done in an offscreen framebuffer // - Rendering is done in an offscreen framebuffer
// - The image of the framebuffer is displayed in post-process in a full-screen quad // - The image of the framebuffer is displayed in post-process in a full-screen quad
// //
class HelloVulkan : public nvvkpp::AppBase class HelloVulkan : public nvvk::AppBase
{ {
public: public:
void setup(const vk::Device& device, void setup(const vk::Instance& instance,
const vk::Device& device,
const vk::PhysicalDevice& physicalDevice, const vk::PhysicalDevice& physicalDevice,
uint32_t queueFamily) override; uint32_t queueFamily) override;
void createDescriptorSetLayout(); void createDescriptorSetLayout();
@ -66,12 +65,12 @@ public:
// The OBJ model // The OBJ model
struct ObjModel struct ObjModel
{ {
uint32_t nbIndices{0}; uint32_t nbIndices{0};
uint32_t nbVertices{0}; uint32_t nbVertices{0};
nvvkBuffer vertexBuffer; // Device buffer of all 'Vertex' nvvk::Buffer vertexBuffer; // Device buffer of all 'Vertex'
nvvkBuffer indexBuffer; // Device buffer of the indices forming triangles nvvk::Buffer indexBuffer; // Device buffer of the indices forming triangles
nvvkBuffer matColorBuffer; // Device buffer of array of 'Wavefront material' nvvk::Buffer matColorBuffer; // Device buffer of array of 'Wavefront material'
nvvkBuffer matIndexBuffer; // Device buffer of array of 'Wavefront material' nvvk::Buffer matIndexBuffer; // Device buffer of array of 'Wavefront material'
}; };
// Instance of the OBJ // Instance of the OBJ
@ -98,19 +97,19 @@ public:
std::vector<ObjInstance> m_objInstance; std::vector<ObjInstance> m_objInstance;
// Graphic pipeline // Graphic pipeline
vk::PipelineLayout m_pipelineLayout; vk::PipelineLayout m_pipelineLayout;
vk::Pipeline m_graphicsPipeline; vk::Pipeline m_graphicsPipeline;
std::vector<vk::DescriptorSetLayoutBinding> m_descSetLayoutBind; nvvk::DescriptorSetBindings m_descSetLayoutBind;
vk::DescriptorPool m_descPool; vk::DescriptorPool m_descPool;
vk::DescriptorSetLayout m_descSetLayout; vk::DescriptorSetLayout m_descSetLayout;
vk::DescriptorSet m_descSet; vk::DescriptorSet m_descSet;
nvvkBuffer m_cameraMat; // Device-Host of the camera matrices nvvk::Buffer m_cameraMat; // Device-Host of the camera matrices
nvvkBuffer m_sceneDesc; // Device buffer of the OBJ instances nvvk::Buffer m_sceneDesc; // Device buffer of the OBJ instances
std::vector<nvvkTexture> m_textures; // vector of all textures of the scene std::vector<nvvk::Texture> m_textures; // vector of all textures of the scene
nvvkpp::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures nvvk::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures
nvvkpp::DebugUtil m_debug; // Utility to name objects nvvk::DebugUtil m_debug; // Utility to name objects
// #Post // #Post
void createOffscreenRender(); void createOffscreenRender();
@ -119,25 +118,25 @@ public:
void updatePostDescriptorSet(); void updatePostDescriptorSet();
void drawPost(vk::CommandBuffer cmdBuf); void drawPost(vk::CommandBuffer cmdBuf);
std::vector<vk::DescriptorSetLayoutBinding> m_postDescSetLayoutBind; nvvk::DescriptorSetBindings m_postDescSetLayoutBind;
vk::DescriptorPool m_postDescPool; vk::DescriptorPool m_postDescPool;
vk::DescriptorSetLayout m_postDescSetLayout; vk::DescriptorSetLayout m_postDescSetLayout;
vk::DescriptorSet m_postDescSet; vk::DescriptorSet m_postDescSet;
vk::Pipeline m_postPipeline; vk::Pipeline m_postPipeline;
vk::PipelineLayout m_postPipelineLayout; vk::PipelineLayout m_postPipelineLayout;
vk::RenderPass m_offscreenRenderPass; vk::RenderPass m_offscreenRenderPass;
vk::Framebuffer m_offscreenFramebuffer; vk::Framebuffer m_offscreenFramebuffer;
nvvkTexture m_offscreenColor; nvvk::Texture m_offscreenColor;
vk::Format m_offscreenColorFormat{vk::Format::eR32G32B32A32Sfloat}; vk::Format m_offscreenColorFormat{vk::Format::eR32G32B32A32Sfloat};
nvvkTexture m_offscreenDepth; nvvk::Texture m_offscreenDepth;
vk::Format m_offscreenDepthFormat{vk::Format::eD32Sfloat}; vk::Format m_offscreenDepthFormat{vk::Format::eD32Sfloat};
// #VKRay // #VKRay
void initRayTracing(); void initRayTracing();
nvvkpp::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model); nvvk::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
void createBottomLevelAS(); void createBottomLevelAS();
void createTopLevelAS(); void createTopLevelAS();
vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties; vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties;
nvvkpp::RaytracingBuilderKHR m_rtBuilder; nvvk::RaytracingBuilderKHR m_rtBuilder;
}; };

View file

@ -30,8 +30,10 @@
// at the top of imgui.cpp. // at the top of imgui.cpp.
#include <array> #include <array>
#include <iostream>
#include <vulkan/vulkan.hpp> #include <vulkan/vulkan.hpp>
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
#include "imgui.h" #include "imgui.h"
#include "imgui_impl_glfw.h" #include "imgui_impl_glfw.h"
@ -40,10 +42,10 @@
#include "nvh/cameramanipulator.hpp" #include "nvh/cameramanipulator.hpp"
#include "nvh/fileoperations.hpp" #include "nvh/fileoperations.hpp"
#include "nvpsystem.hpp" #include "nvpsystem.hpp"
#include "nvvkpp/appbase_vkpp.hpp" #include "nvvk/appbase_vkpp.hpp"
#include "nvvkpp/commands_vkpp.hpp" #include "nvvk/commands_vk.hpp"
#include "nvvkpp/context_vkpp.hpp" #include "nvvk/context_vk.hpp"
#include "nvvkpp/utilities_vkpp.hpp"
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
#define UNUSED(x) (void)(x) #define UNUSED(x) (void)(x)
@ -125,7 +127,7 @@ int main(int argc, char** argv)
vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature; vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature;
// Requesting Vulkan extensions and layers // Requesting Vulkan extensions and layers
nvvkpp::ContextCreateInfo contextInfo(true); nvvk::ContextCreateInfo contextInfo(true);
contextInfo.setVersion(1, 2); contextInfo.setVersion(1, 2);
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true); contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME); contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME);
@ -148,7 +150,7 @@ int main(int argc, char** argv)
// Creating Vulkan base application // Creating Vulkan base application
nvvkpp::Context vkctx{}; nvvk::Context vkctx{};
vkctx.initInstance(contextInfo); vkctx.initInstance(contextInfo);
// Find all compatible devices // Find all compatible devices
auto compatibleDevices = vkctx.getCompatibleDevices(contextInfo); auto compatibleDevices = vkctx.getCompatibleDevices(contextInfo);
@ -164,7 +166,8 @@ int main(int argc, char** argv)
const vk::SurfaceKHR surface = helloVk.getVkSurface(vkctx.m_instance, window); const vk::SurfaceKHR surface = helloVk.getVkSurface(vkctx.m_instance, window);
vkctx.setGCTQueueWithPresent(surface); vkctx.setGCTQueueWithPresent(surface);
helloVk.setup(vkctx.m_device, vkctx.m_physicalDevice, vkctx.m_queueGCT.familyIndex); helloVk.setup(vkctx.m_instance, vkctx.m_device, vkctx.m_physicalDevice,
vkctx.m_queueGCT.familyIndex);
helloVk.createSurface(surface, SAMPLE_WIDTH, SAMPLE_HEIGHT); helloVk.createSurface(surface, SAMPLE_WIDTH, SAMPLE_HEIGHT);
helloVk.createDepthBuffer(); helloVk.createDepthBuffer();
helloVk.createRenderPass(); helloVk.createRenderPass();
@ -238,7 +241,8 @@ int main(int argc, char** argv)
// Clearing screen // Clearing screen
vk::ClearValue clearValues[2]; vk::ClearValue clearValues[2];
clearValues[0].setColor(nvvkpp::util::clearColor(clearColor)); clearValues[0].setColor(
std::array<float, 4>({clearColor[0], clearColor[1], clearColor[2], clearColor[3]}));
clearValues[1].setDepthStencil({1.0f, 0}); clearValues[1].setDepthStencil({1.0f, 0});
// Offscreen render pass // Offscreen render pass
@ -297,7 +301,6 @@ int main(int argc, char** argv)
helloVk.destroyResources(); helloVk.destroyResources();
helloVk.destroy(); helloVk.destroy();
vkctx.m_instance.destroySurfaceKHR(surface);
vkctx.deinit(); vkctx.deinit();
glfwDestroyWindow(window); glfwDestroyWindow(window);

View file

@ -36,13 +36,14 @@ extern std::vector<std::string> defaultSearchPaths;
#include "hello_vulkan.h" #include "hello_vulkan.h"
#include "nvh//cameramanipulator.hpp" #include "nvh//cameramanipulator.hpp"
#include "nvvkpp/descriptorsets_vkpp.hpp" #include "nvvk/descriptorsets_vk.hpp"
#include "nvvkpp/pipeline_vkpp.hpp" #include "nvvk/pipeline_vk.hpp"
#include "nvh/fileoperations.hpp" #include "nvh/fileoperations.hpp"
#include "nvvkpp/commands_vkpp.hpp" #include "nvvk/commands_vk.hpp"
#include "nvvkpp/renderpass_vkpp.hpp" #include "nvvk/renderpasses_vk.hpp"
#include "nvvkpp/utilities_vkpp.hpp" #include "nvvk/shaders_vk.hpp"
// Holding the camera matrices // Holding the camera matrices
struct CameraMatrices struct CameraMatrices
@ -58,11 +59,12 @@ struct CameraMatrices
// Keep the handle on the device // Keep the handle on the device
// Initialize the tool to do all our allocations: buffers, images // Initialize the tool to do all our allocations: buffers, images
// //
void HelloVulkan::setup(const vk::Device& device, void HelloVulkan::setup(const vk::Instance& instance,
const vk::Device& device,
const vk::PhysicalDevice& physicalDevice, const vk::PhysicalDevice& physicalDevice,
uint32_t queueFamily) uint32_t queueFamily)
{ {
AppBase::setup(device, physicalDevice, queueFamily); AppBase::setup(instance, device, physicalDevice, queueFamily);
m_alloc.init(device, physicalDevice); m_alloc.init(device, physicalDevice);
m_debug.setup(m_device); m_debug.setup(m_device);
} }
@ -99,31 +101,31 @@ void HelloVulkan::createDescriptorSetLayout()
uint32_t nbObj = static_cast<uint32_t>(m_objModel.size()); uint32_t nbObj = static_cast<uint32_t>(m_objModel.size());
// Camera matrices (binding = 0) // Camera matrices (binding = 0)
m_descSetLayoutBind.emplace_back( m_descSetLayoutBind.addBinding(
vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR)); vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR));
// Materials (binding = 1) // Materials (binding = 1)
m_descSetLayoutBind.emplace_back( m_descSetLayoutBind.addBinding(
vkDS(1, vkDT::eStorageBuffer, nbObj, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR)); vkDS(1, vkDT::eStorageBuffer, nbObj, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
// Scene description (binding = 2) // Scene description (binding = 2)
m_descSetLayoutBind.emplace_back( // m_descSetLayoutBind.addBinding( //
vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR)); vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
// Textures (binding = 3) // Textures (binding = 3)
m_descSetLayoutBind.emplace_back( m_descSetLayoutBind.addBinding(
vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR)); vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR));
// Materials (binding = 4) // Materials (binding = 4)
m_descSetLayoutBind.emplace_back( m_descSetLayoutBind.addBinding(
vkDS(4, vkDT::eStorageBuffer, nbObj, vkSS::eFragment | vkSS::eClosestHitKHR)); vkDS(4, vkDT::eStorageBuffer, nbObj, vkSS::eFragment | vkSS::eClosestHitKHR));
// Storing vertices (binding = 5) // Storing vertices (binding = 5)
m_descSetLayoutBind.emplace_back( // m_descSetLayoutBind.addBinding( //
vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR)); vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
// Storing indices (binding = 6) // Storing indices (binding = 6)
m_descSetLayoutBind.emplace_back( // m_descSetLayoutBind.addBinding( //
vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR)); vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
m_descSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_descSetLayoutBind); m_descSetLayout = m_descSetLayoutBind.createLayout(m_device);
m_descPool = nvvkpp::util::createDescriptorPool(m_device, m_descSetLayoutBind, 1); m_descPool = m_descSetLayoutBind.createPool(m_device, 1);
m_descSet = nvvkpp::util::createDescriptorSet(m_device, m_descPool, m_descSetLayout); m_descSet = nvvk::allocateDescriptorSet(m_device, m_descPool, m_descSetLayout);
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -135,9 +137,9 @@ void HelloVulkan::updateDescriptorSet()
// Camera matrices and scene description // Camera matrices and scene description
vk::DescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE}; vk::DescriptorBufferInfo dbiUnif{m_cameraMat.buffer, 0, VK_WHOLE_SIZE};
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[0], &dbiUnif)); writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 0, &dbiUnif));
vk::DescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE}; vk::DescriptorBufferInfo dbiSceneDesc{m_sceneDesc.buffer, 0, VK_WHOLE_SIZE};
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[2], &dbiSceneDesc)); writes.emplace_back(m_descSetLayoutBind.makeWrite(m_descSet, 2, &dbiSceneDesc));
// All material buffers, 1 buffer per OBJ // All material buffers, 1 buffer per OBJ
std::vector<vk::DescriptorBufferInfo> dbiMat; std::vector<vk::DescriptorBufferInfo> dbiMat;
@ -151,11 +153,10 @@ void HelloVulkan::updateDescriptorSet()
dbiVert.push_back({m_objModel[i].vertexBuffer.buffer, 0, VK_WHOLE_SIZE}); dbiVert.push_back({m_objModel[i].vertexBuffer.buffer, 0, VK_WHOLE_SIZE});
dbiIdx.push_back({m_objModel[i].indexBuffer.buffer, 0, VK_WHOLE_SIZE}); dbiIdx.push_back({m_objModel[i].indexBuffer.buffer, 0, VK_WHOLE_SIZE});
} }
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[1], dbiMat.data())); writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 1, dbiMat.data()));
writes.emplace_back( writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 4, dbiMatIdx.data()));
nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[4], dbiMatIdx.data())); writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 5, dbiVert.data()));
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[5], dbiVert.data())); writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 6, dbiIdx.data()));
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[6], dbiIdx.data()));
// All texture samplers // All texture samplers
std::vector<vk::DescriptorImageInfo> diit; std::vector<vk::DescriptorImageInfo> diit;
@ -163,7 +164,7 @@ void HelloVulkan::updateDescriptorSet()
{ {
diit.push_back(m_textures[i].descriptor); diit.push_back(m_textures[i].descriptor);
} }
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[3], diit.data())); writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 3, diit.data()));
// Writing the information // Writing the information
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr); m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
@ -189,19 +190,18 @@ void HelloVulkan::createGraphicsPipeline()
m_pipelineLayout = m_device.createPipelineLayout(pipelineLayoutCreateInfo); m_pipelineLayout = m_device.createPipelineLayout(pipelineLayoutCreateInfo);
// Creating the Pipeline // Creating the Pipeline
std::vector<std::string> paths = defaultSearchPaths; std::vector<std::string> paths = defaultSearchPaths;
nvvkpp::GraphicsPipelineGenerator gpb(m_device, m_pipelineLayout, m_offscreenRenderPass); nvvk::GraphicsPipelineGeneratorCombined gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
gpb.depthStencilState = {true}; gpb.depthStencilState.depthTestEnable = true;
gpb.addShader(nvh::loadFile("shaders/vert_shader.vert.spv", true, paths), vkSS::eVertex); gpb.addShader(nvh::loadFile("shaders/vert_shader.vert.spv", true, paths), vkSS::eVertex);
gpb.addShader(nvh::loadFile("shaders/frag_shader.frag.spv", true, paths), vkSS::eFragment); gpb.addShader(nvh::loadFile("shaders/frag_shader.frag.spv", true, paths), vkSS::eFragment);
gpb.vertexInputState.bindingDescriptions = {{0, sizeof(VertexObj)}}; gpb.addBindingDescription({0, sizeof(VertexObj)});
gpb.vertexInputState.attributeDescriptions = { gpb.addAttributeDescriptions({{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)}, {1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)},
{1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)}, {2, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, color)},
{2, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, color)}, {3, 0, vk::Format::eR32G32Sfloat, offsetof(VertexObj, texCoord)}});
{3, 0, vk::Format::eR32G32Sfloat, offsetof(VertexObj, texCoord)}};
m_graphicsPipeline = gpb.create(); m_graphicsPipeline = gpb.createPipeline();
m_debug.setObjectName(m_graphicsPipeline, "Graphics"); m_debug.setObjectName(m_graphicsPipeline, "Graphics");
} }
@ -234,8 +234,8 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size()); model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
// Create the buffers on Device and copy vertices, indices and materials // Create the buffers on Device and copy vertices, indices and materials
nvvkpp::SingleCommandBuffer cmdBufGet(m_device, m_graphicsQueueIndex); nvvk::CommandPool cmdBufGet(m_device, m_graphicsQueueIndex);
vk::CommandBuffer cmdBuf = cmdBufGet.createCommandBuffer(); vk::CommandBuffer cmdBuf = cmdBufGet.createCommandBuffer();
model.vertexBuffer = model.vertexBuffer =
m_alloc.createBuffer(cmdBuf, loader.m_vertices, m_alloc.createBuffer(cmdBuf, loader.m_vertices,
vkBU::eVertexBuffer | vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress); vkBU::eVertexBuffer | vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress);
@ -246,8 +246,8 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, vkBU::eStorageBuffer); model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, vkBU::eStorageBuffer);
// Creates all textures found // Creates all textures found
createTextureImages(cmdBuf, loader.m_textures); createTextureImages(cmdBuf, loader.m_textures);
cmdBufGet.flushCommandBuffer(cmdBuf); cmdBufGet.submitAndWait(cmdBuf);
m_alloc.flushStaging(); m_alloc.finalizeAndReleaseStaging();
std::string objNb = std::to_string(instance.objIndex); std::string objNb = std::to_string(instance.objIndex);
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str())); m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
@ -282,12 +282,12 @@ void HelloVulkan::createUniformBuffer()
void HelloVulkan::createSceneDescriptionBuffer() void HelloVulkan::createSceneDescriptionBuffer()
{ {
using vkBU = vk::BufferUsageFlagBits; using vkBU = vk::BufferUsageFlagBits;
nvvkpp::SingleCommandBuffer cmdGen(m_device, m_graphicsQueueIndex); nvvk::CommandPool cmdGen(m_device, m_graphicsQueueIndex);
auto cmdBuf = cmdGen.createCommandBuffer(); auto cmdBuf = cmdGen.createCommandBuffer();
m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer); m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer);
cmdGen.flushCommandBuffer(cmdBuf); cmdGen.submitAndWait(cmdBuf);
m_alloc.flushStaging(); m_alloc.finalizeAndReleaseStaging();
m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc"); m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc");
} }
@ -307,21 +307,21 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
// If no textures are present, create a dummy one to accommodate the pipeline layout // If no textures are present, create a dummy one to accommodate the pipeline layout
if(textures.empty() && m_textures.empty()) if(textures.empty() && m_textures.empty())
{ {
nvvkTexture texture; nvvk::Texture texture;
std::array<uint8_t, 4> color{255u, 255u, 255u, 255u}; std::array<uint8_t, 4> color{255u, 255u, 255u, 255u};
vk::DeviceSize bufferSize = sizeof(color); vk::DeviceSize bufferSize = sizeof(color);
auto imgSize = vk::Extent2D(1, 1); auto imgSize = vk::Extent2D(1, 1);
auto imageCreateInfo = nvvkpp::image::create2DInfo(imgSize, format); auto imageCreateInfo = nvvk::makeImage2DCreateInfo(imgSize, format);
// Creating the dummy texure
nvvk::Image image = m_alloc.createImage(cmdBuf, bufferSize, color.data(), imageCreateInfo);
vk::ImageViewCreateInfo ivInfo = nvvk::makeImageViewCreateInfo(image.image, imageCreateInfo);
texture = m_alloc.createTexture(image, ivInfo, samplerCreateInfo);
// Creating the VKImage
texture = m_alloc.createImage(cmdBuf, bufferSize, color.data(), imageCreateInfo);
// Setting up the descriptor used by the shader
texture.descriptor =
nvvkpp::image::create2DDescriptor(m_device, texture.image, samplerCreateInfo, format);
// The image format must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL // The image format must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
nvvkpp::image::setImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined, nvvk::cmdBarrierImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eShaderReadOnlyOptimal); vk::ImageLayout::eShaderReadOnlyOptimal);
m_textures.push_back(texture); m_textures.push_back(texture);
} }
else else
@ -348,16 +348,16 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4; vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4;
auto imgSize = vk::Extent2D(texWidth, texHeight); auto imgSize = vk::Extent2D(texWidth, texHeight);
auto imageCreateInfo = nvvkpp::image::create2DInfo(imgSize, format, vkIU::eSampled, true); auto imageCreateInfo = nvvk::makeImage2DCreateInfo(imgSize, format, vkIU::eSampled, true);
{ {
nvvkTexture texture; nvvk::ImageDedicated image =
texture = m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo); m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo);
nvvk::cmdGenerateMipmaps(cmdBuf, image.image, format, imgSize, imageCreateInfo.mipLevels);
vk::ImageViewCreateInfo ivInfo =
nvvk::makeImageViewCreateInfo(image.image, imageCreateInfo);
nvvk::Texture texture = m_alloc.createTexture(image, ivInfo, samplerCreateInfo);
nvvkpp::image::generateMipmaps(cmdBuf, texture.image, format, imgSize,
imageCreateInfo.mipLevels);
texture.descriptor =
nvvkpp::image::create2DDescriptor(m_device, texture.image, samplerCreateInfo, format);
m_textures.push_back(texture); m_textures.push_back(texture);
} }
} }
@ -434,7 +434,7 @@ void HelloVulkan::rasterize(const vk::CommandBuffer& cmdBuf)
cmdBuf.pushConstants<ObjPushConstant>(m_pipelineLayout, vkSS::eVertex | vkSS::eFragment, 0, cmdBuf.pushConstants<ObjPushConstant>(m_pipelineLayout, vkSS::eVertex | vkSS::eFragment, 0,
m_pushConstant); m_pushConstant);
cmdBuf.bindVertexBuffers(0, 1, &model.vertexBuffer.buffer, &offset); cmdBuf.bindVertexBuffers(0, {model.vertexBuffer.buffer}, {offset});
cmdBuf.bindIndexBuffer(model.indexBuffer.buffer, 0, vk::IndexType::eUint32); cmdBuf.bindIndexBuffer(model.indexBuffer.buffer, 0, vk::IndexType::eUint32);
cmdBuf.drawIndexed(model.nbIndices, 1, 0, 0, 0); cmdBuf.drawIndexed(model.nbIndices, 1, 0, 0, 0);
} }
@ -464,49 +464,54 @@ void HelloVulkan::createOffscreenRender()
m_alloc.destroy(m_offscreenDepth); m_alloc.destroy(m_offscreenDepth);
// Creating the color image // Creating the color image
auto colorCreateInfo = nvvkpp::image::create2DInfo(m_size, m_offscreenColorFormat, {
vk::ImageUsageFlagBits::eColorAttachment auto colorCreateInfo = nvvk::makeImage2DCreateInfo(m_size, m_offscreenColorFormat,
| vk::ImageUsageFlagBits::eSampled vk::ImageUsageFlagBits::eColorAttachment
| vk::ImageUsageFlagBits::eStorage); | vk::ImageUsageFlagBits::eSampled
m_offscreenColor = m_alloc.createImage(colorCreateInfo); | vk::ImageUsageFlagBits::eStorage);
m_offscreenColor.descriptor =
nvvkpp::image::create2DDescriptor(m_device, m_offscreenColor.image, vk::SamplerCreateInfo{}, nvvk::Image image = m_alloc.createImage(colorCreateInfo);
m_offscreenColorFormat, vk::ImageLayout::eGeneral); vk::ImageViewCreateInfo ivInfo = nvvk::makeImageViewCreateInfo(image.image, colorCreateInfo);
m_offscreenColor = m_alloc.createTexture(image, ivInfo, vk::SamplerCreateInfo());
m_offscreenColor.descriptor.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
}
// Creating the depth buffer // Creating the depth buffer
auto depthCreateInfo = auto depthCreateInfo =
nvvkpp::image::create2DInfo(m_size, m_offscreenDepthFormat, nvvk::makeImage2DCreateInfo(m_size, m_offscreenDepthFormat,
vk::ImageUsageFlagBits::eDepthStencilAttachment); vk::ImageUsageFlagBits::eDepthStencilAttachment);
m_offscreenDepth = m_alloc.createImage(depthCreateInfo); {
nvvk::Image image = m_alloc.createImage(depthCreateInfo);
vk::ImageViewCreateInfo depthStencilView; vk::ImageViewCreateInfo depthStencilView;
depthStencilView.setViewType(vk::ImageViewType::e2D); depthStencilView.setViewType(vk::ImageViewType::e2D);
depthStencilView.setFormat(m_offscreenDepthFormat); depthStencilView.setFormat(m_offscreenDepthFormat);
depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1}); depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1});
depthStencilView.setImage(m_offscreenDepth.image); depthStencilView.setImage(image.image);
m_offscreenDepth.descriptor.imageView = m_device.createImageView(depthStencilView);
m_offscreenDepth = m_alloc.createTexture(image, depthStencilView);
}
// Setting the image layout for both color and depth // Setting the image layout for both color and depth
{ {
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex); nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
auto cmdBuf = genCmdBuf.createCommandBuffer(); auto cmdBuf = genCmdBuf.createCommandBuffer();
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined, nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eGeneral); vk::ImageLayout::eGeneral);
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageAspectFlagBits::eDepth, nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eUndefined, vk::ImageLayout::eDepthStencilAttachmentOptimal,
vk::ImageLayout::eDepthStencilAttachmentOptimal); vk::ImageAspectFlagBits::eDepth);
genCmdBuf.flushCommandBuffer(cmdBuf); genCmdBuf.submitAndWait(cmdBuf);
} }
// Creating a renderpass for the offscreen // Creating a renderpass for the offscreen
if(!m_offscreenRenderPass) if(!m_offscreenRenderPass)
{ {
m_offscreenRenderPass = m_offscreenRenderPass =
nvvkpp::util::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat, nvvk::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat, 1, true,
1, true, true, vk::ImageLayout::eGeneral, true, vk::ImageLayout::eGeneral, vk::ImageLayout::eGeneral);
vk::ImageLayout::eGeneral);
} }
// Creating the frame buffer for offscreen // Creating the frame buffer for offscreen
@ -543,13 +548,14 @@ void HelloVulkan::createPostPipeline()
// Pipeline: completely generic, no vertices // Pipeline: completely generic, no vertices
std::vector<std::string> paths = defaultSearchPaths; std::vector<std::string> paths = defaultSearchPaths;
nvvkpp::GraphicsPipelineGenerator pipelineGenerator(m_device, m_postPipelineLayout, m_renderPass); nvvk::GraphicsPipelineGeneratorCombined pipelineGenerator(m_device, m_postPipelineLayout,
m_renderPass);
pipelineGenerator.addShader(nvh::loadFile("shaders/passthrough.vert.spv", true, paths), pipelineGenerator.addShader(nvh::loadFile("shaders/passthrough.vert.spv", true, paths),
vk::ShaderStageFlagBits::eVertex); vk::ShaderStageFlagBits::eVertex);
pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths), pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths),
vk::ShaderStageFlagBits::eFragment); vk::ShaderStageFlagBits::eFragment);
pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone); pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone);
m_postPipeline = pipelineGenerator.create(); m_postPipeline = pipelineGenerator.createPipeline();
m_debug.setObjectName(m_postPipeline, "post"); m_debug.setObjectName(m_postPipeline, "post");
} }
@ -563,10 +569,10 @@ void HelloVulkan::createPostDescriptor()
using vkDT = vk::DescriptorType; using vkDT = vk::DescriptorType;
using vkSS = vk::ShaderStageFlagBits; using vkSS = vk::ShaderStageFlagBits;
m_postDescSetLayoutBind.emplace_back(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment)); m_postDescSetLayoutBind.addBinding(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
m_postDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_postDescSetLayoutBind); m_postDescSetLayout = m_postDescSetLayoutBind.createLayout(m_device);
m_postDescPool = nvvkpp::util::createDescriptorPool(m_device, m_postDescSetLayoutBind); m_postDescPool = m_postDescSetLayoutBind.createPool(m_device);
m_postDescSet = nvvkpp::util::createDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout); m_postDescSet = nvvk::allocateDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -575,8 +581,7 @@ void HelloVulkan::createPostDescriptor()
void HelloVulkan::updatePostDescriptorSet() void HelloVulkan::updatePostDescriptorSet()
{ {
vk::WriteDescriptorSet writeDescriptorSets = vk::WriteDescriptorSet writeDescriptorSets =
nvvkpp::util::createWrite(m_postDescSet, m_postDescSetLayoutBind[0], m_postDescSetLayoutBind.makeWrite(m_postDescSet, 0, &m_offscreenColor.descriptor);
&m_offscreenColor.descriptor);
m_device.updateDescriptorSets(writeDescriptorSets, nullptr); m_device.updateDescriptorSets(writeDescriptorSets, nullptr);
} }
@ -614,15 +619,15 @@ void HelloVulkan::initRayTracing()
auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2, auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2,
vk::PhysicalDeviceRayTracingPropertiesKHR>(); vk::PhysicalDeviceRayTracingPropertiesKHR>();
m_rtProperties = properties.get<vk::PhysicalDeviceRayTracingPropertiesKHR>(); m_rtProperties = properties.get<vk::PhysicalDeviceRayTracingPropertiesKHR>();
m_rtBuilder.setup(m_device, m_physicalDevice, m_graphicsQueueIndex); m_rtBuilder.setup(m_device, &m_alloc, m_graphicsQueueIndex);
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Converting a OBJ primitive to the ray tracing geometry used for the BLAS // Converting a OBJ primitive to the ray tracing geometry used for the BLAS
// //
nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model) nvvk::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model)
{ {
nvvkpp::RaytracingBuilderKHR::Blas blas; nvvk::RaytracingBuilderKHR::Blas blas;
vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate; vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate;
asCreate.setGeometryType(vk::GeometryTypeKHR::eTriangles); asCreate.setGeometryType(vk::GeometryTypeKHR::eTriangles);
asCreate.setIndexType(vk::IndexType::eUint32); asCreate.setIndexType(vk::IndexType::eUint32);
@ -659,7 +664,7 @@ nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjM
void HelloVulkan::createBottomLevelAS() void HelloVulkan::createBottomLevelAS()
{ {
// BLAS - Storing each primitive in a geometry // BLAS - Storing each primitive in a geometry
std::vector<nvvkpp::RaytracingBuilderKHR::Blas> allBlas; std::vector<nvvk::RaytracingBuilderKHR::Blas> allBlas;
allBlas.reserve(m_objModel.size()); allBlas.reserve(m_objModel.size());
for(const auto& obj : m_objModel) for(const auto& obj : m_objModel)
{ {
@ -673,16 +678,16 @@ void HelloVulkan::createBottomLevelAS()
void HelloVulkan::createTopLevelAS() void HelloVulkan::createTopLevelAS()
{ {
std::vector<nvvkpp::RaytracingBuilderKHR::Instance> tlas; std::vector<nvvk::RaytracingBuilderKHR::Instance> tlas;
tlas.reserve(m_objInstance.size()); tlas.reserve(m_objInstance.size());
for(int i = 0; i < static_cast<int>(m_objInstance.size()); i++) for(int i = 0; i < static_cast<int>(m_objInstance.size()); i++)
{ {
nvvkpp::RaytracingBuilderKHR::Instance rayInst; nvvk::RaytracingBuilderKHR::Instance rayInst;
rayInst.transform = m_objInstance[i].transform; // Position of the instance rayInst.transform = m_objInstance[i].transform; // Position of the instance
rayInst.instanceId = i; // gl_InstanceID rayInst.instanceId = i; // gl_InstanceID
rayInst.blasId = m_objInstance[i].objIndex; rayInst.blasId = m_objInstance[i].objIndex;
rayInst.hitGroupId = 0; // We will use the same hit group for all objects rayInst.hitGroupId = 0; // We will use the same hit group for all objects
rayInst.flags = vk::GeometryInstanceFlagBitsKHR::eTriangleCullDisable; rayInst.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
tlas.emplace_back(rayInst); tlas.emplace_back(rayInst);
} }
m_rtBuilder.buildTlas(tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace); m_rtBuilder.buildTlas(tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace);
@ -697,25 +702,25 @@ void HelloVulkan::createRtDescriptorSet()
using vkSS = vk::ShaderStageFlagBits; using vkSS = vk::ShaderStageFlagBits;
using vkDSLB = vk::DescriptorSetLayoutBinding; using vkDSLB = vk::DescriptorSetLayoutBinding;
m_rtDescSetLayoutBind.emplace_back(vkDSLB(0, vkDT::eAccelerationStructureKHR, 1, m_rtDescSetLayoutBind.addBinding(vkDSLB(0, vkDT::eAccelerationStructureKHR, 1,
vkSS::eRaygenKHR | vkSS::eClosestHitKHR)); // TLAS vkSS::eRaygenKHR | vkSS::eClosestHitKHR)); // TLAS
m_rtDescSetLayoutBind.emplace_back( m_rtDescSetLayoutBind.addBinding(
vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image
m_rtDescPool = nvvkpp::util::createDescriptorPool(m_device, m_rtDescSetLayoutBind); m_rtDescPool = m_rtDescSetLayoutBind.createPool(m_device);
m_rtDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_rtDescSetLayoutBind); m_rtDescSetLayout = m_rtDescSetLayoutBind.createLayout(m_device);
m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0]; m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0];
vk::AccelerationStructureKHR tlas = m_rtBuilder.getAccelerationStructure();
vk::WriteDescriptorSetAccelerationStructureKHR descASInfo; vk::WriteDescriptorSetAccelerationStructureKHR descASInfo;
descASInfo.setAccelerationStructureCount(1); descASInfo.setAccelerationStructureCount(1);
descASInfo.setPAccelerationStructures(&m_rtBuilder.getAccelerationStructure()); descASInfo.setPAccelerationStructures(&tlas);
vk::DescriptorImageInfo imageInfo{ vk::DescriptorImageInfo imageInfo{
{}, m_offscreenColor.descriptor.imageView, vk::ImageLayout::eGeneral}; {}, m_offscreenColor.descriptor.imageView, vk::ImageLayout::eGeneral};
std::vector<vk::WriteDescriptorSet> writes; std::vector<vk::WriteDescriptorSet> writes;
writes.emplace_back( writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 0, &descASInfo));
nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[0], &descASInfo)); writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 1, &imageInfo));
writes.emplace_back(nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[1], &imageInfo));
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr); m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
} }
@ -744,16 +749,17 @@ void HelloVulkan::createRtPipeline()
std::vector<std::string> paths = defaultSearchPaths; std::vector<std::string> paths = defaultSearchPaths;
vk::ShaderModule raygenSM = vk::ShaderModule raygenSM =
nvvkpp::util::createShaderModule(m_device, // nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rgen.spv", true, paths)); nvh::loadFile("shaders/raytrace.rgen.spv", true, paths));
vk::ShaderModule missSM = vk::ShaderModule missSM =
nvvkpp::util::createShaderModule(m_device, // nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths)); nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths));
// The second miss shader is invoked when a shadow ray misses the geometry. It // The second miss shader is invoked when a shadow ray misses the geometry. It
// simply indicates that no occlusion has been found // simply indicates that no occlusion has been found
vk::ShaderModule shadowmissSM = nvvkpp::util::createShaderModule( vk::ShaderModule shadowmissSM =
m_device, nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths)); nvvk::createShaderModule(m_device,
nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
std::vector<vk::PipelineShaderStageCreateInfo> stages; std::vector<vk::PipelineShaderStageCreateInfo> stages;
@ -779,8 +785,8 @@ void HelloVulkan::createRtPipeline()
// Hit Group - Closest Hit + AnyHit // Hit Group - Closest Hit + AnyHit
vk::ShaderModule chitSM = vk::ShaderModule chitSM =
nvvkpp::util::createShaderModule(m_device, // nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rchit.spv", true, paths)); nvh::loadFile("shaders/raytrace.rchit.spv", true, paths));
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup, vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup,
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR,
@ -844,17 +850,17 @@ void HelloVulkan::createRtShaderBindingTable()
m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize, m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize,
shaderHandleStorage.data()); shaderHandleStorage.data());
// Write the handles in the SBT // Write the handles in the SBT
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex); nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer(); vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
m_rtSBTBuffer = m_rtSBTBuffer =
m_alloc.createBuffer(cmdBuf, shaderHandleStorage, vk::BufferUsageFlagBits::eRayTracingKHR); m_alloc.createBuffer(cmdBuf, shaderHandleStorage, vk::BufferUsageFlagBits::eRayTracingKHR);
m_debug.setObjectName(m_rtSBTBuffer.buffer, "SBT"); m_debug.setObjectName(m_rtSBTBuffer.buffer, "SBT");
genCmdBuf.flushCommandBuffer(cmdBuf); genCmdBuf.submitAndWait(cmdBuf);
m_alloc.flushStaging(); m_alloc.finalizeAndReleaseStaging();
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------

View file

@ -26,16 +26,14 @@
*/ */
#pragma once #pragma once
#include "nvvkpp/allocator_dedicated_vkpp.hpp" #define NVVK_ALLOC_DEDICATED
#include "nvvkpp/appbase_vkpp.hpp" #include "nvvk/allocator_vk.hpp"
#include "nvvkpp/debug_util_vkpp.hpp" #include "nvvk/appbase_vkpp.hpp"
#include "nvvk/debug_util_vk.hpp"
#include "nvvk/descriptorsets_vk.hpp"
// #VKRay // #VKRay
#define ALLOC_DEDICATED #include "nvvk/raytraceKHR_vk.hpp"
#include "nvvkpp/raytraceKHR_vkpp.hpp"
using nvvkBuffer = nvvkpp::BufferDedicated;
using nvvkTexture = nvvkpp::TextureDedicated;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Simple rasterizer of OBJ objects // Simple rasterizer of OBJ objects
@ -44,10 +42,11 @@ using nvvkTexture = nvvkpp::TextureDedicated;
// - Rendering is done in an offscreen framebuffer // - Rendering is done in an offscreen framebuffer
// - The image of the framebuffer is displayed in post-process in a full-screen quad // - The image of the framebuffer is displayed in post-process in a full-screen quad
// //
class HelloVulkan : public nvvkpp::AppBase class HelloVulkan : public nvvk::AppBase
{ {
public: public:
void setup(const vk::Device& device, void setup(const vk::Instance& instance,
const vk::Device& device,
const vk::PhysicalDevice& physicalDevice, const vk::PhysicalDevice& physicalDevice,
uint32_t queueFamily) override; uint32_t queueFamily) override;
void createDescriptorSetLayout(); void createDescriptorSetLayout();
@ -66,12 +65,12 @@ public:
// The OBJ model // The OBJ model
struct ObjModel struct ObjModel
{ {
uint32_t nbIndices{0}; uint32_t nbIndices{0};
uint32_t nbVertices{0}; uint32_t nbVertices{0};
nvvkBuffer vertexBuffer; // Device buffer of all 'Vertex' nvvk::Buffer vertexBuffer; // Device buffer of all 'Vertex'
nvvkBuffer indexBuffer; // Device buffer of the indices forming triangles nvvk::Buffer indexBuffer; // Device buffer of the indices forming triangles
nvvkBuffer matColorBuffer; // Device buffer of array of 'Wavefront material' nvvk::Buffer matColorBuffer; // Device buffer of array of 'Wavefront material'
nvvkBuffer matIndexBuffer; // Device buffer of array of 'Wavefront material' nvvk::Buffer matIndexBuffer; // Device buffer of array of 'Wavefront material'
}; };
// Instance of the OBJ // Instance of the OBJ
@ -98,19 +97,19 @@ public:
std::vector<ObjInstance> m_objInstance; std::vector<ObjInstance> m_objInstance;
// Graphic pipeline // Graphic pipeline
vk::PipelineLayout m_pipelineLayout; vk::PipelineLayout m_pipelineLayout;
vk::Pipeline m_graphicsPipeline; vk::Pipeline m_graphicsPipeline;
std::vector<vk::DescriptorSetLayoutBinding> m_descSetLayoutBind; nvvk::DescriptorSetBindings m_descSetLayoutBind;
vk::DescriptorPool m_descPool; vk::DescriptorPool m_descPool;
vk::DescriptorSetLayout m_descSetLayout; vk::DescriptorSetLayout m_descSetLayout;
vk::DescriptorSet m_descSet; vk::DescriptorSet m_descSet;
nvvkBuffer m_cameraMat; // Device-Host of the camera matrices nvvk::Buffer m_cameraMat; // Device-Host of the camera matrices
nvvkBuffer m_sceneDesc; // Device buffer of the OBJ instances nvvk::Buffer m_sceneDesc; // Device buffer of the OBJ instances
std::vector<nvvkTexture> m_textures; // vector of all textures of the scene std::vector<nvvk::Texture> m_textures; // vector of all textures of the scene
nvvkpp::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures nvvk::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures
nvvkpp::DebugUtil m_debug; // Utility to name objects nvvk::DebugUtil m_debug; // Utility to name objects
// #Post // #Post
void createOffscreenRender(); void createOffscreenRender();
@ -119,41 +118,41 @@ public:
void updatePostDescriptorSet(); void updatePostDescriptorSet();
void drawPost(vk::CommandBuffer cmdBuf); void drawPost(vk::CommandBuffer cmdBuf);
std::vector<vk::DescriptorSetLayoutBinding> m_postDescSetLayoutBind; nvvk::DescriptorSetBindings m_postDescSetLayoutBind;
vk::DescriptorPool m_postDescPool; vk::DescriptorPool m_postDescPool;
vk::DescriptorSetLayout m_postDescSetLayout; vk::DescriptorSetLayout m_postDescSetLayout;
vk::DescriptorSet m_postDescSet; vk::DescriptorSet m_postDescSet;
vk::Pipeline m_postPipeline; vk::Pipeline m_postPipeline;
vk::PipelineLayout m_postPipelineLayout; vk::PipelineLayout m_postPipelineLayout;
vk::RenderPass m_offscreenRenderPass; vk::RenderPass m_offscreenRenderPass;
vk::Framebuffer m_offscreenFramebuffer; vk::Framebuffer m_offscreenFramebuffer;
nvvkTexture m_offscreenColor; nvvk::Texture m_offscreenColor;
vk::Format m_offscreenColorFormat{vk::Format::eR32G32B32A32Sfloat}; vk::Format m_offscreenColorFormat{vk::Format::eR32G32B32A32Sfloat};
nvvkTexture m_offscreenDepth; nvvk::Texture m_offscreenDepth;
vk::Format m_offscreenDepthFormat{vk::Format::eD32Sfloat}; vk::Format m_offscreenDepthFormat{vk::Format::eD32Sfloat};
// #VKRay // #VKRay
void initRayTracing(); void initRayTracing();
nvvkpp::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model); nvvk::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
void createBottomLevelAS(); void createBottomLevelAS();
void createTopLevelAS(); void createTopLevelAS();
void createRtDescriptorSet(); void createRtDescriptorSet();
void updateRtDescriptorSet(); void updateRtDescriptorSet();
void createRtPipeline(); void createRtPipeline();
void createRtShaderBindingTable(); void createRtShaderBindingTable();
void raytrace(const vk::CommandBuffer& cmdBuf, const nvmath::vec4f& clearColor); void raytrace(const vk::CommandBuffer& cmdBuf, const nvmath::vec4f& clearColor);
vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties; vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties;
nvvkpp::RaytracingBuilderKHR m_rtBuilder; nvvk::RaytracingBuilderKHR m_rtBuilder;
std::vector<vk::DescriptorSetLayoutBinding> m_rtDescSetLayoutBind; nvvk::DescriptorSetBindings m_rtDescSetLayoutBind;
vk::DescriptorPool m_rtDescPool; vk::DescriptorPool m_rtDescPool;
vk::DescriptorSetLayout m_rtDescSetLayout; vk::DescriptorSetLayout m_rtDescSetLayout;
vk::DescriptorSet m_rtDescSet; vk::DescriptorSet m_rtDescSet;
std::vector<vk::RayTracingShaderGroupCreateInfoKHR> m_rtShaderGroups; std::vector<vk::RayTracingShaderGroupCreateInfoKHR> m_rtShaderGroups;
vk::PipelineLayout m_rtPipelineLayout; vk::PipelineLayout m_rtPipelineLayout;
vk::Pipeline m_rtPipeline; vk::Pipeline m_rtPipeline;
nvvkBuffer m_rtSBTBuffer; nvvk::Buffer m_rtSBTBuffer;
struct RtPushConstant struct RtPushConstant
{ {

View file

@ -31,6 +31,7 @@
#include <array> #include <array>
#include <vulkan/vulkan.hpp> #include <vulkan/vulkan.hpp>
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
#include "imgui.h" #include "imgui.h"
#include "imgui_impl_glfw.h" #include "imgui_impl_glfw.h"
@ -39,10 +40,10 @@
#include "nvh/cameramanipulator.hpp" #include "nvh/cameramanipulator.hpp"
#include "nvh/fileoperations.hpp" #include "nvh/fileoperations.hpp"
#include "nvpsystem.hpp" #include "nvpsystem.hpp"
#include "nvvkpp/appbase_vkpp.hpp" #include "nvvk/appbase_vkpp.hpp"
#include "nvvkpp/commands_vkpp.hpp" #include "nvvk/commands_vk.hpp"
#include "nvvkpp/context_vkpp.hpp" #include "nvvk/context_vk.hpp"
#include "nvvkpp/utilities_vkpp.hpp"
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
#define UNUSED(x) (void)(x) #define UNUSED(x) (void)(x)
@ -125,7 +126,7 @@ int main(int argc, char** argv)
vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature; vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature;
// Requesting Vulkan extensions and layers // Requesting Vulkan extensions and layers
nvvkpp::ContextCreateInfo contextInfo(true); nvvk::ContextCreateInfo contextInfo(true);
contextInfo.setVersion(1, 2); contextInfo.setVersion(1, 2);
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true); contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME); contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME);
@ -149,7 +150,7 @@ int main(int argc, char** argv)
contextInfo.addDeviceExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME); contextInfo.addDeviceExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
// Creating Vulkan base application // Creating Vulkan base application
nvvkpp::Context vkctx{}; nvvk::Context vkctx{};
vkctx.initInstance(contextInfo); vkctx.initInstance(contextInfo);
// Find all compatible devices // Find all compatible devices
auto compatibleDevices = vkctx.getCompatibleDevices(contextInfo); auto compatibleDevices = vkctx.getCompatibleDevices(contextInfo);
@ -164,7 +165,8 @@ int main(int argc, char** argv)
const vk::SurfaceKHR surface = helloVk.getVkSurface(vkctx.m_instance, window); const vk::SurfaceKHR surface = helloVk.getVkSurface(vkctx.m_instance, window);
vkctx.setGCTQueueWithPresent(surface); vkctx.setGCTQueueWithPresent(surface);
helloVk.setup(vkctx.m_device, vkctx.m_physicalDevice, vkctx.m_queueGCT.familyIndex); helloVk.setup(vkctx.m_instance, vkctx.m_device, vkctx.m_physicalDevice,
vkctx.m_queueGCT.familyIndex);
helloVk.createSurface(surface, SAMPLE_WIDTH, SAMPLE_HEIGHT); helloVk.createSurface(surface, SAMPLE_WIDTH, SAMPLE_HEIGHT);
helloVk.createDepthBuffer(); helloVk.createDepthBuffer();
helloVk.createRenderPass(); helloVk.createRenderPass();
@ -250,7 +252,8 @@ int main(int argc, char** argv)
// Clearing screen // Clearing screen
vk::ClearValue clearValues[2]; vk::ClearValue clearValues[2];
clearValues[0].setColor(nvvkpp::util::clearColor(clearColor)); clearValues[0].setColor(
std::array<float, 4>({clearColor[0], clearColor[1], clearColor[2], clearColor[3]}));
clearValues[1].setDepthStencil({1.0f, 0}); clearValues[1].setDepthStencil({1.0f, 0});
// Offscreen render pass // Offscreen render pass
@ -302,7 +305,6 @@ int main(int argc, char** argv)
helloVk.destroyResources(); helloVk.destroyResources();
helloVk.destroy(); helloVk.destroy();
vkctx.m_instance.destroySurfaceKHR(surface);
vkctx.deinit(); vkctx.deinit();
glfwDestroyWindow(window); glfwDestroyWindow(window);

View file

@ -6,7 +6,7 @@
#include "raycommon.glsl" #include "raycommon.glsl"
#include "wavefront.glsl" #include "wavefront.glsl"
hitAttributeEXT vec3 attribs; hitAttributeEXT vec2 attribs;
// clang-format off // clang-format off
layout(location = 0) rayPayloadInEXT hitPayload prd; layout(location = 0) rayPayloadInEXT hitPayload prd;