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);
m_alloc.unmap(stagingBuffer);
// 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();
cmdBuf.copyBuffer(stagingBuffer.buffer, m_sceneDesc.buffer, vk::BufferCopy(0, 0, bufferSize));
m_debug.endLabel(cmdBuf);
genCmdBuf.flushCommandBuffer(cmdBuf);
genCmdBuf.submitAndWait(cmdBuf);
m_alloc.destroy(stagingBuffer);
m_rtBuilder.updateTlasMatrices(m_tlas);
m_rtBuilder.updateBlas(2);
}
~~~~
<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.
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.
~~~~ 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`.
@ -131,12 +134,12 @@ void HelloVulkan::createTopLevelAS()
m_tlas.reserve(m_objInstance.size());
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.instanceId = i; // gl_InstanceID
rayInst.blasId = m_objInstance[i].objIndex;
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_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
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
~~~~ C++
nvvkpp::RaytracingBuilder::Instance& tinst = m_tlas[wusonIdx];
nvvk::RaytracingBuilder::Instance& tinst = m_tlas[wusonIdx];
tinst.transform = inst.transform;
~~~~
@ -162,12 +165,12 @@ m_rtBuilder.updateTlasMatrices(m_tlas);
![](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
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
@ -177,18 +180,18 @@ building the TLAS.
~~~~ C++
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
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)
VmaMemoryUsage::VMA_MEMORY_USAGE_CPU_TO_GPU
#else
vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
#endif
);
// 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++)
{
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
would fail.
~~~~ C++
// Compute the amount of scratch memory required by the AS builder to update the TLAS
vk::AccelerationStructureMemoryRequirementsInfoKHR memoryRequirementsInfo{
vk::AccelerationStructureMemoryRequirementsTypeKHR::eUpdateScratch,
vk::AccelerationStructureBuildTypeKHR::eDevice, m_tlas.as.accel};
vk::DeviceSize scratchSize =
m_device.getAccelerationStructureMemoryRequirementsKHR(memoryRequirementsInfo).memoryRequirements.size;
// Compute the amount of scratch memory required by the AS builder to update
VkAccelerationStructureMemoryRequirementsInfoKHR memoryRequirementsInfo{
VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_KHR};
memoryRequirementsInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_KHR;
memoryRequirementsInfo.accelerationStructure = m_tlas.as.accel;
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
nvvkBuffer scratchBuffer = m_alloc.createBuffer(scratchSize, vk::BufferUsageFlagBits::eRayTracingKHR
| vk::BufferUsageFlagBits::eShaderDeviceAddress);
vk::DeviceAddress scratchAddress = m_device.getBufferAddress({scratchBuffer.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
@ -219,18 +229,24 @@ add a barrier to make sure the memory finishes copying before updating the TLAS.
~~~~ C++
// Update the instance buffer on the device side and build the TLAS
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_queueIndex);
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
nvvk::CommandPool genCmdBuf(m_device, m_queueIndex);
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);
//VkBufferDeviceAddressInfo bufferInfo{VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO};
bufferInfo.buffer = m_instBuffer.buffer;
VkDeviceAddress instanceAddress = vkGetBufferDeviceAddress(m_device, &bufferInfo);
vk::DeviceAddress instanceAddress = m_device.getBufferAddress(m_instBuffer.buffer);
// Make sure the copy of the instance buffer are copied before triggering the
// acceleration structure build
vk::MemoryBarrier barrier(vk::AccessFlagBits::eTransferWrite, vk::AccessFlagBits::eAccelerationStructureWriteKHR);
cmdBuf.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eAccelerationStructureBuildKHR,
vk::DependencyFlags(), {barrier}, {}, {});
VkMemoryBarrier barrier{VK_STRUCTURE_TYPE_MEMORY_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
@ -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.
~~~~ C++
vk::AccelerationStructureGeometryKHR topASGeometry{vk::GeometryTypeKHR::eInstances};
topASGeometry.geometry.instances.arrayOfPointers = VK_FALSE;
topASGeometry.geometry.instances.data = instanceAddress;
const vk::AccelerationStructureGeometryKHR* pGeometry = &topASGeometry;
VkAccelerationStructureGeometryDataKHR geometry{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR};
geometry.instances.arrayOfPointers = VK_FALSE;
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 VkAccelerationStructureGeometryKHR* pGeometry = &topASGeometry;
vk::AccelerationStructureBuildGeometryInfoKHR topASInfo;
topASInfo.setFlags(m_tlas.flags);
topASInfo.setUpdate(VK_TRUE);
topASInfo.setSrcAccelerationStructure(m_tlas.as.accel);
topASInfo.setDstAccelerationStructure(m_tlas.as.accel);
topASInfo.setGeometryArrayOfPointers(VK_FALSE);
topASInfo.setGeometryCount(1);
topASInfo.setPpGeometries(&pGeometry);
topASInfo.setScratchData(scratchAddress);
VkAccelerationStructureBuildGeometryInfoKHR topASInfo{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR};
topASInfo.flags = m_tlas.flags;
topASInfo.update = VK_TRUE;
topASInfo.srcAccelerationStructure = m_tlas.as.accel;
topASInfo.dstAccelerationStructure = m_tlas.as.accel;
topASInfo.geometryArrayOfPointers = VK_FALSE;
topASInfo.geometryCount = 1;
topASInfo.ppGeometries = &pGeometry;
topASInfo.scratchData.deviceAddress = scratchAddress;
uint32_t nbInstances = (uint32_t)instances.size();
vk::AccelerationStructureBuildOffsetInfoKHR buildOffsetInfo = {nbInstances, 0, 0, 0};
const vk::AccelerationStructureBuildOffsetInfoKHR* pBuildOffsetInfo = &buildOffsetInfo;
VkAccelerationStructureBuildOffsetInfoKHR buildOffsetInfo = {nbInstances, 0, 0, 0};
const VkAccelerationStructureBuildOffsetInfoKHR* pBuildOffsetInfo = &buildOffsetInfo;
// Build the TLAS
// Update the acceleration structure. Note the VK_TRUE parameter to trigger the update,
// and the existing TLAS being passed and updated in place
cmdBuf.buildAccelerationStructureKHR(1, &topASInfo, &pBuildOffsetInfo);
genCmdBuf.flushCommandBuffer(cmdBuf);
vkCmdBuildAccelerationStructureKHR(cmdBuf, 1, &topASInfo, &pBuildOffsetInfo);
genCmdBuf.submitAndWait(cmdBuf);
~~~~
### Cleanup
@ -310,7 +332,7 @@ Add all of the following members to the `HelloVulkan` class:
void updateCompDescriptors(nvvkBuffer& vertex);
void createCompPipelines();
std::vector<vk::DescriptorSetLayoutBinding> m_compDescSetLayoutBind;
nvvk::DescriptorSetBindings m_compDescSetLayoutBind;
vk::DescriptorPool m_compDescPool;
vk::DescriptorSetLayout m_compDescSetLayout;
vk::DescriptorSet m_compDescSet;
@ -323,12 +345,12 @@ The compute shader will work on a single `VertexObj` buffer.
~~~~ C++
void HelloVulkan::createCompDescriptors()
{
m_compDescSetLayoutBind.emplace_back(vk::DescriptorSetLayoutBinding(
m_compDescSetLayoutBind.addBinding(vk::DescriptorSetLayoutBinding(
0, vk::DescriptorType::eStorageBuffer, 1, vk::ShaderStageFlagBits::eCompute));
m_compDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_compDescSetLayoutBind);
m_compDescPool = nvvkpp::util::createDescriptorPool(m_device, m_compDescSetLayoutBind, 1);
m_compDescSet = nvvkpp::util::createDescriptorSet(m_device, m_compDescPool, m_compDescSetLayout);
m_compDescSetLayout = m_compDescSetLayoutBind.createLayout(m_device);
m_compDescPool = m_compDescSetLayoutBind.createPool(m_device, 1);
m_compDescSet = nvvk::allocateDescriptorSet(m_device, m_compDescPool, m_compDescSetLayout);
}
~~~~
@ -339,8 +361,7 @@ void HelloVulkan::updateCompDescriptors(nvvkBuffer& vertex)
{
std::vector<vk::WriteDescriptorSet> writes;
vk::DescriptorBufferInfo dbiUnif{vertex.buffer, 0, VK_WHOLE_SIZE};
writes.emplace_back(
nvvkpp::util::createWrite(m_compDescSet, m_compDescSetLayoutBind[0], &dbiUnif));
writes.emplace_back(m_compDescSetLayoutBind.makeWrite(m_compDescSet, 0, dbiUnif));
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};
computePipelineCreateInfo.stage =
nvvkpp::util::loadShader(m_device,
nvvk::createShaderStageInfo(m_device,
nvh::loadFile("shaders/anim.comp.spv", true, defaultSearchPaths),
vk::ShaderStageFlagBits::eCompute);
m_compPipeline = m_device.createComputePipelines({}, computePipelineCreateInfo, nullptr)[0];
VK_SHADER_STAGE_COMPUTE_BIT);
m_compPipeline = m_device.createComputePipeline({}, computePipelineCreateInfo, nullptr);
m_device.destroy(computePipelineCreateInfo.stage.module);
}
~~~~
@ -445,7 +466,7 @@ void HelloVulkan::animationObject(float time)
updateCompDescriptors(model.vertexBuffer);
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex);
nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
cmdBuf.bindPipeline(vk::PipelineBindPoint::eCompute, m_compPipeline);
@ -454,7 +475,7 @@ void HelloVulkan::animationObject(float time)
cmdBuf.pushConstants(m_compPipelineLayout, vk::ShaderStageFlagBits::eCompute, 0, sizeof(float),
&time);
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
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++
//--------------------------------------------------------------------------------------------------
@ -488,57 +509,63 @@ In `nvvkpp::RaytracingBuilder` in `raytrace_vkpp.hpp`, we can add a function to
{
Blas& blas = m_blas[blasIdx];
// Compute the amount of scratch memory required by the AS builder to update the TLAS
vk::AccelerationStructureMemoryRequirementsInfoKHR memoryRequirementsInfo{
vk::AccelerationStructureMemoryRequirementsTypeKHR::eUpdateScratch,
vk::AccelerationStructureBuildTypeKHR::eDevice, blas.as.accel};
vk::DeviceSize scratchSize =
m_device.getAccelerationStructureMemoryRequirementsKHR(memoryRequirementsInfo).memoryRequirements.size;
// Compute the amount of scratch memory required by the AS builder to update the BLAS
VkAccelerationStructureMemoryRequirementsInfoKHR memoryRequirementsInfo{
VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_KHR};
memoryRequirementsInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_KHR;
memoryRequirementsInfo.accelerationStructure = blas.as.accel;
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
nvvkBuffer scratchBuffer = m_alloc.createBuffer(scratchSize, vk::BufferUsageFlagBits::eRayTracingKHR
| vk::BufferUsageFlagBits::eShaderDeviceAddress);
vk::DeviceAddress scratchAddress = m_device.getBufferAddress({scratchBuffer.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);
const vk::AccelerationStructureGeometryKHR* pGeometry = blas.asGeometry.data();
vk::AccelerationStructureBuildGeometryInfoKHR asInfo{vk::AccelerationStructureTypeKHR::eBottomLevel};
asInfo.setFlags(blas.flags);
asInfo.setUpdate(VK_TRUE);
asInfo.setSrcAccelerationStructure(blas.as.accel);
asInfo.setDstAccelerationStructure(blas.as.accel);
asInfo.setGeometryArrayOfPointers(VK_FALSE);
asInfo.setGeometryCount((uint32_t)blas.asGeometry.size());
asInfo.setPpGeometries(&pGeometry);
asInfo.setScratchData(scratchAddress);
const VkAccelerationStructureGeometryKHR* pGeometry = blas.asGeometry.data();
VkAccelerationStructureBuildGeometryInfoKHR asInfo{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR};
asInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;
asInfo.flags = blas.flags;
asInfo.update = VK_TRUE;
asInfo.srcAccelerationStructure = blas.as.accel;
asInfo.dstAccelerationStructure = blas.as.accel;
asInfo.geometryArrayOfPointers = VK_FALSE;
asInfo.geometryCount = (uint32_t)blas.asGeometry.size();
asInfo.ppGeometries = &pGeometry;
asInfo.scratchData.deviceAddress = scratchAddress;
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++)
pBuildOffset[i] = &blas.asBuildOffsetInfo[i];
// Update the instance buffer on the device side and build the TLAS
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_queueIndex);
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
nvvk::CommandPool genCmdBuf(m_device, m_queueIndex);
VkCommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
// Update the acceleration structure. Note the VK_TRUE parameter to trigger the update,
// and the existing BLAS being passed and updated in place
cmdBuf.buildAccelerationStructureKHR(asInfo, pBuildOffset);
vkCmdBuildAccelerationStructureKHR(cmdBuf, 1, &asInfo, pBuildOffset.data());
genCmdBuf.flushCommandBuffer(cmdBuf);
genCmdBuf.submitAndWait(cmdBuf);
m_alloc.destroy(scratchBuffer);
}
~~~~
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.
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++
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

View file

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

View file

@ -71,14 +71,13 @@ vk::RayTracingShaderGroupCreateInfoKHR callGroup{vk::RayTracingShaderGroupTypeKH
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR};
vk::ShaderModule call0 =
nvvkpp::util::createShaderModule(m_device,
nvvk::createShaderModule(m_device,
nvh::loadFile("shaders/light_point.rcall.spv", true, paths));
vk::ShaderModule call1 =
nvvkpp::util::createShaderModule(m_device,
nvvk::createShaderModule(m_device,
nvh::loadFile("shaders/light_spot.rcall.spv", true, paths));
vk::ShaderModule call2 =
nvvkpp::util::createShaderModule(m_device,
nvh::loadFile("shaders/light_inf.rcall.spv", true, paths));
nvvk::createShaderModule(m_device, nvh::loadFile("shaders/light_inf.rcall.spv", true, paths));
stages.push_back({{}, vk::ShaderStageFlagBits::eCallableKHR, call0, "main"});
callGroup.setGeneralShader(static_cast<uint32_t>(stages.size() - 1));

View file

@ -117,13 +117,13 @@ Replace the definition of buffers and textures and include the right allocator.
~~~~ C++
#if defined(ALLOC_DEDICATED)
#include "nvvkpp/allocator_dedicated_vkpp.hpp"
using nvvkBuffer = nvvkpp::BufferDedicated;
using nvvkTexture = nvvkpp::TextureDedicated;
#include "nvvk/allocator_dedicated_vk.hpp"
using nvvkBuffer = nvvk::BufferDedicated;
using nvvkTexture = nvvk::TextureDedicated;
#elif defined(ALLOC_DMA)
#include "nvvkpp/allocator_dma_vkpp.hpp"
using nvvkBuffer = nvvkpp::BufferDma;
using nvvkTexture = nvvkpp::TextureDma;
#include "nvvk/allocator_dma_vk.hpp"
using nvvkBuffer = nvvk::BufferDma;
using nvvkTexture = nvvk::TextureDma;
#endif
~~~~
@ -131,10 +131,11 @@ And do the same for the allocator
~~~~ C++
#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)
nvvkpp::AllocatorDma m_alloc; // Allocator for buffer, images, acceleration structures
nvvk::DeviceMemoryAllocator m_dmaAllocator;
nvvk::AllocatorDma m_alloc; // Allocator for buffer, images, acceleration structures
nvvk::DeviceMemoryAllocator m_memAllocator;
nvvk::StagingMemoryManagerDma m_staging;
#endif
~~~~
@ -148,34 +149,24 @@ DMA needs to be initialized, which will be done in the `setup()` function:
#if defined(ALLOC_DEDICATED)
m_alloc.init(device, physicalDevice);
#elif defined(ALLOC_DMA)
m_dmaAllocator.init(device, physicalDevice);
m_alloc.init(device, &m_dmaAllocator);
m_memAllocator.init(device, physicalDevice);
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
~~~~
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++
#if defined(ALLOC_DEDICATED)
void* data = m_device.mapMemory(m_cameraMat.allocation, 0, sizeof(CameraMatrices));
void* data = m_alloc.map(m_cameraMat);
memcpy(data, &ubo, sizeof(ubo));
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
m_alloc.unmap(m_cameraMat);
~~~~
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
@ -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.
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
creation of the context in `main.cpp`.
@ -223,15 +214,16 @@ Follow the changes done before and add the following
~~~~ C++
#elif defined(ALLOC_VMA)
#include "nvvkpp/allocator_vma_vkpp.hpp"
using nvvkBuffer = nvvkpp::BufferVma;
using nvvkTexture = nvvkpp::TextureVma;
#include "nvvk/allocator_vma_vk.hpp"
using nvvkBuffer = nvvk::BufferVma;
using nvvkTexture = nvvk::TextureVma;
~~~~
~~~~ C++
#elif defined(ALLOC_VMA)
nvvkpp::AllocatorVma m_alloc; // Allocator for buffer, images, acceleration structures
VmaAllocator m_vmaAllocator;
nvvk::AllocatorVma m_alloc; // Allocator for buffer, images, acceleration structures
nvvk::StagingMemoryManagerVma m_staging;
VmaAllocator m_memAllocator;
~~~~
@ -247,21 +239,13 @@ In `setup()`
~~~~ C++
#elif defined(ALLOC_VMA)
VmaAllocatorCreateInfo allocatorInfo = {};
allocatorInfo.instance = instance;
allocatorInfo.physicalDevice = physicalDevice;
allocatorInfo.device = device;
allocatorInfo.flags = VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT;
vmaCreateAllocator(&allocatorInfo, &m_vmaAllocator);
m_alloc.init(device, m_vmaAllocator);
~~~~
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);
vmaCreateAllocator(&allocatorInfo, &m_memAllocator);
m_staging.init(device, physicalDevice, m_memAllocator);
m_alloc.init(device, m_memAllocator, m_staging);
~~~~
In `destroyResources()`
@ -271,25 +255,6 @@ In `destroyResources()`
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

View file

@ -66,7 +66,7 @@ Finally, there are two functions, one to create the spheres, and one that will c
~~~~ C++
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.
@ -120,13 +120,13 @@ void HelloVulkan::createSpheres()
// Creating all buffers
using vkBU = vk::BufferUsageFlagBits;
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex);
nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
auto cmdBuf = genCmdBuf.createCommandBuffer();
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_spheresMatColorBuffer = m_alloc.createBuffer(cmdBuf, materials, vkBU::eStorageBuffer);
genCmdBuf.flushCommandBuffer(cmdBuf);
genCmdBuf.submitAndWait(cmdBuf);
// Debug information
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
//
nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::sphereToVkGeometryKHR()
nvvk::RaytracingBuilderKHR::Blas HelloVulkan::sphereToVkGeometryKHR()
{
vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate;
asCreate.setGeometryType(vk::GeometryTypeKHR::eAabbs);
@ -181,7 +181,7 @@ nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::sphereToVkGeometryKHR()
offset.setPrimitiveOffset(0);
offset.setTransformOffset(0);
nvvkpp::RaytracingBuilderKHR::Blas blas;
nvvk::RaytracingBuilderKHR::Blas blas;
blas.asGeometry.emplace_back(asGeom);
blas.asCreateGeometryInfo.emplace_back(asCreate);
blas.asBuildOffsetInfo.emplace_back(offset);
@ -217,7 +217,7 @@ The function `createBottomLevelAS()` is creating a BLAS per OBJ, the following m
void HelloVulkan::createBottomLevelAS()
{
// BLAS - Storing each primitive in a geometry
std::vector<nvvkpp::RaytracingBuilderKHR::Blas> allBlas;
std::vector<nvvk::RaytracingBuilderKHR::Blas> allBlas;
allBlas.reserve(m_objModel.size());
for(const auto& obj : m_objModel)
{
@ -248,7 +248,7 @@ Just before building the TLAS, we need to add the following
~~~~ C++
// 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.instanceId = static_cast<uint32_t>(tlas.size()); // gl_InstanceID
rayInst.blasId = static_cast<uint32_t>(m_objModel.size());
@ -301,7 +301,7 @@ Then write the buffer for the spheres
~~~~ C++
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
@ -313,7 +313,7 @@ Here is how the two hit group looks like:
~~~~ C++
// Hit Group0 - Closest Hit
vk::ShaderModule chitSM =
nvvkpp::util::createShaderModule(m_device, //
nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rchit.spv", true, paths));
{
@ -327,10 +327,10 @@ Here is how the two hit group looks like:
// Hit Group1 - Closest Hit + Intersection (procedural)
vk::ShaderModule chit2SM =
nvvkpp::util::createShaderModule(m_device, //
nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace2.rchit.spv", true, paths));
vk::ShaderModule rintSM =
nvvkpp::util::createShaderModule(m_device, //
nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rint.spv", true, paths));
{
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eProceduralHitGroup,

View file

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

View file

@ -31,12 +31,12 @@ Remove most functions and members to keep only what is need to create the accele
~~~~ C++
// #VKRay
void initRayTracing();
nvvkpp::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
nvvk::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
void createBottomLevelAS();
void createTopLevelAS();
vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties;
nvvkpp::RaytracingBuilderKHR m_rtBuilder;
nvvk::RaytracingBuilderKHR m_rtBuilder;
~~~~
## hello_vulkan (source)
@ -61,10 +61,11 @@ m_descSetLayoutBind.emplace_back( //
In `HelloVulkan::updateDescriptorSet`, write the value to the descriptor set.
~~~~ C++
vk::AccelerationStructureKHR tlas = m_rtBuilder.getAccelerationStructure();
vk::WriteDescriptorSetAccelerationStructureKHR descASInfo;
descASInfo.setAccelerationStructureCount(1);
descASInfo.setPAccelerationStructures(&m_rtBuilder.getAccelerationStructure());
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")
!!! Note GitHub repository
https://github.com/nvpro-samples/vk_raytracing_tutorial_KHR
# Introduction
<script type="preformatted">
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
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
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
@ -36,17 +39,15 @@ verbosity and its potential for errors.
## 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 Vulkan headers: https://github.com/KhronosGroup/Vulkan-Headers
* 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
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
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
using Vulkan.
@ -93,7 +98,7 @@ using Vulkan.
# Ray Tracing Setup
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
add the
[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
// #VKRay
#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,
```` C
nvvkpp::RaytracingBuilder m_rtBuilder;
nvvk::RaytracingBuilder m_rtBuilder;
````
and initialize it at the end of `initRaytracing()`:
```` C
m_rtBuilder.setup(m_device, m_physicalDevice, m_graphicsQueueIndex);
m_rtBuilder.setup(m_device, m_alloc, m_graphicsQueueIndex);
````
## Bottom-Level Acceleration Structure
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
`nvvkpp::RaytracingBuilderKHR::Blas`
`nvvk::RaytracingBuilderKHR::Blas`
Add a new method to the `HelloVulkan`
class:
```` C
nvvkpp::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
nvvk::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
````
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
//
nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model)
nvvk::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model)
{
// Setting up the creation info of acceleration structure
vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate;
@ -263,7 +268,7 @@ nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjM
offset.setTransformOffset(0);
// 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.asCreateGeometryInfo.emplace_back(asCreate);
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
`nvvkpp::RaytracingBuilderKHR::Blas` for each object, and trigger a BLAS build:
`nvvk::RaytracingBuilderKHR::Blas` for each object, and trigger a BLAS build:
```` C
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
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()
{
// BLAS - Storing each primitive in a geometry
std::vector<nvvkpp::RaytracingBuilderKHR::Blas> allBlas;
std::vector<nvvk::RaytracingBuilderKHR::Blas> allBlas;
allBlas.reserve(m_objModel.size());
for(const auto& obj : m_objModel)
{
@ -309,11 +314,17 @@ will generate one BLAS for each `RaytracingBuilderKHR::Blas`:
```` C
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};
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};
@ -325,10 +336,11 @@ The creation of the acceleration structure needs all `vk::AccelerationStructureC
set into `vk::AccelerationStructureCreateInfoKHR`.
```` C
vk::AccelerationStructureCreateInfoKHR asCreateInfo{{}, vk::AccelerationStructureTypeKHR::eBottomLevel};
asCreateInfo.setFlags(flags);
asCreateInfo.setMaxGeometryCount((uint32_t)blas.asCreateGeometryInfo.size());
asCreateInfo.setPGeometryInfos(blas.asCreateGeometryInfo.data());
VkAccelerationStructureCreateInfoKHR asCreateInfo{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR};
asCreateInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;
asCreateInfo.flags = flags;
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.
@ -336,9 +348,9 @@ It will also query `vk::Device::getAccelerationStructureMemoryRequirementsKHR` t
and allocate memory accordingly.
```` C
// Create an acceleration structure identifier and allocate memory to store the
// resulting structure data
blas.as = m_alloc.createAcceleration(createinfo);
// Create an acceleration structure identifier and allocate memory to
// store the resulting structure data
blas.as = m_alloc.createAcceleration(asCreateInfo);
m_debug.setObjectName(blas.as.accel, (std::string("Blas" + std::to_string(idx)).c_str()));
````
@ -346,16 +358,28 @@ The acceleration structure builder requires some scratch memory to generate the
BLAS's in a batch, we query the scratch memory requirements for each BLAS, and find the maximum such requirement.
```` C
// Estimate the amount of scratch memory required to build the BLAS, and update the
// size of the scratch buffer that will be allocated to sequentially build all BLASes
vk::AccelerationStructureMemoryRequirementsInfoKHR memoryRequirementsInfo{
vk::AccelerationStructureMemoryRequirementsTypeKHR::eBuildScratch,
vk::AccelerationStructureBuildTypeKHR::eDevice, blas.as.accel};
vk::DeviceSize scratchSize =
m_device.getAccelerationStructureMemoryRequirementsKHR(memoryRequirementsInfo).memoryRequirements.size;
// Estimate the amount of scratch memory required to build the BLAS, and
// update the size of the scratch buffer that will be allocated to
// sequentially build all BLASes
VkAccelerationStructureMemoryRequirementsInfoKHR memoryRequirementsInfo{
VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_KHR};
memoryRequirementsInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_KHR;
memoryRequirementsInfo.accelerationStructure = blas.as.accel;
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;
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++;
}
````
@ -364,9 +388,22 @@ Once that maximum has been found, we allocate a scratch buffer.
```` C
// Allocate the scratch buffers holding the temporary data of the acceleration structure builder
nvvkBuffer scratchBuffer = m_alloc.createBuffer(maxScratch, vk::BufferUsageFlagBits::eRayTracingKHR
| vk::BufferUsageFlagBits::eShaderDeviceAddress);
vk::DeviceAddress scratchAddress = m_device.getBufferAddress({scratchBuffer.buffer});
nvvkBuffer scratchBuffer =
m_alloc.createBuffer(maxScratch, 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);
````
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
@ -374,50 +411,123 @@ build call: this is required as we reuse the scratch space across builds, and he
the previous build has completed before starting the next.
```` C
// Create a command buffer containing all the BLAS builds
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_queueIndex);
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
// 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);
// 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)
{
const vk::AccelerationStructureGeometryKHR* pGeometry = blas.asGeometry.data();
vk::AccelerationStructureBuildGeometryInfoKHR bottomASInfo{vk::AccelerationStructureTypeKHR::eBottomLevel};
bottomASInfo.setFlags(flags);
bottomASInfo.setUpdate(VK_FALSE);
bottomASInfo.setSrcAccelerationStructure({});
bottomASInfo.setDstAccelerationStructure(blas.as.accel);
bottomASInfo.setGeometryArrayOfPointers(VK_FALSE);
bottomASInfo.setGeometryCount((uint32_t)blas.asGeometry.size());
bottomASInfo.setPpGeometries(&pGeometry);
bottomASInfo.setScratchData(scratchAddress);
const VkAccelerationStructureGeometryKHR* pGeometry = blas.asGeometry.data();
VkAccelerationStructureBuildGeometryInfoKHR bottomASInfo{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR};
bottomASInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;
bottomASInfo.flags = flags;
bottomASInfo.update = VK_FALSE;
bottomASInfo.srcAccelerationStructure = VK_NULL_HANDLE;
bottomASInfo.dstAccelerationStructure = blas.as.accel;
bottomASInfo.geometryArrayOfPointers = VK_FALSE;
bottomASInfo.geometryCount = (uint32_t)blas.asGeometry.size();
bottomASInfo.ppGeometries = &pGeometry;
bottomASInfo.scratchData.deviceAddress = scratchAddress;
// 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++)
pBuildOffset[i] = &blas.asBuildOffsetInfo[i];
// 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
// is finished before starting the next one
vk::MemoryBarrier barrier(vk::AccessFlagBits::eAccelerationStructureWriteKHR, vk::AccessFlagBits::eAccelerationStructureWriteKHR);
cmdBuf.pipelineBarrier(vk::PipelineStageFlagBits::eAccelerationStructureBuildKHR,
vk::PipelineStageFlagBits::eAccelerationStructureBuildKHR, {}, {barrier}, {}, {});
VkMemoryBarrier barrier{VK_STRUCTURE_TYPE_MEMORY_BARRIER};
barrier.srcAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR;
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
genCmdBuf.flushCommandBuffer(cmdBuf);
// 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, "%%");
}
````
Finally, destroying what was allocated.
```` C
vkDestroyQueryPool(m_device, queryPool, nullptr);
m_alloc.destroy(scratchBuffer);
m_alloc.flushStaging();
m_alloc.finalizeAndReleaseStaging();
}
````
@ -430,7 +540,7 @@ to the `HelloVulkan` class:
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
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`).
@ -447,16 +557,16 @@ optimized for tracing performance (rather than AS size, for example).
```` C
void HelloVulkan::createTopLevelAS()
{
std::vector<nvvkpp::RaytracingBuilderKHR::Instance> tlas;
std::vector<nvvk::RaytracingBuilderKHR::Instance> tlas;
tlas.reserve(m_objInstance.size());
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.instanceId = i; // gl_InstanceID
rayInst.blasId = m_objInstance[i].objIndex;
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);
}
m_rtBuilder.buildTlas(tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace);
@ -481,20 +591,20 @@ builds or better performance.
```` C
void buildTlas(const std::vector<Instance>& instances,
vk::BuildAccelerationStructureFlagsKHR flags =
vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace)
VkBuildAccelerationStructureFlagsKHR flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR)
{
m_tlas.flags = flags;
{
vk::AccelerationStructureCreateGeometryTypeInfoKHR geometryCreate{vk::GeometryTypeKHR::eInstances};
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;
geometryCreate.maxPrimitiveCount = (static_cast<uint32_t>(instances.size()));
geometryCreate.allowsTransforms = (VK_TRUE);
vk::AccelerationStructureCreateInfoKHR asCreateInfo{{}, vk::AccelerationStructureTypeKHR::eTopLevel};
asCreateInfo.setFlags(flags);
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
@ -502,10 +612,10 @@ resulting size of the TLAS using `vk::Device::getAccelerationStructureMemoryRequ
amount of memory:
```` 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
// required to hold the TLAS data
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,
@ -515,17 +625,22 @@ independent.
```` C
// Compute the amount of scratch memory required by the acceleration structure builder
vk::AccelerationStructureMemoryRequirementsInfoKHR memoryRequirementsInfo{
vk::AccelerationStructureMemoryRequirementsTypeKHR::eBuildScratch,
vk::AccelerationStructureBuildTypeKHR::eDevice, m_tlas.as.accel};
vk::DeviceSize scratchSize =
m_device.getAccelerationStructureMemoryRequirementsKHR(memoryRequirementsInfo).memoryRequirements.size;
VkAccelerationStructureMemoryRequirementsInfoKHR memoryRequirementsInfo{
VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_KHR};
memoryRequirementsInfo.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_KHR;
memoryRequirementsInfo.accelerationStructure = m_tlas.as.accel;
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 memory
nvvkBuffer scratchBuffer = m_alloc.createBuffer(scratchSize, vk::BufferUsageFlagBits::eRayTracingKHR
| vk::BufferUsageFlagBits::eShaderDeviceAddress);
vk::DeviceAddress scratchAddress = m_device.getBufferAddress({scratchBuffer.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);
````
An `Instance` object is nearly identical to a `VkGeometryInstanceKHR` object: the only difference is the transform
@ -536,7 +651,7 @@ TLAS we then convert all the `Instance` objects to `VkGeometryInstanceKHR`:
```` C
// For each instance, build the corresponding instance descriptor
std::vector<vk::AccelerationStructureInstanceKHR> geometryInstances;
std::vector<VkAccelerationStructureInstanceKHR> geometryInstances;
geometryInstances.reserve(instances.size());
for(const auto& inst : instances)
{
@ -550,53 +665,64 @@ TLAS build.
```` C
// Building the TLAS
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_queueIndex);
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
nvvk::CommandPool genCmdBuf(m_device, m_queueIndex);
VkCommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
// Create a buffer holding the actual instance data for use by the AS builder
VkDeviceSize instanceDescsSizeInBytes = instances.size() * sizeof(vk::AccelerationStructureInstanceKHR);
// Create a buffer holding the actual instance data for use by the AS
// 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
// memory
m_instBuffer = m_alloc.createBuffer(cmdBuf, geometryInstances,
vk::BufferUsageFlagBits::eRayTracingKHR | vk::BufferUsageFlagBits::eShaderDeviceAddress);
VK_BUFFER_USAGE_RAY_TRACING_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
m_debug.setObjectName(m_instBuffer.buffer, "TLASInstances");
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
vk::MemoryBarrier barrier(vk::AccessFlagBits::eTransferWrite, vk::AccessFlagBits::eAccelerationStructureWriteKHR);
cmdBuf.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eAccelerationStructureBuildKHR,
vk::DependencyFlags(), {barrier}, {}, {});
VkMemoryBarrier barrier{VK_STRUCTURE_TYPE_MEMORY_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);
````
The build is then triggered, and we execute the command buffer before destroying the temporary buffers.
```` C
// Build the TLAS
vk::AccelerationStructureGeometryKHR topASGeometry{vk::GeometryTypeKHR::eInstances};
topASGeometry.geometry.instances.setArrayOfPointers(VK_FALSE);
topASGeometry.geometry.instances.setData(instanceAddress);
VkAccelerationStructureGeometryDataKHR geometry{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR};
geometry.instances.arrayOfPointers = VK_FALSE;
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;
topASInfo.setFlags(flags);
topASInfo.setUpdate(VK_FALSE);
topASInfo.setSrcAccelerationStructure({});
topASInfo.setDstAccelerationStructure(m_tlas.as.accel);
topASInfo.setGeometryArrayOfPointers(VK_FALSE);
topASInfo.setGeometryCount(1);
topASInfo.setPpGeometries(&pGeometry);
topASInfo.setScratchData(scratchAddress);
const VkAccelerationStructureGeometryKHR* pGeometry = &topASGeometry;
VkAccelerationStructureBuildGeometryInfoKHR topASInfo{VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR};
topASInfo.flags = flags;
topASInfo.update = VK_FALSE;
topASInfo.srcAccelerationStructure = VK_NULL_HANDLE;
topASInfo.dstAccelerationStructure = m_tlas.as.accel;
topASInfo.geometryArrayOfPointers = VK_FALSE;
topASInfo.geometryCount = 1;
topASInfo.ppGeometries = &pGeometry;
topASInfo.scratchData.deviceAddress = scratchAddress;
// Build Offsets info: n instances
vk::AccelerationStructureBuildOffsetInfoKHR buildOffsetInfo{static_cast<uint32_t>(instances.size()), 0, 0, 0};
const vk::AccelerationStructureBuildOffsetInfoKHR* pBuildOffsetInfo = &buildOffsetInfo;
VkAccelerationStructureBuildOffsetInfoKHR buildOffsetInfo{static_cast<uint32_t>(instances.size()), 0, 0, 0};
const VkAccelerationStructureBuildOffsetInfoKHR* pBuildOffsetInfo = &buildOffsetInfo;
// 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);
}
````
@ -633,7 +759,7 @@ In the header, we declare the objects related to this additional descriptor set:
```` C
void createRtDescriptorSet();
std::vector<vk::DescriptorSetLayoutBinding> m_rtDescSetLayoutBind;
nvvk::DescriptorSetBindings m_rtDescSetLayoutBind;
vk::DescriptorPool m_rtDescPool;
vk::DescriptorSetLayout m_rtDescSetLayout;
vk::DescriptorSet m_rtDescSet;
@ -654,25 +780,25 @@ void HelloVulkan::createRtDescriptorSet()
using vkSS = vk::ShaderStageFlagBits;
using vkDSLB = vk::DescriptorSetLayoutBinding;
m_rtDescSetLayoutBind.emplace_back(
vkDSLB(0, vkDT::eAccelerationStructureKHR, 1, vkSS::eRaygenKHR )); // TLAS
m_rtDescSetLayoutBind.emplace_back(
m_rtDescSetLayoutBind.addBinding(vkDSLB(0, vkDT::eAccelerationStructureKHR, 1,
vkSS::eRaygenKHR | vkSS::eClosestHitKHR)); // TLAS
m_rtDescSetLayoutBind.addBinding(
vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image
m_rtDescPool = nvvkpp::util::createDescriptorPool(m_device, m_rtDescSetLayoutBind);
m_rtDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_rtDescSetLayoutBind);
m_rtDescPool = m_rtDescSetLayoutBind.createPool(m_device);
m_rtDescSetLayout = m_rtDescSetLayoutBind.createLayout(m_device);
m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0];
vk::AccelerationStructureKHR tlas = m_rtBuilder.getAccelerationStructure();
vk::WriteDescriptorSetAccelerationStructureKHR descASInfo;
descASInfo.setAccelerationStructureCount(1);
descASInfo.setPAccelerationStructures(&m_rtBuilder.getAccelerationStructure());
descASInfo.setPAccelerationStructures(&tlas);
vk::DescriptorImageInfo imageInfo{
{}, m_offscreenColor.descriptor.imageView, vk::ImageLayout::eGeneral};
std::vector<vk::WriteDescriptorSet> writes;
writes.emplace_back(
nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[0], &descASInfo));
writes.emplace_back(nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[1], &imageInfo));
writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 0, descASInfo));
writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 1, imageInfo));
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
// Camera matrices (binding = 0)
m_descSetLayoutBind.emplace_back(
m_descSetLayoutBind.addBinding(
vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR));
// Materials (binding = 1)
m_descSetLayoutBind.emplace_back(
m_descSetLayoutBind.addBinding(
vkDS(1, vkDT::eStorageBuffer, nbObj, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
// Scene description (binding = 2)
m_descSetLayoutBind.emplace_back( //
m_descSetLayoutBind.addBinding( //
vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
// Textures (binding = 3)
m_descSetLayoutBind.emplace_back(
m_descSetLayoutBind.addBinding(
vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR));
// Materials (binding = 4)
m_descSetLayoutBind.emplace_back(
m_descSetLayoutBind.addBinding(
vkDS(4, vkDT::eStorageBuffer, nbObj, vkSS::eFragment | vkSS::eClosestHitKHR));
// Storing vertices (binding = 5)
m_descSetLayoutBind.emplace_back( //
m_descSetLayoutBind.addBinding( //
vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
// Storing indices (binding = 6)
m_descSetLayoutBind.emplace_back( //
m_descSetLayoutBind.addBinding( //
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});
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(
nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[4], dbiMatIdx.data()));
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[5], dbiVert.data()));
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[6], dbiIdx.data()));
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 1, dbiMat.data()));
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 4, dbiMatIdx.data()));
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 5, dbiVert.data()));
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 6, dbiIdx.data()));
````
Originally the buffers containing the vertices and indices were only used by the rasterization pipeline. The ray tracing
@ -922,10 +1047,10 @@ void HelloVulkan::createRtPipeline()
std::vector<std::string> paths = defaultSearchPaths;
vk::ShaderModule raygenSM =
nvvkpp::util::createShaderModule(m_device, //
nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rgen.spv", true, paths));
vk::ShaderModule missSM =
nvvkpp::util::createShaderModule(m_device, //
nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths));
std::vector<vk::PipelineShaderStageCreateInfo> stages;
@ -960,7 +1085,7 @@ shaders.
```` C
// Hit Group - Closest Hit + AnyHit
vk::ShaderModule chitSM =
nvvkpp::util::createShaderModule(m_device, //
nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rchit.spv", true, paths));
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup,
@ -1139,7 +1264,7 @@ copy the handles into the SBT:
m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize,
shaderHandleStorage.data());
// 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();
m_rtSBTBuffer =
@ -1147,9 +1272,9 @@ copy the handles into the 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
// The second miss shader is invoked when a shadow ray misses the geometry. It
// simply indicates that no occlusion has been found
vk::ShaderModule shadowmissSM = nvvkpp::util::createShaderModule(
m_device, nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
vk::ShaderModule shadowmissSM =
nvvk::createShaderModule(m_device,
nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
````

View file

@ -30,19 +30,22 @@
extern std::vector<std::string> defaultSearchPaths;
#define VMA_IMPLEMENTATION
#define STB_IMAGE_IMPLEMENTATION
#include "fileformats/stb_image.h"
#include "obj_loader.h"
#include "hello_vulkan.h"
#include "nvh//cameramanipulator.hpp"
#include "nvvkpp/descriptorsets_vkpp.hpp"
#include "nvvkpp/pipeline_vkpp.hpp"
#include "nvvk/descriptorsets_vk.hpp"
#include "nvvk/pipeline_vk.hpp"
#include "nvh/fileoperations.hpp"
#include "nvvkpp/commands_vkpp.hpp"
#include "nvvkpp/renderpass_vkpp.hpp"
#include "nvvkpp/utilities_vkpp.hpp"
#include "nvvk/commands_vk.hpp"
#include "nvvk/renderpasses_vk.hpp"
// Holding the camera matrices
struct CameraMatrices
@ -58,31 +61,32 @@ struct CameraMatrices
// Keep the handle on the device
// 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,
uint32_t queueFamily)
{
AppBase::setup(device, physicalDevice, queueFamily);
#if defined(ALLOC_DEDICATED)
AppBase::setup(instance, device, physicalDevice, queueFamily);
#if defined(NVVK_ALLOC_DEDICATED)
m_alloc.init(device, physicalDevice);
#elif defined(ALLOC_DMA)
#elif defined(NVVK_ALLOC_DMA)
m_memAllocator.init(device, physicalDevice);
m_memAllocator.setAllocateFlags(VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR, true);
m_alloc.init(device, &m_memAllocator);
#elif defined(ALLOC_VMA)
m_memAllocator.setAllocateFlags(VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT, true);
m_alloc.init(device, physicalDevice, &m_memAllocator);
#elif defined(NVVK_ALLOC_VMA)
VmaAllocatorCreateInfo allocatorInfo = {};
allocatorInfo.physicalDevice = physicalDevice;
allocatorInfo.instance = instance;
allocatorInfo.device = device;
allocatorInfo.flags |=
VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT | VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT;
allocatorInfo.flags = VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT;
vmaCreateAllocator(&allocatorInfo, &m_memAllocator);
m_alloc.init(device, m_memAllocator);
m_alloc.init(device, physicalDevice, m_memAllocator);
#endif
m_debug.setup(m_device);
m_offscreen.setup(device, m_memAllocator, queueFamily);
m_raytrace.setup(device, physicalDevice, m_memAllocator, queueFamily);
m_offscreen.setup(device, &m_alloc, queueFamily);
m_raytrace.setup(device, physicalDevice, &m_alloc, queueFamily);
}
//--------------------------------------------------------------------------------------------------
@ -100,15 +104,15 @@ void HelloVulkan::updateUniformBuffer()
// #VKRay
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));
memcpy(data, &ubo, sizeof(ubo));
m_device.unmapMemory(m_cameraMat.allocation);
#elif defined(ALLOC_DMA)
#elif defined(NVVK_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)
#elif defined(NVVK_ALLOC_VMA)
void* data;
vmaMapMemory(m_memAllocator, m_cameraMat.allocation, &data);
memcpy(data, &ubo, sizeof(ubo));
@ -128,37 +132,37 @@ void HelloVulkan::createDescriptorSetLayout()
uint32_t nbObj = static_cast<uint32_t>(m_objModel.size());
// Camera matrices (binding = 0)
m_descSetLayoutBind.emplace_back(
m_descSetLayoutBind.addBinding(
vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR));
// Materials (binding = 1)
m_descSetLayoutBind.emplace_back(
m_descSetLayoutBind.addBinding(
vkDS(1, vkDT::eStorageBuffer, nbObj + 1, // Adding Implicit mat too
vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR | vkSS::eAnyHitKHR));
// Scene description (binding = 2)
m_descSetLayoutBind.emplace_back( //
m_descSetLayoutBind.addBinding( //
vkDS(2, vkDT::eStorageBuffer, 1,
vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR | vkSS::eAnyHitKHR));
// Textures (binding = 3)
m_descSetLayoutBind.emplace_back(
m_descSetLayoutBind.addBinding(
vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR));
// 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));
// Storing vertices (binding = 5)
m_descSetLayoutBind.emplace_back( //
m_descSetLayoutBind.addBinding( //
vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR | vkSS::eAnyHitKHR));
// Storing indices (binding = 6)
m_descSetLayoutBind.emplace_back( //
m_descSetLayoutBind.addBinding( //
vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR | vkSS::eAnyHitKHR));
// Storing implicit obj (binding = 7)
m_descSetLayoutBind.emplace_back( //
m_descSetLayoutBind.addBinding( //
vkDS(7, vkDT::eStorageBuffer, 1,
vkSS::eClosestHitKHR | vkSS::eIntersectionKHR | vkSS::eAnyHitKHR));
m_descSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_descSetLayoutBind);
m_descPool = nvvkpp::util::createDescriptorPool(m_device, m_descSetLayoutBind, 1);
m_descSet = nvvkpp::util::createDescriptorSet(m_device, m_descPool, m_descSetLayout);
m_descSetLayout = m_descSetLayoutBind.createLayout(m_device);
m_descPool = m_descSetLayoutBind.createPool(m_device, 1);
m_descSet = nvvk::allocateDescriptorSet(m_device, m_descPool, m_descSetLayout);
}
//--------------------------------------------------------------------------------------------------
@ -170,9 +174,9 @@ void HelloVulkan::updateDescriptorSet()
// Camera matrices and scene description
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};
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
std::vector<vk::DescriptorBufferInfo> dbiMat;
@ -187,11 +191,10 @@ void HelloVulkan::updateDescriptorSet()
dbiIdx.emplace_back(model.indexBuffer.buffer, 0, VK_WHOLE_SIZE);
}
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(
nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[4], dbiMatIdx.data()));
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[5], dbiVert.data()));
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[6], dbiIdx.data()));
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 1, dbiMat.data()));
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 4, dbiMatIdx.data()));
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 5, dbiVert.data()));
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 6, dbiIdx.data()));
// All texture samplers
std::vector<vk::DescriptorImageInfo> diit;
@ -199,10 +202,10 @@ void HelloVulkan::updateDescriptorSet()
{
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};
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
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
@ -229,18 +232,18 @@ void HelloVulkan::createGraphicsPipeline()
// Creating the Pipeline
std::vector<std::string> paths = defaultSearchPaths;
nvvkpp::GraphicsPipelineGenerator gpb(m_device, m_pipelineLayout, m_offscreen.renderPass());
gpb.depthStencilState = {true};
nvvk::GraphicsPipelineGeneratorCombined gpb(m_device, m_pipelineLayout, m_offscreen.renderPass());
gpb.depthStencilState.depthTestEnable = true;
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.vertexInputState.bindingDescriptions = {{0, sizeof(VertexObj)}};
gpb.vertexInputState.attributeDescriptions = {
gpb.addBindingDescription({0, sizeof(VertexObj)});
gpb.addAttributeDescriptions(std::vector<vk::VertexInputAttributeDescription>{
{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
{1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)},
{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");
}
@ -273,7 +276,7 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
// 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();
model.vertexBuffer =
m_alloc.createBuffer(cmdBuf, loader.m_vertices,
@ -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);
// Creates all textures found
createTextureImages(cmdBuf, loader.m_textures);
cmdBufGet.flushCommandBuffer(cmdBuf);
m_alloc.flushStaging();
cmdBufGet.submitAndWait(cmdBuf);
m_alloc.finalizeAndReleaseStaging();
std::string objNb = std::to_string(instance.objIndex);
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
@ -308,7 +311,11 @@ void HelloVulkan::createUniformBuffer()
using vkMP = vk::MemoryPropertyFlagBits;
m_cameraMat = m_alloc.createBuffer(sizeof(CameraMatrices), vkBU::eUniformBuffer,
#ifndef NVVK_ALLOC_VMA
vkMP::eHostVisible | vkMP::eHostCoherent);
#else
VMA_MEMORY_USAGE_CPU_TO_GPU);
#endif // _DEBUG
m_debug.setObjectName(m_cameraMat.buffer, "cameraMat");
}
@ -321,12 +328,12 @@ void HelloVulkan::createUniformBuffer()
void HelloVulkan::createSceneDescriptionBuffer()
{
using vkBU = vk::BufferUsageFlagBits;
nvvkpp::SingleCommandBuffer cmdGen(m_device, m_graphicsQueueIndex);
nvvk::CommandPool cmdGen(m_device, m_graphicsQueueIndex);
auto cmdBuf = cmdGen.createCommandBuffer();
m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer);
cmdGen.flushCommandBuffer(cmdBuf);
m_alloc.flushStaging();
cmdGen.submitAndWait(cmdBuf);
m_alloc.finalizeAndReleaseStaging();
m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc");
}
@ -346,20 +353,20 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
// If no textures are present, create a dummy one to accommodate the pipeline layout
if(textures.empty() && m_textures.empty())
{
nvvkTexture texture;
nvvk::Texture texture;
std::array<uint8_t, 4> color{255u, 255u, 255u, 255u};
vk::DeviceSize bufferSize = sizeof(color);
auto imgSize = vk::Extent2D(1, 1);
auto imageCreateInfo = nvvkpp::image::create2DInfo(imgSize, format);
auto imageCreateInfo = nvvk::makeImage2DCreateInfo(imgSize, format);
// 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);
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);
// 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);
m_textures.push_back(texture);
}
@ -387,16 +394,15 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4;
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;
texture = m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo);
nvvk::Image image = 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);
}
}
@ -436,7 +442,12 @@ void HelloVulkan::destroyResources()
// #VKRay
m_raytrace.destroy();
m_alloc.deinit();
#ifdef NVVK_ALLOC_DMA
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,
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.drawIndexed(model.nbIndices, 1, 0, 0, 0);
}
@ -574,7 +585,7 @@ void HelloVulkan::addImplMaterial(const MaterialObj& mat)
void HelloVulkan::createImplictBuffers()
{
using vkBU = vk::BufferUsageFlagBits;
nvvkpp::SingleCommandBuffer cmdGen(m_device, m_graphicsQueueIndex);
nvvk::CommandPool cmdGen(m_device, m_graphicsQueueIndex);
// Not allowing empty buffers
if(m_implObjects.objImpl.empty())
@ -587,8 +598,8 @@ void HelloVulkan::createImplictBuffers()
vkBU::eStorageBuffer | vkBU::eShaderDeviceAddress);
m_implObjects.implMatBuf =
m_alloc.createBuffer(cmdBuf, m_implObjects.implMat, vkBU::eStorageBuffer);
cmdGen.flushCommandBuffer(cmdBuf);
m_alloc.flushStaging();
cmdGen.submitAndWait(cmdBuf);
m_alloc.finalizeAndReleaseStaging();
m_debug.setObjectName(m_implObjects.implBuf.buffer, "implicitObj");
m_debug.setObjectName(m_implObjects.implMatBuf.buffer, "implicitMat");
}

View file

@ -28,12 +28,12 @@
#include "vkalloc.hpp"
#include "nvvkpp/allocator_dedicated_vkpp.hpp"
#include "nvvkpp/appbase_vkpp.hpp"
#include "nvvkpp/debug_util_vkpp.hpp"
#include "nvvk/allocator_dedicated_vk.hpp"
#include "nvvk/appbase_vkpp.hpp"
#include "nvvk/debug_util_vk.hpp"
// #VKRay
#include "nvvkpp/raytraceKHR_vkpp.hpp"
#include "nvvk/raytraceKHR_vk.hpp"
#include "offscreen.hpp"
#include "obj.hpp"
@ -46,10 +46,11 @@
// - Rendering is done in an offscreen framebuffer
// - 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:
void setup(const vk::Device& device,
void setup(const vk::Instance& instance,
const vk::Device& device,
const vk::PhysicalDevice& physicalDevice,
uint32_t queueFamily) override;
void createDescriptorSetLayout();
@ -78,7 +79,7 @@ public:
// Graphic pipeline
vk::PipelineLayout m_pipelineLayout;
vk::Pipeline m_graphicsPipeline;
std::vector<vk::DescriptorSetLayoutBinding> m_descSetLayoutBind;
nvvk::DescriptorSetBindings m_descSetLayoutBind;
vk::DescriptorPool m_descPool;
vk::DescriptorSetLayout m_descSetLayout;
vk::DescriptorSet m_descSet;
@ -87,15 +88,14 @@ public:
void resetFrame();
void updateFrame();
nvvkBuffer m_cameraMat; // Device-Host of the camera matrices
nvvkBuffer m_sceneDesc; // Device buffer of the OBJ instances
std::vector<nvvkTexture> m_textures; // vector of all textures of the scene
nvvk::Buffer m_cameraMat; // Device-Host of the camera matrices
nvvk::Buffer m_sceneDesc; // Device buffer of the OBJ instances
std::vector<nvvk::Texture> m_textures; // vector of all textures of the scene
nvvkpp::DebugUtil m_debug; // Utility to name objects
nvvkAllocator m_alloc; // Allocator for buffer, images, acceleration structures
nvvkMemAllocator m_memAllocator;
nvvk::DebugUtil m_debug; // Utility to name objects
nvvk::Allocator m_alloc; // Allocator for buffer, images, acceleration structures
nvvk::MemAllocator m_memAllocator;
// #Post
Offscreen m_offscreen;

View file

@ -31,6 +31,7 @@
#include <array>
#include <vulkan/vulkan.hpp>
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
#include "imgui.h"
#include "imgui_impl_glfw.h"
@ -39,10 +40,10 @@
#include "nvh/cameramanipulator.hpp"
#include "nvh/fileoperations.hpp"
#include "nvpsystem.hpp"
#include "nvvkpp/appbase_vkpp.hpp"
#include "nvvkpp/commands_vkpp.hpp"
#include "nvvkpp/context_vkpp.hpp"
#include "nvvkpp/utilities_vkpp.hpp"
#include "nvvk/appbase_vkpp.hpp"
#include "nvvk/commands_vk.hpp"
#include "nvvk/context_vk.hpp"
#include <random>
//////////////////////////////////////////////////////////////////////////
@ -157,7 +158,7 @@ int main(int argc, char** argv)
vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature;
// Requesting Vulkan extensions and layers
nvvkpp::ContextCreateInfo contextInfo(true);
nvvk::ContextCreateInfo contextInfo(true);
contextInfo.setVersion(1, 2);
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
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);
// Creating Vulkan base application
nvvkpp::Context vkctx{};
nvvk::Context vkctx{};
vkctx.initInstance(contextInfo);
// Find all compatible devices
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);
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.createDepthBuffer();
helloVk.createRenderPass();
@ -316,7 +318,8 @@ int main(int argc, char** argv)
// Clearing screen
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});
// Offscreen render pass
@ -368,7 +371,6 @@ int main(int argc, char** argv)
helloVk.destroyResources();
helloVk.destroy();
vkctx.m_instance.destroySurfaceKHR(surface);
vkctx.deinit();
glfwDestroyWindow(window);

View file

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

View file

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

View file

@ -27,7 +27,8 @@
#include <vulkan/vulkan.hpp>
#include "nvvkpp/debug_util_vkpp.hpp"
#include "nvvk/debug_util_vk.hpp"
#include "nvvk/descriptorsets_vk.hpp"
#include "vkalloc.hpp"
//--------------------------------------------------------------------------------------------------
@ -39,7 +40,7 @@
class Offscreen
{
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 createFramebuffer(VkExtent2D& size);
@ -50,10 +51,10 @@ public:
const vk::RenderPass& renderPass() { return m_renderPass; }
const vk::Framebuffer& frameBuffer() { return m_framebuffer; }
const nvvkTexture& colorTexture() { return m_colorTexture; }
const nvvk::Texture& colorTexture() { return m_colorTexture; }
private:
std::vector<vk::DescriptorSetLayoutBinding> m_dsetLayoutBinding;
nvvk::DescriptorSetBindings m_dsetLayoutBinding;
vk::DescriptorPool m_descPool;
vk::DescriptorSetLayout m_dsetLayout;
vk::DescriptorSet m_dset;
@ -62,13 +63,13 @@ private:
vk::RenderPass m_renderPass;
vk::Framebuffer m_framebuffer;
nvvkTexture m_colorTexture;
nvvk::Texture m_colorTexture;
vk::Format m_colorFormat{vk::Format::eR32G32B32A32Sfloat};
nvvkTexture m_depthTexture;
nvvk::Texture m_depthTexture;
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;
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 "nvh/fileoperations.hpp"
#include "nvvkpp/descriptorsets_vkpp.hpp"
#include "nvvkpp/utilities_vkpp.hpp"
#include "nvvk/descriptorsets_vk.hpp"
#include "nvvk/shaders_vk.hpp"
#include "obj_loader.h"
extern std::vector<std::string> defaultSearchPaths;
@ -37,25 +38,19 @@ extern std::vector<std::string> defaultSearchPaths;
void Raytracer::setup(const vk::Device& device,
const vk::PhysicalDevice& physicalDevice,
nvvkMemAllocator& memAlloc,
nvvk::Allocator* allocator,
uint32_t queueFamily)
{
m_device = device;
m_physicalDevice = physicalDevice;
m_alloc.init(device, &memAlloc);
m_alloc = allocator;
m_graphicsQueueIndex = queueFamily;
// Requesting ray tracing properties
auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2,
vk::PhysicalDeviceRayTracingPropertiesKHR>();
m_rtProperties = properties.get<vk::PhysicalDeviceRayTracingPropertiesKHR>();
#if defined(ALLOC_DEDICATED)
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_rtBuilder.setup(m_device, allocator, m_graphicsQueueIndex);
m_debug.setup(device);
}
@ -68,13 +63,13 @@ void Raytracer::destroy()
m_device.destroy(m_rtDescSetLayout);
m_device.destroy(m_rtPipeline);
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
//
nvvkpp::RaytracingBuilderKHR::Blas Raytracer::objectToVkGeometryKHR(const ObjModel& model)
nvvk::RaytracingBuilderKHR::Blas Raytracer::objectToVkGeometryKHR(const ObjModel& model)
{
// Setting up the creation info of acceleration structure
vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate;
@ -110,7 +105,7 @@ nvvkpp::RaytracingBuilderKHR::Blas Raytracer::objectToVkGeometryKHR(const ObjMod
offset.setPrimitiveOffset(0);
offset.setTransformOffset(0);
nvvkpp::RaytracingBuilderKHR::Blas blas;
nvvk::RaytracingBuilderKHR::Blas blas;
blas.asGeometry.emplace_back(asGeom);
blas.asCreateGeometryInfo.emplace_back(asCreate);
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
//
nvvkpp::RaytracingBuilderKHR::Blas Raytracer::implicitToVkGeometryKHR(const ImplInst& implicitObj)
nvvk::RaytracingBuilderKHR::Blas Raytracer::implicitToVkGeometryKHR(const ImplInst& implicitObj)
{
// Setting up the creation info of acceleration structure
@ -152,7 +147,7 @@ nvvkpp::RaytracingBuilderKHR::Blas Raytracer::implicitToVkGeometryKHR(const Impl
offset.setPrimitiveOffset(0);
offset.setTransformOffset(0);
nvvkpp::RaytracingBuilderKHR::Blas blas;
nvvk::RaytracingBuilderKHR::Blas blas;
blas.asGeometry.emplace_back(asGeom);
blas.asCreateGeometryInfo.emplace_back(asCreate);
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)
{
// BLAS - Storing each primitive in a geometry
std::vector<nvvkpp::RaytracingBuilderKHR::Blas> allBlas;
std::vector<nvvk::RaytracingBuilderKHR::Blas> allBlas;
allBlas.reserve(models.size());
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)
{
std::vector<nvvkpp::RaytracingBuilderKHR::Instance> tlas;
std::vector<nvvk::RaytracingBuilderKHR::Instance> tlas;
tlas.reserve(instances.size());
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.instanceId = i; // gl_InstanceID
rayInst.blasId = instances[i].objIndex;
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);
}
// Add the blas containing all implicit
if(!implicitObj.objImpl.empty())
{
nvvkpp::RaytracingBuilderKHR::Instance rayInst;
nvvk::RaytracingBuilderKHR::Instance rayInst;
rayInst.transform = implicitObj.transform; // Position of the instance
rayInst.instanceId = static_cast<uint32_t>(implicitObj.blasId); // Same for material index
rayInst.blasId = static_cast<uint32_t>(implicitObj.blasId);
rayInst.hitGroupId = 1; // We will use the same hit group for all objects (the second one)
rayInst.flags = vk::GeometryInstanceFlagBitsKHR::eTriangleCullDisable;
rayInst.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
tlas.emplace_back(rayInst);
}
@ -224,24 +220,24 @@ void Raytracer::createRtDescriptorSet(const vk::ImageView& outputImage)
using vkSS = vk::ShaderStageFlagBits;
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
m_rtDescSetLayoutBind.emplace_back(
m_rtDescSetLayoutBind.addBinding(
vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image
m_rtDescPool = nvvkpp::util::createDescriptorPool(m_device, m_rtDescSetLayoutBind);
m_rtDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_rtDescSetLayoutBind);
m_rtDescPool = m_rtDescSetLayoutBind.createPool(m_device);
m_rtDescSetLayout = m_rtDescSetLayoutBind.createLayout(m_device);
m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0];
vk::AccelerationStructureKHR tlas = m_rtBuilder.getAccelerationStructure();
vk::WriteDescriptorSetAccelerationStructureKHR descASInfo;
descASInfo.setAccelerationStructureCount(1);
descASInfo.setPAccelerationStructures(&m_rtBuilder.getAccelerationStructure());
descASInfo.setPAccelerationStructures(&tlas);
vk::DescriptorImageInfo imageInfo{{}, outputImage, vk::ImageLayout::eGeneral};
std::vector<vk::WriteDescriptorSet> writes;
writes.emplace_back(
nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[0], &descASInfo));
writes.emplace_back(nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[1], &imageInfo));
writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 0, &descASInfo));
writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 1, &imageInfo));
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;
vk::ShaderModule raygenSM =
nvvkpp::util::createShaderModule(m_device, //
nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rgen.spv", true, paths));
vk::ShaderModule missSM =
nvvkpp::util::createShaderModule(m_device, //
nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths));
// The second miss shader is invoked when a shadow ray misses the geometry. It
// simply indicates that no occlusion has been found
vk::ShaderModule shadowmissSM = nvvkpp::util::createShaderModule(
m_device, nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
vk::ShaderModule shadowmissSM =
nvvk::createShaderModule(m_device,
nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
std::vector<vk::PipelineShaderStageCreateInfo> stages;
@ -305,10 +302,10 @@ void Raytracer::createRtPipeline(vk::DescriptorSetLayout& sceneDescLayout)
// Hit Group0 - Closest Hit + AnyHit
vk::ShaderModule chitSM =
nvvkpp::util::createShaderModule(m_device, //
nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rchit.spv", true, paths));
vk::ShaderModule ahitSM =
nvvkpp::util::createShaderModule(m_device, //
nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rahit.spv", true, paths));
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup,
@ -323,13 +320,13 @@ void Raytracer::createRtPipeline(vk::DescriptorSetLayout& sceneDescLayout)
// Hit Group1 - Closest Hit + Intersection (procedural)
vk::ShaderModule chit2SM =
nvvkpp::util::createShaderModule(m_device, //
nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace2.rchit.spv", true, paths));
vk::ShaderModule ahit2SM =
nvvkpp::util::createShaderModule(m_device, //
nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace2.rahit.spv", true, paths));
vk::ShaderModule rintSM =
nvvkpp::util::createShaderModule(m_device, //
nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rint.spv", true, paths));
{
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eProceduralHitGroup,
@ -350,14 +347,13 @@ void Raytracer::createRtPipeline(vk::DescriptorSetLayout& sceneDescLayout)
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR};
vk::ShaderModule call0 =
nvvkpp::util::createShaderModule(m_device,
nvvk::createShaderModule(m_device,
nvh::loadFile("shaders/light_point.rcall.spv", true, paths));
vk::ShaderModule call1 =
nvvkpp::util::createShaderModule(m_device,
nvvk::createShaderModule(m_device,
nvh::loadFile("shaders/light_spot.rcall.spv", true, paths));
vk::ShaderModule call2 =
nvvkpp::util::createShaderModule(m_device,
nvh::loadFile("shaders/light_inf.rcall.spv", true, paths));
nvvk::createShaderModule(m_device, nvh::loadFile("shaders/light_inf.rcall.spv", true, paths));
stages.push_back({{}, vk::ShaderStageFlagBits::eCallableKHR, call0, "main"});
callGroup.setGeneralShader(static_cast<uint32_t>(stages.size() - 1));
@ -433,17 +429,17 @@ void Raytracer::createRtShaderBindingTable()
m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize,
shaderHandleStorage.data());
// 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();
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");
genCmdBuf.flushCommandBuffer(cmdBuf);
genCmdBuf.submitAndWait(cmdBuf);
m_alloc.flushStaging();
m_alloc->finalizeAndReleaseStaging();
}
//--------------------------------------------------------------------------------------------------

View file

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

View file

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

View file

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

View file

@ -1,24 +1,6 @@
//#define ALLOC_DEDICATED
#define ALLOC_DMA
//#define ALLOC_VMA
//#define NVVK_ALLOC_DEDICATED
#define NVVK_ALLOC_DMA
//#define NVVK_ALLOC_VMA
#if defined(ALLOC_DEDICATED)
#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
#include <nvvk/allocator_vk.hpp>

View file

@ -36,13 +36,13 @@ extern std::vector<std::string> defaultSearchPaths;
#include "hello_vulkan.h"
#include "nvh//cameramanipulator.hpp"
#include "nvvkpp/descriptorsets_vkpp.hpp"
#include "nvvkpp/pipeline_vkpp.hpp"
#include "nvvk/descriptorsets_vk.hpp"
#include "nvvk/pipeline_vk.hpp"
#include "nvh/fileoperations.hpp"
#include "nvvkpp/commands_vkpp.hpp"
#include "nvvkpp/renderpass_vkpp.hpp"
#include "nvvkpp/utilities_vkpp.hpp"
#include "nvvk/commands_vk.hpp"
#include "nvvk/renderpasses_vk.hpp"
// Holding the camera matrices
struct CameraMatrices
@ -56,9 +56,12 @@ struct CameraMatrices
// Keep the handle on the device
// 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_debug.setup(m_device);
}
@ -92,22 +95,23 @@ void HelloVulkan::createDescriptorSetLayout()
uint32_t nbObj = static_cast<uint32_t>(m_objModel.size());
// 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)
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)
m_descSetLayoutBind.emplace_back( //
m_descSetLayoutBind.addBinding( //
vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment));
// 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)
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_descPool = nvvkpp::util::createDescriptorPool(m_device, m_descSetLayoutBind, 1);
m_descSet = nvvkpp::util::createDescriptorSet(m_device, m_descPool, m_descSetLayout);
m_descSetLayout = m_descSetLayoutBind.createLayout(m_device);
m_descPool = m_descSetLayoutBind.createPool(m_device, 1);
m_descSet = nvvk::allocateDescriptorSet(m_device, m_descPool, m_descSetLayout);
}
//--------------------------------------------------------------------------------------------------
@ -119,9 +123,9 @@ void HelloVulkan::updateDescriptorSet()
// Camera matrices and scene description
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};
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
std::vector<vk::DescriptorBufferInfo> dbiMat;
@ -131,8 +135,8 @@ void HelloVulkan::updateDescriptorSet()
dbiMat.push_back({m_objModel[i].matColorBuffer.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(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[4], dbiMatIdx.data()));
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 1, dbiMat.data()));
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 4, dbiMatIdx.data()));
// All texture samplers
std::vector<vk::DescriptorImageInfo> diit;
@ -140,7 +144,7 @@ void HelloVulkan::updateDescriptorSet()
{
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
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
@ -154,7 +158,8 @@ void HelloVulkan::createGraphicsPipeline()
{
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
vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo;
@ -167,17 +172,18 @@ void HelloVulkan::createGraphicsPipeline()
// Creating the Pipeline
std::vector<std::string> paths = defaultSearchPaths;
nvvkpp::GraphicsPipelineGenerator gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
gpb.depthStencilState = {true};
nvvk::GraphicsPipelineGeneratorCombined gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
gpb.depthStencilState.depthTestEnable = true;
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.vertexInputState.bindingDescriptions = {{0, sizeof(VertexObj)}};
gpb.vertexInputState.attributeDescriptions = {{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
gpb.addBindingDescription({0, sizeof(VertexObj)});
gpb.addAttributeDescriptions(std::vector<vk::VertexInputAttributeDescription>{
{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
{1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)},
{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");
}
@ -210,7 +216,7 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
// 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();
model.vertexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_vertices, vkBU::eVertexBuffer);
model.indexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_indices, vkBU::eIndexBuffer);
@ -218,8 +224,8 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
model.matIndexBuffer = m_alloc.createBuffer(cmdBuf, loader.m_matIndx, vkBU::eStorageBuffer);
// Creates all textures found
createTextureImages(cmdBuf, loader.m_textures);
cmdBufGet.flushCommandBuffer(cmdBuf);
m_alloc.flushStaging();
cmdBufGet.submitAndWait(cmdBuf);
m_alloc.finalizeAndReleaseStaging();
std::string objNb = std::to_string(instance.objIndex);
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
@ -241,7 +247,8 @@ void HelloVulkan::createUniformBuffer()
using vkBU = vk::BufferUsageFlagBits;
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");
}
@ -254,42 +261,46 @@ void HelloVulkan::createUniformBuffer()
void HelloVulkan::createSceneDescriptionBuffer()
{
using vkBU = vk::BufferUsageFlagBits;
nvvkpp::SingleCommandBuffer cmdGen(m_device, m_graphicsQueueIndex);
nvvk::CommandPool cmdGen(m_device, m_graphicsQueueIndex);
auto cmdBuf = cmdGen.createCommandBuffer();
m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer);
cmdGen.flushCommandBuffer(cmdBuf);
m_alloc.flushStaging();
cmdGen.submitAndWait(cmdBuf);
m_alloc.finalizeAndReleaseStaging();
m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc");
}
//--------------------------------------------------------------------------------------------------
// 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;
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);
vk::Format format = vk::Format::eR8G8B8A8Srgb;
// If no textures are present, create a dummy one to accommodate the pipeline layout
if(textures.empty() && m_textures.empty())
{
nvvkTexture texture;
nvvk::Texture texture;
std::array<uint8_t, 4> color{255u, 255u, 255u, 255u};
vk::DeviceSize bufferSize = sizeof(color);
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
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);
}
else
@ -302,7 +313,8 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf, const std
o << "media/textures/" << texture;
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
if(!pixels)
@ -315,14 +327,16 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf, const std
vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4;
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;
texture = m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo);
nvvk::ImageDedicated image =
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);
}
}
@ -389,9 +403,10 @@ void HelloVulkan::rasterize(const vk::CommandBuffer& cmdBuf)
auto& inst = m_objInstance[i];
auto& model = m_objModel[inst.objIndex];
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.drawIndexed(model.nbIndices, 1, 0, 0, 0);
}
@ -422,48 +437,60 @@ void HelloVulkan::createOffscreenRender()
m_alloc.destroy(m_offscreenDepth);
// 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::eColorAttachment
| vk::ImageUsageFlagBits::eSampled
| vk::ImageUsageFlagBits::eStorage);
m_offscreenColor = m_alloc.createImage(colorCreateInfo);
m_offscreenColor.descriptor = nvvkpp::image::create2DDescriptor(m_device, m_offscreenColor.image, vk::SamplerCreateInfo{},
m_offscreenColorFormat, vk::ImageLayout::eGeneral);
nvvk::ImageDedicated image = m_alloc.createImage(colorCreateInfo);
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
auto depthCreateInfo =
nvvkpp::image::create2DInfo(m_size, m_offscreenDepthFormat, vk::ImageUsageFlagBits::eDepthStencilAttachment);
m_offscreenDepth = m_alloc.createImage(depthCreateInfo);
nvvk::makeImage2DCreateInfo(m_size, m_offscreenDepthFormat,
vk::ImageUsageFlagBits::eDepthStencilAttachment);
{
nvvk::Image image = m_alloc.createImage(depthCreateInfo);
vk::ImageViewCreateInfo depthStencilView;
depthStencilView.setViewType(vk::ImageViewType::e2D);
depthStencilView.setFormat(m_offscreenDepthFormat);
depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1});
depthStencilView.setImage(m_offscreenDepth.image);
m_offscreenDepth.descriptor.imageView = m_device.createImageView(depthStencilView);
depthStencilView.setImage(image.image);
m_offscreenDepth = m_alloc.createTexture(image, depthStencilView);
}
// 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();
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined, vk::ImageLayout::eGeneral);
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageAspectFlagBits::eDepth,
vk::ImageLayout::eUndefined, vk::ImageLayout::eDepthStencilAttachmentOptimal);
nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eGeneral);
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
if(!m_offscreenRenderPass)
{
m_offscreenRenderPass = nvvkpp::util::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat, 1,
true, true, vk::ImageLayout::eGeneral, vk::ImageLayout::eGeneral);
m_offscreenRenderPass =
nvvk::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat, 1, true,
true, vk::ImageLayout::eGeneral, vk::ImageLayout::eGeneral);
}
// 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);
vk::FramebufferCreateInfo info;
@ -495,11 +522,14 @@ void HelloVulkan::createPostPipeline()
// Pipeline: completely generic, no vertices
std::vector<std::string> paths = defaultSearchPaths;
nvvkpp::GraphicsPipelineGenerator pipelineGenerator(m_device, m_postPipelineLayout, m_renderPass);
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);
nvvk::GraphicsPipelineGeneratorCombined pipelineGenerator(m_device, m_postPipelineLayout,
m_renderPass);
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);
m_postPipeline = pipelineGenerator.create();
m_postPipeline = pipelineGenerator.createPipeline();
m_debug.setObjectName(m_postPipeline, "post");
}
@ -513,10 +543,10 @@ void HelloVulkan::createPostDescriptor()
using vkDT = vk::DescriptorType;
using vkSS = vk::ShaderStageFlagBits;
m_postDescSetLayoutBind.emplace_back(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
m_postDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_postDescSetLayoutBind);
m_postDescPool = nvvkpp::util::createDescriptorPool(m_device, m_postDescSetLayoutBind);
m_postDescSet = nvvkpp::util::createDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
m_postDescSetLayoutBind.addBinding(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
m_postDescSetLayout = m_postDescSetLayoutBind.createLayout(m_device);
m_postDescPool = m_postDescSetLayoutBind.createPool(m_device);
m_postDescSet = nvvk::allocateDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
}
@ -526,7 +556,7 @@ void HelloVulkan::createPostDescriptor()
void HelloVulkan::updatePostDescriptorSet()
{
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);
}
@ -541,9 +571,11 @@ void HelloVulkan::drawPost(vk::CommandBuffer cmdBuf)
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);
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.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);
m_debug.endLabel(cmdBuf);

View file

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

View file

@ -31,6 +31,7 @@
#include <array>
#include <vulkan/vulkan.hpp>
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
#include "imgui.h"
#include "imgui_impl_glfw.h"
@ -39,10 +40,10 @@
#include "nvh/cameramanipulator.hpp"
#include "nvh/fileoperations.hpp"
#include "nvpsystem.hpp"
#include "nvvkpp/appbase_vkpp.hpp"
#include "nvvkpp/commands_vkpp.hpp"
#include "nvvkpp/context_vkpp.hpp"
#include "nvvkpp/utilities_vkpp.hpp"
#include "nvvk/appbase_vkpp.hpp"
#include "nvvk/commands_vk.hpp"
#include "nvvk/context_vk.hpp"
//////////////////////////////////////////////////////////////////////////
#define UNUSED(x) (void)(x)
@ -97,12 +98,14 @@ int main(int argc, char** argv)
return 1;
}
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
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
if(!glfwVulkanSupported())
@ -127,7 +130,7 @@ int main(int argc, char** argv)
vk::PhysicalDeviceScalarBlockLayoutFeaturesEXT scalarFeature;
// Requesting Vulkan extensions and layers
nvvkpp::ContextCreateInfo contextInfo;
nvvk::ContextCreateInfo contextInfo;
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME);
#ifdef _WIN32
@ -144,7 +147,7 @@ int main(int argc, char** argv)
contextInfo.addDeviceExtension(VK_EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME, false, &scalarFeature);
// Creating Vulkan base application
nvvkpp::Context vkctx{};
nvvk::Context vkctx{};
vkctx.initInstance(contextInfo);
// Find all compatible devices
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);
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.createDepthBuffer();
helloVk.createRenderPass();
@ -206,7 +210,8 @@ int main(int argc, char** argv)
{
ImGui::ColorEdit3("Clear color", reinterpret_cast<float*>(&clearColor));
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();
}
@ -221,7 +226,8 @@ int main(int argc, char** argv)
// Clearing screen
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});
// Offscreen render pass
@ -266,8 +272,6 @@ int main(int argc, char** argv)
helloVk.getDevice().waitIdle();
helloVk.destroyResources();
helloVk.destroy();
vkctx.m_instance.destroySurfaceKHR(surface);
vkctx.deinit();
glfwDestroyWindow(window);

View file

@ -35,14 +35,14 @@ extern std::vector<std::string> defaultSearchPaths;
#include "obj_loader.h"
#include "hello_vulkan.h"
#include "nvh//cameramanipulator.hpp"
#include "nvvkpp/descriptorsets_vkpp.hpp"
#include "nvvkpp/pipeline_vkpp.hpp"
#include "nvh/cameramanipulator.hpp"
#include "nvh/fileoperations.hpp"
#include "nvvkpp/commands_vkpp.hpp"
#include "nvvkpp/renderpass_vkpp.hpp"
#include "nvvkpp/utilities_vkpp.hpp"
#include "nvvk/commands_vk.hpp"
#include "nvvk/descriptorsets_vk.hpp"
#include "nvvk/pipeline_vk.hpp"
#include "nvvk/renderpasses_vk.hpp"
#include "nvvk/shaders_vk.hpp"
// Holding the camera matrices
struct CameraMatrices
@ -58,11 +58,12 @@ struct CameraMatrices
// Keep the handle on the device
// 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,
uint32_t queueFamily)
{
AppBase::setup(device, physicalDevice, queueFamily);
AppBase::setup(instance, device, physicalDevice, queueFamily);
m_alloc.init(device, physicalDevice);
m_debug.setup(m_device);
}
@ -99,31 +100,31 @@ void HelloVulkan::createDescriptorSetLayout()
uint32_t nbObj = static_cast<uint32_t>(m_objModel.size());
// Camera matrices (binding = 0)
m_descSetLayoutBind.emplace_back(
m_descSetLayoutBind.addBinding(
vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR));
// Materials (binding = 1)
m_descSetLayoutBind.emplace_back(
m_descSetLayoutBind.addBinding(
vkDS(1, vkDT::eStorageBuffer, nbObj, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
// Scene description (binding = 2)
m_descSetLayoutBind.emplace_back( //
m_descSetLayoutBind.addBinding( //
vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
// Textures (binding = 3)
m_descSetLayoutBind.emplace_back(
m_descSetLayoutBind.addBinding(
vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR));
// Materials (binding = 4)
m_descSetLayoutBind.emplace_back(
m_descSetLayoutBind.addBinding(
vkDS(4, vkDT::eStorageBuffer, nbObj, vkSS::eFragment | vkSS::eClosestHitKHR));
// Storing vertices (binding = 5)
m_descSetLayoutBind.emplace_back( //
m_descSetLayoutBind.addBinding( //
vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
// Storing indices (binding = 6)
m_descSetLayoutBind.emplace_back( //
m_descSetLayoutBind.addBinding( //
vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
m_descSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_descSetLayoutBind);
m_descPool = nvvkpp::util::createDescriptorPool(m_device, m_descSetLayoutBind, 1);
m_descSet = nvvkpp::util::createDescriptorSet(m_device, m_descPool, m_descSetLayout);
m_descSetLayout = m_descSetLayoutBind.createLayout(m_device);
m_descPool = m_descSetLayoutBind.createPool(m_device, 1);
m_descSet = nvvk::allocateDescriptorSet(m_device, m_descPool, m_descSetLayout);
}
//--------------------------------------------------------------------------------------------------
@ -135,27 +136,26 @@ void HelloVulkan::updateDescriptorSet()
// Camera matrices and scene description
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};
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
std::vector<vk::DescriptorBufferInfo> dbiMat;
std::vector<vk::DescriptorBufferInfo> dbiMatIdx;
std::vector<vk::DescriptorBufferInfo> dbiVert;
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);
dbiMatIdx.emplace_back(obj.matIndexBuffer.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);
dbiMat.push_back({m_objModel[i].matColorBuffer.buffer, 0, VK_WHOLE_SIZE});
dbiMatIdx.push_back({m_objModel[i].matIndexBuffer.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});
}
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[1], dbiMat.data()));
writes.emplace_back(
nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[4], dbiMatIdx.data()));
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[5], dbiVert.data()));
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[6], dbiIdx.data()));
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 1, dbiMat.data()));
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 4, dbiMatIdx.data()));
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 5, dbiVert.data()));
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 6, dbiIdx.data()));
// All texture samplers
std::vector<vk::DescriptorImageInfo> diit;
@ -163,7 +163,7 @@ void HelloVulkan::updateDescriptorSet()
{
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
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
@ -190,18 +190,18 @@ void HelloVulkan::createGraphicsPipeline()
// Creating the Pipeline
std::vector<std::string> paths = defaultSearchPaths;
nvvkpp::GraphicsPipelineGenerator gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
gpb.depthStencilState = {true};
nvvk::GraphicsPipelineGeneratorCombined gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
gpb.depthStencilState.depthTestEnable = true;
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.vertexInputState.bindingDescriptions = {{0, sizeof(VertexObj)}};
gpb.vertexInputState.attributeDescriptions = {
gpb.addBindingDescription({0, sizeof(VertexObj)});
gpb.addAttributeDescriptions(std::vector<vk::VertexInputAttributeDescription>{
{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
{1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)},
{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");
}
@ -234,7 +234,7 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
// 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();
model.vertexBuffer =
m_alloc.createBuffer(cmdBuf, loader.m_vertices,
@ -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);
// Creates all textures found
createTextureImages(cmdBuf, loader.m_textures);
cmdBufGet.flushCommandBuffer(cmdBuf);
m_alloc.flushStaging();
cmdBufGet.submitAndWait(cmdBuf);
m_alloc.finalizeAndReleaseStaging();
std::string objNb = std::to_string(instance.objIndex);
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
@ -282,12 +282,12 @@ void HelloVulkan::createUniformBuffer()
void HelloVulkan::createSceneDescriptionBuffer()
{
using vkBU = vk::BufferUsageFlagBits;
nvvkpp::SingleCommandBuffer cmdGen(m_device, m_graphicsQueueIndex);
nvvk::CommandPool cmdGen(m_device, m_graphicsQueueIndex);
auto cmdBuf = cmdGen.createCommandBuffer();
m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer);
cmdGen.flushCommandBuffer(cmdBuf);
m_alloc.flushStaging();
cmdGen.submitAndWait(cmdBuf);
m_alloc.finalizeAndReleaseStaging();
m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc");
}
@ -307,20 +307,20 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
// If no textures are present, create a dummy one to accommodate the pipeline layout
if(textures.empty() && m_textures.empty())
{
nvvkTexture texture;
nvvk::Texture texture;
std::array<uint8_t, 4> color{255u, 255u, 255u, 255u};
vk::DeviceSize bufferSize = sizeof(color);
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
nvvkpp::image::setImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined,
nvvk::cmdBarrierImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eShaderReadOnlyOptimal);
m_textures.push_back(texture);
}
@ -348,16 +348,16 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4;
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;
texture = m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo);
nvvk::ImageDedicated image =
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);
}
}
@ -434,7 +434,7 @@ void HelloVulkan::rasterize(const vk::CommandBuffer& cmdBuf)
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.drawIndexed(model.nbIndices, 1, 0, 0, 0);
}
@ -464,49 +464,54 @@ void HelloVulkan::createOffscreenRender()
m_alloc.destroy(m_offscreenDepth);
// Creating the color image
auto colorCreateInfo = nvvkpp::image::create2DInfo(m_size, m_offscreenColorFormat,
{
auto colorCreateInfo = nvvk::makeImage2DCreateInfo(m_size, m_offscreenColorFormat,
vk::ImageUsageFlagBits::eColorAttachment
| vk::ImageUsageFlagBits::eSampled
| vk::ImageUsageFlagBits::eStorage);
m_offscreenColor = m_alloc.createImage(colorCreateInfo);
m_offscreenColor.descriptor =
nvvkpp::image::create2DDescriptor(m_device, m_offscreenColor.image, vk::SamplerCreateInfo{},
m_offscreenColorFormat, vk::ImageLayout::eGeneral);
nvvk::Image image = m_alloc.createImage(colorCreateInfo);
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
auto depthCreateInfo =
nvvkpp::image::create2DInfo(m_size, m_offscreenDepthFormat,
nvvk::makeImage2DCreateInfo(m_size, m_offscreenDepthFormat,
vk::ImageUsageFlagBits::eDepthStencilAttachment);
m_offscreenDepth = m_alloc.createImage(depthCreateInfo);
{
nvvk::Image image = m_alloc.createImage(depthCreateInfo);
vk::ImageViewCreateInfo depthStencilView;
depthStencilView.setViewType(vk::ImageViewType::e2D);
depthStencilView.setFormat(m_offscreenDepthFormat);
depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1});
depthStencilView.setImage(m_offscreenDepth.image);
m_offscreenDepth.descriptor.imageView = m_device.createImageView(depthStencilView);
depthStencilView.setImage(image.image);
m_offscreenDepth = m_alloc.createTexture(image, depthStencilView);
}
// 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();
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined,
nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eGeneral);
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageAspectFlagBits::eDepth,
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
if(!m_offscreenRenderPass)
{
m_offscreenRenderPass =
nvvkpp::util::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat,
1, 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
@ -543,13 +548,14 @@ void HelloVulkan::createPostPipeline()
// Pipeline: completely generic, no vertices
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),
vk::ShaderStageFlagBits::eVertex);
pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths),
vk::ShaderStageFlagBits::eFragment);
pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone);
m_postPipeline = pipelineGenerator.create();
m_postPipeline = pipelineGenerator.createPipeline();
m_debug.setObjectName(m_postPipeline, "post");
}
@ -563,10 +569,10 @@ void HelloVulkan::createPostDescriptor()
using vkDT = vk::DescriptorType;
using vkSS = vk::ShaderStageFlagBits;
m_postDescSetLayoutBind.emplace_back(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
m_postDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_postDescSetLayoutBind);
m_postDescPool = nvvkpp::util::createDescriptorPool(m_device, m_postDescSetLayoutBind);
m_postDescSet = nvvkpp::util::createDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
m_postDescSetLayoutBind.addBinding(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
m_postDescSetLayout = m_postDescSetLayoutBind.createLayout(m_device);
m_postDescPool = m_postDescSetLayoutBind.createPool(m_device);
m_postDescSet = nvvk::allocateDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
}
//--------------------------------------------------------------------------------------------------
@ -575,8 +581,7 @@ void HelloVulkan::createPostDescriptor()
void HelloVulkan::updatePostDescriptorSet()
{
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);
}
@ -614,13 +619,13 @@ void HelloVulkan::initRayTracing()
auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2,
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
//
nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model)
nvvk::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model)
{
// Setting up the creation info of acceleration structure
vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate;
@ -657,7 +662,7 @@ nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjM
offset.setTransformOffset(0);
// 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.asCreateGeometryInfo.emplace_back(asCreate);
blas.asBuildOffsetInfo.emplace_back(offset);
@ -671,7 +676,7 @@ nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjM
void HelloVulkan::createBottomLevelAS()
{
// BLAS - Storing each primitive in a geometry
std::vector<nvvkpp::RaytracingBuilderKHR::Blas> allBlas;
std::vector<nvvk::RaytracingBuilderKHR::Blas> allBlas;
allBlas.reserve(m_objModel.size());
for(const auto& obj : m_objModel)
{
@ -685,16 +690,16 @@ void HelloVulkan::createBottomLevelAS()
void HelloVulkan::createTopLevelAS()
{
std::vector<nvvkpp::RaytracingBuilderKHR::Instance> tlas;
std::vector<nvvk::RaytracingBuilderKHR::Instance> tlas;
tlas.reserve(m_objInstance.size());
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.instanceId = i; // gl_InstanceID
rayInst.blasId = m_objInstance[i].objIndex;
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);
}
m_rtBuilder.buildTlas(tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace);
@ -709,25 +714,25 @@ void HelloVulkan::createRtDescriptorSet()
using vkSS = vk::ShaderStageFlagBits;
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
m_rtDescSetLayoutBind.emplace_back(
m_rtDescSetLayoutBind.addBinding(
vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image
m_rtDescPool = nvvkpp::util::createDescriptorPool(m_device, m_rtDescSetLayoutBind);
m_rtDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_rtDescSetLayoutBind);
m_rtDescPool = m_rtDescSetLayoutBind.createPool(m_device);
m_rtDescSetLayout = m_rtDescSetLayoutBind.createLayout(m_device);
m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0];
vk::AccelerationStructureKHR tlas = m_rtBuilder.getAccelerationStructure();
vk::WriteDescriptorSetAccelerationStructureKHR descASInfo;
descASInfo.setAccelerationStructureCount(1);
descASInfo.setPAccelerationStructures(&m_rtBuilder.getAccelerationStructure());
descASInfo.setPAccelerationStructures(&tlas);
vk::DescriptorImageInfo imageInfo{
{}, m_offscreenColor.descriptor.imageView, vk::ImageLayout::eGeneral};
std::vector<vk::WriteDescriptorSet> writes;
writes.emplace_back(
nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[0], &descASInfo));
writes.emplace_back(nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[1], &imageInfo));
writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 0, &descASInfo));
writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 1, &imageInfo));
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;
vk::ShaderModule raygenSM =
nvvkpp::util::createShaderModule(m_device, //
nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rgen.spv", true, paths));
vk::ShaderModule missSM =
nvvkpp::util::createShaderModule(m_device, //
nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths));
// The second miss shader is invoked when a shadow ray misses the geometry. It
// simply indicates that no occlusion has been found
vk::ShaderModule shadowmissSM = nvvkpp::util::createShaderModule(
m_device, nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
vk::ShaderModule shadowmissSM =
nvvk::createShaderModule(m_device,
nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
std::vector<vk::PipelineShaderStageCreateInfo> stages;
@ -791,7 +797,7 @@ void HelloVulkan::createRtPipeline()
// Hit Group - Closest Hit + AnyHit
vk::ShaderModule chitSM =
nvvkpp::util::createShaderModule(m_device, //
nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rchit.spv", true, paths));
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup,
@ -857,7 +863,7 @@ void HelloVulkan::createRtShaderBindingTable()
m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize,
shaderHandleStorage.data());
// 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();
m_rtSBTBuffer =
@ -865,9 +871,9 @@ void HelloVulkan::createRtShaderBindingTable()
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.
*/
#pragma once
#include <vulkan/vulkan.hpp>
#include "nvvkpp/allocator_dedicated_vkpp.hpp"
#include "nvvkpp/appbase_vkpp.hpp"
#include "nvvkpp/debug_util_vkpp.hpp"
#define NVVK_ALLOC_DEDICATED
#include "nvvk/allocator_vk.hpp"
#include "nvvk/appbase_vkpp.hpp"
#include "nvvk/debug_util_vk.hpp"
#include "nvvk/descriptorsets_vk.hpp"
// #VKRay
#define ALLOC_DEDICATED
#include "nvvkpp/raytraceKHR_vkpp.hpp"
using nvvkBuffer = nvvkpp::BufferDedicated;
using nvvkTexture = nvvkpp::TextureDedicated;
#include "nvvk/raytraceKHR_vk.hpp"
//--------------------------------------------------------------------------------------------------
// Simple rasterizer of OBJ objects
@ -44,10 +43,11 @@ using nvvkTexture = nvvkpp::TextureDedicated;
// - Rendering is done in an offscreen framebuffer
// - 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:
void setup(const vk::Device& device,
void setup(const vk::Instance& instance,
const vk::Device& device,
const vk::PhysicalDevice& physicalDevice,
uint32_t queueFamily) override;
void createDescriptorSetLayout();
@ -68,10 +68,10 @@ public:
{
uint32_t nbIndices{0};
uint32_t nbVertices{0};
nvvkBuffer vertexBuffer; // Device buffer of all 'Vertex'
nvvkBuffer indexBuffer; // Device buffer of the indices forming triangles
nvvkBuffer matColorBuffer; // Device buffer of array of 'Wavefront material'
nvvkBuffer matIndexBuffer; // Device buffer of array of 'Wavefront material'
nvvk::Buffer vertexBuffer; // Device buffer of all 'Vertex'
nvvk::Buffer indexBuffer; // Device buffer of the indices forming triangles
nvvk::Buffer matColorBuffer; // Device buffer of array of 'Wavefront material'
nvvk::Buffer matIndexBuffer; // Device buffer of array of 'Wavefront material'
};
// Instance of the OBJ
@ -100,17 +100,17 @@ public:
// Graphic pipeline
vk::PipelineLayout m_pipelineLayout;
vk::Pipeline m_graphicsPipeline;
std::vector<vk::DescriptorSetLayoutBinding> m_descSetLayoutBind;
nvvk::DescriptorSetBindings m_descSetLayoutBind;
vk::DescriptorPool m_descPool;
vk::DescriptorSetLayout m_descSetLayout;
vk::DescriptorSet m_descSet;
nvvkBuffer m_cameraMat; // Device-Host of the camera matrices
nvvkBuffer m_sceneDesc; // Device buffer of the OBJ instances
std::vector<nvvkTexture> m_textures; // vector of all textures of the scene
nvvk::Buffer m_cameraMat; // Device-Host of the camera matrices
nvvk::Buffer m_sceneDesc; // Device buffer of the OBJ instances
std::vector<nvvk::Texture> m_textures; // vector of all textures of the scene
nvvkpp::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures
nvvkpp::DebugUtil m_debug; // Utility to name objects
nvvk::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures
nvvk::DebugUtil m_debug; // Utility to name objects
// #Post
void createOffscreenRender();
@ -119,7 +119,7 @@ public:
void updatePostDescriptorSet();
void drawPost(vk::CommandBuffer cmdBuf);
std::vector<vk::DescriptorSetLayoutBinding> m_postDescSetLayoutBind;
nvvk::DescriptorSetBindings m_postDescSetLayoutBind;
vk::DescriptorPool m_postDescPool;
vk::DescriptorSetLayout m_postDescSetLayout;
vk::DescriptorSet m_postDescSet;
@ -127,14 +127,14 @@ public:
vk::PipelineLayout m_postPipelineLayout;
vk::RenderPass m_offscreenRenderPass;
vk::Framebuffer m_offscreenFramebuffer;
nvvkTexture m_offscreenColor;
nvvk::Texture m_offscreenColor;
vk::Format m_offscreenColorFormat{vk::Format::eR32G32B32A32Sfloat};
nvvkTexture m_offscreenDepth;
nvvk::Texture m_offscreenDepth;
vk::Format m_offscreenDepthFormat{vk::Format::eD32Sfloat};
// #VKRay
void initRayTracing();
nvvkpp::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
nvvk::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
void createBottomLevelAS();
void createTopLevelAS();
void createRtDescriptorSet();
@ -145,15 +145,15 @@ public:
vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties;
nvvkpp::RaytracingBuilderKHR m_rtBuilder;
std::vector<vk::DescriptorSetLayoutBinding> m_rtDescSetLayoutBind;
nvvk::RaytracingBuilderKHR m_rtBuilder;
nvvk::DescriptorSetBindings m_rtDescSetLayoutBind;
vk::DescriptorPool m_rtDescPool;
vk::DescriptorSetLayout m_rtDescSetLayout;
vk::DescriptorSet m_rtDescSet;
std::vector<vk::RayTracingShaderGroupCreateInfoKHR> m_rtShaderGroups;
vk::PipelineLayout m_rtPipelineLayout;
vk::Pipeline m_rtPipeline;
nvvkBuffer m_rtSBTBuffer;
nvvk::Buffer m_rtSBTBuffer;
struct RtPushConstant
{

View file

@ -30,8 +30,8 @@
// at the top of imgui.cpp.
#include <array>
#include <vulkan/vulkan.hpp>
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
#include "imgui.h"
#include "imgui_impl_glfw.h"
@ -40,10 +40,10 @@
#include "nvh/cameramanipulator.hpp"
#include "nvh/fileoperations.hpp"
#include "nvpsystem.hpp"
#include "nvvkpp/appbase_vkpp.hpp"
#include "nvvkpp/commands_vkpp.hpp"
#include "nvvkpp/context_vkpp.hpp"
#include "nvvkpp/utilities_vkpp.hpp"
#include "nvvk/appbase_vkpp.hpp"
#include "nvvk/commands_vk.hpp"
#include "nvvk/context_vk.hpp"
//////////////////////////////////////////////////////////////////////////
#define UNUSED(x) (void)(x)
@ -125,7 +125,7 @@ int main(int argc, char** argv)
vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature;
// Requesting Vulkan extensions and layers
nvvkpp::ContextCreateInfo contextInfo(true);
nvvk::ContextCreateInfo contextInfo(true);
contextInfo.setVersion(1, 2);
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME);
@ -148,7 +148,7 @@ int main(int argc, char** argv)
// Creating Vulkan base application
nvvkpp::Context vkctx{};
nvvk::Context vkctx{};
vkctx.initInstance(contextInfo);
// Find all compatible devices
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);
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.createDepthBuffer();
helloVk.createRenderPass();
@ -174,8 +175,8 @@ int main(int argc, char** argv)
helloVk.initGUI(0); // Using sub-pass 0
// 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/plane.obj", defaultSearchPaths));
helloVk.createOffscreenRender();
@ -242,7 +243,8 @@ int main(int argc, char** argv)
// Clearing screen
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});
// Offscreen render pass
@ -294,7 +296,6 @@ int main(int argc, char** argv)
helloVk.destroyResources();
helloVk.destroy();
vkctx.m_instance.destroySurfaceKHR(surface);
vkctx.deinit();
glfwDestroyWindow(window);

View file

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

View file

@ -36,13 +36,14 @@ extern std::vector<std::string> defaultSearchPaths;
#include "hello_vulkan.h"
#include "nvh//cameramanipulator.hpp"
#include "nvvkpp/descriptorsets_vkpp.hpp"
#include "nvvkpp/pipeline_vkpp.hpp"
#include "nvvk/descriptorsets_vk.hpp"
#include "nvvk/pipeline_vk.hpp"
#include "nvh/fileoperations.hpp"
#include "nvvkpp/commands_vkpp.hpp"
#include "nvvkpp/renderpass_vkpp.hpp"
#include "nvvkpp/utilities_vkpp.hpp"
#include "nvvk/commands_vk.hpp"
#include "nvvk/renderpasses_vk.hpp"
#include "nvvk/shaders_vk.hpp"
// Holding the camera matrices
struct CameraMatrices
@ -58,11 +59,12 @@ struct CameraMatrices
// Keep the handle on the device
// 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,
uint32_t queueFamily)
{
AppBase::setup(device, physicalDevice, queueFamily);
AppBase::setup(instance, device, physicalDevice, queueFamily);
m_alloc.init(device, physicalDevice);
m_debug.setup(m_device);
}
@ -99,31 +101,31 @@ void HelloVulkan::createDescriptorSetLayout()
uint32_t nbObj = static_cast<uint32_t>(m_objModel.size());
// Camera matrices (binding = 0)
m_descSetLayoutBind.emplace_back(
m_descSetLayoutBind.addBinding(
vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR));
// Materials (binding = 1)
m_descSetLayoutBind.emplace_back(
m_descSetLayoutBind.addBinding(
vkDS(1, vkDT::eStorageBuffer, nbObj, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
// Scene description (binding = 2)
m_descSetLayoutBind.emplace_back( //
m_descSetLayoutBind.addBinding( //
vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
// Textures (binding = 3)
m_descSetLayoutBind.emplace_back(
m_descSetLayoutBind.addBinding(
vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR));
// Materials (binding = 4)
m_descSetLayoutBind.emplace_back(
m_descSetLayoutBind.addBinding(
vkDS(4, vkDT::eStorageBuffer, nbObj, vkSS::eFragment | vkSS::eClosestHitKHR));
// Storing vertices (binding = 5)
m_descSetLayoutBind.emplace_back( //
m_descSetLayoutBind.addBinding( //
vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
// Storing indices (binding = 6)
m_descSetLayoutBind.emplace_back( //
m_descSetLayoutBind.addBinding( //
vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
m_descSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_descSetLayoutBind);
m_descPool = nvvkpp::util::createDescriptorPool(m_device, m_descSetLayoutBind, 1);
m_descSet = nvvkpp::util::createDescriptorSet(m_device, m_descPool, m_descSetLayout);
m_descSetLayout = m_descSetLayoutBind.createLayout(m_device);
m_descPool = m_descSetLayoutBind.createPool(m_device, 1);
m_descSet = nvvk::allocateDescriptorSet(m_device, m_descPool, m_descSetLayout);
}
//--------------------------------------------------------------------------------------------------
@ -135,9 +137,9 @@ void HelloVulkan::updateDescriptorSet()
// Camera matrices and scene description
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};
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
std::vector<vk::DescriptorBufferInfo> dbiMat;
@ -151,11 +153,10 @@ void HelloVulkan::updateDescriptorSet()
dbiVert.emplace_back(obj.vertexBuffer.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(
nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[4], dbiMatIdx.data()));
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[5], dbiVert.data()));
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[6], dbiIdx.data()));
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 1, dbiMat.data()));
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 4, dbiMatIdx.data()));
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 5, dbiVert.data()));
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 6, dbiIdx.data()));
// All texture samplers
std::vector<vk::DescriptorImageInfo> diit;
@ -163,7 +164,7 @@ void HelloVulkan::updateDescriptorSet()
{
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
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
@ -190,18 +191,17 @@ void HelloVulkan::createGraphicsPipeline()
// Creating the Pipeline
std::vector<std::string> paths = defaultSearchPaths;
nvvkpp::GraphicsPipelineGenerator gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
gpb.depthStencilState = {true};
nvvk::GraphicsPipelineGeneratorCombined gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
gpb.depthStencilState.depthTestEnable = true;
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.vertexInputState.bindingDescriptions = {{0, sizeof(VertexObj)}};
gpb.vertexInputState.attributeDescriptions = {
{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
gpb.addBindingDescription({0, sizeof(VertexObj)});
gpb.addAttributeDescriptions({{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
{1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)},
{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");
}
@ -234,7 +234,7 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
// 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();
model.vertexBuffer =
m_alloc.createBuffer(cmdBuf, loader.m_vertices,
@ -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);
// Creates all textures found
createTextureImages(cmdBuf, loader.m_textures);
cmdBufGet.flushCommandBuffer(cmdBuf);
m_alloc.flushStaging();
cmdBufGet.submitAndWait(cmdBuf);
m_alloc.finalizeAndReleaseStaging();
std::string objNb = std::to_string(instance.objIndex);
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
@ -282,12 +282,12 @@ void HelloVulkan::createUniformBuffer()
void HelloVulkan::createSceneDescriptionBuffer()
{
using vkBU = vk::BufferUsageFlagBits;
nvvkpp::SingleCommandBuffer cmdGen(m_device, m_graphicsQueueIndex);
nvvk::CommandPool cmdGen(m_device, m_graphicsQueueIndex);
auto cmdBuf = cmdGen.createCommandBuffer();
m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer);
cmdGen.flushCommandBuffer(cmdBuf);
m_alloc.flushStaging();
cmdGen.submitAndWait(cmdBuf);
m_alloc.finalizeAndReleaseStaging();
m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc");
}
@ -307,20 +307,20 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
// If no textures are present, create a dummy one to accommodate the pipeline layout
if(textures.empty() && m_textures.empty())
{
nvvkTexture texture;
nvvk::Texture texture;
std::array<uint8_t, 4> color{255u, 255u, 255u, 255u};
vk::DeviceSize bufferSize = sizeof(color);
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
nvvkpp::image::setImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined,
nvvk::cmdBarrierImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eShaderReadOnlyOptimal);
m_textures.push_back(texture);
}
@ -348,16 +348,16 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4;
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;
texture = m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo);
nvvk::ImageDedicated image =
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);
}
}
@ -441,7 +441,7 @@ void HelloVulkan::rasterize(const vk::CommandBuffer& cmdBuf)
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.drawIndexed(model.nbIndices, 1, 0, 0, 0);
}
@ -471,49 +471,54 @@ void HelloVulkan::createOffscreenRender()
m_alloc.destroy(m_offscreenDepth);
// Creating the color image
auto colorCreateInfo = nvvkpp::image::create2DInfo(m_size, m_offscreenColorFormat,
{
auto colorCreateInfo = nvvk::makeImage2DCreateInfo(m_size, m_offscreenColorFormat,
vk::ImageUsageFlagBits::eColorAttachment
| vk::ImageUsageFlagBits::eSampled
| vk::ImageUsageFlagBits::eStorage);
m_offscreenColor = m_alloc.createImage(colorCreateInfo);
m_offscreenColor.descriptor =
nvvkpp::image::create2DDescriptor(m_device, m_offscreenColor.image, vk::SamplerCreateInfo{},
m_offscreenColorFormat, vk::ImageLayout::eGeneral);
nvvk::ImageDedicated image = m_alloc.createImage(colorCreateInfo);
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
auto depthCreateInfo =
nvvkpp::image::create2DInfo(m_size, m_offscreenDepthFormat,
nvvk::makeImage2DCreateInfo(m_size, m_offscreenDepthFormat,
vk::ImageUsageFlagBits::eDepthStencilAttachment);
m_offscreenDepth = m_alloc.createImage(depthCreateInfo);
{
nvvk::Image image = m_alloc.createImage(depthCreateInfo);
vk::ImageViewCreateInfo depthStencilView;
depthStencilView.setViewType(vk::ImageViewType::e2D);
depthStencilView.setFormat(m_offscreenDepthFormat);
depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1});
depthStencilView.setImage(m_offscreenDepth.image);
m_offscreenDepth.descriptor.imageView = m_device.createImageView(depthStencilView);
depthStencilView.setImage(image.image);
m_offscreenDepth = m_alloc.createTexture(image, depthStencilView);
}
// 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();
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined,
nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eGeneral);
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageAspectFlagBits::eDepth,
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
if(!m_offscreenRenderPass)
{
m_offscreenRenderPass =
nvvkpp::util::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat,
1, 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
@ -550,13 +555,14 @@ void HelloVulkan::createPostPipeline()
// Pipeline: completely generic, no vertices
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),
vk::ShaderStageFlagBits::eVertex);
pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths),
vk::ShaderStageFlagBits::eFragment);
pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone);
m_postPipeline = pipelineGenerator.create();
m_postPipeline = pipelineGenerator.createPipeline();
m_debug.setObjectName(m_postPipeline, "post");
}
@ -570,10 +576,10 @@ void HelloVulkan::createPostDescriptor()
using vkDT = vk::DescriptorType;
using vkSS = vk::ShaderStageFlagBits;
m_postDescSetLayoutBind.emplace_back(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
m_postDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_postDescSetLayoutBind);
m_postDescPool = nvvkpp::util::createDescriptorPool(m_device, m_postDescSetLayoutBind);
m_postDescSet = nvvkpp::util::createDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
m_postDescSetLayoutBind.addBinding(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
m_postDescSetLayout = m_postDescSetLayoutBind.createLayout(m_device);
m_postDescPool = m_postDescSetLayoutBind.createPool(m_device);
m_postDescSet = nvvk::allocateDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
}
//--------------------------------------------------------------------------------------------------
@ -582,8 +588,7 @@ void HelloVulkan::createPostDescriptor()
void HelloVulkan::updatePostDescriptorSet()
{
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);
}
@ -621,13 +626,13 @@ void HelloVulkan::initRayTracing()
auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2,
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
//
nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model)
nvvk::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model)
{
vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate;
asCreate.setGeometryType(vk::GeometryTypeKHR::eTriangles);
@ -658,7 +663,7 @@ nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjM
offset.setPrimitiveOffset(0);
offset.setTransformOffset(0);
nvvkpp::RaytracingBuilderKHR::Blas blas;
nvvk::RaytracingBuilderKHR::Blas blas;
blas.asGeometry.emplace_back(asGeom);
blas.asCreateGeometryInfo.emplace_back(asCreate);
blas.asBuildOffsetInfo.emplace_back(offset);
@ -685,12 +690,12 @@ void HelloVulkan::createTopLevelAS()
m_tlas.reserve(m_objInstance.size());
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.instanceId = i; // gl_InstanceID
rayInst.blasId = m_objInstance[i].objIndex;
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_rtBuilder.buildTlas(m_tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace
@ -706,25 +711,25 @@ void HelloVulkan::createRtDescriptorSet()
using vkSS = vk::ShaderStageFlagBits;
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
m_rtDescSetLayoutBind.emplace_back(
m_rtDescSetLayoutBind.addBinding(
vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image
m_rtDescPool = nvvkpp::util::createDescriptorPool(m_device, m_rtDescSetLayoutBind);
m_rtDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_rtDescSetLayoutBind);
m_rtDescPool = m_rtDescSetLayoutBind.createPool(m_device);
m_rtDescSetLayout = m_rtDescSetLayoutBind.createLayout(m_device);
m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0];
vk::AccelerationStructureKHR tlas = m_rtBuilder.getAccelerationStructure();
vk::WriteDescriptorSetAccelerationStructureKHR descASInfo;
descASInfo.setAccelerationStructureCount(1);
descASInfo.setPAccelerationStructures(&m_rtBuilder.getAccelerationStructure());
descASInfo.setPAccelerationStructures(&tlas);
vk::DescriptorImageInfo imageInfo{
{}, m_offscreenColor.descriptor.imageView, vk::ImageLayout::eGeneral};
std::vector<vk::WriteDescriptorSet> writes;
writes.emplace_back(
nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[0], &descASInfo));
writes.emplace_back(nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[1], &imageInfo));
writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 0, &descASInfo));
writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 1, &imageInfo));
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;
vk::ShaderModule raygenSM =
nvvkpp::util::createShaderModule(m_device, //
nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rgen.spv", true, paths));
vk::ShaderModule missSM =
nvvkpp::util::createShaderModule(m_device, //
nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths));
// The second miss shader is invoked when a shadow ray misses the geometry. It
// simply indicates that no occlusion has been found
vk::ShaderModule shadowmissSM = nvvkpp::util::createShaderModule(
m_device, nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
vk::ShaderModule shadowmissSM =
nvvk::createShaderModule(m_device,
nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
std::vector<vk::PipelineShaderStageCreateInfo> stages;
@ -788,7 +794,7 @@ void HelloVulkan::createRtPipeline()
// Hit Group - Closest Hit + AnyHit
vk::ShaderModule chitSM =
nvvkpp::util::createShaderModule(m_device, //
nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rchit.spv", true, paths));
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup,
@ -853,7 +859,7 @@ void HelloVulkan::createRtShaderBindingTable()
m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize,
shaderHandleStorage.data());
// 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();
m_rtSBTBuffer =
@ -861,9 +867,9 @@ void HelloVulkan::createRtShaderBindingTable()
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);
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;
}
// Update the buffer
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);
// Copy data to staging buffer
auto* gInst = m_alloc.map(stagingBuffer);
memcpy(gInst, m_objInstance.data(), bufferSize);
m_alloc.unmap(stagingBuffer);
// 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();
cmdBuf.copyBuffer(stagingBuffer.buffer, m_sceneDesc.buffer, vk::BufferCopy(0, 0, bufferSize));
m_debug.endLabel(cmdBuf);
genCmdBuf.flushCommandBuffer(cmdBuf);
genCmdBuf.submitAndWait(cmdBuf);
m_alloc.destroy(stagingBuffer);
m_rtBuilder.updateTlasMatrices(m_tlas);
@ -957,7 +963,7 @@ void HelloVulkan::animationObject(float time)
updateCompDescriptors(model.vertexBuffer);
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex);
nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
vk::CommandBuffer cmdBuf = genCmdBuf.createCommandBuffer();
cmdBuf.bindPipeline(vk::PipelineBindPoint::eCompute, m_compPipeline);
@ -966,27 +972,26 @@ void HelloVulkan::animationObject(float time)
cmdBuf.pushConstants(m_compPipelineLayout, vk::ShaderStageFlagBits::eCompute, 0, sizeof(float),
&time);
cmdBuf.dispatch(model.nbVertices, 1, 1);
genCmdBuf.flushCommandBuffer(cmdBuf);
genCmdBuf.submitAndWait(cmdBuf);
}
//////////////////////////////////////////////////////////////////////////
// #VK_compute
void HelloVulkan::createCompDescriptors()
{
m_compDescSetLayoutBind.emplace_back(vk::DescriptorSetLayoutBinding(
m_compDescSetLayoutBind.addBinding(vk::DescriptorSetLayoutBinding(
0, vk::DescriptorType::eStorageBuffer, 1, vk::ShaderStageFlagBits::eCompute));
m_compDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_compDescSetLayoutBind);
m_compDescPool = nvvkpp::util::createDescriptorPool(m_device, m_compDescSetLayoutBind, 1);
m_compDescSet = nvvkpp::util::createDescriptorSet(m_device, m_compDescPool, m_compDescSetLayout);
m_compDescSetLayout = m_compDescSetLayoutBind.createLayout(m_device);
m_compDescPool = m_compDescSetLayoutBind.createPool(m_device, 1);
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;
vk::DescriptorBufferInfo dbiUnif{vertex.buffer, 0, VK_WHOLE_SIZE};
writes.emplace_back(
nvvkpp::util::createWrite(m_compDescSet, m_compDescSetLayoutBind[0], &dbiUnif));
writes.emplace_back(m_compDescSetLayoutBind.makeWrite(m_compDescSet, 0, &dbiUnif));
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};
computePipelineCreateInfo.stage =
nvvkpp::util::loadShader(m_device,
nvvk::createShaderStageInfo(m_device,
nvh::loadFile("shaders/anim.comp.spv", true, defaultSearchPaths),
vk::ShaderStageFlagBits::eCompute);
VK_SHADER_STAGE_COMPUTE_BIT);
m_compPipeline = m_device.createComputePipeline({}, computePipelineCreateInfo, nullptr);
m_device.destroy(computePipelineCreateInfo.stage.module);
}

View file

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

View file

@ -39,10 +39,12 @@
#include "nvh/cameramanipulator.hpp"
#include "nvh/fileoperations.hpp"
#include "nvpsystem.hpp"
#include "nvvkpp/appbase_vkpp.hpp"
#include "nvvkpp/commands_vkpp.hpp"
#include "nvvkpp/context_vkpp.hpp"
#include "nvvkpp/utilities_vkpp.hpp"
#include "nvvk/appbase_vkpp.hpp"
#include "nvvk/commands_vk.hpp"
#include "nvvk/context_vk.hpp"
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
//////////////////////////////////////////////////////////////////////////
#define UNUSED(x) (void)(x)
@ -124,7 +126,7 @@ int main(int argc, char** argv)
vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature;
// Requesting Vulkan extensions and layers
nvvkpp::ContextCreateInfo contextInfo(true);
nvvk::ContextCreateInfo contextInfo(true);
contextInfo.setVersion(1, 2);
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
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);
// Creating Vulkan base application
nvvkpp::Context vkctx{};
nvvk::Context vkctx{};
vkctx.initInstance(contextInfo);
// Find all compatible devices
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);
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.createDepthBuffer();
helloVk.createRenderPass();
@ -256,7 +259,8 @@ int main(int argc, char** argv)
// Clearing screen
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});
// Offscreen render pass
@ -308,7 +312,6 @@ int main(int argc, char** argv)
helloVk.destroyResources();
helloVk.destroy();
vkctx.m_instance.destroySurfaceKHR(surface);
vkctx.deinit();
glfwDestroyWindow(window);

View file

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

View file

@ -36,13 +36,14 @@ extern std::vector<std::string> defaultSearchPaths;
#include "hello_vulkan.h"
#include "nvh//cameramanipulator.hpp"
#include "nvvkpp/descriptorsets_vkpp.hpp"
#include "nvvkpp/pipeline_vkpp.hpp"
#include "nvvk/descriptorsets_vk.hpp"
#include "nvvk/pipeline_vk.hpp"
#include "nvh/fileoperations.hpp"
#include "nvvkpp/commands_vkpp.hpp"
#include "nvvkpp/renderpass_vkpp.hpp"
#include "nvvkpp/utilities_vkpp.hpp"
#include "nvvk/commands_vk.hpp"
#include "nvvk/renderpasses_vk.hpp"
#include "nvvk/shaders_vk.hpp"
// Holding the camera matrices
struct CameraMatrices
@ -58,11 +59,12 @@ struct CameraMatrices
// Keep the handle on the device
// 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,
uint32_t queueFamily)
{
AppBase::setup(device, physicalDevice, queueFamily);
AppBase::setup(instance, device, physicalDevice, queueFamily);
m_alloc.init(device, physicalDevice);
m_debug.setup(m_device);
}
@ -99,34 +101,34 @@ void HelloVulkan::createDescriptorSetLayout()
uint32_t nbObj = static_cast<uint32_t>(m_objModel.size());
// Camera matrices (binding = 0)
m_descSetLayoutBind.emplace_back(
m_descSetLayoutBind.addBinding(
vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR));
// Materials (binding = 1)
m_descSetLayoutBind.emplace_back(
m_descSetLayoutBind.addBinding(
vkDS(1, vkDT::eStorageBuffer, nbObj,
vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR | vkSS::eAnyHitKHR));
// Scene description (binding = 2)
m_descSetLayoutBind.emplace_back( //
m_descSetLayoutBind.addBinding( //
vkDS(2, vkDT::eStorageBuffer, 1,
vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR | vkSS::eAnyHitKHR));
// Textures (binding = 3)
m_descSetLayoutBind.emplace_back(
m_descSetLayoutBind.addBinding(
vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR));
// Materials (binding = 4)
m_descSetLayoutBind.emplace_back( //
m_descSetLayoutBind.addBinding( //
vkDS(4, vkDT::eStorageBuffer, nbObj,
vkSS::eFragment | vkSS::eClosestHitKHR | vkSS::eAnyHitKHR));
// Storing vertices (binding = 5)
m_descSetLayoutBind.emplace_back( //
m_descSetLayoutBind.addBinding( //
vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR | vkSS::eAnyHitKHR));
// Storing indices (binding = 6)
m_descSetLayoutBind.emplace_back( //
m_descSetLayoutBind.addBinding( //
vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR | vkSS::eAnyHitKHR));
m_descSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_descSetLayoutBind);
m_descPool = nvvkpp::util::createDescriptorPool(m_device, m_descSetLayoutBind, 1);
m_descSet = nvvkpp::util::createDescriptorSet(m_device, m_descPool, m_descSetLayout);
m_descSetLayout = m_descSetLayoutBind.createLayout(m_device);
m_descPool = m_descSetLayoutBind.createPool(m_device, 1);
m_descSet = nvvk::allocateDescriptorSet(m_device, m_descPool, m_descSetLayout);
}
//--------------------------------------------------------------------------------------------------
@ -138,9 +140,9 @@ void HelloVulkan::updateDescriptorSet()
// Camera matrices and scene description
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};
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
std::vector<vk::DescriptorBufferInfo> dbiMat;
@ -154,11 +156,10 @@ void HelloVulkan::updateDescriptorSet()
dbiVert.emplace_back(obj.vertexBuffer.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(
nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[4], dbiMatIdx.data()));
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[5], dbiVert.data()));
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[6], dbiIdx.data()));
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 1, dbiMat.data()));
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 4, dbiMatIdx.data()));
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 5, dbiVert.data()));
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 6, dbiIdx.data()));
// All texture samplers
std::vector<vk::DescriptorImageInfo> diit;
@ -166,7 +167,7 @@ void HelloVulkan::updateDescriptorSet()
{
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
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
@ -193,18 +194,17 @@ void HelloVulkan::createGraphicsPipeline()
// Creating the Pipeline
std::vector<std::string> paths = defaultSearchPaths;
nvvkpp::GraphicsPipelineGenerator gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
gpb.depthStencilState = {true};
nvvk::GraphicsPipelineGeneratorCombined gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
gpb.depthStencilState.depthTestEnable = true;
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.vertexInputState.bindingDescriptions = {{0, sizeof(VertexObj)}};
gpb.vertexInputState.attributeDescriptions = {
{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
gpb.addBindingDescription({0, sizeof(VertexObj)});
gpb.addAttributeDescriptions({{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
{1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)},
{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");
}
@ -237,7 +237,7 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
// 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();
model.vertexBuffer =
m_alloc.createBuffer(cmdBuf, loader.m_vertices,
@ -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);
// Creates all textures found
createTextureImages(cmdBuf, loader.m_textures);
cmdBufGet.flushCommandBuffer(cmdBuf);
m_alloc.flushStaging();
cmdBufGet.submitAndWait(cmdBuf);
m_alloc.finalizeAndReleaseStaging();
std::string objNb = std::to_string(instance.objIndex);
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
@ -285,12 +285,12 @@ void HelloVulkan::createUniformBuffer()
void HelloVulkan::createSceneDescriptionBuffer()
{
using vkBU = vk::BufferUsageFlagBits;
nvvkpp::SingleCommandBuffer cmdGen(m_device, m_graphicsQueueIndex);
nvvk::CommandPool cmdGen(m_device, m_graphicsQueueIndex);
auto cmdBuf = cmdGen.createCommandBuffer();
m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer);
cmdGen.flushCommandBuffer(cmdBuf);
m_alloc.flushStaging();
cmdGen.submitAndWait(cmdBuf);
m_alloc.finalizeAndReleaseStaging();
m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc");
}
@ -310,20 +310,20 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
// If no textures are present, create a dummy one to accommodate the pipeline layout
if(textures.empty() && m_textures.empty())
{
nvvkTexture texture;
nvvk::Texture texture;
std::array<uint8_t, 4> color{255u, 255u, 255u, 255u};
vk::DeviceSize bufferSize = sizeof(color);
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
nvvkpp::image::setImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined,
nvvk::cmdBarrierImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eShaderReadOnlyOptimal);
m_textures.push_back(texture);
}
@ -351,16 +351,16 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4;
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;
texture = m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo);
nvvk::ImageDedicated image =
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);
}
}
@ -437,7 +437,7 @@ void HelloVulkan::rasterize(const vk::CommandBuffer& cmdBuf)
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.drawIndexed(model.nbIndices, 1, 0, 0, 0);
}
@ -467,49 +467,54 @@ void HelloVulkan::createOffscreenRender()
m_alloc.destroy(m_offscreenDepth);
// Creating the color image
auto colorCreateInfo = nvvkpp::image::create2DInfo(m_size, m_offscreenColorFormat,
{
auto colorCreateInfo = nvvk::makeImage2DCreateInfo(m_size, m_offscreenColorFormat,
vk::ImageUsageFlagBits::eColorAttachment
| vk::ImageUsageFlagBits::eSampled
| vk::ImageUsageFlagBits::eStorage);
m_offscreenColor = m_alloc.createImage(colorCreateInfo);
m_offscreenColor.descriptor =
nvvkpp::image::create2DDescriptor(m_device, m_offscreenColor.image, vk::SamplerCreateInfo{},
m_offscreenColorFormat, vk::ImageLayout::eGeneral);
nvvk::ImageDedicated image = m_alloc.createImage(colorCreateInfo);
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
auto depthCreateInfo =
nvvkpp::image::create2DInfo(m_size, m_offscreenDepthFormat,
nvvk::makeImage2DCreateInfo(m_size, m_offscreenDepthFormat,
vk::ImageUsageFlagBits::eDepthStencilAttachment);
m_offscreenDepth = m_alloc.createImage(depthCreateInfo);
{
nvvk::Image image = m_alloc.createImage(depthCreateInfo);
vk::ImageViewCreateInfo depthStencilView;
depthStencilView.setViewType(vk::ImageViewType::e2D);
depthStencilView.setFormat(m_offscreenDepthFormat);
depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1});
depthStencilView.setImage(m_offscreenDepth.image);
m_offscreenDepth.descriptor.imageView = m_device.createImageView(depthStencilView);
depthStencilView.setImage(image.image);
m_offscreenDepth = m_alloc.createTexture(image, depthStencilView);
}
// 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();
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined,
nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eGeneral);
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageAspectFlagBits::eDepth,
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
if(!m_offscreenRenderPass)
{
m_offscreenRenderPass =
nvvkpp::util::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat,
1, 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
@ -546,13 +551,14 @@ void HelloVulkan::createPostPipeline()
// Pipeline: completely generic, no vertices
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),
vk::ShaderStageFlagBits::eVertex);
pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths),
vk::ShaderStageFlagBits::eFragment);
pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone);
m_postPipeline = pipelineGenerator.create();
m_postPipeline = pipelineGenerator.createPipeline();
m_debug.setObjectName(m_postPipeline, "post");
}
@ -566,10 +572,10 @@ void HelloVulkan::createPostDescriptor()
using vkDT = vk::DescriptorType;
using vkSS = vk::ShaderStageFlagBits;
m_postDescSetLayoutBind.emplace_back(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
m_postDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_postDescSetLayoutBind);
m_postDescPool = nvvkpp::util::createDescriptorPool(m_device, m_postDescSetLayoutBind);
m_postDescSet = nvvkpp::util::createDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
m_postDescSetLayoutBind.addBinding(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
m_postDescSetLayout = m_postDescSetLayoutBind.createLayout(m_device);
m_postDescPool = m_postDescSetLayoutBind.createPool(m_device);
m_postDescSet = nvvk::allocateDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
}
//--------------------------------------------------------------------------------------------------
@ -578,8 +584,7 @@ void HelloVulkan::createPostDescriptor()
void HelloVulkan::updatePostDescriptorSet()
{
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);
}
@ -617,13 +622,13 @@ void HelloVulkan::initRayTracing()
auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2,
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
//
nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model)
nvvk::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model)
{
vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate;
asCreate.setGeometryType(vk::GeometryTypeKHR::eTriangles);
@ -655,7 +660,7 @@ nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjM
offset.setPrimitiveOffset(0);
offset.setTransformOffset(0);
nvvkpp::RaytracingBuilderKHR::Blas blas;
nvvk::RaytracingBuilderKHR::Blas blas;
blas.asGeometry.emplace_back(asGeom);
blas.asCreateGeometryInfo.emplace_back(asCreate);
blas.asBuildOffsetInfo.emplace_back(offset);
@ -665,7 +670,7 @@ nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjM
void HelloVulkan::createBottomLevelAS()
{
// BLAS - Storing each primitive in a geometry
std::vector<nvvkpp::RaytracingBuilderKHR::Blas> allBlas;
std::vector<nvvk::RaytracingBuilderKHR::Blas> allBlas;
allBlas.reserve(m_objModel.size());
for(const auto& obj : m_objModel)
{
@ -679,16 +684,16 @@ void HelloVulkan::createBottomLevelAS()
void HelloVulkan::createTopLevelAS()
{
std::vector<nvvkpp::RaytracingBuilderKHR::Instance> tlas;
std::vector<nvvk::RaytracingBuilderKHR::Instance> tlas;
tlas.reserve(m_objInstance.size());
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.instanceId = i; // gl_InstanceID
rayInst.blasId = m_objInstance[i].objIndex;
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);
}
m_rtBuilder.buildTlas(tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace);
@ -703,25 +708,25 @@ void HelloVulkan::createRtDescriptorSet()
using vkSS = vk::ShaderStageFlagBits;
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
m_rtDescSetLayoutBind.emplace_back(
m_rtDescSetLayoutBind.addBinding(
vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image
m_rtDescPool = nvvkpp::util::createDescriptorPool(m_device, m_rtDescSetLayoutBind);
m_rtDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_rtDescSetLayoutBind);
m_rtDescPool = m_rtDescSetLayoutBind.createPool(m_device);
m_rtDescSetLayout = m_rtDescSetLayoutBind.createLayout(m_device);
m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0];
vk::AccelerationStructureKHR tlas = m_rtBuilder.getAccelerationStructure();
vk::WriteDescriptorSetAccelerationStructureKHR descASInfo;
descASInfo.setAccelerationStructureCount(1);
descASInfo.setPAccelerationStructures(&m_rtBuilder.getAccelerationStructure());
descASInfo.setPAccelerationStructures(&tlas);
vk::DescriptorImageInfo imageInfo{
{}, m_offscreenColor.descriptor.imageView, vk::ImageLayout::eGeneral};
std::vector<vk::WriteDescriptorSet> writes;
writes.emplace_back(
nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[0], &descASInfo));
writes.emplace_back(nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[1], &imageInfo));
writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 0, &descASInfo));
writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 1, &imageInfo));
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;
vk::ShaderModule raygenSM =
nvvkpp::util::createShaderModule(m_device, //
nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rgen.spv", true, paths));
vk::ShaderModule missSM =
nvvkpp::util::createShaderModule(m_device, //
nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths));
// The second miss shader is invoked when a shadow ray misses the geometry. It
// simply indicates that no occlusion has been found
vk::ShaderModule shadowmissSM = nvvkpp::util::createShaderModule(
m_device, nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
vk::ShaderModule shadowmissSM =
nvvk::createShaderModule(m_device,
nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
std::vector<vk::PipelineShaderStageCreateInfo> stages;
@ -785,10 +791,10 @@ void HelloVulkan::createRtPipeline()
// Hit Group - Closest Hit + AnyHit
vk::ShaderModule chitSM =
nvvkpp::util::createShaderModule(m_device, //
nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rchit.spv", true, paths));
vk::ShaderModule ahitSM =
nvvkpp::util::createShaderModule(m_device, //
nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rahit.spv", true, paths));
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup,
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR,
@ -855,7 +861,7 @@ void HelloVulkan::createRtShaderBindingTable()
m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize,
shaderHandleStorage.data());
// 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();
m_rtSBTBuffer =
@ -863,9 +869,9 @@ void HelloVulkan::createRtShaderBindingTable()
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
#include "nvvkpp/allocator_dedicated_vkpp.hpp"
#include "nvvkpp/appbase_vkpp.hpp"
#include "nvvkpp/debug_util_vkpp.hpp"
#define NVVK_ALLOC_DEDICATED
#include "nvvk/allocator_vk.hpp"
#include "nvvk/appbase_vkpp.hpp"
#include "nvvk/debug_util_vk.hpp"
#include "nvvk/descriptorsets_vk.hpp"
// #VKRay
#define ALLOC_DEDICATED
#include "nvvkpp/raytraceKHR_vkpp.hpp"
using nvvkBuffer = nvvkpp::BufferDedicated;
using nvvkTexture = nvvkpp::TextureDedicated;
#include "nvvk/raytraceKHR_vk.hpp"
//--------------------------------------------------------------------------------------------------
// Simple rasterizer of OBJ objects
@ -44,10 +42,11 @@ using nvvkTexture = nvvkpp::TextureDedicated;
// - Rendering is done in an offscreen framebuffer
// - 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:
void setup(const vk::Device& device,
void setup(const vk::Instance& instance,
const vk::Device& device,
const vk::PhysicalDevice& physicalDevice,
uint32_t queueFamily) override;
void createDescriptorSetLayout();
@ -68,10 +67,10 @@ public:
{
uint32_t nbIndices{0};
uint32_t nbVertices{0};
nvvkBuffer vertexBuffer; // Device buffer of all 'Vertex'
nvvkBuffer indexBuffer; // Device buffer of the indices forming triangles
nvvkBuffer matColorBuffer; // Device buffer of array of 'Wavefront material'
nvvkBuffer matIndexBuffer; // Device buffer of array of 'Wavefront material'
nvvk::Buffer vertexBuffer; // Device buffer of all 'Vertex'
nvvk::Buffer indexBuffer; // Device buffer of the indices forming triangles
nvvk::Buffer matColorBuffer; // Device buffer of array of 'Wavefront material'
nvvk::Buffer matIndexBuffer; // Device buffer of array of 'Wavefront material'
};
// Instance of the OBJ
@ -100,17 +99,17 @@ public:
// Graphic pipeline
vk::PipelineLayout m_pipelineLayout;
vk::Pipeline m_graphicsPipeline;
std::vector<vk::DescriptorSetLayoutBinding> m_descSetLayoutBind;
nvvk::DescriptorSetBindings m_descSetLayoutBind;
vk::DescriptorPool m_descPool;
vk::DescriptorSetLayout m_descSetLayout;
vk::DescriptorSet m_descSet;
nvvkBuffer m_cameraMat; // Device-Host of the camera matrices
nvvkBuffer m_sceneDesc; // Device buffer of the OBJ instances
std::vector<nvvkTexture> m_textures; // vector of all textures of the scene
nvvk::Buffer m_cameraMat; // Device-Host of the camera matrices
nvvk::Buffer m_sceneDesc; // Device buffer of the OBJ instances
std::vector<nvvk::Texture> m_textures; // vector of all textures of the scene
nvvkpp::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures
nvvkpp::DebugUtil m_debug; // Utility to name objects
nvvk::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures
nvvk::DebugUtil m_debug; // Utility to name objects
// #Post
void createOffscreenRender();
@ -119,7 +118,7 @@ public:
void updatePostDescriptorSet();
void drawPost(vk::CommandBuffer cmdBuf);
std::vector<vk::DescriptorSetLayoutBinding> m_postDescSetLayoutBind;
nvvk::DescriptorSetBindings m_postDescSetLayoutBind;
vk::DescriptorPool m_postDescPool;
vk::DescriptorSetLayout m_postDescSetLayout;
vk::DescriptorSet m_postDescSet;
@ -127,14 +126,14 @@ public:
vk::PipelineLayout m_postPipelineLayout;
vk::RenderPass m_offscreenRenderPass;
vk::Framebuffer m_offscreenFramebuffer;
nvvkTexture m_offscreenColor;
nvvk::Texture m_offscreenColor;
vk::Format m_offscreenColorFormat{vk::Format::eR32G32B32A32Sfloat};
nvvkTexture m_offscreenDepth;
nvvk::Texture m_offscreenDepth;
vk::Format m_offscreenDepthFormat{vk::Format::eD32Sfloat};
// #VKRay
void initRayTracing();
nvvkpp::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
nvvk::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
void createBottomLevelAS();
void createTopLevelAS();
void createRtDescriptorSet();
@ -146,15 +145,15 @@ public:
void updateFrame();
vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties;
nvvkpp::RaytracingBuilderKHR m_rtBuilder;
std::vector<vk::DescriptorSetLayoutBinding> m_rtDescSetLayoutBind;
nvvk::RaytracingBuilderKHR m_rtBuilder;
nvvk::DescriptorSetBindings m_rtDescSetLayoutBind;
vk::DescriptorPool m_rtDescPool;
vk::DescriptorSetLayout m_rtDescSetLayout;
vk::DescriptorSet m_rtDescSet;
std::vector<vk::RayTracingShaderGroupCreateInfoKHR> m_rtShaderGroups;
vk::PipelineLayout m_rtPipelineLayout;
vk::Pipeline m_rtPipeline;
nvvkBuffer m_rtSBTBuffer;
nvvk::Buffer m_rtSBTBuffer;
int m_maxFrames{10000};
struct RtPushConstant

View file

@ -39,10 +39,11 @@
#include "nvh/cameramanipulator.hpp"
#include "nvh/fileoperations.hpp"
#include "nvpsystem.hpp"
#include "nvvkpp/appbase_vkpp.hpp"
#include "nvvkpp/commands_vkpp.hpp"
#include "nvvkpp/context_vkpp.hpp"
#include "nvvkpp/utilities_vkpp.hpp"
#include "nvvk/appbase_vkpp.hpp"
#include "nvvk/commands_vk.hpp"
#include "nvvk/context_vk.hpp"
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
//////////////////////////////////////////////////////////////////////////
#define UNUSED(x) (void)(x)
@ -124,7 +125,7 @@ int main(int argc, char** argv)
vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature;
// Requesting Vulkan extensions and layers
nvvkpp::ContextCreateInfo contextInfo(true);
nvvk::ContextCreateInfo contextInfo(true);
contextInfo.setVersion(1, 2);
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
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);
// Creating Vulkan base application
nvvkpp::Context vkctx{};
nvvk::Context vkctx{};
vkctx.initInstance(contextInfo);
// Find all compatible devices
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);
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.createDepthBuffer();
helloVk.createRenderPass();
@ -244,7 +246,8 @@ int main(int argc, char** argv)
// Clearing screen
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});
// Offscreen render pass
@ -296,7 +299,6 @@ int main(int argc, char** argv)
helloVk.destroyResources();
helloVk.destroy();
vkctx.m_instance.destroySurfaceKHR(surface);
vkctx.deinit();
glfwDestroyWindow(window);

View file

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

View file

@ -36,13 +36,14 @@ extern std::vector<std::string> defaultSearchPaths;
#include "hello_vulkan.h"
#include "nvh//cameramanipulator.hpp"
#include "nvvkpp/descriptorsets_vkpp.hpp"
#include "nvvkpp/pipeline_vkpp.hpp"
#include "nvvk/descriptorsets_vk.hpp"
#include "nvvk/pipeline_vk.hpp"
#include "nvh/fileoperations.hpp"
#include "nvvkpp/commands_vkpp.hpp"
#include "nvvkpp/renderpass_vkpp.hpp"
#include "nvvkpp/utilities_vkpp.hpp"
#include "nvvk/commands_vk.hpp"
#include "nvvk/renderpasses_vk.hpp"
#include "nvvk/shaders_vk.hpp"
// Holding the camera matrices
struct CameraMatrices
@ -58,11 +59,12 @@ struct CameraMatrices
// Keep the handle on the device
// 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,
uint32_t queueFamily)
{
AppBase::setup(device, physicalDevice, queueFamily);
AppBase::setup(instance, device, physicalDevice, queueFamily);
m_alloc.init(device, physicalDevice);
m_debug.setup(m_device);
}
@ -99,31 +101,31 @@ void HelloVulkan::createDescriptorSetLayout()
uint32_t nbObj = static_cast<uint32_t>(m_objModel.size());
// Camera matrices (binding = 0)
m_descSetLayoutBind.emplace_back(
m_descSetLayoutBind.addBinding(
vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR));
// Materials (binding = 1)
m_descSetLayoutBind.emplace_back(
m_descSetLayoutBind.addBinding(
vkDS(1, vkDT::eStorageBuffer, nbObj, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
// Scene description (binding = 2)
m_descSetLayoutBind.emplace_back( //
m_descSetLayoutBind.addBinding( //
vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
// Textures (binding = 3)
m_descSetLayoutBind.emplace_back(
m_descSetLayoutBind.addBinding(
vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR));
// Materials (binding = 4)
m_descSetLayoutBind.emplace_back(
m_descSetLayoutBind.addBinding(
vkDS(4, vkDT::eStorageBuffer, nbObj, vkSS::eFragment | vkSS::eClosestHitKHR));
// Storing vertices (binding = 5)
m_descSetLayoutBind.emplace_back( //
m_descSetLayoutBind.addBinding( //
vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
// Storing indices (binding = 6)
m_descSetLayoutBind.emplace_back( //
m_descSetLayoutBind.addBinding( //
vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
m_descSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_descSetLayoutBind);
m_descPool = nvvkpp::util::createDescriptorPool(m_device, m_descSetLayoutBind, 1);
m_descSet = nvvkpp::util::createDescriptorSet(m_device, m_descPool, m_descSetLayout);
m_descSetLayout = m_descSetLayoutBind.createLayout(m_device);
m_descPool = m_descSetLayoutBind.createPool(m_device, 1);
m_descSet = nvvk::allocateDescriptorSet(m_device, m_descPool, m_descSetLayout);
}
//--------------------------------------------------------------------------------------------------
@ -135,9 +137,9 @@ void HelloVulkan::updateDescriptorSet()
// Camera matrices and scene description
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};
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
std::vector<vk::DescriptorBufferInfo> dbiMat;
@ -151,11 +153,10 @@ void HelloVulkan::updateDescriptorSet()
dbiVert.emplace_back(obj.vertexBuffer.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(
nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[4], dbiMatIdx.data()));
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[5], dbiVert.data()));
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[6], dbiIdx.data()));
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 1, dbiMat.data()));
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 4, dbiMatIdx.data()));
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 5, dbiVert.data()));
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 6, dbiIdx.data()));
// All texture samplers
std::vector<vk::DescriptorImageInfo> diit;
@ -163,7 +164,7 @@ void HelloVulkan::updateDescriptorSet()
{
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
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
@ -190,18 +191,17 @@ void HelloVulkan::createGraphicsPipeline()
// Creating the Pipeline
std::vector<std::string> paths = defaultSearchPaths;
nvvkpp::GraphicsPipelineGenerator gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
gpb.depthStencilState = {true};
nvvk::GraphicsPipelineGeneratorCombined gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
gpb.depthStencilState.depthTestEnable = true;
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.vertexInputState.bindingDescriptions = {{0, sizeof(VertexObj)}};
gpb.vertexInputState.attributeDescriptions = {
{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
gpb.addBindingDescription({0, sizeof(VertexObj)});
gpb.addAttributeDescriptions({{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
{1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)},
{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");
}
@ -234,7 +234,7 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
// 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();
model.vertexBuffer =
m_alloc.createBuffer(cmdBuf, loader.m_vertices,
@ -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);
// Creates all textures found
createTextureImages(cmdBuf, loader.m_textures);
cmdBufGet.flushCommandBuffer(cmdBuf);
m_alloc.flushStaging();
cmdBufGet.submitAndWait(cmdBuf);
m_alloc.finalizeAndReleaseStaging();
std::string objNb = std::to_string(instance.objIndex);
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
@ -282,12 +282,12 @@ void HelloVulkan::createUniformBuffer()
void HelloVulkan::createSceneDescriptionBuffer()
{
using vkBU = vk::BufferUsageFlagBits;
nvvkpp::SingleCommandBuffer cmdGen(m_device, m_graphicsQueueIndex);
nvvk::CommandPool cmdGen(m_device, m_graphicsQueueIndex);
auto cmdBuf = cmdGen.createCommandBuffer();
m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer);
cmdGen.flushCommandBuffer(cmdBuf);
m_alloc.flushStaging();
cmdGen.submitAndWait(cmdBuf);
m_alloc.finalizeAndReleaseStaging();
m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc");
}
@ -307,20 +307,20 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
// If no textures are present, create a dummy one to accommodate the pipeline layout
if(textures.empty() && m_textures.empty())
{
nvvkTexture texture;
nvvk::Texture texture;
std::array<uint8_t, 4> color{255u, 255u, 255u, 255u};
vk::DeviceSize bufferSize = sizeof(color);
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
nvvkpp::image::setImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined,
nvvk::cmdBarrierImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eShaderReadOnlyOptimal);
m_textures.push_back(texture);
}
@ -348,16 +348,16 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4;
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;
texture = m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo);
nvvk::ImageDedicated image =
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);
}
}
@ -434,7 +434,7 @@ void HelloVulkan::rasterize(const vk::CommandBuffer& cmdBuf)
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.drawIndexed(model.nbIndices, 1, 0, 0, 0);
}
@ -464,49 +464,54 @@ void HelloVulkan::createOffscreenRender()
m_alloc.destroy(m_offscreenDepth);
// Creating the color image
auto colorCreateInfo = nvvkpp::image::create2DInfo(m_size, m_offscreenColorFormat,
{
auto colorCreateInfo = nvvk::makeImage2DCreateInfo(m_size, m_offscreenColorFormat,
vk::ImageUsageFlagBits::eColorAttachment
| vk::ImageUsageFlagBits::eSampled
| vk::ImageUsageFlagBits::eStorage);
m_offscreenColor = m_alloc.createImage(colorCreateInfo);
m_offscreenColor.descriptor =
nvvkpp::image::create2DDescriptor(m_device, m_offscreenColor.image, vk::SamplerCreateInfo{},
m_offscreenColorFormat, vk::ImageLayout::eGeneral);
nvvk::ImageDedicated image = m_alloc.createImage(colorCreateInfo);
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
auto depthCreateInfo =
nvvkpp::image::create2DInfo(m_size, m_offscreenDepthFormat,
nvvk::makeImage2DCreateInfo(m_size, m_offscreenDepthFormat,
vk::ImageUsageFlagBits::eDepthStencilAttachment);
m_offscreenDepth = m_alloc.createImage(depthCreateInfo);
{
nvvk::Image image = m_alloc.createImage(depthCreateInfo);
vk::ImageViewCreateInfo depthStencilView;
depthStencilView.setViewType(vk::ImageViewType::e2D);
depthStencilView.setFormat(m_offscreenDepthFormat);
depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1});
depthStencilView.setImage(m_offscreenDepth.image);
m_offscreenDepth.descriptor.imageView = m_device.createImageView(depthStencilView);
depthStencilView.setImage(image.image);
m_offscreenDepth = m_alloc.createTexture(image, depthStencilView);
}
// 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();
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined,
nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eGeneral);
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageAspectFlagBits::eDepth,
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
if(!m_offscreenRenderPass)
{
m_offscreenRenderPass =
nvvkpp::util::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat,
1, 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
@ -543,13 +548,14 @@ void HelloVulkan::createPostPipeline()
// Pipeline: completely generic, no vertices
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),
vk::ShaderStageFlagBits::eVertex);
pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths),
vk::ShaderStageFlagBits::eFragment);
pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone);
m_postPipeline = pipelineGenerator.create();
m_postPipeline = pipelineGenerator.createPipeline();
m_debug.setObjectName(m_postPipeline, "post");
}
@ -563,10 +569,10 @@ void HelloVulkan::createPostDescriptor()
using vkDT = vk::DescriptorType;
using vkSS = vk::ShaderStageFlagBits;
m_postDescSetLayoutBind.emplace_back(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
m_postDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_postDescSetLayoutBind);
m_postDescPool = nvvkpp::util::createDescriptorPool(m_device, m_postDescSetLayoutBind);
m_postDescSet = nvvkpp::util::createDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
m_postDescSetLayoutBind.addBinding(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
m_postDescSetLayout = m_postDescSetLayoutBind.createLayout(m_device);
m_postDescPool = m_postDescSetLayoutBind.createPool(m_device);
m_postDescSet = nvvk::allocateDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
}
//--------------------------------------------------------------------------------------------------
@ -575,8 +581,7 @@ void HelloVulkan::createPostDescriptor()
void HelloVulkan::updatePostDescriptorSet()
{
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);
}
@ -614,15 +619,15 @@ void HelloVulkan::initRayTracing()
auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2,
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
//
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;
asCreate.setGeometryType(vk::GeometryTypeKHR::eTriangles);
asCreate.setIndexType(vk::IndexType::eUint32);
@ -659,7 +664,7 @@ nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjM
void HelloVulkan::createBottomLevelAS()
{
// BLAS - Storing each primitive in a geometry
std::vector<nvvkpp::RaytracingBuilderKHR::Blas> allBlas;
std::vector<nvvk::RaytracingBuilderKHR::Blas> allBlas;
allBlas.reserve(m_objModel.size());
for(const auto& obj : m_objModel)
{
@ -673,16 +678,16 @@ void HelloVulkan::createBottomLevelAS()
void HelloVulkan::createTopLevelAS()
{
std::vector<nvvkpp::RaytracingBuilderKHR::Instance> tlas;
std::vector<nvvk::RaytracingBuilderKHR::Instance> tlas;
tlas.reserve(m_objInstance.size());
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.instanceId = i; // gl_InstanceID
rayInst.blasId = m_objInstance[i].objIndex;
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);
}
m_rtBuilder.buildTlas(tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace);
@ -697,25 +702,25 @@ void HelloVulkan::createRtDescriptorSet()
using vkSS = vk::ShaderStageFlagBits;
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
m_rtDescSetLayoutBind.emplace_back(
m_rtDescSetLayoutBind.addBinding(
vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image
m_rtDescPool = nvvkpp::util::createDescriptorPool(m_device, m_rtDescSetLayoutBind);
m_rtDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_rtDescSetLayoutBind);
m_rtDescPool = m_rtDescSetLayoutBind.createPool(m_device);
m_rtDescSetLayout = m_rtDescSetLayoutBind.createLayout(m_device);
m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0];
vk::AccelerationStructureKHR tlas = m_rtBuilder.getAccelerationStructure();
vk::WriteDescriptorSetAccelerationStructureKHR descASInfo;
descASInfo.setAccelerationStructureCount(1);
descASInfo.setPAccelerationStructures(&m_rtBuilder.getAccelerationStructure());
descASInfo.setPAccelerationStructures(&tlas);
vk::DescriptorImageInfo imageInfo{
{}, m_offscreenColor.descriptor.imageView, vk::ImageLayout::eGeneral};
std::vector<vk::WriteDescriptorSet> writes;
writes.emplace_back(
nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[0], &descASInfo));
writes.emplace_back(nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[1], &imageInfo));
writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 0, &descASInfo));
writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 1, &imageInfo));
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;
vk::ShaderModule raygenSM =
nvvkpp::util::createShaderModule(m_device, //
nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rgen.spv", true, paths));
vk::ShaderModule missSM =
nvvkpp::util::createShaderModule(m_device, //
nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths));
// The second miss shader is invoked when a shadow ray misses the geometry. It
// simply indicates that no occlusion has been found
vk::ShaderModule shadowmissSM = nvvkpp::util::createShaderModule(
m_device, nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
vk::ShaderModule shadowmissSM =
nvvk::createShaderModule(m_device,
nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
std::vector<vk::PipelineShaderStageCreateInfo> stages;
@ -779,7 +785,7 @@ void HelloVulkan::createRtPipeline()
// Hit Group - Closest Hit + AnyHit
vk::ShaderModule chitSM =
nvvkpp::util::createShaderModule(m_device, //
nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rchit.spv", true, paths));
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup,
@ -795,14 +801,13 @@ void HelloVulkan::createRtPipeline()
VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR};
vk::ShaderModule call0 =
nvvkpp::util::createShaderModule(m_device,
nvvk::createShaderModule(m_device,
nvh::loadFile("shaders/light_point.rcall.spv", true, paths));
vk::ShaderModule call1 =
nvvkpp::util::createShaderModule(m_device,
nvvk::createShaderModule(m_device,
nvh::loadFile("shaders/light_spot.rcall.spv", true, paths));
vk::ShaderModule call2 =
nvvkpp::util::createShaderModule(m_device,
nvh::loadFile("shaders/light_inf.rcall.spv", true, paths));
nvvk::createShaderModule(m_device, nvh::loadFile("shaders/light_inf.rcall.spv", true, paths));
stages.push_back({{}, vk::ShaderStageFlagBits::eCallableKHR, call0, "main"});
callGroup.setGeneralShader(static_cast<uint32_t>(stages.size() - 1));
@ -874,7 +879,7 @@ void HelloVulkan::createRtShaderBindingTable()
m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize,
shaderHandleStorage.data());
// 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();
m_rtSBTBuffer =
@ -882,9 +887,9 @@ void HelloVulkan::createRtShaderBindingTable()
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
#include "nvvkpp/allocator_dedicated_vkpp.hpp"
#include "nvvkpp/appbase_vkpp.hpp"
#include "nvvkpp/debug_util_vkpp.hpp"
#define NVVK_ALLOC_DEDICATED
#include "nvvk/allocator_vk.hpp"
#include "nvvk/appbase_vkpp.hpp"
#include "nvvk/debug_util_vk.hpp"
#include "nvvk/descriptorsets_vk.hpp"
// #VKRay
#define ALLOC_DEDICATED
#include "nvvkpp/raytraceKHR_vkpp.hpp"
#include "nvvk/raytraceKHR_vk.hpp"
using nvvkBuffer = nvvkpp::BufferDedicated;
using nvvkTexture = nvvkpp::TextureDedicated;
//--------------------------------------------------------------------------------------------------
// Simple rasterizer of OBJ objects
@ -44,10 +43,11 @@ using nvvkTexture = nvvkpp::TextureDedicated;
// - Rendering is done in an offscreen framebuffer
// - 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:
void setup(const vk::Device& device,
void setup(const vk::Instance& instance,
const vk::Device& device,
const vk::PhysicalDevice& physicalDevice,
uint32_t queueFamily) override;
void createDescriptorSetLayout();
@ -68,10 +68,10 @@ public:
{
uint32_t nbIndices{0};
uint32_t nbVertices{0};
nvvkBuffer vertexBuffer; // Device buffer of all 'Vertex'
nvvkBuffer indexBuffer; // Device buffer of the indices forming triangles
nvvkBuffer matColorBuffer; // Device buffer of array of 'Wavefront material'
nvvkBuffer matIndexBuffer; // Device buffer of array of 'Wavefront material'
nvvk::Buffer vertexBuffer; // Device buffer of all 'Vertex'
nvvk::Buffer indexBuffer; // Device buffer of the indices forming triangles
nvvk::Buffer matColorBuffer; // Device buffer of array of 'Wavefront material'
nvvk::Buffer matIndexBuffer; // Device buffer of array of 'Wavefront material'
};
// Instance of the OBJ
@ -103,17 +103,17 @@ public:
// Graphic pipeline
vk::PipelineLayout m_pipelineLayout;
vk::Pipeline m_graphicsPipeline;
std::vector<vk::DescriptorSetLayoutBinding> m_descSetLayoutBind;
nvvk::DescriptorSetBindings m_descSetLayoutBind;
vk::DescriptorPool m_descPool;
vk::DescriptorSetLayout m_descSetLayout;
vk::DescriptorSet m_descSet;
nvvkBuffer m_cameraMat; // Device-Host of the camera matrices
nvvkBuffer m_sceneDesc; // Device buffer of the OBJ instances
std::vector<nvvkTexture> m_textures; // vector of all textures of the scene
nvvk::Buffer m_cameraMat; // Device-Host of the camera matrices
nvvk::Buffer m_sceneDesc; // Device buffer of the OBJ instances
std::vector<nvvk::Texture> m_textures; // vector of all textures of the scene
nvvkpp::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures
nvvkpp::DebugUtil m_debug; // Utility to name objects
nvvk::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures
nvvk::DebugUtil m_debug; // Utility to name objects
// #Post
void createOffscreenRender();
@ -122,7 +122,7 @@ public:
void updatePostDescriptorSet();
void drawPost(vk::CommandBuffer cmdBuf);
std::vector<vk::DescriptorSetLayoutBinding> m_postDescSetLayoutBind;
nvvk::DescriptorSetBindings m_postDescSetLayoutBind;
vk::DescriptorPool m_postDescPool;
vk::DescriptorSetLayout m_postDescSetLayout;
vk::DescriptorSet m_postDescSet;
@ -130,14 +130,14 @@ public:
vk::PipelineLayout m_postPipelineLayout;
vk::RenderPass m_offscreenRenderPass;
vk::Framebuffer m_offscreenFramebuffer;
nvvkTexture m_offscreenColor;
nvvk::Texture m_offscreenColor;
vk::Format m_offscreenColorFormat{vk::Format::eR32G32B32A32Sfloat};
nvvkTexture m_offscreenDepth;
nvvk::Texture m_offscreenDepth;
vk::Format m_offscreenDepthFormat{vk::Format::eD32Sfloat};
// #VKRay
void initRayTracing();
nvvkpp::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
nvvk::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
void createBottomLevelAS();
void createTopLevelAS();
void createRtDescriptorSet();
@ -148,15 +148,15 @@ public:
vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties;
nvvkpp::RaytracingBuilderKHR m_rtBuilder;
std::vector<vk::DescriptorSetLayoutBinding> m_rtDescSetLayoutBind;
nvvk::RaytracingBuilderKHR m_rtBuilder;
nvvk::DescriptorSetBindings m_rtDescSetLayoutBind;
vk::DescriptorPool m_rtDescPool;
vk::DescriptorSetLayout m_rtDescSetLayout;
vk::DescriptorSet m_rtDescSet;
std::vector<vk::RayTracingShaderGroupCreateInfoKHR> m_rtShaderGroups;
vk::PipelineLayout m_rtPipelineLayout;
vk::Pipeline m_rtPipeline;
nvvkBuffer m_rtSBTBuffer;
nvvk::Buffer m_rtSBTBuffer;
struct RtPushConstant
{

View file

@ -31,6 +31,7 @@
#include <array>
#include <vulkan/vulkan.hpp>
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
#include "imgui.h"
#include "imgui_impl_glfw.h"
@ -39,10 +40,10 @@
#include "nvh/cameramanipulator.hpp"
#include "nvh/fileoperations.hpp"
#include "nvpsystem.hpp"
#include "nvvkpp/appbase_vkpp.hpp"
#include "nvvkpp/commands_vkpp.hpp"
#include "nvvkpp/context_vkpp.hpp"
#include "nvvkpp/utilities_vkpp.hpp"
#include "nvvk/appbase_vkpp.hpp"
#include "nvvk/commands_vk.hpp"
#include "nvvk/context_vk.hpp"
//////////////////////////////////////////////////////////////////////////
#define UNUSED(x) (void)(x)
@ -141,7 +142,7 @@ int main(int argc, char** argv)
vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature;
// Requesting Vulkan extensions and layers
nvvkpp::ContextCreateInfo contextInfo(true);
nvvk::ContextCreateInfo contextInfo(true);
contextInfo.setVersion(1, 2);
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
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);
// Creating Vulkan base application
nvvkpp::Context vkctx{};
nvvk::Context vkctx{};
vkctx.initInstance(contextInfo);
// Find all compatible devices
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);
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.createDepthBuffer();
helloVk.createRenderPass();
@ -258,7 +260,8 @@ int main(int argc, char** argv)
// Clearing screen
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});
// Offscreen render pass
@ -310,7 +313,6 @@ int main(int argc, char** argv)
helloVk.destroyResources();
helloVk.destroy();
vkctx.m_instance.destroySurfaceKHR(surface);
vkctx.deinit();
glfwDestroyWindow(window);

View file

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

View file

@ -38,13 +38,14 @@ extern std::vector<std::string> defaultSearchPaths;
#include "hello_vulkan.h"
#include "nvh//cameramanipulator.hpp"
#include "nvvkpp/descriptorsets_vkpp.hpp"
#include "nvvkpp/pipeline_vkpp.hpp"
#include "nvvk/descriptorsets_vk.hpp"
#include "nvvk/pipeline_vk.hpp"
#include "nvh/fileoperations.hpp"
#include "nvvkpp/commands_vkpp.hpp"
#include "nvvkpp/renderpass_vkpp.hpp"
#include "nvvkpp/utilities_vkpp.hpp"
#include "nvvk/commands_vk.hpp"
#include "nvvk/renderpasses_vk.hpp"
#include "nvvk/shaders_vk.hpp"
// Holding the camera matrices
struct CameraMatrices
@ -60,25 +61,26 @@ struct CameraMatrices
// Keep the handle on the device
// 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,
uint32_t queueFamily)
{
AppBase::setup(device, physicalDevice, queueFamily);
#if defined(ALLOC_DEDICATED)
AppBase::setup(instance, device, physicalDevice, queueFamily);
#if defined(NVVK_ALLOC_DEDICATED)
m_alloc.init(device, physicalDevice);
#elif defined(ALLOC_DMA)
#elif defined(NVVK_ALLOC_DMA)
m_memAllocator.init(device, physicalDevice);
m_memAllocator.setAllocateFlags(VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR, true);
m_alloc.init(device, &m_memAllocator);
#elif defined(ALLOC_VMA)
m_memAllocator.setAllocateFlags(VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT, true);
m_alloc.init(device, physicalDevice, &m_memAllocator);
#elif defined(NVVK_ALLOC_VMA)
VmaAllocatorCreateInfo allocatorInfo = {};
allocatorInfo.instance = instance;
allocatorInfo.physicalDevice = physicalDevice;
allocatorInfo.device = device;
allocatorInfo.flags |=
VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT | VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT;
allocatorInfo.flags = VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT;
vmaCreateAllocator(&allocatorInfo, &m_memAllocator);
m_alloc.init(device, m_memAllocator);
m_alloc.init(device, physicalDevice, m_memAllocator);
#endif
m_debug.setup(m_device);
}
@ -98,20 +100,9 @@ void HelloVulkan::updateUniformBuffer()
// #VKRay
ubo.projInverse = nvmath::invert(ubo.proj);
#if defined(ALLOC_DEDICATED)
void* data = m_device.mapMemory(m_cameraMat.allocation, 0, sizeof(CameraMatrices));
void* data = m_alloc.map(m_cameraMat);
memcpy(data, &ubo, sizeof(ubo));
m_device.unmapMemory(m_cameraMat.allocation);
#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
m_alloc.unmap(m_cameraMat);
}
//--------------------------------------------------------------------------------------------------
@ -126,31 +117,31 @@ void HelloVulkan::createDescriptorSetLayout()
uint32_t nbObj = static_cast<uint32_t>(m_objModel.size());
// Camera matrices (binding = 0)
m_descSetLayoutBind.emplace_back(
m_descSetLayoutBind.addBinding(
vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR));
// Materials (binding = 1)
m_descSetLayoutBind.emplace_back(
m_descSetLayoutBind.addBinding(
vkDS(1, vkDT::eStorageBuffer, nbObj, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
// Scene description (binding = 2)
m_descSetLayoutBind.emplace_back( //
m_descSetLayoutBind.addBinding( //
vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
// Textures (binding = 3)
m_descSetLayoutBind.emplace_back(
m_descSetLayoutBind.addBinding(
vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR));
// Materials (binding = 4)
m_descSetLayoutBind.emplace_back(
m_descSetLayoutBind.addBinding(
vkDS(4, vkDT::eStorageBuffer, nbObj, vkSS::eFragment | vkSS::eClosestHitKHR));
// Storing vertices (binding = 5)
m_descSetLayoutBind.emplace_back( //
m_descSetLayoutBind.addBinding( //
vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
// Storing indices (binding = 6)
m_descSetLayoutBind.emplace_back( //
m_descSetLayoutBind.addBinding( //
vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
m_descSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_descSetLayoutBind);
m_descPool = nvvkpp::util::createDescriptorPool(m_device, m_descSetLayoutBind, 1);
m_descSet = nvvkpp::util::createDescriptorSet(m_device, m_descPool, m_descSetLayout);
m_descSetLayout = m_descSetLayoutBind.createLayout(m_device);
m_descPool = m_descSetLayoutBind.createPool(m_device, 1);
m_descSet = nvvk::allocateDescriptorSet(m_device, m_descPool, m_descSetLayout);
}
//--------------------------------------------------------------------------------------------------
@ -162,9 +153,9 @@ void HelloVulkan::updateDescriptorSet()
// Camera matrices and scene description
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};
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
std::vector<vk::DescriptorBufferInfo> dbiMat;
@ -178,11 +169,10 @@ void HelloVulkan::updateDescriptorSet()
dbiVert.emplace_back(obj.vertexBuffer.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(
nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[4], dbiMatIdx.data()));
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[5], dbiVert.data()));
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[6], dbiIdx.data()));
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 1, dbiMat.data()));
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 4, dbiMatIdx.data()));
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 5, dbiVert.data()));
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 6, dbiIdx.data()));
// All texture samplers
std::vector<vk::DescriptorImageInfo> diit;
@ -190,7 +180,7 @@ void HelloVulkan::updateDescriptorSet()
{
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
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
@ -217,18 +207,17 @@ void HelloVulkan::createGraphicsPipeline()
// Creating the Pipeline
std::vector<std::string> paths = defaultSearchPaths;
nvvkpp::GraphicsPipelineGenerator gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
gpb.depthStencilState = {true};
nvvk::GraphicsPipelineGeneratorCombined gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
gpb.depthStencilState.depthTestEnable = true;
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.vertexInputState.bindingDescriptions = {{0, sizeof(VertexObj)}};
gpb.vertexInputState.attributeDescriptions = {
{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
gpb.addBindingDescription({0, sizeof(VertexObj)});
gpb.addAttributeDescriptions({{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
{1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)},
{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");
}
@ -261,7 +250,7 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
// 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();
model.vertexBuffer =
m_alloc.createBuffer(cmdBuf, loader.m_vertices,
@ -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);
// Creates all textures found
createTextureImages(cmdBuf, loader.m_textures);
cmdBufGet.flushCommandBuffer(cmdBuf);
m_alloc.flushStaging();
cmdBufGet.submitAndWait(cmdBuf);
m_alloc.finalizeAndReleaseStaging();
std::string objNb = std::to_string(instance.objIndex);
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
@ -296,12 +285,7 @@ void HelloVulkan::createUniformBuffer()
using vkMP = vk::MemoryPropertyFlagBits;
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
);
vkMP::eHostVisible | vkMP::eHostCoherent);
m_debug.setObjectName(m_cameraMat.buffer, "cameraMat");
}
@ -314,12 +298,12 @@ void HelloVulkan::createUniformBuffer()
void HelloVulkan::createSceneDescriptionBuffer()
{
using vkBU = vk::BufferUsageFlagBits;
nvvkpp::SingleCommandBuffer cmdGen(m_device, m_graphicsQueueIndex);
nvvk::CommandPool cmdGen(m_device, m_graphicsQueueIndex);
auto cmdBuf = cmdGen.createCommandBuffer();
m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer);
cmdGen.flushCommandBuffer(cmdBuf);
m_alloc.flushStaging();
cmdGen.submitAndWait(cmdBuf);
m_alloc.finalizeAndReleaseStaging();
m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc");
}
@ -339,20 +323,20 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
// If no textures are present, create a dummy one to accommodate the pipeline layout
if(textures.empty() && m_textures.empty())
{
nvvkTexture texture;
nvvk::Texture texture;
std::array<uint8_t, 4> color{255u, 255u, 255u, 255u};
vk::DeviceSize bufferSize = sizeof(color);
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
nvvkpp::image::setImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined,
nvvk::cmdBarrierImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eShaderReadOnlyOptimal);
m_textures.push_back(texture);
}
@ -380,16 +364,15 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4;
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;
texture = m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo);
nvvk::Image image = 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);
}
}
@ -439,9 +422,10 @@ void HelloVulkan::destroyResources()
m_device.destroy(m_rtPipelineLayout);
m_alloc.destroy(m_rtSBTBuffer);
#if defined(ALLOC_DMA)
m_alloc.deinit();
#if defined(NVVK_ALLOC_DMA)
m_memAllocator.deinit();
#elif defined(ALLOC_VMA)
#elif defined(NVVK_ALLOC_VMA)
vmaDestroyAllocator(m_memAllocator);
#endif
}
@ -472,7 +456,7 @@ void HelloVulkan::rasterize(const vk::CommandBuffer& cmdBuf)
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.drawIndexed(model.nbIndices, 1, 0, 0, 0);
}
@ -502,49 +486,54 @@ void HelloVulkan::createOffscreenRender()
m_alloc.destroy(m_offscreenDepth);
// Creating the color image
auto colorCreateInfo = nvvkpp::image::create2DInfo(m_size, m_offscreenColorFormat,
{
auto colorCreateInfo = nvvk::makeImage2DCreateInfo(m_size, m_offscreenColorFormat,
vk::ImageUsageFlagBits::eColorAttachment
| vk::ImageUsageFlagBits::eSampled
| vk::ImageUsageFlagBits::eStorage);
m_offscreenColor = m_alloc.createImage(colorCreateInfo);
m_offscreenColor.descriptor =
nvvkpp::image::create2DDescriptor(m_device, m_offscreenColor.image, vk::SamplerCreateInfo{},
m_offscreenColorFormat, vk::ImageLayout::eGeneral);
nvvk::Image image = m_alloc.createImage(colorCreateInfo);
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
auto depthCreateInfo =
nvvkpp::image::create2DInfo(m_size, m_offscreenDepthFormat,
nvvk::makeImage2DCreateInfo(m_size, m_offscreenDepthFormat,
vk::ImageUsageFlagBits::eDepthStencilAttachment);
m_offscreenDepth = m_alloc.createImage(depthCreateInfo);
{
nvvk::Image image = m_alloc.createImage(depthCreateInfo);
vk::ImageViewCreateInfo depthStencilView;
depthStencilView.setViewType(vk::ImageViewType::e2D);
depthStencilView.setFormat(m_offscreenDepthFormat);
depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1});
depthStencilView.setImage(m_offscreenDepth.image);
m_offscreenDepth.descriptor.imageView = m_device.createImageView(depthStencilView);
depthStencilView.setImage(image.image);
m_offscreenDepth = m_alloc.createTexture(image, depthStencilView);
}
// 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();
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined,
nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eGeneral);
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageAspectFlagBits::eDepth,
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
if(!m_offscreenRenderPass)
{
m_offscreenRenderPass =
nvvkpp::util::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat,
1, 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
@ -581,13 +570,14 @@ void HelloVulkan::createPostPipeline()
// Pipeline: completely generic, no vertices
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),
vk::ShaderStageFlagBits::eVertex);
pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths),
vk::ShaderStageFlagBits::eFragment);
pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone);
m_postPipeline = pipelineGenerator.create();
m_postPipeline = pipelineGenerator.createPipeline();
m_debug.setObjectName(m_postPipeline, "post");
}
@ -601,10 +591,10 @@ void HelloVulkan::createPostDescriptor()
using vkDT = vk::DescriptorType;
using vkSS = vk::ShaderStageFlagBits;
m_postDescSetLayoutBind.emplace_back(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
m_postDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_postDescSetLayoutBind);
m_postDescPool = nvvkpp::util::createDescriptorPool(m_device, m_postDescSetLayoutBind);
m_postDescSet = nvvkpp::util::createDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
m_postDescSetLayoutBind.addBinding(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
m_postDescSetLayout = m_postDescSetLayoutBind.createLayout(m_device);
m_postDescPool = m_postDescSetLayoutBind.createPool(m_device);
m_postDescSet = nvvk::allocateDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
}
//--------------------------------------------------------------------------------------------------
@ -613,8 +603,7 @@ void HelloVulkan::createPostDescriptor()
void HelloVulkan::updatePostDescriptorSet()
{
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);
}
@ -652,21 +641,15 @@ void HelloVulkan::initRayTracing()
auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2,
vk::PhysicalDeviceRayTracingPropertiesKHR>();
m_rtProperties = properties.get<vk::PhysicalDeviceRayTracingPropertiesKHR>();
#if defined(ALLOC_DEDICATED)
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
m_rtBuilder.setup(m_device, &m_alloc, m_graphicsQueueIndex);
}
//--------------------------------------------------------------------------------------------------
// 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;
asCreate.setGeometryType(vk::GeometryTypeKHR::eTriangles);
asCreate.setIndexType(vk::IndexType::eUint32);
@ -703,7 +686,7 @@ nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjM
void HelloVulkan::createBottomLevelAS()
{
// BLAS - Storing each primitive in a geometry
std::vector<nvvkpp::RaytracingBuilderKHR::Blas> allBlas;
std::vector<nvvk::RaytracingBuilderKHR::Blas> allBlas;
allBlas.reserve(m_objModel.size());
for(const auto& obj : m_objModel)
{
@ -717,16 +700,16 @@ void HelloVulkan::createBottomLevelAS()
void HelloVulkan::createTopLevelAS()
{
std::vector<nvvkpp::RaytracingBuilderKHR::Instance> tlas;
std::vector<nvvk::RaytracingBuilderKHR::Instance> tlas;
tlas.reserve(m_objInstance.size());
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.instanceId = i; // gl_InstanceID
rayInst.blasId = m_objInstance[i].objIndex;
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);
}
m_rtBuilder.buildTlas(tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace);
@ -741,25 +724,25 @@ void HelloVulkan::createRtDescriptorSet()
using vkSS = vk::ShaderStageFlagBits;
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
m_rtDescSetLayoutBind.emplace_back(
m_rtDescSetLayoutBind.addBinding(
vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image
m_rtDescPool = nvvkpp::util::createDescriptorPool(m_device, m_rtDescSetLayoutBind);
m_rtDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_rtDescSetLayoutBind);
m_rtDescPool = m_rtDescSetLayoutBind.createPool(m_device);
m_rtDescSetLayout = m_rtDescSetLayoutBind.createLayout(m_device);
m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0];
vk::AccelerationStructureKHR tlas = m_rtBuilder.getAccelerationStructure();
vk::WriteDescriptorSetAccelerationStructureKHR descASInfo;
descASInfo.setAccelerationStructureCount(1);
descASInfo.setPAccelerationStructures(&m_rtBuilder.getAccelerationStructure());
descASInfo.setPAccelerationStructures(&tlas);
vk::DescriptorImageInfo imageInfo{
{}, m_offscreenColor.descriptor.imageView, vk::ImageLayout::eGeneral};
std::vector<vk::WriteDescriptorSet> writes;
writes.emplace_back(
nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[0], &descASInfo));
writes.emplace_back(nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[1], &imageInfo));
writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 0, &descASInfo));
writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 1, &imageInfo));
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;
vk::ShaderModule raygenSM =
nvvkpp::util::createShaderModule(m_device, //
nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rgen.spv", true, paths));
vk::ShaderModule missSM =
nvvkpp::util::createShaderModule(m_device, //
nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths));
// The second miss shader is invoked when a shadow ray misses the geometry. It
// simply indicates that no occlusion has been found
vk::ShaderModule shadowmissSM = nvvkpp::util::createShaderModule(
m_device, nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
vk::ShaderModule shadowmissSM =
nvvk::createShaderModule(m_device,
nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
std::vector<vk::PipelineShaderStageCreateInfo> stages;
@ -823,7 +807,7 @@ void HelloVulkan::createRtPipeline()
// Hit Group - Closest Hit + AnyHit
vk::ShaderModule chitSM =
nvvkpp::util::createShaderModule(m_device, //
nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rchit.spv", true, paths));
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup,
@ -888,7 +872,7 @@ void HelloVulkan::createRtShaderBindingTable()
m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize,
shaderHandleStorage.data());
// 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();
m_rtSBTBuffer =
@ -896,9 +880,9 @@ void HelloVulkan::createRtShaderBindingTable()
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
// #VKRay
//#define ALLOC_DEDICATED
#define ALLOC_DMA
//#define ALLOC_VMA
//#define NVVK_ALLOC_DEDICATED
#define NVVK_ALLOC_DMA
//#define NVVK_ALLOC_VMA
#include "nvvkpp/appbase_vkpp.hpp"
#include "nvvkpp/debug_util_vkpp.hpp"
#include "nvvk/allocator_vk.hpp"
#include "nvvk/appbase_vkpp.hpp"
#include "nvvk/debug_util_vk.hpp"
#include "nvvk/descriptorsets_vk.hpp"
// #VKRay
#include "nvvkpp/raytraceKHR_vkpp.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
#include "nvvk/raytraceKHR_vk.hpp"
//--------------------------------------------------------------------------------------------------
// Simple rasterizer of OBJ objects
@ -58,10 +46,11 @@ using nvvkTexture = nvvkpp::TextureVma;
// - Rendering is done in an offscreen framebuffer
// - 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:
void setup(const vk::Device& device,
void setup(const vk::Instance& instance,
const vk::Device& device,
const vk::PhysicalDevice& physicalDevice,
uint32_t queueFamily) override;
void createDescriptorSetLayout();
@ -82,10 +71,10 @@ public:
{
uint32_t nbIndices{0};
uint32_t nbVertices{0};
nvvkBuffer vertexBuffer; // Device buffer of all 'Vertex'
nvvkBuffer indexBuffer; // Device buffer of the indices forming triangles
nvvkBuffer matColorBuffer; // Device buffer of array of 'Wavefront material'
nvvkBuffer matIndexBuffer; // Device buffer of array of 'Wavefront material'
nvvk::Buffer vertexBuffer; // Device buffer of all 'Vertex'
nvvk::Buffer indexBuffer; // Device buffer of the indices forming triangles
nvvk::Buffer matColorBuffer; // Device buffer of array of 'Wavefront material'
nvvk::Buffer matIndexBuffer; // Device buffer of array of 'Wavefront material'
};
// Instance of the OBJ
@ -114,26 +103,26 @@ public:
// Graphic pipeline
vk::PipelineLayout m_pipelineLayout;
vk::Pipeline m_graphicsPipeline;
std::vector<vk::DescriptorSetLayoutBinding> m_descSetLayoutBind;
nvvk::DescriptorSetBindings m_descSetLayoutBind;
vk::DescriptorPool m_descPool;
vk::DescriptorSetLayout m_descSetLayout;
vk::DescriptorSet m_descSet;
nvvkBuffer m_cameraMat; // Device-Host of the camera matrices
nvvkBuffer m_sceneDesc; // Device buffer of the OBJ instances
std::vector<nvvkTexture> m_textures; // vector of all textures of the scene
nvvk::Buffer m_cameraMat; // Device-Host of the camera matrices
nvvk::Buffer m_sceneDesc; // Device buffer of the OBJ instances
std::vector<nvvk::Texture> m_textures; // vector of all textures of the scene
#if defined(ALLOC_DEDICATED)
nvvkpp::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures
#elif defined(ALLOC_DMA)
nvvkpp::AllocatorDma m_alloc; // Allocator for buffer, images, acceleration structures
#if defined(NVVK_ALLOC_DEDICATED)
nvvk::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures
#elif defined(NVVK_ALLOC_DMA)
nvvk::AllocatorDma m_alloc; // Allocator for buffer, images, acceleration structures
nvvk::DeviceMemoryAllocator m_memAllocator;
#elif defined(ALLOC_VMA)
nvvkpp::AllocatorVma m_alloc; // Allocator for buffer, images, acceleration structures
#elif defined(NVVK_ALLOC_VMA)
nvvk::AllocatorVma m_alloc; // Allocator for buffer, images, acceleration structures
VmaAllocator m_memAllocator;
#endif
nvvkpp::DebugUtil m_debug; // Utility to name objects
nvvk::DebugUtil m_debug; // Utility to name objects
// #Post
void createOffscreenRender();
@ -142,7 +131,7 @@ public:
void updatePostDescriptorSet();
void drawPost(vk::CommandBuffer cmdBuf);
std::vector<vk::DescriptorSetLayoutBinding> m_postDescSetLayoutBind;
nvvk::DescriptorSetBindings m_postDescSetLayoutBind;
vk::DescriptorPool m_postDescPool;
vk::DescriptorSetLayout m_postDescSetLayout;
vk::DescriptorSet m_postDescSet;
@ -150,14 +139,14 @@ public:
vk::PipelineLayout m_postPipelineLayout;
vk::RenderPass m_offscreenRenderPass;
vk::Framebuffer m_offscreenFramebuffer;
nvvkTexture m_offscreenColor;
nvvk::Texture m_offscreenColor;
vk::Format m_offscreenColorFormat{vk::Format::eR32G32B32A32Sfloat};
nvvkTexture m_offscreenDepth;
nvvk::Texture m_offscreenDepth;
vk::Format m_offscreenDepthFormat{vk::Format::eD32Sfloat};
// #VKRay
void initRayTracing();
nvvkpp::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
nvvk::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
void createBottomLevelAS();
void createTopLevelAS();
void createRtDescriptorSet();
@ -168,15 +157,15 @@ public:
vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties;
nvvkpp::RaytracingBuilderKHR m_rtBuilder;
std::vector<vk::DescriptorSetLayoutBinding> m_rtDescSetLayoutBind;
nvvk::RaytracingBuilderKHR m_rtBuilder;
nvvk::DescriptorSetBindings m_rtDescSetLayoutBind;
vk::DescriptorPool m_rtDescPool;
vk::DescriptorSetLayout m_rtDescSetLayout;
vk::DescriptorSet m_rtDescSet;
std::vector<vk::RayTracingShaderGroupCreateInfoKHR> m_rtShaderGroups;
vk::PipelineLayout m_rtPipelineLayout;
vk::Pipeline m_rtPipeline;
nvvkBuffer m_rtSBTBuffer;
nvvk::Buffer m_rtSBTBuffer;
struct RtPushConstant
{

View file

@ -32,6 +32,7 @@
#include <array>
#include <random>
#include <vulkan/vulkan.hpp>
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
#include "imgui.h"
#include "imgui_impl_glfw.h"
@ -40,10 +41,10 @@
#include "nvh/cameramanipulator.hpp"
#include "nvh/fileoperations.hpp"
#include "nvpsystem.hpp"
#include "nvvkpp/appbase_vkpp.hpp"
#include "nvvkpp/commands_vkpp.hpp"
#include "nvvkpp/context_vkpp.hpp"
#include "nvvkpp/utilities_vkpp.hpp"
#include "nvvk/appbase_vkpp.hpp"
#include "nvvk/commands_vk.hpp"
#include "nvvk/context_vk.hpp"
//////////////////////////////////////////////////////////////////////////
#define UNUSED(x) (void)(x)
@ -125,7 +126,7 @@ int main(int argc, char** argv)
vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature;
// Requesting Vulkan extensions and layers
nvvkpp::ContextCreateInfo contextInfo(true);
nvvk::ContextCreateInfo contextInfo(true);
contextInfo.setVersion(1, 2);
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
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);
// Creating Vulkan base application
nvvkpp::Context vkctx{};
nvvk::Context vkctx{};
vkctx.initInstance(contextInfo);
// Find all compatible devices
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);
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.createDepthBuffer();
helloVk.createRenderPass();
@ -258,7 +260,8 @@ int main(int argc, char** argv)
// Clearing screen
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});
// Offscreen render pass
@ -310,7 +313,6 @@ int main(int argc, char** argv)
helloVk.destroyResources();
helloVk.destroy();
vkctx.m_instance.destroySurfaceKHR(surface);
vkctx.deinit();
glfwDestroyWindow(window);

View file

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

View file

@ -36,13 +36,14 @@ extern std::vector<std::string> defaultSearchPaths;
#include "hello_vulkan.h"
#include "nvh//cameramanipulator.hpp"
#include "nvvkpp/descriptorsets_vkpp.hpp"
#include "nvvkpp/pipeline_vkpp.hpp"
#include "nvvk/descriptorsets_vk.hpp"
#include "nvvk/pipeline_vk.hpp"
#include "nvh/fileoperations.hpp"
#include "nvvkpp/commands_vkpp.hpp"
#include "nvvkpp/renderpass_vkpp.hpp"
#include "nvvkpp/utilities_vkpp.hpp"
#include "nvvk/commands_vk.hpp"
#include "nvvk/renderpasses_vk.hpp"
#include "nvvk/shaders_vk.hpp"
#include <random>
// Holding the camera matrices
@ -59,11 +60,12 @@ struct CameraMatrices
// Keep the handle on the device
// 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,
uint32_t queueFamily)
{
AppBase::setup(device, physicalDevice, queueFamily);
AppBase::setup(instance, device, physicalDevice, queueFamily);
m_alloc.init(device, physicalDevice);
m_debug.setup(m_device);
}
@ -100,34 +102,34 @@ void HelloVulkan::createDescriptorSetLayout()
uint32_t nbObj = static_cast<uint32_t>(m_objModel.size());
// Camera matrices (binding = 0)
m_descSetLayoutBind.emplace_back(
m_descSetLayoutBind.addBinding(
vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR));
// 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));
// Scene description (binding = 2)
m_descSetLayoutBind.emplace_back( //
m_descSetLayoutBind.addBinding( //
vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
// Textures (binding = 3)
m_descSetLayoutBind.emplace_back(
m_descSetLayoutBind.addBinding(
vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR));
// Materials Index (binding = 4)
m_descSetLayoutBind.emplace_back(
m_descSetLayoutBind.addBinding(
vkDS(4, vkDT::eStorageBuffer, nbObj + 1, vkSS::eFragment | vkSS::eClosestHitKHR));
// Storing vertices (binding = 5)
m_descSetLayoutBind.emplace_back( //
m_descSetLayoutBind.addBinding( //
vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
// Storing indices (binding = 6)
m_descSetLayoutBind.emplace_back( //
m_descSetLayoutBind.addBinding( //
vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
// Storing spheres (binding = 7)
m_descSetLayoutBind.emplace_back( //
m_descSetLayoutBind.addBinding( //
vkDS(7, vkDT::eStorageBuffer, 1, vkSS::eClosestHitKHR | vkSS::eIntersectionKHR));
m_descSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_descSetLayoutBind);
m_descPool = nvvkpp::util::createDescriptorPool(m_device, m_descSetLayoutBind, 1);
m_descSet = nvvkpp::util::createDescriptorSet(m_device, m_descPool, m_descSetLayout);
m_descSetLayout = m_descSetLayoutBind.createLayout(m_device);
m_descPool = m_descSetLayoutBind.createPool(m_device, 1);
m_descSet = nvvk::allocateDescriptorSet(m_device, m_descPool, m_descSetLayout);
}
//--------------------------------------------------------------------------------------------------
@ -139,9 +141,9 @@ void HelloVulkan::updateDescriptorSet()
// Camera matrices and scene description
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};
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
std::vector<vk::DescriptorBufferInfo> dbiMat;
@ -158,14 +160,13 @@ void HelloVulkan::updateDescriptorSet()
dbiMat.emplace_back(m_spheresMatColorBuffer.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(
nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[4], dbiMatIdx.data()));
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[5], dbiVert.data()));
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[6], dbiIdx.data()));
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 1, dbiMat.data()));
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 4, dbiMatIdx.data()));
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 5, dbiVert.data()));
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 6, dbiIdx.data()));
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
std::vector<vk::DescriptorImageInfo> diit;
@ -173,7 +174,7 @@ void HelloVulkan::updateDescriptorSet()
{
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
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
@ -200,18 +201,17 @@ void HelloVulkan::createGraphicsPipeline()
// Creating the Pipeline
std::vector<std::string> paths = defaultSearchPaths;
nvvkpp::GraphicsPipelineGenerator gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
gpb.depthStencilState = {true};
nvvk::GraphicsPipelineGeneratorCombined gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
gpb.depthStencilState.depthTestEnable = true;
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.vertexInputState.bindingDescriptions = {{0, sizeof(VertexObj)}};
gpb.vertexInputState.attributeDescriptions = {
{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
gpb.addBindingDescription({0, sizeof(VertexObj)});
gpb.addAttributeDescriptions({{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
{1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)},
{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");
}
@ -244,7 +244,7 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
// 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();
model.vertexBuffer =
m_alloc.createBuffer(cmdBuf, loader.m_vertices,
@ -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);
// Creates all textures found
createTextureImages(cmdBuf, loader.m_textures);
cmdBufGet.flushCommandBuffer(cmdBuf);
m_alloc.flushStaging();
cmdBufGet.submitAndWait(cmdBuf);
m_alloc.finalizeAndReleaseStaging();
std::string objNb = std::to_string(instance.objIndex);
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
@ -292,12 +292,12 @@ void HelloVulkan::createUniformBuffer()
void HelloVulkan::createSceneDescriptionBuffer()
{
using vkBU = vk::BufferUsageFlagBits;
nvvkpp::SingleCommandBuffer cmdGen(m_device, m_graphicsQueueIndex);
nvvk::CommandPool cmdGen(m_device, m_graphicsQueueIndex);
auto cmdBuf = cmdGen.createCommandBuffer();
m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer);
cmdGen.flushCommandBuffer(cmdBuf);
m_alloc.flushStaging();
cmdGen.submitAndWait(cmdBuf);
m_alloc.finalizeAndReleaseStaging();
m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc");
}
@ -317,20 +317,20 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
// If no textures are present, create a dummy one to accommodate the pipeline layout
if(textures.empty() && m_textures.empty())
{
nvvkTexture texture;
nvvk::Texture texture;
std::array<uint8_t, 4> color{255u, 255u, 255u, 255u};
vk::DeviceSize bufferSize = sizeof(color);
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
nvvkpp::image::setImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined,
nvvk::cmdBarrierImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eShaderReadOnlyOptimal);
m_textures.push_back(texture);
}
@ -358,16 +358,16 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4;
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;
texture = m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo);
nvvk::ImageDedicated image =
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);
}
}
@ -449,7 +449,7 @@ void HelloVulkan::rasterize(const vk::CommandBuffer& cmdBuf)
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.drawIndexed(model.nbIndices, 1, 0, 0, 0);
}
@ -479,49 +479,54 @@ void HelloVulkan::createOffscreenRender()
m_alloc.destroy(m_offscreenDepth);
// Creating the color image
auto colorCreateInfo = nvvkpp::image::create2DInfo(m_size, m_offscreenColorFormat,
{
auto colorCreateInfo = nvvk::makeImage2DCreateInfo(m_size, m_offscreenColorFormat,
vk::ImageUsageFlagBits::eColorAttachment
| vk::ImageUsageFlagBits::eSampled
| vk::ImageUsageFlagBits::eStorage);
m_offscreenColor = m_alloc.createImage(colorCreateInfo);
m_offscreenColor.descriptor =
nvvkpp::image::create2DDescriptor(m_device, m_offscreenColor.image, vk::SamplerCreateInfo{},
m_offscreenColorFormat, vk::ImageLayout::eGeneral);
nvvk::Image image = m_alloc.createImage(colorCreateInfo);
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
auto depthCreateInfo =
nvvkpp::image::create2DInfo(m_size, m_offscreenDepthFormat,
nvvk::makeImage2DCreateInfo(m_size, m_offscreenDepthFormat,
vk::ImageUsageFlagBits::eDepthStencilAttachment);
m_offscreenDepth = m_alloc.createImage(depthCreateInfo);
{
nvvk::Image image = m_alloc.createImage(depthCreateInfo);
vk::ImageViewCreateInfo depthStencilView;
depthStencilView.setViewType(vk::ImageViewType::e2D);
depthStencilView.setFormat(m_offscreenDepthFormat);
depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1});
depthStencilView.setImage(m_offscreenDepth.image);
m_offscreenDepth.descriptor.imageView = m_device.createImageView(depthStencilView);
depthStencilView.setImage(image.image);
m_offscreenDepth = m_alloc.createTexture(image, depthStencilView);
}
// 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();
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined,
nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eGeneral);
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageAspectFlagBits::eDepth,
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
if(!m_offscreenRenderPass)
{
m_offscreenRenderPass =
nvvkpp::util::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat,
1, 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
@ -558,13 +563,14 @@ void HelloVulkan::createPostPipeline()
// Pipeline: completely generic, no vertices
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),
vk::ShaderStageFlagBits::eVertex);
pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths),
vk::ShaderStageFlagBits::eFragment);
pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone);
m_postPipeline = pipelineGenerator.create();
m_postPipeline = pipelineGenerator.createPipeline();
m_debug.setObjectName(m_postPipeline, "post");
}
@ -578,10 +584,10 @@ void HelloVulkan::createPostDescriptor()
using vkDT = vk::DescriptorType;
using vkSS = vk::ShaderStageFlagBits;
m_postDescSetLayoutBind.emplace_back(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
m_postDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_postDescSetLayoutBind);
m_postDescPool = nvvkpp::util::createDescriptorPool(m_device, m_postDescSetLayoutBind);
m_postDescSet = nvvkpp::util::createDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
m_postDescSetLayoutBind.addBinding(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
m_postDescSetLayout = m_postDescSetLayoutBind.createLayout(m_device);
m_postDescPool = m_postDescSetLayoutBind.createPool(m_device);
m_postDescSet = nvvk::allocateDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
}
//--------------------------------------------------------------------------------------------------
@ -590,8 +596,7 @@ void HelloVulkan::createPostDescriptor()
void HelloVulkan::updatePostDescriptorSet()
{
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);
}
@ -629,13 +634,13 @@ void HelloVulkan::initRayTracing()
auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2,
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
//
nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model)
nvvk::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model)
{
vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate;
asCreate.setGeometryType(vk::GeometryTypeKHR::eTriangles);
@ -667,7 +672,7 @@ nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjM
offset.setPrimitiveOffset(0);
offset.setTransformOffset(0);
nvvkpp::RaytracingBuilderKHR::Blas blas;
nvvk::RaytracingBuilderKHR::Blas blas;
blas.asGeometry.emplace_back(asGeom);
blas.asCreateGeometryInfo.emplace_back(asCreate);
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
//
nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::sphereToVkGeometryKHR()
nvvk::RaytracingBuilderKHR::Blas HelloVulkan::sphereToVkGeometryKHR()
{
vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate;
asCreate.setGeometryType(vk::GeometryTypeKHR::eAabbs);
@ -705,7 +710,7 @@ nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::sphereToVkGeometryKHR()
offset.setPrimitiveOffset(0);
offset.setTransformOffset(0);
nvvkpp::RaytracingBuilderKHR::Blas blas;
nvvk::RaytracingBuilderKHR::Blas blas;
blas.asGeometry.emplace_back(asGeom);
blas.asCreateGeometryInfo.emplace_back(asCreate);
blas.asBuildOffsetInfo.emplace_back(offset);
@ -759,13 +764,13 @@ void HelloVulkan::createSpheres()
// Creating all buffers
using vkBU = vk::BufferUsageFlagBits;
nvvkpp::SingleCommandBuffer genCmdBuf(m_device, m_graphicsQueueIndex);
nvvk::CommandPool genCmdBuf(m_device, m_graphicsQueueIndex);
auto cmdBuf = genCmdBuf.createCommandBuffer();
m_spheresBuffer = m_alloc.createBuffer(cmdBuf, m_spheres, vkBU::eStorageBuffer);
m_spheresAabbBuffer = m_alloc.createBuffer(cmdBuf, aabbs, vkBU::eShaderDeviceAddress);
m_spheresMatIndexBuffer = m_alloc.createBuffer(cmdBuf, matIdx, vkBU::eStorageBuffer);
m_spheresMatColorBuffer = m_alloc.createBuffer(cmdBuf, materials, vkBU::eStorageBuffer);
genCmdBuf.flushCommandBuffer(cmdBuf);
genCmdBuf.submitAndWait(cmdBuf);
// Debug information
m_debug.setObjectName(m_spheresBuffer.buffer, "spheres");
@ -777,7 +782,7 @@ void HelloVulkan::createSpheres()
void HelloVulkan::createBottomLevelAS()
{
// BLAS - Storing each primitive in a geometry
std::vector<nvvkpp::RaytracingBuilderKHR::Blas> allBlas;
std::vector<nvvk::RaytracingBuilderKHR::Blas> allBlas;
allBlas.reserve(m_objModel.size());
for(const auto& obj : m_objModel)
{
@ -798,27 +803,27 @@ void HelloVulkan::createBottomLevelAS()
void HelloVulkan::createTopLevelAS()
{
std::vector<nvvkpp::RaytracingBuilderKHR::Instance> tlas;
std::vector<nvvk::RaytracingBuilderKHR::Instance> tlas;
tlas.reserve(m_objInstance.size());
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.instanceId = i; // gl_InstanceID
rayInst.blasId = m_objInstance[i].objIndex;
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);
}
// 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.instanceId = static_cast<uint32_t>(tlas.size()); // gl_InstanceID
rayInst.blasId = static_cast<uint32_t>(m_objModel.size());
rayInst.hitGroupId = 1; // We will use the same hit group for all objects
rayInst.flags = vk::GeometryInstanceFlagBitsKHR::eTriangleCullDisable;
rayInst.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
tlas.emplace_back(rayInst);
}
@ -834,25 +839,25 @@ void HelloVulkan::createRtDescriptorSet()
using vkSS = vk::ShaderStageFlagBits;
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
m_rtDescSetLayoutBind.emplace_back(
m_rtDescSetLayoutBind.addBinding(
vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image
m_rtDescPool = nvvkpp::util::createDescriptorPool(m_device, m_rtDescSetLayoutBind);
m_rtDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_rtDescSetLayoutBind);
m_rtDescPool = m_rtDescSetLayoutBind.createPool(m_device);
m_rtDescSetLayout = m_rtDescSetLayoutBind.createLayout(m_device);
m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0];
vk::AccelerationStructureKHR tlas = m_rtBuilder.getAccelerationStructure();
vk::WriteDescriptorSetAccelerationStructureKHR descASInfo;
descASInfo.setAccelerationStructureCount(1);
descASInfo.setPAccelerationStructures(&m_rtBuilder.getAccelerationStructure());
descASInfo.setPAccelerationStructures(&tlas);
vk::DescriptorImageInfo imageInfo{
{}, m_offscreenColor.descriptor.imageView, vk::ImageLayout::eGeneral};
std::vector<vk::WriteDescriptorSet> writes;
writes.emplace_back(
nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[0], &descASInfo));
writes.emplace_back(nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[1], &imageInfo));
writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 0, &descASInfo));
writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 1, &imageInfo));
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;
vk::ShaderModule raygenSM =
nvvkpp::util::createShaderModule(m_device, //
nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rgen.spv", true, paths));
vk::ShaderModule missSM =
nvvkpp::util::createShaderModule(m_device, //
nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths));
// The second miss shader is invoked when a shadow ray misses the geometry. It
// simply indicates that no occlusion has been found
vk::ShaderModule shadowmissSM = nvvkpp::util::createShaderModule(
m_device, nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
vk::ShaderModule shadowmissSM =
nvvk::createShaderModule(m_device,
nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
std::vector<vk::PipelineShaderStageCreateInfo> stages;
@ -916,7 +922,7 @@ void HelloVulkan::createRtPipeline()
// Hit Group0 - Closest Hit
vk::ShaderModule chitSM =
nvvkpp::util::createShaderModule(m_device, //
nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rchit.spv", true, paths));
{
@ -930,10 +936,10 @@ void HelloVulkan::createRtPipeline()
// Hit Group1 - Closest Hit + Intersection (procedural)
vk::ShaderModule chit2SM =
nvvkpp::util::createShaderModule(m_device, //
nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace2.rchit.spv", true, paths));
vk::ShaderModule rintSM =
nvvkpp::util::createShaderModule(m_device, //
nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rint.spv", true, paths));
{
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eProceduralHitGroup,
@ -1003,7 +1009,7 @@ void HelloVulkan::createRtShaderBindingTable()
m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize,
shaderHandleStorage.data());
// 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();
m_rtSBTBuffer =
@ -1011,9 +1017,9 @@ void HelloVulkan::createRtShaderBindingTable()
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
#include "nvvkpp/allocator_dedicated_vkpp.hpp"
#include "nvvkpp/appbase_vkpp.hpp"
#include "nvvkpp/debug_util_vkpp.hpp"
#define NVVK_ALLOC_DEDICATED
#include "nvvk/allocator_vk.hpp"
#include "nvvk/appbase_vkpp.hpp"
#include "nvvk/debug_util_vk.hpp"
#include "nvvk/descriptorsets_vk.hpp"
// #VKRay
#define ALLOC_DEDICATED
#include "nvvkpp/raytraceKHR_vkpp.hpp"
using nvvkBuffer = nvvkpp::BufferDedicated;
using nvvkTexture = nvvkpp::TextureDedicated;
#include "nvvk/raytraceKHR_vk.hpp"
//--------------------------------------------------------------------------------------------------
// Simple rasterizer of OBJ objects
@ -44,10 +42,11 @@ using nvvkTexture = nvvkpp::TextureDedicated;
// - Rendering is done in an offscreen framebuffer
// - 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:
void setup(const vk::Device& device,
void setup(const vk::Instance& instance,
const vk::Device& device,
const vk::PhysicalDevice& physicalDevice,
uint32_t queueFamily) override;
void createDescriptorSetLayout();
@ -68,10 +67,10 @@ public:
{
uint32_t nbIndices{0};
uint32_t nbVertices{0};
nvvkBuffer vertexBuffer; // Device buffer of all 'Vertex'
nvvkBuffer indexBuffer; // Device buffer of the indices forming triangles
nvvkBuffer matColorBuffer; // Device buffer of array of 'Wavefront material'
nvvkBuffer matIndexBuffer; // Device buffer of array of 'Wavefront material'
nvvk::Buffer vertexBuffer; // Device buffer of all 'Vertex'
nvvk::Buffer indexBuffer; // Device buffer of the indices forming triangles
nvvk::Buffer matColorBuffer; // Device buffer of array of 'Wavefront material'
nvvk::Buffer matIndexBuffer; // Device buffer of array of 'Wavefront material'
};
// Instance of the OBJ
@ -100,17 +99,17 @@ public:
// Graphic pipeline
vk::PipelineLayout m_pipelineLayout;
vk::Pipeline m_graphicsPipeline;
std::vector<vk::DescriptorSetLayoutBinding> m_descSetLayoutBind;
nvvk::DescriptorSetBindings m_descSetLayoutBind;
vk::DescriptorPool m_descPool;
vk::DescriptorSetLayout m_descSetLayout;
vk::DescriptorSet m_descSet;
nvvkBuffer m_cameraMat; // Device-Host of the camera matrices
nvvkBuffer m_sceneDesc; // Device buffer of the OBJ instances
std::vector<nvvkTexture> m_textures; // vector of all textures of the scene
nvvk::Buffer m_cameraMat; // Device-Host of the camera matrices
nvvk::Buffer m_sceneDesc; // Device buffer of the OBJ instances
std::vector<nvvk::Texture> m_textures; // vector of all textures of the scene
nvvkpp::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures
nvvkpp::DebugUtil m_debug; // Utility to name objects
nvvk::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures
nvvk::DebugUtil m_debug; // Utility to name objects
// #Post
void createOffscreenRender();
@ -119,7 +118,7 @@ public:
void updatePostDescriptorSet();
void drawPost(vk::CommandBuffer cmdBuf);
std::vector<vk::DescriptorSetLayoutBinding> m_postDescSetLayoutBind;
nvvk::DescriptorSetBindings m_postDescSetLayoutBind;
vk::DescriptorPool m_postDescPool;
vk::DescriptorSetLayout m_postDescSetLayout;
vk::DescriptorSet m_postDescSet;
@ -127,14 +126,14 @@ public:
vk::PipelineLayout m_postPipelineLayout;
vk::RenderPass m_offscreenRenderPass;
vk::Framebuffer m_offscreenFramebuffer;
nvvkTexture m_offscreenColor;
nvvk::Texture m_offscreenColor;
vk::Format m_offscreenColorFormat{vk::Format::eR32G32B32A32Sfloat};
nvvkTexture m_offscreenDepth;
nvvk::Texture m_offscreenDepth;
vk::Format m_offscreenDepthFormat{vk::Format::eD32Sfloat};
// #VKRay
void initRayTracing();
nvvkpp::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
nvvk::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
void createBottomLevelAS();
void createTopLevelAS();
void createRtDescriptorSet();
@ -145,15 +144,15 @@ public:
vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties;
nvvkpp::RaytracingBuilderKHR m_rtBuilder;
std::vector<vk::DescriptorSetLayoutBinding> m_rtDescSetLayoutBind;
nvvk::RaytracingBuilderKHR m_rtBuilder;
nvvk::DescriptorSetBindings m_rtDescSetLayoutBind;
vk::DescriptorPool m_rtDescPool;
vk::DescriptorSetLayout m_rtDescSetLayout;
vk::DescriptorSet m_rtDescSet;
std::vector<vk::RayTracingShaderGroupCreateInfoKHR> m_rtShaderGroups;
vk::PipelineLayout m_rtPipelineLayout;
vk::Pipeline m_rtPipeline;
nvvkBuffer m_rtSBTBuffer;
nvvk::Buffer m_rtSBTBuffer;
struct RtPushConstant
{
@ -176,12 +175,12 @@ public:
nvmath::vec3f maximum;
};
nvvkpp::RaytracingBuilderKHR::Blas sphereToVkGeometryKHR();
nvvk::RaytracingBuilderKHR::Blas sphereToVkGeometryKHR();
std::vector<Sphere> m_spheres; // All spheres
nvvkBuffer m_spheresBuffer; // Buffer holding the spheres
nvvkBuffer m_spheresAabbBuffer; // Buffer of all Aabb
nvvkBuffer m_spheresMatColorBuffer; // Multiple materials
nvvkBuffer m_spheresMatIndexBuffer; // Define which sphere uses which material
nvvk::Buffer m_spheresBuffer; // Buffer holding the spheres
nvvk::Buffer m_spheresAabbBuffer; // Buffer of all Aabb
nvvk::Buffer m_spheresMatColorBuffer; // Multiple materials
nvvk::Buffer m_spheresMatIndexBuffer; // Define which sphere uses which material
void createSpheres();
};

View file

@ -31,6 +31,7 @@
#include <array>
#include <vulkan/vulkan.hpp>
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
#include "imgui.h"
#include "imgui_impl_glfw.h"
@ -39,10 +40,10 @@
#include "nvh/cameramanipulator.hpp"
#include "nvh/fileoperations.hpp"
#include "nvpsystem.hpp"
#include "nvvkpp/appbase_vkpp.hpp"
#include "nvvkpp/commands_vkpp.hpp"
#include "nvvkpp/context_vkpp.hpp"
#include "nvvkpp/utilities_vkpp.hpp"
#include "nvvk/appbase_vkpp.hpp"
#include "nvvk/commands_vk.hpp"
#include "nvvk/context_vk.hpp"
//////////////////////////////////////////////////////////////////////////
#define UNUSED(x) (void)(x)
@ -124,7 +125,7 @@ int main(int argc, char** argv)
vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature;
// Requesting Vulkan extensions and layers
nvvkpp::ContextCreateInfo contextInfo(true);
nvvk::ContextCreateInfo contextInfo(true);
contextInfo.setVersion(1, 2);
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
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);
// Creating Vulkan base application
nvvkpp::Context vkctx{};
nvvk::Context vkctx{};
vkctx.initInstance(contextInfo);
// Find all compatible devices
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);
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.createDepthBuffer();
helloVk.createRenderPass();
@ -241,7 +243,8 @@ int main(int argc, char** argv)
// Clearing screen
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});
// Offscreen render pass
@ -293,7 +296,6 @@ int main(int argc, char** argv)
helloVk.destroyResources();
helloVk.destroy();
vkctx.m_instance.destroySurfaceKHR(surface);
vkctx.deinit();
glfwDestroyWindow(window);

View file

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

View file

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

View file

@ -36,13 +36,14 @@ extern std::vector<std::string> defaultSearchPaths;
#include "hello_vulkan.h"
#include "nvh//cameramanipulator.hpp"
#include "nvvkpp/descriptorsets_vkpp.hpp"
#include "nvvkpp/pipeline_vkpp.hpp"
#include "nvvk/descriptorsets_vk.hpp"
#include "nvvk/pipeline_vk.hpp"
#include "nvh/fileoperations.hpp"
#include "nvvkpp/commands_vkpp.hpp"
#include "nvvkpp/renderpass_vkpp.hpp"
#include "nvvkpp/utilities_vkpp.hpp"
#include "nvvk/commands_vk.hpp"
#include "nvvk/renderpasses_vk.hpp"
#include "nvvk/shaders_vk.hpp"
// Holding the camera matrices
struct CameraMatrices
@ -58,11 +59,12 @@ struct CameraMatrices
// Keep the handle on the device
// 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,
uint32_t queueFamily)
{
AppBase::setup(device, physicalDevice, queueFamily);
AppBase::setup(instance, device, physicalDevice, queueFamily);
m_alloc.init(device, physicalDevice);
m_debug.setup(m_device);
}
@ -99,31 +101,31 @@ void HelloVulkan::createDescriptorSetLayout()
uint32_t nbObj = static_cast<uint32_t>(m_objModel.size());
// Camera matrices (binding = 0)
m_descSetLayoutBind.emplace_back(
m_descSetLayoutBind.addBinding(
vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR));
// Materials (binding = 1)
m_descSetLayoutBind.emplace_back(
m_descSetLayoutBind.addBinding(
vkDS(1, vkDT::eStorageBuffer, nbObj, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
// Scene description (binding = 2)
m_descSetLayoutBind.emplace_back( //
m_descSetLayoutBind.addBinding( //
vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
// Textures (binding = 3)
m_descSetLayoutBind.emplace_back(
m_descSetLayoutBind.addBinding(
vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR));
// Materials (binding = 4)
m_descSetLayoutBind.emplace_back(
m_descSetLayoutBind.addBinding(
vkDS(4, vkDT::eStorageBuffer, nbObj, vkSS::eFragment | vkSS::eClosestHitKHR));
// Storing vertices (binding = 5)
m_descSetLayoutBind.emplace_back( //
m_descSetLayoutBind.addBinding( //
vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
// Storing indices (binding = 6)
m_descSetLayoutBind.emplace_back( //
m_descSetLayoutBind.addBinding( //
vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
m_descSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_descSetLayoutBind);
m_descPool = nvvkpp::util::createDescriptorPool(m_device, m_descSetLayoutBind, 1);
m_descSet = nvvkpp::util::createDescriptorSet(m_device, m_descPool, m_descSetLayout);
m_descSetLayout = m_descSetLayoutBind.createLayout(m_device);
m_descPool = m_descSetLayoutBind.createPool(m_device, 1);
m_descSet = nvvk::allocateDescriptorSet(m_device, m_descPool, m_descSetLayout);
}
//--------------------------------------------------------------------------------------------------
@ -135,9 +137,9 @@ void HelloVulkan::updateDescriptorSet()
// Camera matrices and scene description
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};
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
std::vector<vk::DescriptorBufferInfo> dbiMat;
@ -151,11 +153,10 @@ void HelloVulkan::updateDescriptorSet()
dbiVert.emplace_back(obj.vertexBuffer.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(
nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[4], dbiMatIdx.data()));
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[5], dbiVert.data()));
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[6], dbiIdx.data()));
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 1, dbiMat.data()));
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 4, dbiMatIdx.data()));
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 5, dbiVert.data()));
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 6, dbiIdx.data()));
// All texture samplers
std::vector<vk::DescriptorImageInfo> diit;
@ -163,7 +164,7 @@ void HelloVulkan::updateDescriptorSet()
{
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
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
@ -190,18 +191,17 @@ void HelloVulkan::createGraphicsPipeline()
// Creating the Pipeline
std::vector<std::string> paths = defaultSearchPaths;
nvvkpp::GraphicsPipelineGenerator gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
gpb.depthStencilState = {true};
nvvk::GraphicsPipelineGeneratorCombined gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
gpb.depthStencilState.depthTestEnable = true;
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.vertexInputState.bindingDescriptions = {{0, sizeof(VertexObj)}};
gpb.vertexInputState.attributeDescriptions = {
{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
gpb.addBindingDescription({0, sizeof(VertexObj)});
gpb.addAttributeDescriptions({{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
{1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)},
{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");
}
@ -234,7 +234,7 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
// 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();
model.vertexBuffer =
m_alloc.createBuffer(cmdBuf, loader.m_vertices,
@ -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);
// Creates all textures found
createTextureImages(cmdBuf, loader.m_textures);
cmdBufGet.flushCommandBuffer(cmdBuf);
m_alloc.flushStaging();
cmdBufGet.submitAndWait(cmdBuf);
m_alloc.finalizeAndReleaseStaging();
std::string objNb = std::to_string(instance.objIndex);
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
@ -282,12 +282,12 @@ void HelloVulkan::createUniformBuffer()
void HelloVulkan::createSceneDescriptionBuffer()
{
using vkBU = vk::BufferUsageFlagBits;
nvvkpp::SingleCommandBuffer cmdGen(m_device, m_graphicsQueueIndex);
nvvk::CommandPool cmdGen(m_device, m_graphicsQueueIndex);
auto cmdBuf = cmdGen.createCommandBuffer();
m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer);
cmdGen.flushCommandBuffer(cmdBuf);
m_alloc.flushStaging();
cmdGen.submitAndWait(cmdBuf);
m_alloc.finalizeAndReleaseStaging();
m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc");
}
@ -307,20 +307,20 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
// If no textures are present, create a dummy one to accommodate the pipeline layout
if(textures.empty() && m_textures.empty())
{
nvvkTexture texture;
nvvk::Texture texture;
std::array<uint8_t, 4> color{255u, 255u, 255u, 255u};
vk::DeviceSize bufferSize = sizeof(color);
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
nvvkpp::image::setImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined,
nvvk::cmdBarrierImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eShaderReadOnlyOptimal);
m_textures.push_back(texture);
}
@ -348,16 +348,16 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4;
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;
texture = m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo);
nvvk::ImageDedicated image =
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);
}
}
@ -434,7 +434,7 @@ void HelloVulkan::rasterize(const vk::CommandBuffer& cmdBuf)
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.drawIndexed(model.nbIndices, 1, 0, 0, 0);
}
@ -464,49 +464,54 @@ void HelloVulkan::createOffscreenRender()
m_alloc.destroy(m_offscreenDepth);
// Creating the color image
auto colorCreateInfo = nvvkpp::image::create2DInfo(m_size, m_offscreenColorFormat,
{
auto colorCreateInfo = nvvk::makeImage2DCreateInfo(m_size, m_offscreenColorFormat,
vk::ImageUsageFlagBits::eColorAttachment
| vk::ImageUsageFlagBits::eSampled
| vk::ImageUsageFlagBits::eStorage);
m_offscreenColor = m_alloc.createImage(colorCreateInfo);
m_offscreenColor.descriptor =
nvvkpp::image::create2DDescriptor(m_device, m_offscreenColor.image, vk::SamplerCreateInfo{},
m_offscreenColorFormat, vk::ImageLayout::eGeneral);
nvvk::Image image = m_alloc.createImage(colorCreateInfo);
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
auto depthCreateInfo =
nvvkpp::image::create2DInfo(m_size, m_offscreenDepthFormat,
nvvk::makeImage2DCreateInfo(m_size, m_offscreenDepthFormat,
vk::ImageUsageFlagBits::eDepthStencilAttachment);
m_offscreenDepth = m_alloc.createImage(depthCreateInfo);
{
nvvk::Image image = m_alloc.createImage(depthCreateInfo);
vk::ImageViewCreateInfo depthStencilView;
depthStencilView.setViewType(vk::ImageViewType::e2D);
depthStencilView.setFormat(m_offscreenDepthFormat);
depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1});
depthStencilView.setImage(m_offscreenDepth.image);
m_offscreenDepth.descriptor.imageView = m_device.createImageView(depthStencilView);
depthStencilView.setImage(image.image);
m_offscreenDepth = m_alloc.createTexture(image, depthStencilView);
}
// 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();
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined,
nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eGeneral);
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageAspectFlagBits::eDepth,
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
if(!m_offscreenRenderPass)
{
m_offscreenRenderPass =
nvvkpp::util::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat,
1, 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
@ -543,13 +548,14 @@ void HelloVulkan::createPostPipeline()
// Pipeline: completely generic, no vertices
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),
vk::ShaderStageFlagBits::eVertex);
pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths),
vk::ShaderStageFlagBits::eFragment);
pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone);
m_postPipeline = pipelineGenerator.create();
m_postPipeline = pipelineGenerator.createPipeline();
m_debug.setObjectName(m_postPipeline, "post");
}
@ -563,10 +569,10 @@ void HelloVulkan::createPostDescriptor()
using vkDT = vk::DescriptorType;
using vkSS = vk::ShaderStageFlagBits;
m_postDescSetLayoutBind.emplace_back(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
m_postDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_postDescSetLayoutBind);
m_postDescPool = nvvkpp::util::createDescriptorPool(m_device, m_postDescSetLayoutBind);
m_postDescSet = nvvkpp::util::createDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
m_postDescSetLayoutBind.addBinding(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
m_postDescSetLayout = m_postDescSetLayoutBind.createLayout(m_device);
m_postDescPool = m_postDescSetLayoutBind.createPool(m_device);
m_postDescSet = nvvk::allocateDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
}
//--------------------------------------------------------------------------------------------------
@ -575,8 +581,7 @@ void HelloVulkan::createPostDescriptor()
void HelloVulkan::updatePostDescriptorSet()
{
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);
}
@ -614,15 +619,15 @@ void HelloVulkan::initRayTracing()
auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2,
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
//
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;
asCreate.setGeometryType(vk::GeometryTypeKHR::eTriangles);
asCreate.setIndexType(vk::IndexType::eUint32);
@ -659,7 +664,7 @@ nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjM
void HelloVulkan::createBottomLevelAS()
{
// BLAS - Storing each primitive in a geometry
std::vector<nvvkpp::RaytracingBuilderKHR::Blas> allBlas;
std::vector<nvvk::RaytracingBuilderKHR::Blas> allBlas;
allBlas.reserve(m_objModel.size());
for(const auto& obj : m_objModel)
{
@ -673,16 +678,16 @@ void HelloVulkan::createBottomLevelAS()
void HelloVulkan::createTopLevelAS()
{
std::vector<nvvkpp::RaytracingBuilderKHR::Instance> tlas;
std::vector<nvvk::RaytracingBuilderKHR::Instance> tlas;
tlas.reserve(m_objInstance.size());
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.instanceId = i; // gl_InstanceID
rayInst.blasId = m_objInstance[i].objIndex;
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);
}
m_rtBuilder.buildTlas(tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace);
@ -697,25 +702,25 @@ void HelloVulkan::createRtDescriptorSet()
using vkSS = vk::ShaderStageFlagBits;
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
m_rtDescSetLayoutBind.emplace_back(
m_rtDescSetLayoutBind.addBinding(
vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image
m_rtDescPool = nvvkpp::util::createDescriptorPool(m_device, m_rtDescSetLayoutBind);
m_rtDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_rtDescSetLayoutBind);
m_rtDescPool = m_rtDescSetLayoutBind.createPool(m_device);
m_rtDescSetLayout = m_rtDescSetLayoutBind.createLayout(m_device);
m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0];
vk::AccelerationStructureKHR tlas = m_rtBuilder.getAccelerationStructure();
vk::WriteDescriptorSetAccelerationStructureKHR descASInfo;
descASInfo.setAccelerationStructureCount(1);
descASInfo.setPAccelerationStructures(&m_rtBuilder.getAccelerationStructure());
descASInfo.setPAccelerationStructures(&tlas);
vk::DescriptorImageInfo imageInfo{
{}, m_offscreenColor.descriptor.imageView, vk::ImageLayout::eGeneral};
std::vector<vk::WriteDescriptorSet> writes;
writes.emplace_back(
nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[0], &descASInfo));
writes.emplace_back(nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[1], &imageInfo));
writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 0, &descASInfo));
writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 1, &imageInfo));
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;
vk::ShaderModule raygenSM =
nvvkpp::util::createShaderModule(m_device, //
nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rgen.spv", true, paths));
vk::ShaderModule missSM =
nvvkpp::util::createShaderModule(m_device, //
nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths));
// The second miss shader is invoked when a shadow ray misses the geometry. It
// simply indicates that no occlusion has been found
vk::ShaderModule shadowmissSM = nvvkpp::util::createShaderModule(
m_device, nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
vk::ShaderModule shadowmissSM =
nvvk::createShaderModule(m_device,
nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
std::vector<vk::PipelineShaderStageCreateInfo> stages;
@ -779,7 +785,7 @@ void HelloVulkan::createRtPipeline()
// Hit Group - Closest Hit + AnyHit
vk::ShaderModule chitSM =
nvvkpp::util::createShaderModule(m_device, //
nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rchit.spv", true, paths));
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup,
@ -844,7 +850,7 @@ void HelloVulkan::createRtShaderBindingTable()
m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize,
shaderHandleStorage.data());
// 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();
m_rtSBTBuffer =
@ -852,9 +858,9 @@ void HelloVulkan::createRtShaderBindingTable()
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
#include "nvvkpp/allocator_dedicated_vkpp.hpp"
#include "nvvkpp/appbase_vkpp.hpp"
#include "nvvkpp/debug_util_vkpp.hpp"
#define NVVK_ALLOC_DEDICATED
#include "nvvk/allocator_vk.hpp"
#include "nvvk/appbase_vkpp.hpp"
#include "nvvk/debug_util_vk.hpp"
#include "nvvk/descriptorsets_vk.hpp"
// #VKRay
#define ALLOC_DEDICATED
#include "nvvkpp/raytraceKHR_vkpp.hpp"
using nvvkBuffer = nvvkpp::BufferDedicated;
using nvvkTexture = nvvkpp::TextureDedicated;
#include "nvvk/raytraceKHR_vk.hpp"
//--------------------------------------------------------------------------------------------------
// Simple rasterizer of OBJ objects
@ -44,10 +42,11 @@ using nvvkTexture = nvvkpp::TextureDedicated;
// - Rendering is done in an offscreen framebuffer
// - 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:
void setup(const vk::Device& device,
void setup(const vk::Instance& instance,
const vk::Device& device,
const vk::PhysicalDevice& physicalDevice,
uint32_t queueFamily) override;
void createDescriptorSetLayout();
@ -68,10 +67,10 @@ public:
{
uint32_t nbIndices{0};
uint32_t nbVertices{0};
nvvkBuffer vertexBuffer; // Device buffer of all 'Vertex'
nvvkBuffer indexBuffer; // Device buffer of the indices forming triangles
nvvkBuffer matColorBuffer; // Device buffer of array of 'Wavefront material'
nvvkBuffer matIndexBuffer; // Device buffer of array of 'Wavefront material'
nvvk::Buffer vertexBuffer; // Device buffer of all 'Vertex'
nvvk::Buffer indexBuffer; // Device buffer of the indices forming triangles
nvvk::Buffer matColorBuffer; // Device buffer of array of 'Wavefront material'
nvvk::Buffer matIndexBuffer; // Device buffer of array of 'Wavefront material'
};
// Instance of the OBJ
@ -100,17 +99,17 @@ public:
// Graphic pipeline
vk::PipelineLayout m_pipelineLayout;
vk::Pipeline m_graphicsPipeline;
std::vector<vk::DescriptorSetLayoutBinding> m_descSetLayoutBind;
nvvk::DescriptorSetBindings m_descSetLayoutBind;
vk::DescriptorPool m_descPool;
vk::DescriptorSetLayout m_descSetLayout;
vk::DescriptorSet m_descSet;
nvvkBuffer m_cameraMat; // Device-Host of the camera matrices
nvvkBuffer m_sceneDesc; // Device buffer of the OBJ instances
std::vector<nvvkTexture> m_textures; // vector of all textures of the scene
nvvk::Buffer m_cameraMat; // Device-Host of the camera matrices
nvvk::Buffer m_sceneDesc; // Device buffer of the OBJ instances
std::vector<nvvk::Texture> m_textures; // vector of all textures of the scene
nvvkpp::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures
nvvkpp::DebugUtil m_debug; // Utility to name objects
nvvk::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures
nvvk::DebugUtil m_debug; // Utility to name objects
// #Post
void createOffscreenRender();
@ -119,7 +118,7 @@ public:
void updatePostDescriptorSet();
void drawPost(vk::CommandBuffer cmdBuf);
std::vector<vk::DescriptorSetLayoutBinding> m_postDescSetLayoutBind;
nvvk::DescriptorSetBindings m_postDescSetLayoutBind;
vk::DescriptorPool m_postDescPool;
vk::DescriptorSetLayout m_postDescSetLayout;
vk::DescriptorSet m_postDescSet;
@ -127,14 +126,14 @@ public:
vk::PipelineLayout m_postPipelineLayout;
vk::RenderPass m_offscreenRenderPass;
vk::Framebuffer m_offscreenFramebuffer;
nvvkTexture m_offscreenColor;
nvvk::Texture m_offscreenColor;
vk::Format m_offscreenColorFormat{vk::Format::eR32G32B32A32Sfloat};
nvvkTexture m_offscreenDepth;
nvvk::Texture m_offscreenDepth;
vk::Format m_offscreenDepthFormat{vk::Format::eD32Sfloat};
// #VKRay
void initRayTracing();
nvvkpp::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
nvvk::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
void createBottomLevelAS();
void createTopLevelAS();
void createRtDescriptorSet();
@ -146,15 +145,15 @@ public:
void updateFrame();
vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties;
nvvkpp::RaytracingBuilderKHR m_rtBuilder;
std::vector<vk::DescriptorSetLayoutBinding> m_rtDescSetLayoutBind;
nvvk::RaytracingBuilderKHR m_rtBuilder;
nvvk::DescriptorSetBindings m_rtDescSetLayoutBind;
vk::DescriptorPool m_rtDescPool;
vk::DescriptorSetLayout m_rtDescSetLayout;
vk::DescriptorSet m_rtDescSet;
std::vector<vk::RayTracingShaderGroupCreateInfoKHR> m_rtShaderGroups;
vk::PipelineLayout m_rtPipelineLayout;
vk::Pipeline m_rtPipeline;
nvvkBuffer m_rtSBTBuffer;
nvvk::Buffer m_rtSBTBuffer;
int m_maxFrames{100};
struct RtPushConstant

View file

@ -31,6 +31,7 @@
#include <array>
#include <vulkan/vulkan.hpp>
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
#include "imgui.h"
#include "imgui_impl_glfw.h"
@ -39,10 +40,10 @@
#include "nvh/cameramanipulator.hpp"
#include "nvh/fileoperations.hpp"
#include "nvpsystem.hpp"
#include "nvvkpp/appbase_vkpp.hpp"
#include "nvvkpp/commands_vkpp.hpp"
#include "nvvkpp/context_vkpp.hpp"
#include "nvvkpp/utilities_vkpp.hpp"
#include "nvvk/appbase_vkpp.hpp"
#include "nvvk/commands_vk.hpp"
#include "nvvk/context_vk.hpp"
//////////////////////////////////////////////////////////////////////////
#define UNUSED(x) (void)(x)
@ -132,7 +133,7 @@ int main(int argc, char** argv)
vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature;
// Requesting Vulkan extensions and layers
nvvkpp::ContextCreateInfo contextInfo(true);
nvvk::ContextCreateInfo contextInfo(true);
contextInfo.setVersion(1, 2);
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
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);
// Creating Vulkan base application
nvvkpp::Context vkctx{};
nvvk::Context vkctx{};
vkctx.initInstance(contextInfo);
// Find all compatible devices
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);
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.createDepthBuffer();
helloVk.createRenderPass();
@ -254,7 +256,8 @@ int main(int argc, char** argv)
// Clearing screen
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});
// Offscreen render pass
@ -306,7 +309,6 @@ int main(int argc, char** argv)
helloVk.destroyResources();
helloVk.destroy();
vkctx.m_instance.destroySurfaceKHR(surface);
vkctx.deinit();
glfwDestroyWindow(window);

View file

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

View file

@ -36,13 +36,14 @@ extern std::vector<std::string> defaultSearchPaths;
#include "hello_vulkan.h"
#include "nvh//cameramanipulator.hpp"
#include "nvvkpp/descriptorsets_vkpp.hpp"
#include "nvvkpp/pipeline_vkpp.hpp"
#include "nvvk/descriptorsets_vk.hpp"
#include "nvvk/pipeline_vk.hpp"
#include "nvh/fileoperations.hpp"
#include "nvvkpp/commands_vkpp.hpp"
#include "nvvkpp/renderpass_vkpp.hpp"
#include "nvvkpp/utilities_vkpp.hpp"
#include "nvvk/commands_vk.hpp"
#include "nvvk/renderpasses_vk.hpp"
#include "nvvk/shaders_vk.hpp"
// Holding the camera matrices
struct CameraMatrices
@ -58,11 +59,12 @@ struct CameraMatrices
// Keep the handle on the device
// 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,
uint32_t queueFamily)
{
AppBase::setup(device, physicalDevice, queueFamily);
AppBase::setup(instance, device, physicalDevice, queueFamily);
m_alloc.init(device, physicalDevice);
m_debug.setup(m_device);
}
@ -99,31 +101,31 @@ void HelloVulkan::createDescriptorSetLayout()
uint32_t nbObj = static_cast<uint32_t>(m_objModel.size());
// Camera matrices (binding = 0)
m_descSetLayoutBind.emplace_back(
m_descSetLayoutBind.addBinding(
vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR));
// Materials (binding = 1)
m_descSetLayoutBind.emplace_back(
m_descSetLayoutBind.addBinding(
vkDS(1, vkDT::eStorageBuffer, nbObj, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
// Scene description (binding = 2)
m_descSetLayoutBind.emplace_back( //
m_descSetLayoutBind.addBinding( //
vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
// Textures (binding = 3)
m_descSetLayoutBind.emplace_back(
m_descSetLayoutBind.addBinding(
vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR));
// Materials (binding = 4)
m_descSetLayoutBind.emplace_back(
m_descSetLayoutBind.addBinding(
vkDS(4, vkDT::eStorageBuffer, nbObj, vkSS::eFragment | vkSS::eClosestHitKHR));
// Storing vertices (binding = 5)
m_descSetLayoutBind.emplace_back( //
m_descSetLayoutBind.addBinding( //
vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
// Storing indices (binding = 6)
m_descSetLayoutBind.emplace_back( //
m_descSetLayoutBind.addBinding( //
vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
m_descSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_descSetLayoutBind);
m_descPool = nvvkpp::util::createDescriptorPool(m_device, m_descSetLayoutBind, 1);
m_descSet = nvvkpp::util::createDescriptorSet(m_device, m_descPool, m_descSetLayout);
m_descSetLayout = m_descSetLayoutBind.createLayout(m_device);
m_descPool = m_descSetLayoutBind.createPool(m_device, 1);
m_descSet = nvvk::allocateDescriptorSet(m_device, m_descPool, m_descSetLayout);
}
//--------------------------------------------------------------------------------------------------
@ -135,9 +137,9 @@ void HelloVulkan::updateDescriptorSet()
// Camera matrices and scene description
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};
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
std::vector<vk::DescriptorBufferInfo> dbiMat;
@ -151,11 +153,10 @@ void HelloVulkan::updateDescriptorSet()
dbiVert.push_back({m_objModel[i].vertexBuffer.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(
nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[4], dbiMatIdx.data()));
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[5], dbiVert.data()));
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[6], dbiIdx.data()));
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 1, dbiMat.data()));
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 4, dbiMatIdx.data()));
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 5, dbiVert.data()));
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 6, dbiIdx.data()));
// All texture samplers
std::vector<vk::DescriptorImageInfo> diit;
@ -163,7 +164,7 @@ void HelloVulkan::updateDescriptorSet()
{
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
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
@ -190,18 +191,17 @@ void HelloVulkan::createGraphicsPipeline()
// Creating the Pipeline
std::vector<std::string> paths = defaultSearchPaths;
nvvkpp::GraphicsPipelineGenerator gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
gpb.depthStencilState = {true};
nvvk::GraphicsPipelineGeneratorCombined gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
gpb.depthStencilState.depthTestEnable = true;
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.vertexInputState.bindingDescriptions = {{0, sizeof(VertexObj)}};
gpb.vertexInputState.attributeDescriptions = {
{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
gpb.addBindingDescription({0, sizeof(VertexObj)});
gpb.addAttributeDescriptions({{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
{1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)},
{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");
}
@ -234,7 +234,7 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
// 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();
model.vertexBuffer =
m_alloc.createBuffer(cmdBuf, loader.m_vertices,
@ -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);
// Creates all textures found
createTextureImages(cmdBuf, loader.m_textures);
cmdBufGet.flushCommandBuffer(cmdBuf);
m_alloc.flushStaging();
cmdBufGet.submitAndWait(cmdBuf);
m_alloc.finalizeAndReleaseStaging();
std::string objNb = std::to_string(instance.objIndex);
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
@ -282,12 +282,12 @@ void HelloVulkan::createUniformBuffer()
void HelloVulkan::createSceneDescriptionBuffer()
{
using vkBU = vk::BufferUsageFlagBits;
nvvkpp::SingleCommandBuffer cmdGen(m_device, m_graphicsQueueIndex);
nvvk::CommandPool cmdGen(m_device, m_graphicsQueueIndex);
auto cmdBuf = cmdGen.createCommandBuffer();
m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer);
cmdGen.flushCommandBuffer(cmdBuf);
m_alloc.flushStaging();
cmdGen.submitAndWait(cmdBuf);
m_alloc.finalizeAndReleaseStaging();
m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc");
}
@ -307,20 +307,20 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
// If no textures are present, create a dummy one to accommodate the pipeline layout
if(textures.empty() && m_textures.empty())
{
nvvkTexture texture;
nvvk::Texture texture;
std::array<uint8_t, 4> color{255u, 255u, 255u, 255u};
vk::DeviceSize bufferSize = sizeof(color);
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
nvvkpp::image::setImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined,
nvvk::cmdBarrierImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eShaderReadOnlyOptimal);
m_textures.push_back(texture);
}
@ -348,16 +348,16 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4;
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;
texture = m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo);
nvvk::ImageDedicated image =
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);
}
}
@ -434,7 +434,7 @@ void HelloVulkan::rasterize(const vk::CommandBuffer& cmdBuf)
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.drawIndexed(model.nbIndices, 1, 0, 0, 0);
}
@ -464,49 +464,54 @@ void HelloVulkan::createOffscreenRender()
m_alloc.destroy(m_offscreenDepth);
// Creating the color image
auto colorCreateInfo = nvvkpp::image::create2DInfo(m_size, m_offscreenColorFormat,
{
auto colorCreateInfo = nvvk::makeImage2DCreateInfo(m_size, m_offscreenColorFormat,
vk::ImageUsageFlagBits::eColorAttachment
| vk::ImageUsageFlagBits::eSampled
| vk::ImageUsageFlagBits::eStorage);
m_offscreenColor = m_alloc.createImage(colorCreateInfo);
m_offscreenColor.descriptor =
nvvkpp::image::create2DDescriptor(m_device, m_offscreenColor.image, vk::SamplerCreateInfo{},
m_offscreenColorFormat, vk::ImageLayout::eGeneral);
nvvk::Image image = m_alloc.createImage(colorCreateInfo);
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
auto depthCreateInfo =
nvvkpp::image::create2DInfo(m_size, m_offscreenDepthFormat,
nvvk::makeImage2DCreateInfo(m_size, m_offscreenDepthFormat,
vk::ImageUsageFlagBits::eDepthStencilAttachment);
m_offscreenDepth = m_alloc.createImage(depthCreateInfo);
{
nvvk::Image image = m_alloc.createImage(depthCreateInfo);
vk::ImageViewCreateInfo depthStencilView;
depthStencilView.setViewType(vk::ImageViewType::e2D);
depthStencilView.setFormat(m_offscreenDepthFormat);
depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1});
depthStencilView.setImage(m_offscreenDepth.image);
m_offscreenDepth.descriptor.imageView = m_device.createImageView(depthStencilView);
depthStencilView.setImage(image.image);
m_offscreenDepth = m_alloc.createTexture(image, depthStencilView);
}
// 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();
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined,
nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eGeneral);
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageAspectFlagBits::eDepth,
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
if(!m_offscreenRenderPass)
{
m_offscreenRenderPass =
nvvkpp::util::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat,
1, 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
@ -543,13 +548,14 @@ void HelloVulkan::createPostPipeline()
// Pipeline: completely generic, no vertices
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),
vk::ShaderStageFlagBits::eVertex);
pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths),
vk::ShaderStageFlagBits::eFragment);
pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone);
m_postPipeline = pipelineGenerator.create();
m_postPipeline = pipelineGenerator.createPipeline();
m_debug.setObjectName(m_postPipeline, "post");
}
@ -563,10 +569,10 @@ void HelloVulkan::createPostDescriptor()
using vkDT = vk::DescriptorType;
using vkSS = vk::ShaderStageFlagBits;
m_postDescSetLayoutBind.emplace_back(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
m_postDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_postDescSetLayoutBind);
m_postDescPool = nvvkpp::util::createDescriptorPool(m_device, m_postDescSetLayoutBind);
m_postDescSet = nvvkpp::util::createDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
m_postDescSetLayoutBind.addBinding(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
m_postDescSetLayout = m_postDescSetLayoutBind.createLayout(m_device);
m_postDescPool = m_postDescSetLayoutBind.createPool(m_device);
m_postDescSet = nvvk::allocateDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
}
//--------------------------------------------------------------------------------------------------
@ -575,8 +581,7 @@ void HelloVulkan::createPostDescriptor()
void HelloVulkan::updatePostDescriptorSet()
{
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);
}
@ -614,15 +619,15 @@ void HelloVulkan::initRayTracing()
auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2,
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
//
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;
asCreate.setGeometryType(vk::GeometryTypeKHR::eTriangles);
asCreate.setIndexType(vk::IndexType::eUint32);
@ -659,7 +664,7 @@ nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjM
void HelloVulkan::createBottomLevelAS()
{
// BLAS - Storing each primitive in a geometry
std::vector<nvvkpp::RaytracingBuilderKHR::Blas> allBlas;
std::vector<nvvk::RaytracingBuilderKHR::Blas> allBlas;
allBlas.reserve(m_objModel.size());
for(const auto& obj : m_objModel)
{
@ -673,17 +678,16 @@ void HelloVulkan::createBottomLevelAS()
void HelloVulkan::createTopLevelAS()
{
std::vector<nvvkpp::RaytracingBuilderKHR::Instance> tlas;
std::vector<nvvk::RaytracingBuilderKHR::Instance> tlas;
tlas.reserve(m_objInstance.size());
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.instanceId = i; // gl_InstanceID
rayInst.blasId = m_objInstance[i].objIndex;
rayInst.hitGroupId = 0; // We will use the same hit group for all objects
rayInst.flags = vk::GeometryInstanceFlagBitsKHR::eTriangleCullDisable;
rayInst.hitGroupId = m_objInstance[i].hitgroup;
rayInst.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
rayInst.hitGroupId = m_objInstance[i].hitgroup; // Using the hit group set in main
tlas.emplace_back(rayInst);
}
m_rtBuilder.buildTlas(tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace);
@ -698,25 +702,25 @@ void HelloVulkan::createRtDescriptorSet()
using vkSS = vk::ShaderStageFlagBits;
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
m_rtDescSetLayoutBind.emplace_back(
m_rtDescSetLayoutBind.addBinding(
vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image
m_rtDescPool = nvvkpp::util::createDescriptorPool(m_device, m_rtDescSetLayoutBind);
m_rtDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_rtDescSetLayoutBind);
m_rtDescPool = m_rtDescSetLayoutBind.createPool(m_device);
m_rtDescSetLayout = m_rtDescSetLayoutBind.createLayout(m_device);
m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0];
vk::AccelerationStructureKHR tlas = m_rtBuilder.getAccelerationStructure();
vk::WriteDescriptorSetAccelerationStructureKHR descASInfo;
descASInfo.setAccelerationStructureCount(1);
descASInfo.setPAccelerationStructures(&m_rtBuilder.getAccelerationStructure());
descASInfo.setPAccelerationStructures(&tlas);
vk::DescriptorImageInfo imageInfo{
{}, m_offscreenColor.descriptor.imageView, vk::ImageLayout::eGeneral};
std::vector<vk::WriteDescriptorSet> writes;
writes.emplace_back(
nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[0], &descASInfo));
writes.emplace_back(nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[1], &imageInfo));
writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 0, &descASInfo));
writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 1, &imageInfo));
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;
vk::ShaderModule raygenSM =
nvvkpp::util::createShaderModule(m_device, //
nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rgen.spv", true, paths));
vk::ShaderModule missSM =
nvvkpp::util::createShaderModule(m_device, //
nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths));
// The second miss shader is invoked when a shadow ray misses the geometry. It
// simply indicates that no occlusion has been found
vk::ShaderModule shadowmissSM = nvvkpp::util::createShaderModule(
m_device, nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
vk::ShaderModule shadowmissSM =
nvvk::createShaderModule(m_device,
nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
std::vector<vk::PipelineShaderStageCreateInfo> stages;
@ -780,10 +785,10 @@ void HelloVulkan::createRtPipeline()
// Hit Group - Closest Hit + AnyHit
vk::ShaderModule chitSM =
nvvkpp::util::createShaderModule(m_device, //
nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rchit.spv", true, paths));
vk::ShaderModule chit2SM =
nvvkpp::util::createShaderModule(m_device, //
nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace2.rchit.spv", true, paths));
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup,
@ -893,7 +898,7 @@ void HelloVulkan::createRtShaderBindingTable()
}
// 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();
m_rtSBTBuffer = m_alloc.createBuffer(cmdBuf, sbtBuffer, vk::BufferUsageFlagBits::eRayTracingKHR);
@ -901,9 +906,9 @@ void HelloVulkan::createRtShaderBindingTable()
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
#include "nvvkpp/allocator_dedicated_vkpp.hpp"
#include "nvvkpp/appbase_vkpp.hpp"
#include "nvvkpp/debug_util_vkpp.hpp"
#define NVVK_ALLOC_DEDICATED
#include "nvvk/allocator_vk.hpp"
#include "nvvk/appbase_vkpp.hpp"
#include "nvvk/debug_util_vk.hpp"
#include "nvvk/descriptorsets_vk.hpp"
// #VKRay
#define ALLOC_DEDICATED
#include "nvvkpp/raytraceKHR_vkpp.hpp"
using nvvkBuffer = nvvkpp::BufferDedicated;
using nvvkTexture = nvvkpp::TextureDedicated;
#include "nvvk/raytraceKHR_vk.hpp"
//--------------------------------------------------------------------------------------------------
// Simple rasterizer of OBJ objects
@ -44,10 +42,11 @@ using nvvkTexture = nvvkpp::TextureDedicated;
// - Rendering is done in an offscreen framebuffer
// - 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:
void setup(const vk::Device& device,
void setup(const vk::Instance& instance,
const vk::Device& device,
const vk::PhysicalDevice& physicalDevice,
uint32_t queueFamily) override;
void createDescriptorSetLayout();
@ -68,10 +67,10 @@ public:
{
uint32_t nbIndices{0};
uint32_t nbVertices{0};
nvvkBuffer vertexBuffer; // Device buffer of all 'Vertex'
nvvkBuffer indexBuffer; // Device buffer of the indices forming triangles
nvvkBuffer matColorBuffer; // Device buffer of array of 'Wavefront material'
nvvkBuffer matIndexBuffer; // Device buffer of array of 'Wavefront material'
nvvk::Buffer vertexBuffer; // Device buffer of all 'Vertex'
nvvk::Buffer indexBuffer; // Device buffer of the indices forming triangles
nvvk::Buffer matColorBuffer; // Device buffer of array of 'Wavefront material'
nvvk::Buffer matIndexBuffer; // Device buffer of array of 'Wavefront material'
};
// Instance of the OBJ
@ -101,17 +100,17 @@ public:
// Graphic pipeline
vk::PipelineLayout m_pipelineLayout;
vk::Pipeline m_graphicsPipeline;
std::vector<vk::DescriptorSetLayoutBinding> m_descSetLayoutBind;
nvvk::DescriptorSetBindings m_descSetLayoutBind;
vk::DescriptorPool m_descPool;
vk::DescriptorSetLayout m_descSetLayout;
vk::DescriptorSet m_descSet;
nvvkBuffer m_cameraMat; // Device-Host of the camera matrices
nvvkBuffer m_sceneDesc; // Device buffer of the OBJ instances
std::vector<nvvkTexture> m_textures; // vector of all textures of the scene
nvvk::Buffer m_cameraMat; // Device-Host of the camera matrices
nvvk::Buffer m_sceneDesc; // Device buffer of the OBJ instances
std::vector<nvvk::Texture> m_textures; // vector of all textures of the scene
nvvkpp::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures
nvvkpp::DebugUtil m_debug; // Utility to name objects
nvvk::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures
nvvk::DebugUtil m_debug; // Utility to name objects
// #Post
void createOffscreenRender();
@ -120,7 +119,7 @@ public:
void updatePostDescriptorSet();
void drawPost(vk::CommandBuffer cmdBuf);
std::vector<vk::DescriptorSetLayoutBinding> m_postDescSetLayoutBind;
nvvk::DescriptorSetBindings m_postDescSetLayoutBind;
vk::DescriptorPool m_postDescPool;
vk::DescriptorSetLayout m_postDescSetLayout;
vk::DescriptorSet m_postDescSet;
@ -128,14 +127,14 @@ public:
vk::PipelineLayout m_postPipelineLayout;
vk::RenderPass m_offscreenRenderPass;
vk::Framebuffer m_offscreenFramebuffer;
nvvkTexture m_offscreenColor;
nvvk::Texture m_offscreenColor;
vk::Format m_offscreenColorFormat{vk::Format::eR32G32B32A32Sfloat};
nvvkTexture m_offscreenDepth;
nvvk::Texture m_offscreenDepth;
vk::Format m_offscreenDepthFormat{vk::Format::eD32Sfloat};
// #VKRay
void initRayTracing();
nvvkpp::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
nvvk::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
void createBottomLevelAS();
void createTopLevelAS();
void createRtDescriptorSet();
@ -146,15 +145,15 @@ public:
vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties;
nvvkpp::RaytracingBuilderKHR m_rtBuilder;
std::vector<vk::DescriptorSetLayoutBinding> m_rtDescSetLayoutBind;
nvvk::RaytracingBuilderKHR m_rtBuilder;
nvvk::DescriptorSetBindings m_rtDescSetLayoutBind;
vk::DescriptorPool m_rtDescPool;
vk::DescriptorSetLayout m_rtDescSetLayout;
vk::DescriptorSet m_rtDescSet;
std::vector<vk::RayTracingShaderGroupCreateInfoKHR> m_rtShaderGroups;
vk::PipelineLayout m_rtPipelineLayout;
vk::Pipeline m_rtPipeline;
nvvkBuffer m_rtSBTBuffer;
nvvk::Buffer m_rtSBTBuffer;
struct RtPushConstant
{

View file

@ -31,6 +31,7 @@
#include <array>
#include <vulkan/vulkan.hpp>
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
#include "imgui.h"
#include "imgui_impl_glfw.h"
@ -39,10 +40,9 @@
#include "nvh/cameramanipulator.hpp"
#include "nvh/fileoperations.hpp"
#include "nvpsystem.hpp"
#include "nvvkpp/appbase_vkpp.hpp"
#include "nvvkpp/commands_vkpp.hpp"
#include "nvvkpp/context_vkpp.hpp"
#include "nvvkpp/utilities_vkpp.hpp"
#include "nvvk/appbase_vkpp.hpp"
#include "nvvk/commands_vk.hpp"
#include "nvvk/context_vk.hpp"
//////////////////////////////////////////////////////////////////////////
#define UNUSED(x) (void)(x)
@ -124,7 +124,7 @@ int main(int argc, char** argv)
vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature;
// Requesting Vulkan extensions and layers
nvvkpp::ContextCreateInfo contextInfo(true);
nvvk::ContextCreateInfo contextInfo(true);
contextInfo.setVersion(1, 2);
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
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);
// Creating Vulkan base application
nvvkpp::Context vkctx{};
nvvk::Context vkctx{};
vkctx.initInstance(contextInfo);
// Find all compatible devices
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);
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.createDepthBuffer();
helloVk.createRenderPass();
@ -251,7 +252,8 @@ int main(int argc, char** argv)
// Clearing screen
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});
// Offscreen render pass
@ -303,7 +305,6 @@ int main(int argc, char** argv)
helloVk.destroyResources();
helloVk.destroy();
vkctx.m_instance.destroySurfaceKHR(surface);
vkctx.deinit();
glfwDestroyWindow(window);

View file

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

View file

@ -36,13 +36,13 @@ extern std::vector<std::string> defaultSearchPaths;
#include "hello_vulkan.h"
#include "nvh//cameramanipulator.hpp"
#include "nvvkpp/descriptorsets_vkpp.hpp"
#include "nvvkpp/pipeline_vkpp.hpp"
#include "nvvk/descriptorsets_vk.hpp"
#include "nvvk/pipeline_vk.hpp"
#include "nvh/fileoperations.hpp"
#include "nvvkpp/commands_vkpp.hpp"
#include "nvvkpp/renderpass_vkpp.hpp"
#include "nvvkpp/utilities_vkpp.hpp"
#include "nvvk/commands_vk.hpp"
#include "nvvk/renderpasses_vk.hpp"
// Holding the camera matrices
struct CameraMatrices
@ -58,11 +58,12 @@ struct CameraMatrices
// Keep the handle on the device
// 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,
uint32_t queueFamily)
{
AppBase::setup(device, physicalDevice, queueFamily);
AppBase::setup(instance, device, physicalDevice, queueFamily);
m_alloc.init(device, physicalDevice);
m_debug.setup(m_device);
}
@ -99,33 +100,33 @@ void HelloVulkan::createDescriptorSetLayout()
uint32_t nbObj = static_cast<uint32_t>(m_objModel.size());
// Camera matrices (binding = 0)
m_descSetLayoutBind.emplace_back(
m_descSetLayoutBind.addBinding(
vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR));
// Materials (binding = 1)
m_descSetLayoutBind.emplace_back(
m_descSetLayoutBind.addBinding(
vkDS(1, vkDT::eStorageBuffer, nbObj, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
// Scene description (binding = 2)
m_descSetLayoutBind.emplace_back( //
m_descSetLayoutBind.addBinding( //
vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
// Textures (binding = 3)
m_descSetLayoutBind.emplace_back(
m_descSetLayoutBind.addBinding(
vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR));
// Materials (binding = 4)
m_descSetLayoutBind.emplace_back(
m_descSetLayoutBind.addBinding(
vkDS(4, vkDT::eStorageBuffer, nbObj, vkSS::eFragment | vkSS::eClosestHitKHR));
// Storing vertices (binding = 5)
m_descSetLayoutBind.emplace_back( //
m_descSetLayoutBind.addBinding( //
vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
// Storing indices (binding = 6)
m_descSetLayoutBind.emplace_back( //
m_descSetLayoutBind.addBinding( //
vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
// The top level acceleration structure
m_descSetLayoutBind.emplace_back( //
m_descSetLayoutBind.addBinding( //
vkDS(7, vkDT::eAccelerationStructureKHR, 1, vkSS::eFragment));
m_descSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_descSetLayoutBind);
m_descPool = nvvkpp::util::createDescriptorPool(m_device, m_descSetLayoutBind, 1);
m_descSet = nvvkpp::util::createDescriptorSet(m_device, m_descPool, m_descSetLayout);
m_descSetLayout = m_descSetLayoutBind.createLayout(m_device);
m_descPool = m_descSetLayoutBind.createPool(m_device, 1);
m_descSet = nvvk::allocateDescriptorSet(m_device, m_descPool, m_descSetLayout);
}
//--------------------------------------------------------------------------------------------------
@ -137,9 +138,9 @@ void HelloVulkan::updateDescriptorSet()
// Camera matrices and scene description
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};
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
std::vector<vk::DescriptorBufferInfo> dbiMat;
@ -153,11 +154,10 @@ void HelloVulkan::updateDescriptorSet()
dbiVert.emplace_back(obj.vertexBuffer.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(
nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[4], dbiMatIdx.data()));
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[5], dbiVert.data()));
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[6], dbiIdx.data()));
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 1, dbiMat.data()));
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 4, dbiMatIdx.data()));
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 5, dbiVert.data()));
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 6, dbiIdx.data()));
// All texture samplers
std::vector<vk::DescriptorImageInfo> diit;
@ -165,13 +165,13 @@ void HelloVulkan::updateDescriptorSet()
{
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;
descASInfo.setAccelerationStructureCount(1);
descASInfo.setPAccelerationStructures(&m_rtBuilder.getAccelerationStructure());
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));
// Writing the information
@ -199,18 +199,17 @@ void HelloVulkan::createGraphicsPipeline()
// Creating the Pipeline
std::vector<std::string> paths = defaultSearchPaths;
nvvkpp::GraphicsPipelineGenerator gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
gpb.depthStencilState = {true};
nvvk::GraphicsPipelineGeneratorCombined gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
gpb.depthStencilState.depthTestEnable = true;
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.vertexInputState.bindingDescriptions = {{0, sizeof(VertexObj)}};
gpb.vertexInputState.attributeDescriptions = {
{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
gpb.addBindingDescription({0, sizeof(VertexObj)});
gpb.addAttributeDescriptions({{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
{1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)},
{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");
}
@ -243,7 +242,7 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
// 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();
model.vertexBuffer =
m_alloc.createBuffer(cmdBuf, loader.m_vertices,
@ -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);
// Creates all textures found
createTextureImages(cmdBuf, loader.m_textures);
cmdBufGet.flushCommandBuffer(cmdBuf);
m_alloc.flushStaging();
cmdBufGet.submitAndWait(cmdBuf);
m_alloc.finalizeAndReleaseStaging();
std::string objNb = std::to_string(instance.objIndex);
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
@ -291,12 +290,12 @@ void HelloVulkan::createUniformBuffer()
void HelloVulkan::createSceneDescriptionBuffer()
{
using vkBU = vk::BufferUsageFlagBits;
nvvkpp::SingleCommandBuffer cmdGen(m_device, m_graphicsQueueIndex);
nvvk::CommandPool cmdGen(m_device, m_graphicsQueueIndex);
auto cmdBuf = cmdGen.createCommandBuffer();
m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer);
cmdGen.flushCommandBuffer(cmdBuf);
m_alloc.flushStaging();
cmdGen.submitAndWait(cmdBuf);
m_alloc.finalizeAndReleaseStaging();
m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc");
}
@ -316,20 +315,20 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
// If no textures are present, create a dummy one to accommodate the pipeline layout
if(textures.empty() && m_textures.empty())
{
nvvkTexture texture;
nvvk::Texture texture;
std::array<uint8_t, 4> color{255u, 255u, 255u, 255u};
vk::DeviceSize bufferSize = sizeof(color);
auto imgSize = vk::Extent2D(1, 1);
auto imageCreateInfo = nvvkpp::image::create2DInfo(imgSize, format);
auto imageCreateInfo = nvvk::makeImage2DCreateInfo(imgSize, format);
// 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);
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);
// 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);
m_textures.push_back(texture);
}
@ -357,16 +356,15 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4;
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;
texture = m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo);
nvvk::Image image = 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);
}
}
@ -438,7 +436,7 @@ void HelloVulkan::rasterize(const vk::CommandBuffer& cmdBuf)
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.drawIndexed(model.nbIndices, 1, 0, 0, 0);
}
@ -467,49 +465,54 @@ void HelloVulkan::createOffscreenRender()
m_alloc.destroy(m_offscreenDepth);
// Creating the color image
auto colorCreateInfo = nvvkpp::image::create2DInfo(m_size, m_offscreenColorFormat,
{
auto colorCreateInfo = nvvk::makeImage2DCreateInfo(m_size, m_offscreenColorFormat,
vk::ImageUsageFlagBits::eColorAttachment
| vk::ImageUsageFlagBits::eSampled
| vk::ImageUsageFlagBits::eStorage);
m_offscreenColor = m_alloc.createImage(colorCreateInfo);
m_offscreenColor.descriptor =
nvvkpp::image::create2DDescriptor(m_device, m_offscreenColor.image, vk::SamplerCreateInfo{},
m_offscreenColorFormat, vk::ImageLayout::eGeneral);
nvvk::Image image = m_alloc.createImage(colorCreateInfo);
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
auto depthCreateInfo =
nvvkpp::image::create2DInfo(m_size, m_offscreenDepthFormat,
nvvk::makeImage2DCreateInfo(m_size, m_offscreenDepthFormat,
vk::ImageUsageFlagBits::eDepthStencilAttachment);
m_offscreenDepth = m_alloc.createImage(depthCreateInfo);
{
nvvk::Image image = m_alloc.createImage(depthCreateInfo);
vk::ImageViewCreateInfo depthStencilView;
depthStencilView.setViewType(vk::ImageViewType::e2D);
depthStencilView.setFormat(m_offscreenDepthFormat);
depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1});
depthStencilView.setImage(m_offscreenDepth.image);
m_offscreenDepth.descriptor.imageView = m_device.createImageView(depthStencilView);
depthStencilView.setImage(image.image);
m_offscreenDepth = m_alloc.createTexture(image, depthStencilView);
}
// 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();
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined,
nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eGeneral);
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageAspectFlagBits::eDepth,
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
if(!m_offscreenRenderPass)
{
m_offscreenRenderPass =
nvvkpp::util::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat,
1, 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
@ -546,13 +549,14 @@ void HelloVulkan::createPostPipeline()
// Pipeline: completely generic, no vertices
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),
vk::ShaderStageFlagBits::eVertex);
pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths),
vk::ShaderStageFlagBits::eFragment);
pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone);
m_postPipeline = pipelineGenerator.create();
m_postPipeline = pipelineGenerator.createPipeline();
m_debug.setObjectName(m_postPipeline, "post");
}
@ -566,10 +570,10 @@ void HelloVulkan::createPostDescriptor()
using vkDT = vk::DescriptorType;
using vkSS = vk::ShaderStageFlagBits;
m_postDescSetLayoutBind.emplace_back(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
m_postDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_postDescSetLayoutBind);
m_postDescPool = nvvkpp::util::createDescriptorPool(m_device, m_postDescSetLayoutBind);
m_postDescSet = nvvkpp::util::createDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
m_postDescSetLayoutBind.addBinding(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
m_postDescSetLayout = m_postDescSetLayoutBind.createLayout(m_device);
m_postDescPool = m_postDescSetLayoutBind.createPool(m_device);
m_postDescSet = nvvk::allocateDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
}
//--------------------------------------------------------------------------------------------------
@ -578,8 +582,7 @@ void HelloVulkan::createPostDescriptor()
void HelloVulkan::updatePostDescriptorSet()
{
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);
}
@ -617,13 +620,13 @@ void HelloVulkan::initRayTracing()
auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2,
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
//
nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model)
nvvk::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjModel& model)
{
// Setting up the creation info of acceleration structure
vk::AccelerationStructureCreateGeometryTypeInfoKHR asCreate;
@ -660,7 +663,7 @@ nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjM
offset.setTransformOffset(0);
// 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.asCreateGeometryInfo.emplace_back(asCreate);
blas.asBuildOffsetInfo.emplace_back(offset);
@ -674,7 +677,7 @@ nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjM
void HelloVulkan::createBottomLevelAS()
{
// BLAS - Storing each primitive in a geometry
std::vector<nvvkpp::RaytracingBuilderKHR::Blas> allBlas;
std::vector<nvvk::RaytracingBuilderKHR::Blas> allBlas;
allBlas.reserve(m_objModel.size());
for(const auto& obj : m_objModel)
{
@ -688,16 +691,16 @@ void HelloVulkan::createBottomLevelAS()
void HelloVulkan::createTopLevelAS()
{
std::vector<nvvkpp::RaytracingBuilderKHR::Instance> tlas;
std::vector<nvvk::RaytracingBuilderKHR::Instance> tlas;
tlas.reserve(m_objInstance.size());
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.instanceId = i; // gl_InstanceID
rayInst.blasId = m_objInstance[i].objIndex;
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);
}
m_rtBuilder.buildTlas(tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace);

View file

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

View file

@ -30,8 +30,10 @@
// at the top of imgui.cpp.
#include <array>
#include <iostream>
#include <vulkan/vulkan.hpp>
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
#include "imgui.h"
#include "imgui_impl_glfw.h"
@ -40,10 +42,10 @@
#include "nvh/cameramanipulator.hpp"
#include "nvh/fileoperations.hpp"
#include "nvpsystem.hpp"
#include "nvvkpp/appbase_vkpp.hpp"
#include "nvvkpp/commands_vkpp.hpp"
#include "nvvkpp/context_vkpp.hpp"
#include "nvvkpp/utilities_vkpp.hpp"
#include "nvvk/appbase_vkpp.hpp"
#include "nvvk/commands_vk.hpp"
#include "nvvk/context_vk.hpp"
//////////////////////////////////////////////////////////////////////////
#define UNUSED(x) (void)(x)
@ -125,7 +127,7 @@ int main(int argc, char** argv)
vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature;
// Requesting Vulkan extensions and layers
nvvkpp::ContextCreateInfo contextInfo(true);
nvvk::ContextCreateInfo contextInfo(true);
contextInfo.setVersion(1, 2);
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
contextInfo.addInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME);
@ -148,7 +150,7 @@ int main(int argc, char** argv)
// Creating Vulkan base application
nvvkpp::Context vkctx{};
nvvk::Context vkctx{};
vkctx.initInstance(contextInfo);
// Find all compatible devices
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);
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.createDepthBuffer();
helloVk.createRenderPass();
@ -238,7 +241,8 @@ int main(int argc, char** argv)
// Clearing screen
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});
// Offscreen render pass
@ -297,7 +301,6 @@ int main(int argc, char** argv)
helloVk.destroyResources();
helloVk.destroy();
vkctx.m_instance.destroySurfaceKHR(surface);
vkctx.deinit();
glfwDestroyWindow(window);

View file

@ -36,13 +36,14 @@ extern std::vector<std::string> defaultSearchPaths;
#include "hello_vulkan.h"
#include "nvh//cameramanipulator.hpp"
#include "nvvkpp/descriptorsets_vkpp.hpp"
#include "nvvkpp/pipeline_vkpp.hpp"
#include "nvvk/descriptorsets_vk.hpp"
#include "nvvk/pipeline_vk.hpp"
#include "nvh/fileoperations.hpp"
#include "nvvkpp/commands_vkpp.hpp"
#include "nvvkpp/renderpass_vkpp.hpp"
#include "nvvkpp/utilities_vkpp.hpp"
#include "nvvk/commands_vk.hpp"
#include "nvvk/renderpasses_vk.hpp"
#include "nvvk/shaders_vk.hpp"
// Holding the camera matrices
struct CameraMatrices
@ -58,11 +59,12 @@ struct CameraMatrices
// Keep the handle on the device
// 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,
uint32_t queueFamily)
{
AppBase::setup(device, physicalDevice, queueFamily);
AppBase::setup(instance, device, physicalDevice, queueFamily);
m_alloc.init(device, physicalDevice);
m_debug.setup(m_device);
}
@ -99,31 +101,31 @@ void HelloVulkan::createDescriptorSetLayout()
uint32_t nbObj = static_cast<uint32_t>(m_objModel.size());
// Camera matrices (binding = 0)
m_descSetLayoutBind.emplace_back(
m_descSetLayoutBind.addBinding(
vkDS(0, vkDT::eUniformBuffer, 1, vkSS::eVertex | vkSS::eRaygenKHR));
// Materials (binding = 1)
m_descSetLayoutBind.emplace_back(
m_descSetLayoutBind.addBinding(
vkDS(1, vkDT::eStorageBuffer, nbObj, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
// Scene description (binding = 2)
m_descSetLayoutBind.emplace_back( //
m_descSetLayoutBind.addBinding( //
vkDS(2, vkDT::eStorageBuffer, 1, vkSS::eVertex | vkSS::eFragment | vkSS::eClosestHitKHR));
// Textures (binding = 3)
m_descSetLayoutBind.emplace_back(
m_descSetLayoutBind.addBinding(
vkDS(3, vkDT::eCombinedImageSampler, nbTxt, vkSS::eFragment | vkSS::eClosestHitKHR));
// Materials (binding = 4)
m_descSetLayoutBind.emplace_back(
m_descSetLayoutBind.addBinding(
vkDS(4, vkDT::eStorageBuffer, nbObj, vkSS::eFragment | vkSS::eClosestHitKHR));
// Storing vertices (binding = 5)
m_descSetLayoutBind.emplace_back( //
m_descSetLayoutBind.addBinding( //
vkDS(5, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
// Storing indices (binding = 6)
m_descSetLayoutBind.emplace_back( //
m_descSetLayoutBind.addBinding( //
vkDS(6, vkDT::eStorageBuffer, nbObj, vkSS::eClosestHitKHR));
m_descSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_descSetLayoutBind);
m_descPool = nvvkpp::util::createDescriptorPool(m_device, m_descSetLayoutBind, 1);
m_descSet = nvvkpp::util::createDescriptorSet(m_device, m_descPool, m_descSetLayout);
m_descSetLayout = m_descSetLayoutBind.createLayout(m_device);
m_descPool = m_descSetLayoutBind.createPool(m_device, 1);
m_descSet = nvvk::allocateDescriptorSet(m_device, m_descPool, m_descSetLayout);
}
//--------------------------------------------------------------------------------------------------
@ -135,9 +137,9 @@ void HelloVulkan::updateDescriptorSet()
// Camera matrices and scene description
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};
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
std::vector<vk::DescriptorBufferInfo> dbiMat;
@ -151,11 +153,10 @@ void HelloVulkan::updateDescriptorSet()
dbiVert.push_back({m_objModel[i].vertexBuffer.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(
nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[4], dbiMatIdx.data()));
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[5], dbiVert.data()));
writes.emplace_back(nvvkpp::util::createWrite(m_descSet, m_descSetLayoutBind[6], dbiIdx.data()));
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 1, dbiMat.data()));
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 4, dbiMatIdx.data()));
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 5, dbiVert.data()));
writes.emplace_back(m_descSetLayoutBind.makeWriteArray(m_descSet, 6, dbiIdx.data()));
// All texture samplers
std::vector<vk::DescriptorImageInfo> diit;
@ -163,7 +164,7 @@ void HelloVulkan::updateDescriptorSet()
{
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
m_device.updateDescriptorSets(static_cast<uint32_t>(writes.size()), writes.data(), 0, nullptr);
@ -190,18 +191,17 @@ void HelloVulkan::createGraphicsPipeline()
// Creating the Pipeline
std::vector<std::string> paths = defaultSearchPaths;
nvvkpp::GraphicsPipelineGenerator gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
gpb.depthStencilState = {true};
nvvk::GraphicsPipelineGeneratorCombined gpb(m_device, m_pipelineLayout, m_offscreenRenderPass);
gpb.depthStencilState.depthTestEnable = true;
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.vertexInputState.bindingDescriptions = {{0, sizeof(VertexObj)}};
gpb.vertexInputState.attributeDescriptions = {
{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
gpb.addBindingDescription({0, sizeof(VertexObj)});
gpb.addAttributeDescriptions({{0, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, pos)},
{1, 0, vk::Format::eR32G32B32Sfloat, offsetof(VertexObj, nrm)},
{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");
}
@ -234,7 +234,7 @@ void HelloVulkan::loadModel(const std::string& filename, nvmath::mat4f transform
model.nbVertices = static_cast<uint32_t>(loader.m_vertices.size());
// 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();
model.vertexBuffer =
m_alloc.createBuffer(cmdBuf, loader.m_vertices,
@ -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);
// Creates all textures found
createTextureImages(cmdBuf, loader.m_textures);
cmdBufGet.flushCommandBuffer(cmdBuf);
m_alloc.flushStaging();
cmdBufGet.submitAndWait(cmdBuf);
m_alloc.finalizeAndReleaseStaging();
std::string objNb = std::to_string(instance.objIndex);
m_debug.setObjectName(model.vertexBuffer.buffer, (std::string("vertex_" + objNb).c_str()));
@ -282,12 +282,12 @@ void HelloVulkan::createUniformBuffer()
void HelloVulkan::createSceneDescriptionBuffer()
{
using vkBU = vk::BufferUsageFlagBits;
nvvkpp::SingleCommandBuffer cmdGen(m_device, m_graphicsQueueIndex);
nvvk::CommandPool cmdGen(m_device, m_graphicsQueueIndex);
auto cmdBuf = cmdGen.createCommandBuffer();
m_sceneDesc = m_alloc.createBuffer(cmdBuf, m_objInstance, vkBU::eStorageBuffer);
cmdGen.flushCommandBuffer(cmdBuf);
m_alloc.flushStaging();
cmdGen.submitAndWait(cmdBuf);
m_alloc.finalizeAndReleaseStaging();
m_debug.setObjectName(m_sceneDesc.buffer, "sceneDesc");
}
@ -307,20 +307,20 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
// If no textures are present, create a dummy one to accommodate the pipeline layout
if(textures.empty() && m_textures.empty())
{
nvvkTexture texture;
nvvk::Texture texture;
std::array<uint8_t, 4> color{255u, 255u, 255u, 255u};
vk::DeviceSize bufferSize = sizeof(color);
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
nvvkpp::image::setImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined,
nvvk::cmdBarrierImageLayout(cmdBuf, texture.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eShaderReadOnlyOptimal);
m_textures.push_back(texture);
}
@ -348,16 +348,16 @@ void HelloVulkan::createTextureImages(const vk::CommandBuffer& cmdBuf,
vk::DeviceSize bufferSize = static_cast<uint64_t>(texWidth) * texHeight * sizeof(uint8_t) * 4;
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;
texture = m_alloc.createImage(cmdBuf, bufferSize, pixels, imageCreateInfo);
nvvk::ImageDedicated image =
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);
}
}
@ -434,7 +434,7 @@ void HelloVulkan::rasterize(const vk::CommandBuffer& cmdBuf)
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.drawIndexed(model.nbIndices, 1, 0, 0, 0);
}
@ -464,49 +464,54 @@ void HelloVulkan::createOffscreenRender()
m_alloc.destroy(m_offscreenDepth);
// Creating the color image
auto colorCreateInfo = nvvkpp::image::create2DInfo(m_size, m_offscreenColorFormat,
{
auto colorCreateInfo = nvvk::makeImage2DCreateInfo(m_size, m_offscreenColorFormat,
vk::ImageUsageFlagBits::eColorAttachment
| vk::ImageUsageFlagBits::eSampled
| vk::ImageUsageFlagBits::eStorage);
m_offscreenColor = m_alloc.createImage(colorCreateInfo);
m_offscreenColor.descriptor =
nvvkpp::image::create2DDescriptor(m_device, m_offscreenColor.image, vk::SamplerCreateInfo{},
m_offscreenColorFormat, vk::ImageLayout::eGeneral);
nvvk::Image image = m_alloc.createImage(colorCreateInfo);
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
auto depthCreateInfo =
nvvkpp::image::create2DInfo(m_size, m_offscreenDepthFormat,
nvvk::makeImage2DCreateInfo(m_size, m_offscreenDepthFormat,
vk::ImageUsageFlagBits::eDepthStencilAttachment);
m_offscreenDepth = m_alloc.createImage(depthCreateInfo);
{
nvvk::Image image = m_alloc.createImage(depthCreateInfo);
vk::ImageViewCreateInfo depthStencilView;
depthStencilView.setViewType(vk::ImageViewType::e2D);
depthStencilView.setFormat(m_offscreenDepthFormat);
depthStencilView.setSubresourceRange({vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1});
depthStencilView.setImage(m_offscreenDepth.image);
m_offscreenDepth.descriptor.imageView = m_device.createImageView(depthStencilView);
depthStencilView.setImage(image.image);
m_offscreenDepth = m_alloc.createTexture(image, depthStencilView);
}
// 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();
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined,
nvvk::cmdBarrierImageLayout(cmdBuf, m_offscreenColor.image, vk::ImageLayout::eUndefined,
vk::ImageLayout::eGeneral);
nvvkpp::image::setImageLayout(cmdBuf, m_offscreenDepth.image, vk::ImageAspectFlagBits::eDepth,
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
if(!m_offscreenRenderPass)
{
m_offscreenRenderPass =
nvvkpp::util::createRenderPass(m_device, {m_offscreenColorFormat}, m_offscreenDepthFormat,
1, 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
@ -543,13 +548,14 @@ void HelloVulkan::createPostPipeline()
// Pipeline: completely generic, no vertices
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),
vk::ShaderStageFlagBits::eVertex);
pipelineGenerator.addShader(nvh::loadFile("shaders/post.frag.spv", true, paths),
vk::ShaderStageFlagBits::eFragment);
pipelineGenerator.rasterizationState.setCullMode(vk::CullModeFlagBits::eNone);
m_postPipeline = pipelineGenerator.create();
m_postPipeline = pipelineGenerator.createPipeline();
m_debug.setObjectName(m_postPipeline, "post");
}
@ -563,10 +569,10 @@ void HelloVulkan::createPostDescriptor()
using vkDT = vk::DescriptorType;
using vkSS = vk::ShaderStageFlagBits;
m_postDescSetLayoutBind.emplace_back(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
m_postDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_postDescSetLayoutBind);
m_postDescPool = nvvkpp::util::createDescriptorPool(m_device, m_postDescSetLayoutBind);
m_postDescSet = nvvkpp::util::createDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
m_postDescSetLayoutBind.addBinding(vkDS(0, vkDT::eCombinedImageSampler, 1, vkSS::eFragment));
m_postDescSetLayout = m_postDescSetLayoutBind.createLayout(m_device);
m_postDescPool = m_postDescSetLayoutBind.createPool(m_device);
m_postDescSet = nvvk::allocateDescriptorSet(m_device, m_postDescPool, m_postDescSetLayout);
}
//--------------------------------------------------------------------------------------------------
@ -575,8 +581,7 @@ void HelloVulkan::createPostDescriptor()
void HelloVulkan::updatePostDescriptorSet()
{
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);
}
@ -614,15 +619,15 @@ void HelloVulkan::initRayTracing()
auto properties = m_physicalDevice.getProperties2<vk::PhysicalDeviceProperties2,
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
//
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;
asCreate.setGeometryType(vk::GeometryTypeKHR::eTriangles);
asCreate.setIndexType(vk::IndexType::eUint32);
@ -659,7 +664,7 @@ nvvkpp::RaytracingBuilderKHR::Blas HelloVulkan::objectToVkGeometryKHR(const ObjM
void HelloVulkan::createBottomLevelAS()
{
// BLAS - Storing each primitive in a geometry
std::vector<nvvkpp::RaytracingBuilderKHR::Blas> allBlas;
std::vector<nvvk::RaytracingBuilderKHR::Blas> allBlas;
allBlas.reserve(m_objModel.size());
for(const auto& obj : m_objModel)
{
@ -673,16 +678,16 @@ void HelloVulkan::createBottomLevelAS()
void HelloVulkan::createTopLevelAS()
{
std::vector<nvvkpp::RaytracingBuilderKHR::Instance> tlas;
std::vector<nvvk::RaytracingBuilderKHR::Instance> tlas;
tlas.reserve(m_objInstance.size());
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.instanceId = i; // gl_InstanceID
rayInst.blasId = m_objInstance[i].objIndex;
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);
}
m_rtBuilder.buildTlas(tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace);
@ -697,25 +702,25 @@ void HelloVulkan::createRtDescriptorSet()
using vkSS = vk::ShaderStageFlagBits;
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
m_rtDescSetLayoutBind.emplace_back(
m_rtDescSetLayoutBind.addBinding(
vkDSLB(1, vkDT::eStorageImage, 1, vkSS::eRaygenKHR)); // Output image
m_rtDescPool = nvvkpp::util::createDescriptorPool(m_device, m_rtDescSetLayoutBind);
m_rtDescSetLayout = nvvkpp::util::createDescriptorSetLayout(m_device, m_rtDescSetLayoutBind);
m_rtDescPool = m_rtDescSetLayoutBind.createPool(m_device);
m_rtDescSetLayout = m_rtDescSetLayoutBind.createLayout(m_device);
m_rtDescSet = m_device.allocateDescriptorSets({m_rtDescPool, 1, &m_rtDescSetLayout})[0];
vk::AccelerationStructureKHR tlas = m_rtBuilder.getAccelerationStructure();
vk::WriteDescriptorSetAccelerationStructureKHR descASInfo;
descASInfo.setAccelerationStructureCount(1);
descASInfo.setPAccelerationStructures(&m_rtBuilder.getAccelerationStructure());
descASInfo.setPAccelerationStructures(&tlas);
vk::DescriptorImageInfo imageInfo{
{}, m_offscreenColor.descriptor.imageView, vk::ImageLayout::eGeneral};
std::vector<vk::WriteDescriptorSet> writes;
writes.emplace_back(
nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[0], &descASInfo));
writes.emplace_back(nvvkpp::util::createWrite(m_rtDescSet, m_rtDescSetLayoutBind[1], &imageInfo));
writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 0, &descASInfo));
writes.emplace_back(m_rtDescSetLayoutBind.makeWrite(m_rtDescSet, 1, &imageInfo));
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;
vk::ShaderModule raygenSM =
nvvkpp::util::createShaderModule(m_device, //
nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rgen.spv", true, paths));
vk::ShaderModule missSM =
nvvkpp::util::createShaderModule(m_device, //
nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rmiss.spv", true, paths));
// The second miss shader is invoked when a shadow ray misses the geometry. It
// simply indicates that no occlusion has been found
vk::ShaderModule shadowmissSM = nvvkpp::util::createShaderModule(
m_device, nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
vk::ShaderModule shadowmissSM =
nvvk::createShaderModule(m_device,
nvh::loadFile("shaders/raytraceShadow.rmiss.spv", true, paths));
std::vector<vk::PipelineShaderStageCreateInfo> stages;
@ -779,7 +785,7 @@ void HelloVulkan::createRtPipeline()
// Hit Group - Closest Hit + AnyHit
vk::ShaderModule chitSM =
nvvkpp::util::createShaderModule(m_device, //
nvvk::createShaderModule(m_device, //
nvh::loadFile("shaders/raytrace.rchit.spv", true, paths));
vk::RayTracingShaderGroupCreateInfoKHR hg{vk::RayTracingShaderGroupTypeKHR::eTrianglesHitGroup,
@ -844,7 +850,7 @@ void HelloVulkan::createRtShaderBindingTable()
m_device.getRayTracingShaderGroupHandlesKHR(m_rtPipeline, 0, groupCount, sbtSize,
shaderHandleStorage.data());
// 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();
m_rtSBTBuffer =
@ -852,9 +858,9 @@ void HelloVulkan::createRtShaderBindingTable()
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
#include "nvvkpp/allocator_dedicated_vkpp.hpp"
#include "nvvkpp/appbase_vkpp.hpp"
#include "nvvkpp/debug_util_vkpp.hpp"
#define NVVK_ALLOC_DEDICATED
#include "nvvk/allocator_vk.hpp"
#include "nvvk/appbase_vkpp.hpp"
#include "nvvk/debug_util_vk.hpp"
#include "nvvk/descriptorsets_vk.hpp"
// #VKRay
#define ALLOC_DEDICATED
#include "nvvkpp/raytraceKHR_vkpp.hpp"
using nvvkBuffer = nvvkpp::BufferDedicated;
using nvvkTexture = nvvkpp::TextureDedicated;
#include "nvvk/raytraceKHR_vk.hpp"
//--------------------------------------------------------------------------------------------------
// Simple rasterizer of OBJ objects
@ -44,10 +42,11 @@ using nvvkTexture = nvvkpp::TextureDedicated;
// - Rendering is done in an offscreen framebuffer
// - 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:
void setup(const vk::Device& device,
void setup(const vk::Instance& instance,
const vk::Device& device,
const vk::PhysicalDevice& physicalDevice,
uint32_t queueFamily) override;
void createDescriptorSetLayout();
@ -68,10 +67,10 @@ public:
{
uint32_t nbIndices{0};
uint32_t nbVertices{0};
nvvkBuffer vertexBuffer; // Device buffer of all 'Vertex'
nvvkBuffer indexBuffer; // Device buffer of the indices forming triangles
nvvkBuffer matColorBuffer; // Device buffer of array of 'Wavefront material'
nvvkBuffer matIndexBuffer; // Device buffer of array of 'Wavefront material'
nvvk::Buffer vertexBuffer; // Device buffer of all 'Vertex'
nvvk::Buffer indexBuffer; // Device buffer of the indices forming triangles
nvvk::Buffer matColorBuffer; // Device buffer of array of 'Wavefront material'
nvvk::Buffer matIndexBuffer; // Device buffer of array of 'Wavefront material'
};
// Instance of the OBJ
@ -100,17 +99,17 @@ public:
// Graphic pipeline
vk::PipelineLayout m_pipelineLayout;
vk::Pipeline m_graphicsPipeline;
std::vector<vk::DescriptorSetLayoutBinding> m_descSetLayoutBind;
nvvk::DescriptorSetBindings m_descSetLayoutBind;
vk::DescriptorPool m_descPool;
vk::DescriptorSetLayout m_descSetLayout;
vk::DescriptorSet m_descSet;
nvvkBuffer m_cameraMat; // Device-Host of the camera matrices
nvvkBuffer m_sceneDesc; // Device buffer of the OBJ instances
std::vector<nvvkTexture> m_textures; // vector of all textures of the scene
nvvk::Buffer m_cameraMat; // Device-Host of the camera matrices
nvvk::Buffer m_sceneDesc; // Device buffer of the OBJ instances
std::vector<nvvk::Texture> m_textures; // vector of all textures of the scene
nvvkpp::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures
nvvkpp::DebugUtil m_debug; // Utility to name objects
nvvk::AllocatorDedicated m_alloc; // Allocator for buffer, images, acceleration structures
nvvk::DebugUtil m_debug; // Utility to name objects
// #Post
void createOffscreenRender();
@ -119,7 +118,7 @@ public:
void updatePostDescriptorSet();
void drawPost(vk::CommandBuffer cmdBuf);
std::vector<vk::DescriptorSetLayoutBinding> m_postDescSetLayoutBind;
nvvk::DescriptorSetBindings m_postDescSetLayoutBind;
vk::DescriptorPool m_postDescPool;
vk::DescriptorSetLayout m_postDescSetLayout;
vk::DescriptorSet m_postDescSet;
@ -127,14 +126,14 @@ public:
vk::PipelineLayout m_postPipelineLayout;
vk::RenderPass m_offscreenRenderPass;
vk::Framebuffer m_offscreenFramebuffer;
nvvkTexture m_offscreenColor;
nvvk::Texture m_offscreenColor;
vk::Format m_offscreenColorFormat{vk::Format::eR32G32B32A32Sfloat};
nvvkTexture m_offscreenDepth;
nvvk::Texture m_offscreenDepth;
vk::Format m_offscreenDepthFormat{vk::Format::eD32Sfloat};
// #VKRay
void initRayTracing();
nvvkpp::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
nvvk::RaytracingBuilderKHR::Blas objectToVkGeometryKHR(const ObjModel& model);
void createBottomLevelAS();
void createTopLevelAS();
void createRtDescriptorSet();
@ -145,15 +144,15 @@ public:
vk::PhysicalDeviceRayTracingPropertiesKHR m_rtProperties;
nvvkpp::RaytracingBuilderKHR m_rtBuilder;
std::vector<vk::DescriptorSetLayoutBinding> m_rtDescSetLayoutBind;
nvvk::RaytracingBuilderKHR m_rtBuilder;
nvvk::DescriptorSetBindings m_rtDescSetLayoutBind;
vk::DescriptorPool m_rtDescPool;
vk::DescriptorSetLayout m_rtDescSetLayout;
vk::DescriptorSet m_rtDescSet;
std::vector<vk::RayTracingShaderGroupCreateInfoKHR> m_rtShaderGroups;
vk::PipelineLayout m_rtPipelineLayout;
vk::Pipeline m_rtPipeline;
nvvkBuffer m_rtSBTBuffer;
nvvk::Buffer m_rtSBTBuffer;
struct RtPushConstant
{

View file

@ -31,6 +31,7 @@
#include <array>
#include <vulkan/vulkan.hpp>
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
#include "imgui.h"
#include "imgui_impl_glfw.h"
@ -39,10 +40,10 @@
#include "nvh/cameramanipulator.hpp"
#include "nvh/fileoperations.hpp"
#include "nvpsystem.hpp"
#include "nvvkpp/appbase_vkpp.hpp"
#include "nvvkpp/commands_vkpp.hpp"
#include "nvvkpp/context_vkpp.hpp"
#include "nvvkpp/utilities_vkpp.hpp"
#include "nvvk/appbase_vkpp.hpp"
#include "nvvk/commands_vk.hpp"
#include "nvvk/context_vk.hpp"
//////////////////////////////////////////////////////////////////////////
#define UNUSED(x) (void)(x)
@ -125,7 +126,7 @@ int main(int argc, char** argv)
vk::PhysicalDeviceRayTracingFeaturesKHR raytracingFeature;
// Requesting Vulkan extensions and layers
nvvkpp::ContextCreateInfo contextInfo(true);
nvvk::ContextCreateInfo contextInfo(true);
contextInfo.setVersion(1, 2);
contextInfo.addInstanceLayer("VK_LAYER_LUNARG_monitor", true);
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);
// Creating Vulkan base application
nvvkpp::Context vkctx{};
nvvk::Context vkctx{};
vkctx.initInstance(contextInfo);
// Find all compatible devices
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);
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.createDepthBuffer();
helloVk.createRenderPass();
@ -250,7 +252,8 @@ int main(int argc, char** argv)
// Clearing screen
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});
// Offscreen render pass
@ -302,7 +305,6 @@ int main(int argc, char** argv)
helloVk.destroyResources();
helloVk.destroy();
vkctx.m_instance.destroySurfaceKHR(surface);
vkctx.deinit();
glfwDestroyWindow(window);

View file

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